Wachtrijen:introductie en basisservices
Bekijk de RTOS Revealed-serie
Wachtrijen werden geïntroduceerd in een eerder artikel. Ze bieden een flexibelere manier om eenvoudige berichten tussen taken door te geven dan mailboxen.
Wachtrijen gebruiken
In Nucleus SE worden wachtrijen geconfigureerd tijdens het bouwen. Er kunnen maximaal 16 wachtrijen zijn geconfigureerd voor een toepassing. Als er geen wachtrijen zijn geconfigureerd, worden er geen datastructuren of service-oproepcode behorende bij wachtrijen in de applicatie opgenomen.
Een wachtrij is gewoon een set opslaglocaties, elk groot genoeg om een enkel gegevensitem van het type ADDR te bevatten. , waarvan de toegang wordt gecontroleerd, zodat het veilig kan worden gebruikt door meerdere taken. Taken kunnen herhaaldelijk naar een wachtrij schrijven totdat alle locaties vol zijn. Taken kunnen uit een wachtrij worden gelezen en gegevens worden normaal gesproken ontvangen op basis van first in, first out (FIFO). Als u probeert naar een volle wachtrij te verzenden of te lezen uit een lege wachtrij, kan dit leiden tot een fout of taakonderbreking, afhankelijk van de opties die zijn geselecteerd in de API-aanroep en de Nucleus SE-configuratie.
Wachtrijen en leidingen
Nucleus SE ondersteunt ook buizen, die ook in een eerder artikel zijn geïntroduceerd en in een toekomstig artikel in detail worden behandeld. Het belangrijkste verschil tussen wachtrijen en leidingen is de berichtgrootte. Wachtrijen bevatten berichten die bestaan uit een enkele ADDR – dit zijn gewoonlijk aanwijzingen. Een pijp bevat berichten die een willekeurig aantal bytes lang zijn; de maat wordt voor elke leiding in de toepassing vastgelegd en tijdens de configuratie ingesteld.
Wachtrijen configureren
Aantal wachtrijen
Zoals met de meeste aspecten van Nucleus SE, wordt de configuratie van wachtrijen voornamelijk beheerd door #define uitspraken in nuse_config.h . De belangrijkste instelling is NUSE_QUEUE_NUMBER , die bepaalt hoeveel wachtrijen voor de toepassing zijn geconfigureerd. De standaardinstelling is 0 (dwz er zijn geen wachtrijen in gebruik) en u kunt deze instellen op elke waarde tot 16. Een foutieve waarde zal resulteren in een compileerfout, die wordt gegenereerd door een test in nuse_config_check.h (dit is opgenomen in nuse_config.c en dus gecompileerd met deze module) resulterend in een #error verklaring wordt gecompileerd.
Het kiezen van een waarde die niet nul is, is de "master enable" voor wachtrijen. Dit heeft tot gevolg dat sommige datastructuren dienovereenkomstig worden gedefinieerd en gedimensioneerd, waarover meer in het volgende artikel. Het activeert ook de instellingen voor het inschakelen van de API.
API ingeschakeld
Elke API-functie (serviceaanroep) in Nucleus SE heeft een activerende #define symbool in nuse_config.h . Voor wachtrijen zijn dit:
NUSE_QUEUE_SEND
NUSE_QUEUE_RECEIVE
NUSE_QUEUE_JAM
NUSE_QUEUE_RESET
NUSE_QUEUE_INFORMATION
NUSE_QUEUE_COUNT
Standaard zijn deze allemaal ingesteld op FALSE , waardoor elke serviceoproep wordt uitgeschakeld en het opnemen van implementatiecodes wordt voorkomen. Om wachtrijen voor een toepassing te configureren, moet u de API-aanroepen selecteren die u wilt gebruiken en hun activeringssymbolen instellen op TRUE .
Hier is een uittreksel uit het standaard nuse_config.h-bestand.
#define NUSE_QUEUE_NUMBER 0 /* Aantal wachtrijen in de
systeem - 0-16 * /
/ * serviceoproep enablers * /
#define NUSE_QUEUE_SEND VALSE
#define NUSE_QUEUE_RECEIVE VALSE
#define NUSE_QUEUE_JAM VALSE
#define NUSE_QUEUE_RESET FALSE
#define NUSE_QUEUE_INFORMATION FALSE
#define NUSE_QUEUE_COUNT FALSE
Er treedt een compileerfout op als een wachtrij-API-functie is ingeschakeld en er geen wachtrijen zijn geconfigureerd (behalve voor NUSE_Queue_Count() wat altijd is toegestaan). Als uw code een API-aanroep gebruikt, die niet is ingeschakeld, zal er een linktime-fout optreden, omdat er geen implementatiecode in de applicatie is opgenomen.
Wachtrijserviceoproepen
Nucleus RTOS ondersteunt tien service calls die horen bij wachtrijen, die de volgende functionaliteit bieden:
Stuur een bericht naar een wachtrij. Geïmplementeerd door NUSE_Queue_Send() in Nucleus SE.
Ontvang een bericht uit een wachtrij. Geïmplementeerd door NUSE_Queue_Receive() in Nucleus SE.
Stuur een bericht naar de voorkant van een wachtrij. Geïmplementeerd door NUSE_Queue_Jam() in Nucleus SE.
Herstel een wachtrij in de ongebruikte staat, zonder dat taken zijn opgeschort (reset). Geïmplementeerd door NUSE_Queue_Reset() in Nucleus SE.
Geef informatie over een gespecificeerde wachtrij. Geïmplementeerd door NUSE_Queue_Information() in Nucleus SE.
Retourneer een telling van het aantal wachtrijen dat (momenteel) is geconfigureerd voor de toepassing. Geïmplementeerd door NUSE_Queue_Count() in Nucleus SE.
Voeg een nieuwe wachtrij toe aan de applicatie (maken). Niet geïmplementeerd in Nucleus SE.
Verwijder een wachtrij uit de applicatie (verwijderen). Niet geïmplementeerd in Nucleus SE.
Retour verwijzingen naar alle wachtrijen (momenteel) in de toepassing. Niet geïmplementeerd in Nucleus SE.
Stuur een bericht naar alle taken die in een wachtrij staan (uitzending). Niet geïmplementeerd in Nucleus SE.
De implementatie van elk van deze service calls wordt in detail onderzocht.
Wachtrij schrijven en lezen
De fundamentele bewerkingen die op een wachtrij kunnen worden uitgevoerd, zijn het schrijven van gegevens ernaar - wat soms verzenden wordt genoemd – en er gegevens uit lezen – wat ook wel ontvangen wordt genoemd . Het is ook mogelijk om gegevens naar de voorkant van een wachtrij te schrijven - dit wordt ook wel jamming genoemd . Nucleus RTOS en Nucleus SE bieden elk drie basis-API-aanroepen voor deze bewerkingen, die hier worden besproken.
Schrijven naar een wachtrij
De Nucleus RTOS API-aanroep voor het schrijven naar een wachtrij is zeer flexibel, waardoor u voor onbepaalde tijd of met een time-out kunt opschorten als de bewerking niet onmiddellijk kan worden voltooid; d.w.z. u probeert naar een volledige wachtrij te schrijven. Nucleus SE biedt dezelfde service, behalve dat taakonderbreking optioneel is en time-out niet is geïmplementeerd.
Nucleus RTOS biedt ook de mogelijkheid om uit te zenden naar een wachtrij, maar dit wordt niet ondersteund door Nucleus SE. Het wordt beschreven onder Niet-geïmplementeerde API's in het volgende artikel.
Nucleus RTOS API-oproep voor verzending naar een wachtrij
Serviceoproep prototype:
STATUS NU_Send_To_Queue(NU_QUEUE *queue, VOID *message,
UNSIGNED size, UNSIGNED opschorten);
Parameters:
wachtrij – verwijzing naar het door de gebruiker geleverde wachtrijcontroleblok
bericht – een verwijzing naar het te verzenden bericht
maat – het aantal UNSIGNED gegevenselementen in het bericht. Als de wachtrij berichten met een variabele lengte ondersteunt, moet deze parameter gelijk zijn aan of kleiner zijn dan de berichtgrootte die door de wachtrij wordt ondersteund. Als de wachtrij berichten met een vaste grootte ondersteunt, moet deze parameter exact hetzelfde zijn als de berichtgrootte die door de wachtrij wordt ondersteund.
opschorten – specificatie voor taakonderbreking; kan NU_NO_SUSPEND . zijn of NU_SUSPEND of een time-outwaarde
Retourneren:
NU_SUCCESS – het gesprek is succesvol afgerond
NU_INVALID_QUEUE – de wachtrijaanwijzer is ongeldig
NU_INVALID_POINTER – de berichtaanwijzer is NULL
NU_INVALID_SIZE – de berichtgrootte is niet compatibel met de berichtgrootte die door de wachtrij wordt ondersteund
NU_INVALID_SUSPEND – opschorten is geprobeerd vanuit een niet-taakthread
NU_QUEUE_FULL – de wachtrij is vol en opschorten is niet gespecificeerd
NU_TIMEOUT – de wachtrij is nog steeds vol, zelfs na onderbreking voor de opgegeven time-outwaarde
NU_QUEUE_DELETED – de wachtrij is verwijderd terwijl de taak was opgeschort
NU_QUEUE_RESET – de wachtrij is gereset terwijl de taak was opgeschort
Nucleus SE API-oproep voor verzending naar een wachtrij
Deze API-aanroep ondersteunt de belangrijkste functionaliteit van de Nucleus RTOS API.
Serviceoproep prototype:
STATUS NUSE_Queue_Send(NUSE_QUEUE wachtrij, ADDR *message,
U8 opschorten);
Parameters:
wachtrij – de index (ID) van de te gebruiken wachtrij
bericht – een verwijzing naar het te verzenden bericht, een enkele variabele van het type ADDR
opschorten – specificatie voor taakonderbreking; kan NUSE_NO_SUSPEND . zijn of NUSE_SUSPEND
Retourneren:
NUSE_SUCCESS – het gesprek is succesvol afgerond
NUSE_INVALID_QUEUE – de wachtrij-index is ongeldig
NUSE_INVALID_POINTER – de berichtaanwijzer is NULL
NUSE_INVALID_SUSPEND – er is geprobeerd om opschorting uit te voeren vanuit een niet-taakthread of wanneer het blokkeren van API-aanroepen niet was ingeschakeld
NUSE_QUEUE_FULL – de wachtrij is vol en opschorten is niet gespecificeerd
NUSE_QUEUE_WAS_RESET – de wachtrij is gereset terwijl de taak was opgeschort
Nucleus SE-implementatie van Queue ASend
Het grootste deel van de code van de NUSE_Queue_Send() API-functie – na parametercontrole – wordt geselecteerd door voorwaardelijke compilatie, afhankelijk van of ondersteuning voor het blokkeren (taakonderbreken) API-aanroepen is ingeschakeld. We zullen de twee varianten hier afzonderlijk bekijken.
Als blokkeren niet is ingeschakeld, is de code voor deze API-aanroep vrij eenvoudig:
if (NUSE_Queue_Items[queue] ==NUSE_Queue_Size[queue]) /* wachtrij vol */{ return_value =NUSE_QUEUE_FULL;}else /* wachtrij-element beschikbaar */{ NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] =*bericht; if (NUSE_Queue_Head[wachtrij] ==NUSE_Queue_Size[wachtrij]) { NUSE_Queue_Head[wachtrij] =0; } NUSE_Queue_Items[wachtrij]++; return_value =NUSE_SUCCESS;}
De functie controleert eenvoudig of er ruimte is in de wachtrij en gebruikt de NUSE_Queue_Head[] index om het bericht op te slaan in het gegevensgebied van de wachtrij.
Als blokkeren is ingeschakeld, wordt de code complexer:
do{ if (NUSE_Queue_Items[queue] ==NUSE_Queue_Size[queue]) /* wachtrij vol */ { if (suspend ==NUSE_NO_SUSPEND) { return_value =NUSE_QUEUE_FULL; } else { /* block task */ NUSE_Queue_Blocking_Count[wachtrij]++; NUSE_Suspend_Task(NUSE_Task_Active, (wachtrij <<4) | NUSE_QUEUE_SUSPEND); return_value =NUSE_Task_Blocking_Return [NUSE_Task_Active]; if (return_value !=NUSE_SUCCESS) { opschorten =NUSE_NO_SUSPEND; } } } else { /* wachtrij-element beschikbaar */ NUSE_Queue_Data[wachtrij][NUSE_Queue_Head[wachtrij]++] =*bericht; if (NUSE_Queue_Head[wachtrij] ==NUSE_Queue_Size[wachtrij]) { NUSE_Queue_Head[wachtrij] =0; } NUSE_Queue_Items[wachtrij]++; if (NUSE_Queue_Blocking_Count[wachtrij] !=0) { U8 index; /* controleer of een taak in deze wachtrij is geblokkeerd */ NUSE_Queue_Blocking_Count[wachtrij]--; for (index=0; indexEnige uitleg van de code kan nuttig zijn:
De code is ingesloten in een do…while loop, die doorgaat terwijl de parameter suspend de waarde NUSE_SUSPEND . heeft .
Als de wachtrij vol is en onderbreken is ingesteld op NUSE_NO_SUSPEND , de API-aanroep wordt afgesloten met NUSE_QUEUE_FULL . Als opschorten was ingesteld op NUSE_SUSPEND , wordt de taak opgeschort. Bij terugkeer (d.w.z. wanneer de taak wordt gewekt), als de geretourneerde waarde NUSE_SUCCESS is , wat aangeeft dat de taak is geactiveerd omdat een bericht is gelezen (in tegenstelling tot een reset van de wachtrij), keert de code terug naar boven.
Als de wachtrij niet vol is, wordt het aangeleverde bericht opgeslagen met de NUSE_Queue_Head[] index om het bericht op te slaan in het gegevensgebied van de wachtrij. Er wordt gecontroleerd of er taken in de wachtrij staan (wacht op ontvangst). Als er nog taken wachten, wordt de eerste gewekt. De opschorten variabele is ingesteld op NUSE_NO_SUSPEND en de API-aanroep wordt afgesloten met NUSE_SUCCESS .
Ingebed
- Een inleiding tot Cam Locks en hoe ze werken
- Een inleiding tot oogschroeven en hoe ze werken
- Een inleiding tot doorvoertules en hoe ze werken
- Een inleiding tot roestvrij staal en hoe het wordt gemaakt
- C# Basisinvoer en -uitvoer
- Mailboxen:introductie en basisservices
- Semaphores:nutsvoorzieningen en datastructuren
- Semaphores:introductie en basisdiensten
- Event flag-groepen:nutsvoorzieningen en datastructuren
- Event flag-groepen:introductie en basisservices
- Oppervlakteslijpdiensten:proces en precisie