Zelo lep primer. Da še objasnim zakaj je tako.
- Koda: Izberi vse
DMA_Completed = false; //Spremljivka je nastavljena na false
LL_DMA_EnableStream(...); //start DMA transfer
//V tej točki prevajalnik vidi, da je spremenljivka predhodno nastavljena na false, in si misli "ah sej to ni potrebno delati", ter celoten izraz vrže ven iz kode.
//TO je seveda narobe, saj se DMA_Completed postavi na true v interrupt handlerju
//Če dodamo volatile, compiler NEBO sklepal nič po svoje in bo ob vsakem branju spremenljivke dejansko pogledal vrednost v RAM-u in ne le v delovnih registrih (someking cache je disablan).
while (!DMA_Completed)
{
//wait for DMA to complete
}
Ker pa je danes ogromno embedded programov napisanih v RTOS-u, je spodaj primer, kako to narediti tam.
- Koda: Izberi vse
//Kreiraj nov semafor z enim tokenom.
osSemaptoreId sync_sem = osSemaphoreCreate(..., 1);
osSemaphoreWait(sync_sem, 0); //Zakleni semafor takoj (gre skozi, ker imamo en token na voljo)
LL_DMA_Start...(start transfer)...
osSemaphoreWait(sync_sem, timeout); //Čakaj na semafor ponovno. Sedaj bomo čakali dokler ga nekdo ne odklene.
//DMA je končal v tej točki...
//Izbriši semafor
osSemaphoreDelete(sync_sem);
- Koda: Izberi vse
PPP_IRQ_Handler(void) {
osSemaphoreRelease(sync_sem); //Odkleni semafor
}
Zakaj semafor? Semafor je OS element, ki je sposoben postaviti thread v "blocked" stanje ter omogočiti izvajanje drugih thread-ov. Torej medtem ko čakamo, da DMA konča, lahko delamo nekaj tretjega v drugem threadu. Ko DMA konča, skočimo na izvajanje nazaj. Seveda se je potrebno vprašati, koliko podatkov pošiljamo preko DMA in ali ima smisel to delati ali le počakati v while zanki (ponavadi ima smiselno semafor).
Knowledge sharing is people' caring., T. MAJERLE