Skip to content

Commit 5cdd58d

Browse files
Add FreeRTOS functionality tests (#2257)
FreeRTOS often seems to have interesting corner cases. Add two simple tests that have been useful while debugging issues found from users or from FreeRTOS updates.
1 parent 96a2e92 commit 5cdd58d

File tree

3 files changed

+352
-0
lines changed

3 files changed

+352
-0
lines changed

libraries/FreeRTOS/tests/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This folder contains FreeRTOS functionality tests, not generally useful for users.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Simple stress test to ensure each thread has its own Newlib reent structure
2+
// The random numbers from each task should be identical.
3+
4+
#include <FreeRTOS.h>
5+
#include <task.h>
6+
7+
void go(void *param) {
8+
(void) param;
9+
srand(0);
10+
int i = 0;
11+
while(1) {
12+
char buff[100];
13+
TaskStatus_t st;
14+
vTaskGetInfo(NULL, &st, pdFALSE, eInvalid);
15+
sprintf(buff, "task %ld: %d = %d\n", st.xTaskNumber, i++, rand());
16+
Serial.print(buff);
17+
delay(1000);
18+
}
19+
}
20+
21+
void setup() {
22+
delay(5000);
23+
// put your setup code here, to run once:
24+
xTaskCreate(go, "c1", 1024, nullptr, 1, nullptr);
25+
xTaskCreate(go, "c2", 1024, nullptr, 1, nullptr);
26+
xTaskCreate(go, "c3", 1024, nullptr, 1, nullptr);
27+
}
28+
29+
void loop() {
30+
// put your main code here, to run repeatedly:
31+
32+
}
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
// FreeRTOS system call/mutex stress test
2+
3+
#include <Arduino.h>
4+
#include <FreeRTOS.h>
5+
#include <task.h>
6+
#include <semphr.h>
7+
#define DELAY 1
8+
#define SERIAL_DEBUG Serial1
9+
#define STACK_SIZE 512
10+
#define CORE_0 (1 << 0)
11+
#define CORE_1 (1 << 1)
12+
13+
void semphrTakeConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore);
14+
void semphrGiveConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore);
15+
16+
/*
17+
I want to keep the possibility of using different and independent
18+
mutexes for each of the functions that operate on the heap.
19+
20+
If you want to enable the use of these mutexes remove the defines
21+
on lines 30 and 31 and enable the their initialization in setup()
22+
*/
23+
SemaphoreHandle_t xSemaphoreMalloc = NULL;
24+
// SemaphoreHandle_t xSemaphoreRealloc = NULL;
25+
// SemaphoreHandle_t xSemaphoreFree = NULL;
26+
27+
/*
28+
A lazy way to use the same mutex for malloc, realloc and free
29+
in order to bring us back to the same situation as the MCVE
30+
posted here: https://github.com/earlephilhower/arduino-pico/issues/795#issuecomment-1227122082
31+
*/
32+
#define xSemaphoreRealloc xSemaphoreMalloc
33+
#define xSemaphoreFree xSemaphoreMalloc
34+
35+
const bool useMutexOnMalloc = false;
36+
const bool useMutexOnRealloc = false;
37+
const bool useMutexOnFree = false;
38+
39+
/*
40+
Enabling this, a realloc will be performed and the string "_realloc"
41+
will be concateneted to *tmp
42+
*/
43+
const bool tryRealloc = true;
44+
45+
TaskHandle_t loop2Handle = NULL;
46+
TaskHandle_t loop3Handle = NULL;
47+
TaskHandle_t loop4Handle = NULL;
48+
TaskHandle_t loop5Handle = NULL;
49+
TaskHandle_t loop6Handle = NULL;
50+
TaskHandle_t loop7Handle = NULL;
51+
52+
void loop2(void *pvPramaters);
53+
void loop3(void *pvPramaters);
54+
void loop4(void *pvPramaters);
55+
void loop5(void *pvPramaters);
56+
void loop6(void *pvPramaters);
57+
void loop7(void *pvPramaters);
58+
59+
void setup()
60+
{
61+
pinMode(LED_BUILTIN, OUTPUT);
62+
63+
xSemaphoreMalloc = xSemaphoreCreateMutex();
64+
// xSemaphoreRealloc = xSemaphoreCreateMutex();
65+
// xSemaphoreFree = xSemaphoreCreateMutex();
66+
67+
xTaskCreate(loop2, "loop2", STACK_SIZE, NULL, 1, &loop2Handle);
68+
vTaskCoreAffinitySet(loop2Handle, CORE_0);
69+
xTaskCreate(loop3, "loop3", STACK_SIZE, NULL, 1, &loop3Handle);
70+
vTaskCoreAffinitySet(loop3Handle, CORE_1);
71+
xTaskCreate(loop4, "loop4", STACK_SIZE, NULL, 1, &loop4Handle);
72+
vTaskCoreAffinitySet(loop4Handle, CORE_0);
73+
xTaskCreate(loop5, "loop5", STACK_SIZE, NULL, 1, &loop5Handle);
74+
vTaskCoreAffinitySet(loop5Handle, CORE_1);
75+
xTaskCreate(loop6, "loop6", STACK_SIZE, NULL, 1, &loop6Handle);
76+
vTaskCoreAffinitySet(loop6Handle, CORE_0);
77+
xTaskCreate(loop7, "loop7", STACK_SIZE, NULL, 1, &loop7Handle);
78+
vTaskCoreAffinitySet(loop7Handle, CORE_1);
79+
}
80+
static int _loop[8];
81+
82+
void loop()
83+
{
84+
while (1)
85+
{
86+
_loop[0]++;
87+
digitalWrite(LED_BUILTIN, HIGH);
88+
delay(500);
89+
digitalWrite(LED_BUILTIN, LOW);
90+
delay(500);
91+
for (int i=0; i<8; i++) Serial.printf("%d ", _loop[i]);
92+
Serial.println("");
93+
}
94+
}
95+
96+
void loop1()
97+
{
98+
while (1)
99+
{
100+
_loop[1]++;
101+
char *tmp;
102+
103+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
104+
tmp = (char *)malloc(10 * sizeof(char));
105+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
106+
107+
strcpy(tmp, "foo");
108+
109+
if (tryRealloc)
110+
{
111+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
112+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
113+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
114+
strcat(tmp, "_realloc");
115+
}
116+
117+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
118+
free(tmp);
119+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
120+
121+
delay(DELAY);
122+
}
123+
}
124+
125+
void loop2(void *pvPramaters)
126+
{
127+
(void) pvPramaters;
128+
while (1)
129+
{
130+
_loop[2]++;
131+
char *tmp;
132+
133+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
134+
tmp = (char *)malloc(10 * sizeof(char));
135+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
136+
137+
strcpy(tmp, "bar");
138+
139+
if (tryRealloc)
140+
{
141+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
142+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
143+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
144+
strcat(tmp, "_realloc");
145+
}
146+
147+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
148+
free(tmp);
149+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
150+
151+
delay(DELAY);
152+
}
153+
}
154+
155+
void loop3(void *pvPramaters)
156+
{
157+
(void) pvPramaters;
158+
while (1)
159+
{
160+
_loop[3]++;
161+
char *tmp;
162+
163+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
164+
tmp = (char *)malloc(10 * sizeof(char));
165+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
166+
167+
strcpy(tmp, "yeah");
168+
169+
if (tryRealloc)
170+
{
171+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
172+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
173+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
174+
strcat(tmp, "_realloc");
175+
}
176+
177+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
178+
free(tmp);
179+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
180+
181+
delay(DELAY);
182+
}
183+
}
184+
185+
void loop4(void *pvPramaters)
186+
{
187+
(void) pvPramaters;
188+
while (1)
189+
{
190+
_loop[4]++;
191+
char *tmp;
192+
193+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
194+
tmp = (char *)malloc(10 * sizeof(char));
195+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
196+
197+
strcpy(tmp, "baz");
198+
199+
if (tryRealloc)
200+
{
201+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
202+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
203+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
204+
strcat(tmp, "_realloc");
205+
}
206+
207+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
208+
free(tmp);
209+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
210+
211+
delay(DELAY);
212+
}
213+
}
214+
215+
void loop5(void *pvPramaters)
216+
{
217+
(void) pvPramaters;
218+
while (1)
219+
{
220+
_loop[5]++;
221+
char *tmp;
222+
223+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
224+
tmp = (char *)malloc(10 * sizeof(char));
225+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
226+
227+
strcpy(tmp, "asd");
228+
229+
if (tryRealloc)
230+
{
231+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
232+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
233+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
234+
strcat(tmp, "_realloc");
235+
}
236+
237+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
238+
free(tmp);
239+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
240+
241+
delay(DELAY);
242+
}
243+
}
244+
245+
void loop6(void *pvPramaters)
246+
{
247+
(void) pvPramaters;
248+
while (1)
249+
{
250+
_loop[6]++;
251+
char *tmp;
252+
253+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
254+
tmp = (char *)malloc(10 * sizeof(char));
255+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
256+
257+
strcpy(tmp, "lol");
258+
259+
if (tryRealloc)
260+
{
261+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
262+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
263+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
264+
strcat(tmp, "_realloc");
265+
}
266+
267+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
268+
free(tmp);
269+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
270+
271+
delay(DELAY);
272+
}
273+
}
274+
275+
void loop7(void *pvPramaters)
276+
{
277+
(void) pvPramaters;
278+
while (1)
279+
{
280+
_loop[7]++;
281+
char *tmp;
282+
283+
semphrTakeConditional(useMutexOnMalloc, xSemaphoreMalloc);
284+
tmp = (char *)malloc(10 * sizeof(char));
285+
semphrGiveConditional(useMutexOnMalloc, xSemaphoreMalloc);
286+
287+
strcpy(tmp, "yay");
288+
289+
if (tryRealloc)
290+
{
291+
semphrTakeConditional(useMutexOnRealloc, xSemaphoreRealloc);
292+
tmp = (char *)realloc(tmp, 20 * sizeof(char));
293+
semphrGiveConditional(useMutexOnRealloc, xSemaphoreRealloc);
294+
strcat(tmp, "_realloc");
295+
}
296+
297+
semphrTakeConditional(useMutexOnFree, xSemaphoreFree);
298+
free(tmp);
299+
semphrGiveConditional(useMutexOnFree, xSemaphoreFree);
300+
301+
delay(DELAY);
302+
}
303+
}
304+
305+
void semphrTakeConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore)
306+
{
307+
if (useMutexOn)
308+
{
309+
xSemaphoreTake(xSemaphore, TickType_t(portMAX_DELAY));
310+
}
311+
}
312+
313+
void semphrGiveConditional(bool useMutexOn, SemaphoreHandle_t xSemaphore)
314+
{
315+
if (useMutexOn)
316+
{
317+
xSemaphoreGive(xSemaphore);
318+
}
319+
}

0 commit comments

Comments
 (0)