Loading...
Searching...
No Matches
CmsisRtos2Threads.ino

Runs threads with ARM's CMSIS-RTOS2 API, which works the same on any CMSIS-RTOS2 system. Needs Tools > Operating System > FreeRTOS (SMP) + CMSIS-RTOS2.

The kernel is already running when setup() starts, so osKernelInitialize() and osKernelStart() are not needed. setup() prints the kernel's name (osKernelGetInfo()) and starts two threads with osThreadNew(): one blinks the LED with osDelay(), the other reads A0 exactly every 100 ms (osDelayUntil()) and puts each reading in a message queue. The sampling thread runs at osPriorityAboveNormal, above loop()'s osPriorityNormal, so its timing holds while loop() waits for readings with osMessageQueueGet() and prints them. See CMSIS-RTOS2.

Wiring
A voltage to measure on A0, e.g. a potentiometer wiper (0-3.3 V).
Output
Serial Monitor at 115200 baud; the LED flashes once a second:
Kernel: FreeRTOS V11.1.0+
1203 ms: A0 = 1650 mV
1303 ms: A0 = 1651 mV
// Runs threads with ARM's CMSIS-RTOS2 API, which works the same on any
// CMSIS-RTOS2 system (Keil RTX, Zephyr, other FreeRTOS boards).
// Needs Tools > Operating System > FreeRTOS (SMP) + CMSIS-RTOS2.
//
// The kernel is already running when setup() starts, so osKernelInitialize()
// and osKernelStart() are not needed. setup() starts two threads: one blinks
// the LED, the other reads A0 every 100 ms and puts each reading in a message
// queue. loop() is a thread too: it waits for readings and prints them.
#include <cmsis_os2.h>
struct Reading {
uint32_t time_ms;
uint32_t millivolts;
};
osMessageQueueId_t readings;
void blinkThread(void*) {
for (;;) {
osDelay(100); // in ticks: 1 tick = 1 ms
osDelay(900);
}
}
void sampleThread(void*) {
uint32_t wake = osKernelGetTickCount();
for (;;) {
const Reading r = {osKernelGetTickCount(), analogReadMillivolts(A0)};
if (osMessageQueuePut(readings, &r, 0, 0) != osOK) {
Serial.println("Queue full: reading dropped");
}
wake += 100;
osDelayUntil(wake); // every 100 ms, however long the work took
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {}
char kernel[32];
osKernelGetInfo(nullptr, kernel, sizeof(kernel));
Serial.print("Kernel: ");
Serial.println(kernel);
readings = osMessageQueueNew(20, sizeof(Reading), nullptr);
osThreadAttr_t blink = {}; // unset fields: defaults (osPriorityNormal, like loop())
blink.name = "blink";
blink.stack_size = 1024; // bytes
osThreadNew(blinkThread, nullptr, &blink);
osThreadAttr_t sample = {};
sample.name = "sample";
sample.stack_size = 2048;
sample.priority = osPriorityAboveNormal; // above loop(), so its timing holds
osThreadNew(sampleThread, nullptr, &sample);
}
void loop() {
Reading r;
if (osMessageQueueGet(readings, &r, nullptr, osWaitForever) == osOK) { // waits for a reading
Serial.print(r.time_ms);
Serial.print(" ms: A0 = ");
Serial.print(r.millivolts);
Serial.println(" mV");
}
}
@ OUTPUT
Definition Common.h:40
@ HIGH
Definition Common.h:32
@ LOW
Definition Common.h:31
SerialUSBClass Serial
USB serial port, the one the Serial Monitor uses.
uint32_t analogReadMillivolts(pin_size_t pin)
Reads an analog pin as a voltage, whatever its ADC and full scale.
void digitalWrite(pin_size_t pinNumber, PinStatus status)
Sets an output pin HIGH (3.3 V) or LOW (0 V).
void pinMode(pin_size_t pinNumber, PinMode pinMode)
Sets a pin as an input or an output.
void loop(void)
Written by the sketch: runs over and over after setup(), on core 0.
void setup(void)
Written by the sketch: runs once after reset, on core 0.
#define LED_BUILTIN
On-board LED.
Definition pins_arduino.h:63