Defining, creating and controlling thread functions in the system.
Program demonstruje ovládání blikání LED diody z jiného vlákna, čímž je uvolněno hlavní vlákno.
#include "byzance.h"
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
DigitalOut led(LED_BLUE);
Thread thread;
void led_thread() {
while (true) { //loop the thread
led = !led; //flip blue led
Thread::wait(1000); //wait for a second
}
}
void init() {
Byzance::led_module(false); //disable LED module for Byzance
thread.start(led_thread); //start the thread
}
void loop(){
pc.printf("i do nothing\n"); //main thread does actually nothing
Thread::wait(500);
}
Synchronize execution of threads, for example to protect access to a shared resource.
Program demonstruje vyžití mutexu jako ošetření přístupu ke sdílenému zdroji. Sdíleným zdrojem je v tomto případě LED dioda, ke které je přistupováno z hlavního a vedlejšího vlákna. Obě vlákna blikají diodou, každé ovšem s jinou frekvencí - je demonstrováno pravidelné střídání vláken.
#include "byzance.h"
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
DigitalOut led(LED_BLUE);
Thread thread;
Mutex led_protection; //led access protection
void led_thread() {
while (true) { //loop the thread
led_protection.lock(); //lock or wait forever for unlock
for(uint8_t i=0; i<10; i++){ //blink 10 times fast
led = LED_MODULE_ON; //flip blue led
Thread::wait(50);
led = LED_MODULE_OFF;
Thread::wait(50);
}
led_protection.unlock();
}
}
void init() {
Byzance::led_module(false); //disable LED module for Byzance
thread.start(led_thread); //start the thread
}
void loop(){
led_protection.lock(); //lock or wait forever for unlock
for(uint8_t i=0; i<10; i++){ //blink 5 times slow
led = LED_MODULE_ON;
Thread::wait(200);
led = LED_MODULE_OFF;
Thread::wait(200);
}
led_protection.unlock();
}
Manages thread access to a pool of shared resources of a certain type.
Semaphore semaphore;
Signals
Each Thread can wait for signals and to be notified of events.
Hlavní vlákno v pětisekundových intervalech nastavuje signál vedlejšímu vláknu. Vedlejší vlákno vždy čeká na signál a v případě jeho obdržení, zabliká 10x LED diodou.
#include "byzance.h"
#define BLINK_SIGNAL 0x01
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
DigitalOut led(LED_BLUE);
Thread thread;
void led_thread() {
while (true) { //loop the thread
osEvent event = Thread::signal_wait(0); //wait for any signal forever
if(event.status == osEventSignal && (event.value.signals & BLINK_SIGNAL)){ //if event was signal and signal is BLINK_SIGNAL
for(uint8_t i=0; i<10; i++){ //blink 10 times fast
led = LED_MODULE_ON;
Thread::wait(50);
led = LED_MODULE_OFF;
Thread::wait(50);
}
}
}
}
void init() {
Byzance::led_module(false); //disable LED module for Byzance
thread.start(led_thread); //start the thread
}
void loop(){ //set signal for thread once in 5 seconds
thread.signal_set(BLINK_SIGNAL);
Thread::wait(5000);
}
Allows queue pointers to data from producer threads to consumer threads.
Program demonstruje využití fronty. Stiskem tlačítka je vždy přidán jeden záznam do fronty z kontextu ISR. Hlavní vlákno pak postupně zpracovává jednotlivé záznamy z fronty tím, že na každou událost provede 10 bliknutí. Například osm stisků tlačítka postupně zařadí do fronty 80 bliknutí LED.
#include "byzance.h"
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
DigitalOut led(LED_BLUE);
InterruptIn button(USR);
Queue<void, 16> queue; //maximum is 16 records, no data type delivered
void button_pressed(){
queue.put(0); //on button pressed, add record to queue
}
void init() {
Byzance::led_module(false); //disable LED module for Byzance
button.fall(&button_pressed);
}
//try to press button multiple times
void loop(){
osEvent event = queue.get(); //wait for not empty queue forever
static int pressed_times=0;
if(event.status == osEventMessage){ //if event was osEventMessage
pressed_times++;
pc.printf("button pressed %d times\n",pressed_times);
for(uint8_t i=0; i<10; i++){ //blink 10 times for each record in queue
led = LED_MODULE_ON;
Thread::wait(50);
led = LED_MODULE_OFF;
Thread::wait(50);
}
}
}
Demonstruje využití dynamické alokace v oblasti paměti s fixní velikostí, v příkladu je dále využito třídu Queue. Odesílací vlákno alokuje a přidá v najednou 5 zpráv do fronty. Hlavní vlákno poté zprávy postupně zpracovává a dealokuje z paměti.
#include "byzance.h"
typedef struct {
float voltage; /* AD result of measured voltage */
float current; /* AD result of measured current */
uint32_t counter; /* A counter value */
} message_t;
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
MemoryPool<message_t, 16> mpool;
Queue<message_t, 16> queue;
Thread thread;
void send_thread (void) {
uint32_t i = 0;
while (true) { //every 5 seconds queue 4 msgs
for(uint8_t j = 0; j < 5; j++){
i++; // fake data update
message_t *message = mpool.alloc(); //alloc memory for message
message->voltage = (i * 0.1) * 33;
message->current = (i * 0.1) * 11;
message->counter = i;
queue.put(message); //queue the message
}
pc.printf("sent 5 msgs from send thread\n");
Thread::wait(5000);
}
}
void init(){
thread.start(callback(send_thread));
}
void loop() {
osEvent evt = queue.get(); //wait for not empty queue
if (evt.status == osEventMessage) {
message_t *message = (message_t*)evt.value.p;
pc.printf("received msg no. %d voltage: %f V, current: %f A\n",message->counter, message->voltage, message->current);
mpool.free(message); //free msg from memory
}
}
Like queue, with the added benefit of providing a memory pool for allocating messages - combination of MemoryPool and Queue.
Příklad využití spojení dynamické alokace a fronty v jednom - třídy Mail. Odesílací vlákno alokuje a přidá v najednou 5 zpráv do fronty. Hlavní vlákno poté zprávy postupně zpracovává a dealokuje z paměti.
#include "byzance.h"
typedef struct {
float voltage; /* AD result of measured voltage */
float current; /* AD result of measured current */
uint32_t counter; /* A counter value */
} message_t;
Serial pc(SERIAL_TX, SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);
Mail<message_t, 16> mail_box;
Thread thread;
void send_thread (void) {
uint32_t i = 0;
while (true) { //every 5 seconds queue 4 msgs
for(uint8_t j = 0; j < 5; j++){
i++; // fake data update
message_t *message = mail_box.alloc(); //alloc memory for message
message->voltage = (i * 0.1) * 33;
message->current = (i * 0.1) * 11;
message->counter = i;
mail_box.put(message); //queue the message
}
pc.printf("sent 4 mails from send thread\n");
Thread::wait(5000);
}
}
void init(){
thread.start(callback(send_thread));
}
void loop() {
osEvent evt = mail_box.get();
if (evt.status == osEventMail) {
message_t *message = (message_t*)evt.value.p;
pc.printf("received mail no. %d voltage: %f V, current: %f A\n",message->counter, message->voltage, message->current);
mail_box.free(message); //free msg from memory
}
}
Interrupts
The same RTOS API can be used in ISR. See InterruptIn reference.