RTOS Mail
A fejezet tartalma:Az mbed-RTOS Mail (levélküldés) szolgáltatása az üzenetsor (Queue) és a vele társított memóriakészlet (MemoryPool) tulajdonságait egyesíti egyetlen objektumosztályban. Ennek annyi előnye van csupán, hogy nem kell külön-külön példányosítanunk az üzenetsort és a memóriakészletet, s így nem kell külön névvel bajlódnunk és véletlenül sem fordulhat elő, hogy azokat különböző típusúnak vagy méretűnek definiáljuk. Az előzőekhez hasonlóan az mbed-RTOS Mail is templát osztály, azaz nekünk meg megadnunk, hogy milyen adatstruktúrákat tároljon, és azokból legfeljebb hány darabot.
1.
ábra: Az mbed-RTOS levélküldő szolgáltatása
Levelesláda létrehozása
Meg kell adnunk az elküldeni kívánt üzenetek (levelek) struktúra típusát, és az egyidejűleg tárolni kívánt üzenetek maximális darabszámát (a levelesláda méretét). Például:
typedef struct {
float voltage; // ADC feszültségmérés eredménye
float current; // ADC árammérés eredménye
uint32_t counter; // Egy kiolvasott számláló értéke
} message_t;
Mail mailbox; // 16 elemű levelesláda létrehozása
Levelesláda kezelése
Üzenetküldés szempontjából az mbed-RTOS
Mail is templát osztály ugyanúgy használható, mint a Queue üzenetsor, memóriakezelés
(lefoglalás, eltárolás, felszabadítás) szempontjából pedig ugyanolyan,
mint a MemoryPool (memória
készlet). Ezek alapján nem meglepő, hogy a Mail osztály tagfüggvényei a Queue és a MemoryPool tagfüggvényeinek
egyesített halmazát imitálják. Van azonban néhány apró különbség a
paraméterezésben.
A memória blokkok lefoglalása a Mail
objektumpéldányok alloc()
metódusával végezhető:
T* alloc ( uint32_t
timeout = 0 )
|
---|
Paraméterek: timeout - a maximális várakozási idő, ezredmásodpercekben megadva. Az alapértelmezett 0 érték azt jelenti, hogy nincs várakozás. Visszatérési érték: A függvény visszatérési értéke a szabad memória blokkra mutató pointer, vagy NULL, hiba esetén. A kapott pointer típusa (amit itt a T* jelöl) olyan adatstruktúrára mutató lesz, amilyen struktúra típust a Mail példányosításakor megadtunk. Megjegyzés: Ez a függvény megszakításból is hívható, de csak 0 paraméterrel! |
A felhasznált memória blokk felszabadítása a Mail objektumpéldányok free() metódusával végezhető:
osStatus free ( T * mptr
) |
---|
Paraméterek: mptr - az absztrakt T típusú üzenetre mutató pointer, amelyet a Mail::get() hívásakor kaptunk. A T* olyan adatstruktúrára mutató típust jelent, amilyen struktúra típust a Mail példányosításakor megadtunk. Visszatérési érték: A függvény visszatérési értéke az alábbi státusz, vagy hibakódok valamelyike lehet:
|
Az üzenetek küldése a Mail objektumpéldányok put() metódusával végezhető:
osStatus put ( T * mptr )
|
---|
Paraméterek: mptr - az absztrakt T típusú üzenetre mutató pointer Visszatérési érték: A függvény visszatérési értéke az alábbi státusz, vagy hibakódok valamelyike lehet:
|
Az üzenetek fogadása a Mail objektumpéldányok get() metódusával végezhető:
osEvent get ( uint32_t
timeout = osWaitForever ) |
---|
Paraméterek: timeout - a maximális várakozási idő, ezredmásodpercekben megadva. A várakozás alapértelmezetten korlátlan ideig tarthat. Ha 0 értéket adunk meg, az azt jelenti, hogy nincs várakozás, tehát ha van a tárban üzenet, akkor kivesszük, egyébként pedig hibakóddal tér vissza a függvény. Visszatérési érték: A függvény visszatérési értéke egy osEvent típusú struktúra, melynek status nevű eleme az alábbi státusz, vagy hibakódok valamelyike lehet:
Megjegyzés: Ez a függvény megszakításból is hívható, de csak 0 várakozási értékkel. |
Mintapélda: Üzenetküldés a Mail objektumosztály használatával
Az alábbi program csupán az előző fejezetben mutatott mintapélda átirata. A programban most is három lebegőpontos (float) típusú adatot tartalmazó adatstruktúrákat küldözgetünk üzenet gyanánt, melyeknek itt egy Mail típusú levelesláda biztosít tárterületet.Az első programszál véletlen színek közötti átmenetekhez generál RGB színkódokat interpolációval (a színkomponensek 0 - 1.0 közötti lebegőpontos számok), s ezeket a színkódokat küldjük el üzenetként, s minden üzenet után 0.1 másodpercet várunk.
A második programszál fogadja az üzeneteket, az RGB LED-en megjeleníti a kapott színkombinációt, majd felszabadítja a kapott üzenethez tartozó memória blokkot.
Hardver követelmények:
- FRDM-KL25Z kártya
#include "mbed.h"
#include "rtos.h"
PwmOut rled(LED_RED);
PwmOut gled(LED_GREEN);
PwmOut bled(LED_BLUE);
typedef struct {
float red;
float green;
float blue;
} message_t;
Mail <memory_t,4> mbox; //Mailbox for 4 messages
void led_thread(void const *argument) {
rled.period_ms(20); //Set period to 20 ms
rled.write(1.0f); //Initialize to 0% duty cycle
gled.period_ms(20); //Set period to 20 ms
gled.write(1.0f); //Initialize to 0% duty cycle
bled.period_ms(20); //Set period to 20 ms
bled.write(1.0f); //Initialize to 0% duty cycle
while (true) {
osEvent evt = mbox.get(); //Wait for a message
if(evt.status == osEventMail) {
message_t *mymessage = (message_t*)evt.value.p;
rled = 1.0f - mymessage->red;
gled = 1.0f - mymessage->green;
bled = 1.0f - mymessage->blue;
mbox.free(mymessage); //Free up memory
}
}
}
float frand(void) {
int32_t rv = 0x8000 -(rand()&0xFFFF);
return (rv*rv/1073741824.0f);
}
int main (void) {
float RGB1[3];
float RGB2[3];
float INC[3];
Thread thread2(led_thread);
//--- Create a random color ---------------------
for (int x=0; x<3; x++) {
RGB1[x] = frand();
}
while (true) {
//--- Create a new random color -----------------
for (int x=0; x<3; x++) {
RGB2[x] = frand();
}
//--- Determine increments to go from color 1 to color 2 in 25 steps
for (int x=0; x<3; x++) {
INC[x] = (RGB1[x] - RGB2[x]) / 25;
}
//--- Send color codes to thread2 ---------------
for (int s=0; s<25; s++) {
message_t *message = mbox.alloc(); //Allocate memory
message->red = RGB1[0];
message->green = RGB1[1];
message->blue = RGB1[2];
mbox.put(message); //Send data as message
Thread::wait(100);
for (int x=0; x<3; x++) {
RGB1[x] -= INC[x]; //Approach to second colour
}
}
}
}
Megjegyzés: A véletlenszám
generátor itt egy újabbra cseréltük, az előző fejezethez képest, abban
a reményben, hogy ez talán előnyben részesíti a "tisztább" színeket, a
kevert átlag helyett.