aboutsummaryrefslogtreecommitdiffstats
path: root/src/gos/freertos.c
blob: 9b22af1bd877836f1bd9eddaba20f61af8d4e0df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */

/**
 * @file    src/gos/freertos.c
 * @brief   GOS FreeRTOS Operating System support.
 */
#include "heivs/config.h"
#include "gfx.h"
#include "heivs/delay.h"
#include "freertos/FreeRTOS.h"
#include "config/FreeRTOSConfig.h"
#include <string.h>

#if configUSE_MUTEXES != 1
	#error "GOS: configUSE_MUTEXES must be defined in FreeRTOSConfig.h"
#endif

#if configUSE_COUNTING_SEMAPHORES  != 1
	#error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h"
#endif

void _gosInit(void)
{
	// IMPORTANT: Check for already started scheduler here!!!
	vTaskStartScheduler(); 
}

void* gfxRealloc(void *ptr, size_t oldsz, size_t newsz)
{
	void *np;

	if (newsz <= oldsz)
		return ptr;

	np = gfxAlloc(newsz);
	if (!np)
		return 0;

	if (oldsz) {
		memcpy(np, ptr, oldsz);
		vPortFree(ptr);
	}

	return np;
}

void gfxSleepMilliseconds(delaytime_t ms)
{
	if(ms == TIME_IMMEDIATE) {
		taskYIELD();
	} else {
		vTaskDelay(ms);
	}
}

void gfxSleepMicroseconds(delaytime_t ms)
{
	delay_wait_us(ms);
}

portTickType MS2ST(portTickType ms)
{
	uint64_t	val;

	if(configTICK_RATE_HZ == 1000) {	// gain time because no test to do in most case
		return ms;
	}

	val = ms;
	val *= configTICK_RATE_HZ;
	val += 999;
	val /= 1000;

	return val;
}

void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit)
{
	if (val > limit)
		val = limit;

	psem->counter = val;
	psem->limit = limit;
	psem->sem = xSemaphoreCreateCounting(limit,val);

	vTraceSetSemaphoreName(psem->sem, "uGFXSema"); // for FreeRTOS+Trace debug
}

void gfxSemDestroy(gfxSem* psem)
{
	vSemaphoreDelete(psem->sem);
}

bool_t gfxSemWait(gfxSem* psem, delaytime_t ms)
{
	psem->counter--;

	if(xSemaphoreTake(psem->sem, MS2ST(ms)) == pdPASS)
		return TRUE;

	psem->counter++;

	return FALSE;
}

void gfxSemSignal(gfxSem* psem)
{
	taskENTER_CRITICAL();

	if(psem->counter < psem->limit) {
		psem->counter++;
		xSemaphoreGive(psem->sem);
	}

	taskYIELD();
	taskEXIT_CRITICAL();
}

void gfxSemSignalI(gfxSem* psem)
{
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	if(psem->counter < psem->limit) {
		psem->counter++;
		xSemaphoreGiveFromISR(psem->sem,&xHigherPriorityTaskWoken);
	}
}

gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param)
{
	xTaskHandle task = NULL;
	stacksz = (size_t)stackarea;

	if (stacksz < configMINIMAL_STACK_SIZE)
		stacksz = configMINIMAL_STACK_SIZE;

	if (xTaskCreate(fn, (signed char*)"uGFX_TASK", stacksz, param, prio, &task )!= pdPASS) {
		for (;;);
	}

	return task;
}

#endif /* GFX_USE_OS_FREERTOS */
/** @} */
#endif /* USE_UGFX */