Forum: Mikrocontroller und Digitale Elektronik FreeRTOS: Critical section und blockierender Queue


von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Hallo,

folgender Code zum Senden eines Bytes stammt aus dem UART-Beispiel von
FreeRTOS:
1
  portENTER_CRITICAL();
2
  {
3
    /* Is there space to write directly to the UART? */
4
    if( *plTHREEmpty == ( portLONG ) pdTRUE )
5
    {
6
      /* We wrote the character directly to the UART, so was 
7
      successful. */
8
      *plTHREEmpty = pdFALSE;
9
      UART0_THR = cOutChar;
10
      xReturn = pdPASS;
11
    }
12
    else 
13
    {
14
      /* We cannot write directly to the UART, so queue the character.
15
      Block for a maximum of xBlockTime if there is no space in the
16
      queue. */
17
      /* was passiert wenn dieser Queue blockt? context switch? */
18
      xReturn = xQueueSend( xCharsForTx, &cOutChar, xBlockTime );
19
20
      /* Depending on queue sizing and task prioritisation:  While we 
21
      were blocked waiting to post interrupts were not disabled.  It is 
22
      possible that the serial ISR has emptied the Tx queue, in which
23
      case we need to start the Tx off again. */
24
      if( ( *plTHREEmpty == ( portLONG ) pdTRUE ) && ( xReturn == pdPASS )
25
)
26
      {
27
        xQueueReceive( xCharsForTx, &cOutChar, serNO_BLOCK );
28
        *plTHREEmpty = pdFALSE;
29
        UART0_THR = cOutChar;
30
      }
31
    }
32
  }
33
  portEXIT_CRITICAL();

Was mir nicht ganz klar ist: CRITICAL unterbindet ja preemtive
Kontextwechsel. Was passiert aber wenn xQueueSend blockiert? Findet
dann ein Kontextwechsel statt, oder werden alle Tasks komplett
angehalten?

Andreas

von A.K. (Gast)


Lesenswert?

Korrekt erkannt, das sollte man so nicht machen.

von A.K. (Gast)


Lesenswert?

Korrektur: Es geht, weil das Interrupt-Flag ein Bestandteil vom
Task-Kontext ist. Da xQueueSend ggf. einen Taskwechsel durchführt, wird
als Teil dieses Taskwechsels der Interrupt wieder eingeschaltet. Das
muss man Auge behalten, wenn man bei abgeschalteten Interrupts Routinen
aufruft, die blockieren können.

von A.K. (Gast)


Lesenswert?

"CRITICAL unterbindet ja preemtive Kontextwechsel"

Das ja, aber kooperative Taskwechsel sind erlaubt. Und xQueueSend
enthält einen solchen

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Aha, das erklärt auch den Satz "While we were blocked waiting to post
interrupts were not disabled.". Während der Task blockiert laufen die
anderen Tasks also ganz normal weiter und unterbrechen sich ggf. auch
preemtiv gegenseitig, und bei der Rückkehr in den blockierten Task sind
die Interrupts wieder deaktiviert. Kann man das so stehen lassen?

von A.K. (Gast)


Lesenswert?

Richtig.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.