-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on examples from: https://github.com/greiman/FreeRTOS-Arduino Signed-off-by: Frederic.Pillon <[email protected]>
- Loading branch information
Showing
2 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Test to determine context switch time with a semaphore | ||
// Connect a scope to LED_BUILTIN pin | ||
// Measure difference in time between first pulse with no context switch | ||
// and second pulse started in ledControl and ended in ledOffTask. | ||
// This is the time for the semaphore and a context switch. | ||
#include <STM32FreeRTOS.h> | ||
|
||
#define LED_PIN LED_BUILTIN | ||
// Semaphore to trigger context switch | ||
SemaphoreHandle_t xSemaphore; | ||
//------------------------------------------------------------------------------ | ||
// high priority thread to set pin low | ||
static void ledOffTask(void *pvParameters) { | ||
for (;;) { | ||
xSemaphoreTake(xSemaphore, portMAX_DELAY); | ||
digitalWrite(LED_PIN, LOW); | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
// lower priority thread to toggle LED and trigger thread 1 | ||
static void ledControl(void *pvParameters) { | ||
for (;;) { | ||
// first pulse to get time with no context switch | ||
digitalWrite(LED_PIN, HIGH); | ||
digitalWrite(LED_PIN, LOW); | ||
|
||
// start second pulse | ||
digitalWrite(LED_PIN, HIGH); | ||
|
||
// trigger context switch for task that ends pulse | ||
xSemaphoreGive(xSemaphore); | ||
|
||
// sleep until next tick | ||
vTaskDelay(1); | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
void setup() { | ||
Serial.begin(9600); | ||
pinMode(LED_PIN, OUTPUT); | ||
|
||
// create high priority thread | ||
xTaskCreate(ledOffTask, | ||
"Task1", | ||
configMINIMAL_STACK_SIZE, | ||
NULL, | ||
tskIDLE_PRIORITY + 2, | ||
NULL); | ||
|
||
// create lower priority thread | ||
xTaskCreate(ledControl, | ||
"Task2", | ||
configMINIMAL_STACK_SIZE, | ||
NULL, | ||
tskIDLE_PRIORITY + 1, | ||
NULL); | ||
|
||
// create semaphore | ||
vSemaphoreCreateBinary(xSemaphore); | ||
|
||
// start FreeRTOS | ||
vTaskStartScheduler(); | ||
|
||
// should never return | ||
Serial.println("Die"); | ||
while(1); | ||
} | ||
//------------------------------------------------------------------------------ | ||
void loop() { | ||
// Not used - idle loop has a very small, configMINIMAL_STACK_SIZE, stack | ||
// loop must never block | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Data logger based on a FIFO to decouple SD write latency from data | ||
// acquisition. | ||
|
||
// The FIFO uses two semaphores to synchronize between tasks. | ||
|
||
#include <SPI.h> | ||
#include <STM32FreeRTOS.h> | ||
#include <SD.h> | ||
|
||
// interval between points in units of 1000 usec | ||
const uint16_t intervalTicks = 1; | ||
//------------------------------------------------------------------------------ | ||
// SD file definitions | ||
const uint8_t sdChipSelect = SS; | ||
File file; | ||
//------------------------------------------------------------------------------ | ||
// Fifo definitions | ||
|
||
// size of fifo in records | ||
const size_t FIFO_SIZE = 200; | ||
|
||
// count of data records in fifo | ||
SemaphoreHandle_t fifoData; | ||
|
||
// count of free buffers in fifo | ||
SemaphoreHandle_t fifoSpace; | ||
|
||
// data type for fifo item | ||
struct FifoItem_t { | ||
uint32_t usec; | ||
int value; | ||
int error; | ||
}; | ||
// array of data items | ||
FifoItem_t fifoArray[FIFO_SIZE]; | ||
//------------------------------------------------------------------------------ | ||
// handle for sensor task | ||
TaskHandle_t sens; | ||
static void Task1(void *arg) { | ||
// index of record to be filled | ||
size_t fifoHead = 0; | ||
|
||
// count of overrun errors | ||
int error = 0; | ||
|
||
// dummy data | ||
int count = 0; | ||
|
||
// initialise the ticks variable with the current time. | ||
TickType_t ticks = xTaskGetTickCount(); | ||
|
||
while (1) { | ||
// wait until time for next data point | ||
vTaskDelayUntil(&ticks, intervalTicks); | ||
|
||
// get a buffer | ||
if (xSemaphoreTake(fifoSpace, 0) != pdTRUE) { | ||
// fifo full - indicate missed point | ||
error++; | ||
continue; | ||
} | ||
FifoItem_t* p = &fifoArray[fifoHead]; | ||
p->usec = micros(); | ||
|
||
// replace next line with data read from sensor | ||
// f | ||
p->value = count++; | ||
|
||
p->error = error; | ||
error = 0; | ||
|
||
// signal new data | ||
xSemaphoreGive(fifoData); | ||
|
||
// advance FIFO index | ||
fifoHead = fifoHead < (FIFO_SIZE - 1) ? fifoHead + 1 : 0; | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
// SD write task | ||
static void Task2(void *arg) { | ||
// FIFO index for record to be written | ||
size_t fifoTail = 0; | ||
|
||
// time in micros of last point | ||
uint32_t last = 0; | ||
|
||
while(1) { | ||
// wait for next data record | ||
xSemaphoreTake(fifoData, portMAX_DELAY); | ||
|
||
FifoItem_t* p = &fifoArray[fifoTail]; | ||
|
||
// print interval between points | ||
if (last) { | ||
file.print(p->usec - last); | ||
} else { | ||
file.write("NA"); | ||
} | ||
last = p->usec; | ||
file.write(','); | ||
file.print(p->value); | ||
file.write(','); | ||
file.println(p->error); | ||
|
||
// release record | ||
xSemaphoreGive(fifoSpace); | ||
|
||
// advance FIFO index | ||
fifoTail = fifoTail < (FIFO_SIZE - 1) ? fifoTail + 1 : 0; | ||
|
||
// check for end run | ||
if (Serial.available()) { | ||
// close file to insure data is saved correctly | ||
file.close(); | ||
|
||
// print messages | ||
Serial.println(F("Done")); | ||
Serial.print(F("Task1 unused stack entries: ")); | ||
Serial.println(uxTaskGetStackHighWaterMark(sens)); | ||
Serial.print(F("Task2 unused stack entries: ")); | ||
Serial.println(uxTaskGetStackHighWaterMark(0)); | ||
// ARM free heap not implemented yet | ||
// Serial.print(F("Free heap (bytes): ")); | ||
// Serial.println(freeHeap()); | ||
while(1); | ||
} | ||
} | ||
} | ||
//------------------------------------------------------------------------------ | ||
void setup() { | ||
// task creation status | ||
portBASE_TYPE s1, s2; | ||
|
||
Serial.begin(9600); | ||
while(!Serial); | ||
Serial.println(F("Type any character to begin")); | ||
while(!Serial.available()); | ||
|
||
// open file | ||
if (!SD.begin(sdChipSelect)) { | ||
Serial.println("Card failed, or not present"); | ||
// don't do anything more: | ||
while(1); | ||
} | ||
Serial.println("card initialized."); | ||
|
||
file = SD.open("DATA.CSV", FILE_WRITE); | ||
if(!file) { | ||
Serial.println("error opening DATA.CSV"); | ||
while(1); | ||
} | ||
// initialize fifoData semaphore to no data available | ||
fifoData = xSemaphoreCreateCounting(FIFO_SIZE, 0); | ||
|
||
// initialize fifoSpace semaphore to FIFO_SIZE free records | ||
fifoSpace = xSemaphoreCreateCounting(FIFO_SIZE, FIFO_SIZE); | ||
|
||
// create sensor task at priority two | ||
s1 = xTaskCreate(Task1, NULL, configMINIMAL_STACK_SIZE, NULL, 2, &sens); | ||
|
||
// create SD write task at priority one | ||
s2 = xTaskCreate(Task2, NULL, configMINIMAL_STACK_SIZE + 200, NULL, 1, NULL); | ||
|
||
// check for creation errors | ||
if (fifoData == NULL || fifoSpace == NULL || s1 != pdPASS || s2 != pdPASS ) { | ||
Serial.println(F("Creation problem")); | ||
while(1); | ||
} | ||
// throw away serial input | ||
while (Serial.available()) Serial.read(); | ||
Serial.println(F("Type any character to end")); | ||
|
||
// start scheduler | ||
vTaskStartScheduler(); | ||
Serial.println(F("Insufficient RAM")); | ||
while(1); | ||
} | ||
//------------------------------------------------------------------------------ | ||
// WARNING idle loop has a very small stack (configMINIMAL_STACK_SIZE) | ||
// loop must never block | ||
void loop() { | ||
// not used | ||
} |