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"Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);DigitalOutled(LED_BLUE);Thread thread;voidled_thread() {while (true) { //loop the thread led =!led; //flip blue led Thread::wait(1000); //wait for a second }}voidinit() { Byzance::led_module(false); //disable LED module for Byzancethread.start(led_thread); //start the thread}voidloop(){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"Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);DigitalOutled(LED_BLUE);Thread thread;Mutex led_protection; //led access protectionvoidled_thread() {while (true) { //loop the threadled_protection.lock(); //lock or wait forever for unlockfor(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(); }}voidinit() { Byzance::led_module(false); //disable LED module for Byzancethread.start(led_thread); //start the thread}voidloop(){led_protection.lock(); //lock or wait forever for unlockfor(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"#defineBLINK_SIGNAL0x01Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);DigitalOutled(LED_BLUE);Thread thread;voidled_thread() {while (true) { //loop the thread osEvent event = Thread::signal_wait(0); //wait for any signal foreverif(event.status == osEventSignal && (event.value.signals & BLINK_SIGNAL)){ //if event was signal and signal is BLINK_SIGNALfor(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); } } }}voidinit() { Byzance::led_module(false); //disable LED module for Byzancethread.start(led_thread); //start the thread}voidloop(){ //set signal for thread once in 5 secondsthread.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"Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);DigitalOutled(LED_BLUE);InterruptInbutton(USR);Queue<void,16> queue; //maximum is 16 records, no data type deliveredvoidbutton_pressed(){queue.put(0); //on button pressed, add record to queue}voidinit() { Byzance::led_module(false); //disable LED module for Byzancebutton.fall(&button_pressed);}//try to press button multiple timesvoidloop(){ osEvent event =queue.get(); //wait for not empty queue foreverstaticint 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"typedefstruct {float voltage; /* AD result of measured voltage */float current; /* AD result of measured current */uint32_t counter; /* A counter value */} message_t;Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);MemoryPool<message_t,16> mpool;Queue<message_t,16> queue;Thread thread;voidsend_thread (void) {uint32_t i =0;while (true) { //every 5 seconds queue 4 msgsfor(uint8_t j =0; j <5; j++){ i++; // fake data updatemessage_t*message =mpool.alloc(); //alloc memory for messagemessage->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); }}voidinit(){thread.start(callback(send_thread));}voidloop() { osEvent evt =queue.get(); //wait for not empty queueif (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"typedefstruct {float voltage; /* AD result of measured voltage */float current; /* AD result of measured current */uint32_t counter; /* A counter value */} message_t;Serialpc(SERIAL_TX,SERIAL_RX); //USBSerial pc(0x1f00, 0x2012, 0x0001, false);Mail<message_t,16> mail_box;Thread thread;voidsend_thread (void) {uint32_t i =0;while (true) { //every 5 seconds queue 4 msgsfor(uint8_t j =0; j <5; j++){ i++; // fake data updatemessage_t*message =mail_box.alloc(); //alloc memory for messagemessage->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); }}voidinit(){thread.start(callback(send_thread));}voidloop() { 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.