I now have ChibiOS/RT and FreeRTOS running on Due. Should I bother to post them?
It seems like few Arduino users need or want to use a real-time kernel.
Here is the typical response from an "old timer" about using a RTOS.
When I author code that will run UNDER an OS, I by definition do not have access to the resources that will allow me to thread my own code. I am force to use the provided OS threading model and constructs.
I've developed some very complex systems though the years. I've been programming in ASM before C even existed.
I have never used an "RTOS", I've always teased out and separated my code so timer interrupts always provide me the abilty to implement the required schedules. I'm also careful to author my code so scheduling can be changed around without complete rewrites. A recent design included a design that had Zigbee Radio (proprietary comm), Ethernet, host Serial, and a ton of real-time I/O, including router functions to packet route / bridge radio and Ethernet AND host serial traffic (packets route across all 3 "channels"). No RTOS was used, and suspect any RTOS would have cause a lot of packet jitter where the current system is very deterministic ...
So what is the primary motive for which people feel the need to use RTOS's on micro-controllers? Sorry, I don't get it.
Here is an "tutorial" by FreeRTOS that compares solutions without and with a RTOS RTOS Tutorial - Using an RTOS on small embedded computers.
I am an "old timer" and have used real-time kernels since the mid 1970s. Often using a real-time kernel makes an application really easy.
Here are two tasks for a data logger that trivially logs data to an SD at 1000 points/second without losing data because of the occasional long SD write latency.
I ran this on Due with a buffer queue of 250 points, enough for a 250 millisecond write latency. The ADC reader put data at the head of the queue and the SD writer takes data from the tail of the queue.
It could easily log data at much faster rates if a timer was used to trigger the data read thread.
Here is the ADC read task. In my example it runs every 1000 microseconds and reads four ADC channels.
// ADC read thread
static msg_t Thread1(void *arg) {
uint8_t over = 0;
// read data until terminate signal
while (!chThdShouldTerminate()) {
// sleep until time for next point
chThdSleep(SLEEP_TICKS);
// get pointer to next free data point
point* h = q.headItem();
if (h) {
// save time in micros
h->usec = micros();
// read ADC channels
for (uint8_t i = 0; i < ADC_COUNT; i++) {
h->data[i] = analogRead(i);
}
// count of overruns since last data
h->over = over;
// advance queue head so writer will see point
q.headNext();
// clear overrun count
over = 0;
} else {
// count overrun - queue full
if (over < MAX_OVER) over++;
}
}
return 0;
}
Data is written to the SD by this thread:
// format data point and write to SD
void loop() {
// get count of points in queue
size_t n = q.count();
for (size_t i = 0; i < n; i++) {
// get pointer to next data point
point* p = q.tailItem();
// write data point
file.print(p->usec);
file.write(',');
// format ADC values
for (uint8_t i = 0; i < ADC_COUNT; i++) {
file.print(p->data[i]);
file.write(',');
}
// format overrun count
file.println(p->over);
// free data point storage in queue
q.tailNext();
}
// check for write error
if (file.writeError) sd.errorHalt_P(PSTR("write error"));
}
Here is the first part of the data file. Note that there is no jitter in the time in micros. Exactly 1000 microseconds between calls to the ADC read task.
micros,data0,data1,data2,data3,over
3769007,659,728,752,759,0
3770007,602,567,576,585,0
3771007,527,480,480,489,0
3772007,466,426,421,429,0
3773007,420,388,383,390,0
3774007,386,362,358,365,0
3775007,363,344,341,347,0
3776007,347,331,329,335,0
3777007,335,321,320,326,0
3778007,326,314,314,319,0