Skip to content

Commit 6fb5ec0

Browse files
committed
Added some examples
Based on examples from: https://github.com/greiman/FreeRTOS-Arduino Signed-off-by: Frederic.Pillon <frederic.pillon@st.com>
1 parent 4f0b266 commit 6fb5ec0

File tree

2 files changed

+256
-0
lines changed

2 files changed

+256
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Test to determine context switch time with a semaphore
2+
// Connect a scope to LED_BUILTIN pin
3+
// Measure difference in time between first pulse with no context switch
4+
// and second pulse started in ledControl and ended in ledOffTask.
5+
// This is the time for the semaphore and a context switch.
6+
#include <STM32FreeRTOS.h>
7+
8+
#define LED_PIN LED_BUILTIN
9+
// Semaphore to trigger context switch
10+
SemaphoreHandle_t xSemaphore;
11+
//------------------------------------------------------------------------------
12+
// high priority thread to set pin low
13+
static void ledOffTask(void *pvParameters) {
14+
for (;;) {
15+
xSemaphoreTake(xSemaphore, portMAX_DELAY);
16+
digitalWrite(LED_PIN, LOW);
17+
}
18+
}
19+
//------------------------------------------------------------------------------
20+
// lower priority thread to toggle LED and trigger thread 1
21+
static void ledControl(void *pvParameters) {
22+
for (;;) {
23+
// first pulse to get time with no context switch
24+
digitalWrite(LED_PIN, HIGH);
25+
digitalWrite(LED_PIN, LOW);
26+
27+
// start second pulse
28+
digitalWrite(LED_PIN, HIGH);
29+
30+
// trigger context switch for task that ends pulse
31+
xSemaphoreGive(xSemaphore);
32+
33+
// sleep until next tick
34+
vTaskDelay(1);
35+
}
36+
}
37+
//------------------------------------------------------------------------------
38+
void setup() {
39+
Serial.begin(9600);
40+
pinMode(LED_PIN, OUTPUT);
41+
42+
// create high priority thread
43+
xTaskCreate(ledOffTask,
44+
"Task1",
45+
configMINIMAL_STACK_SIZE,
46+
NULL,
47+
tskIDLE_PRIORITY + 2,
48+
NULL);
49+
50+
// create lower priority thread
51+
xTaskCreate(ledControl,
52+
"Task2",
53+
configMINIMAL_STACK_SIZE,
54+
NULL,
55+
tskIDLE_PRIORITY + 1,
56+
NULL);
57+
58+
// create semaphore
59+
vSemaphoreCreateBinary(xSemaphore);
60+
61+
// start FreeRTOS
62+
vTaskStartScheduler();
63+
64+
// should never return
65+
Serial.println("Die");
66+
while(1);
67+
}
68+
//------------------------------------------------------------------------------
69+
void loop() {
70+
// Not used - idle loop has a very small, configMINIMAL_STACK_SIZE, stack
71+
// loop must never block
72+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Data logger based on a FIFO to decouple SD write latency from data
2+
// acquisition.
3+
4+
// The FIFO uses two semaphores to synchronize between tasks.
5+
6+
#include <SPI.h>
7+
#include <STM32FreeRTOS.h>
8+
#include <SD.h>
9+
10+
// interval between points in units of 1000 usec
11+
const uint16_t intervalTicks = 1;
12+
//------------------------------------------------------------------------------
13+
// SD file definitions
14+
const uint8_t sdChipSelect = SS;
15+
File file;
16+
//------------------------------------------------------------------------------
17+
// Fifo definitions
18+
19+
// size of fifo in records
20+
const size_t FIFO_SIZE = 200;
21+
22+
// count of data records in fifo
23+
SemaphoreHandle_t fifoData;
24+
25+
// count of free buffers in fifo
26+
SemaphoreHandle_t fifoSpace;
27+
28+
// data type for fifo item
29+
struct FifoItem_t {
30+
uint32_t usec;
31+
int value;
32+
int error;
33+
};
34+
// array of data items
35+
FifoItem_t fifoArray[FIFO_SIZE];
36+
//------------------------------------------------------------------------------
37+
// handle for sensor task
38+
TaskHandle_t sens;
39+
static void Task1(void *arg) {
40+
// index of record to be filled
41+
size_t fifoHead = 0;
42+
43+
// count of overrun errors
44+
int error = 0;
45+
46+
// dummy data
47+
int count = 0;
48+
49+
// initialise the ticks variable with the current time.
50+
TickType_t ticks = xTaskGetTickCount();
51+
52+
while (1) {
53+
// wait until time for next data point
54+
vTaskDelayUntil(&ticks, intervalTicks);
55+
56+
// get a buffer
57+
if (xSemaphoreTake(fifoSpace, 0) != pdTRUE) {
58+
// fifo full - indicate missed point
59+
error++;
60+
continue;
61+
}
62+
FifoItem_t* p = &fifoArray[fifoHead];
63+
p->usec = micros();
64+
65+
// replace next line with data read from sensor
66+
// f
67+
p->value = count++;
68+
69+
p->error = error;
70+
error = 0;
71+
72+
// signal new data
73+
xSemaphoreGive(fifoData);
74+
75+
// advance FIFO index
76+
fifoHead = fifoHead < (FIFO_SIZE - 1) ? fifoHead + 1 : 0;
77+
}
78+
}
79+
//------------------------------------------------------------------------------
80+
// SD write task
81+
static void Task2(void *arg) {
82+
// FIFO index for record to be written
83+
size_t fifoTail = 0;
84+
85+
// time in micros of last point
86+
uint32_t last = 0;
87+
88+
while(1) {
89+
// wait for next data record
90+
xSemaphoreTake(fifoData, portMAX_DELAY);
91+
92+
FifoItem_t* p = &fifoArray[fifoTail];
93+
94+
// print interval between points
95+
if (last) {
96+
file.print(p->usec - last);
97+
} else {
98+
file.write("NA");
99+
}
100+
last = p->usec;
101+
file.write(',');
102+
file.print(p->value);
103+
file.write(',');
104+
file.println(p->error);
105+
106+
// release record
107+
xSemaphoreGive(fifoSpace);
108+
109+
// advance FIFO index
110+
fifoTail = fifoTail < (FIFO_SIZE - 1) ? fifoTail + 1 : 0;
111+
112+
// check for end run
113+
if (Serial.available()) {
114+
// close file to insure data is saved correctly
115+
file.close();
116+
117+
// print messages
118+
Serial.println(F("Done"));
119+
Serial.print(F("Task1 unused stack entries: "));
120+
Serial.println(uxTaskGetStackHighWaterMark(sens));
121+
Serial.print(F("Task2 unused stack entries: "));
122+
Serial.println(uxTaskGetStackHighWaterMark(0));
123+
// ARM free heap not implemented yet
124+
// Serial.print(F("Free heap (bytes): "));
125+
// Serial.println(freeHeap());
126+
while(1);
127+
}
128+
}
129+
}
130+
//------------------------------------------------------------------------------
131+
void setup() {
132+
// task creation status
133+
portBASE_TYPE s1, s2;
134+
135+
Serial.begin(9600);
136+
while(!Serial);
137+
Serial.println(F("Type any character to begin"));
138+
while(!Serial.available());
139+
140+
// open file
141+
if (!SD.begin(sdChipSelect)) {
142+
Serial.println("Card failed, or not present");
143+
// don't do anything more:
144+
while(1);
145+
}
146+
Serial.println("card initialized.");
147+
148+
file = SD.open("DATA.CSV", FILE_WRITE);
149+
if(!file) {
150+
Serial.println("error opening DATA.CSV");
151+
while(1);
152+
}
153+
// initialize fifoData semaphore to no data available
154+
fifoData = xSemaphoreCreateCounting(FIFO_SIZE, 0);
155+
156+
// initialize fifoSpace semaphore to FIFO_SIZE free records
157+
fifoSpace = xSemaphoreCreateCounting(FIFO_SIZE, FIFO_SIZE);
158+
159+
// create sensor task at priority two
160+
s1 = xTaskCreate(Task1, NULL, configMINIMAL_STACK_SIZE, NULL, 2, &sens);
161+
162+
// create SD write task at priority one
163+
s2 = xTaskCreate(Task2, NULL, configMINIMAL_STACK_SIZE + 200, NULL, 1, NULL);
164+
165+
// check for creation errors
166+
if (fifoData == NULL || fifoSpace == NULL || s1 != pdPASS || s2 != pdPASS ) {
167+
Serial.println(F("Creation problem"));
168+
while(1);
169+
}
170+
// throw away serial input
171+
while (Serial.available()) Serial.read();
172+
Serial.println(F("Type any character to end"));
173+
174+
// start scheduler
175+
vTaskStartScheduler();
176+
Serial.println(F("Insufficient RAM"));
177+
while(1);
178+
}
179+
//------------------------------------------------------------------------------
180+
// WARNING idle loop has a very small stack (configMINIMAL_STACK_SIZE)
181+
// loop must never block
182+
void loop() {
183+
// not used
184+
}

0 commit comments

Comments
 (0)