Forum: Mikrocontroller und Digitale Elektronik FreeROTS Fehler "AssertFail" durch Befehl xQueueReceive


von Philipp (Gast)


Lesenswert?

Hallo zusammen,

momentan bin ich dabei, ein Steuerungsprotokoll für einen 
mini-Quadrocopter zu implementieren. Es geht konkret um den Crazyflie 
2.0. Die Software läuft auf einem STM32F4, auf dem FreeRTOS läuft. Das 
Projekt ist hier zu finden:
https://github.com/bitcraze/crazyflie-firmware

Nachdem ich endlich die IDE ( Eclipse ) zum Laufen gebracht habe, kann 
ich nun auch endlich meinen Code mit dem GDB debuggen.

Mein Problem ist jetzt allerdings folgendes:
Ich habe einen Task erstellt, der zuerst eine Routine zum Empfangen 
eines Datenframes aufruft. Danach wird, falls eine Frame empfangen 
wurde, dieses ausgewertet.
1
static void extRxTask(void *param)
2
{
3
  while (true)
4
  {
5
  
6
    extRxReceiveSBusFrame();
7
    if(SBUS_Flags.New_Frame_received==1){
8
       extRxDecodeSBusChannels();
9
        }
10
  }
11
}
Probleme macht die erstgenannte Routine extRxReceivedSBusFrame(). In 
dieser soll mit der Funktion xQueueReceive(uart5queue, &byte, 
portMAX_DELAY) aus einer Queue ein Byte empfangen werden.
1
static void extRxReceiveSBusFrame(void){
2
    char byte;
3
    xQueueReceive(uart5queue, &byte, portMAX_DELAY);    // Don't wait if queue empty
4
5
    // Prüfe Synchronisierung
6
     if(SBUS_Flags.SBUS_synced){ 
7
      //Lese Frame
8
       if (SBUS_Byteindex<24){
9
         SBUS_Byte[SBUS_Byteindex++]=byte;
10
       }
11
       else if (byte == SBUS_Endbyte || SBUS_Byteindex==24)   { 
12
         SBUS_Flags.New_Frame_received=1;
13
         SBUS_Byteindex=0;
14
       }
15
       else {
16
         SBUS_Flags.SBUS_synced=0;// Synchronisierung verloren
17
         SBUS_lost_Frames++;
18
       }
19
     }
20
     else { 
21
      // Synchronisiere
22
      if(byte==SBUS_Endbyte){
23
       SBUS_Flags.Endbyte_received=1;
24
      }
25
      else if (byte==SBUS_Startbyte && SBUS_Flags.Endbyte_received){
26
       SBUS_Flags.SBUS_synced=1;
27
       SBUS_Flags.Endbyte_received=0;
28
       SBUS_Byteindex=1;
29
       SBUS_Byte[0]=SBUS_Startbyte;
30
      }  
31
     }
32
33
}

Nach meinem Verständnis legt dieser Befehl den Task "schlafen", bis sich 
Elemente in der Queue befinden. Sobald wieder ein Element in der Queue 
abgelegt wird, lässt der Taskscheduler die Funktion an der 
unterbrochenen Stelle weiterlaufen.

Der Sender ist bei mir eine ISR Routine, die Zeichen von einem UART 
empfängt und diese mit xQueueSendFromISR in die uart5queue legt:
1
void __attribute__((used)) USART5_IRQHandler(void)
2
{
3
  uint8_t rxData;
4
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
5
6
  if (USART_GetITStatus(UART5_TYPE, USART_IT_RXNE))
7
  {
8
    rxData = USART_ReceiveData(UART5_TYPE) & 0x00FF;
9
    xQueueSendFromISR(uart5queue, &rxData, &xHigherPriorityTaskWoken);
10
  }
11
}


Bei mir führt der xQueueReceive Befehl jedoch dazu, dass das Programm in 
eine Art Fehlermodus, genauer gesagt in die Funktion AssertFailed() 
gleitet wird. Dabei wird von der xQueueReceive(..) Funktion erst in 
diese Funktion gesprungen:
1
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
2
{
3
BaseType_t xEntryTimeSet = pdFALSE;
4
TimeOut_t xTimeOut;
5
int8_t *pcOriginalReadPosition;
6
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
7
8
  configASSERT( pxQueue );
9
  configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
10
  #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
11
  {
12
    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
13
  }
14
  #endif

Mit dem Makro configASSERT( pxQueue ) springt das Programm 
schlussendlich in die Funktion assertFail(...) hier, und zwar weil der 
Pointer pxQueue offensichtlich leer ist:
1
void assertFail(char *exp, char *file, int line)
2
{
3
  storeAssertSnapshotData(file, line);
4
  DEBUG_PRINT("Assert failed %s:%d\n", file, line);
5
6
  ledClearAll();
7
  ledSet(ERR_LED1, 1);
8
  ledSet(ERR_LED2, 1);
9
  while (1);
10
}

Damit hängt sich das Programm auf.

Da das hier mein erster Umgang mit FreeRTOS ist, bin ich völlig ratlos 
wo hier der Fehler sein könnte. Ich würde mich super freuen, wenn jemand 
Hilfsbereites sich das kurz anschauen könnte. Hoffe dass ich euch durch 
das Einbinden des jeweils relevanten Codes das Überfliegen erleichtert 
habe, das spart hoffentlich etwas Zeit und man muss nicht erst Dateien 
im Anhang durchstöbern.

Vielen Dank schonmal für eure Hilfe,

Gruß Philipp

von Philipp (Gast)


Lesenswert?

Könnte es vielleicht sein, dass die xQueueReceive() Funktion nicht in 
eine Unterfunktion geschrieben werden darf, sondern sich direkt in der 
Funktion des entsprechenden Tasks befinden muss?

von Stefan K. (stefan64)


Lesenswert?

Philipp schrieb:
> Könnte es vielleicht sein, dass die xQueueReceive() Funktion nicht in
> eine Unterfunktion geschrieben werden darf, sondern sich direkt in der
> Funktion des entsprechenden Tasks befinden muss?

Nein, das kann nicht sein. Falls der Queue-Aufruf bei Dir direkt aus der 
Task-Funktion funktioniert, dann tippe ich auf ein Stack-Problem.

Wahrscheinlicher ist, dass uart5queue nicht initialisiert ist. Wo wird 
bei Dir die Queue initialisiert?


QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,
                             UBaseType_t uxItemSize );


Gruß, Stefan

von Philipp (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe doch mal die beiden relevanten c-Files angehängt.

Die Queue habe ich initialiert, und zwar in der Datei uart5.c mit dem 
Befehl
1
 static xQueueHandle uart5queue;
Muss die Queue denn vielleicht dort initialisiert werden, wo sich auch 
der Befehl xQueueReceive befindet?

von Philipp (Gast)


Lesenswert?

Nachtrag:

Den Befehl
1
 uart5queue = xQueueCreate(32, sizeof(uint8_t));
 führe ich in der gleichen Datei in der Init Funktion aus.

von Stefan K. (stefan64)


Lesenswert?

Sieht eigendlich alles ganz ok aus. Kannst Du mal nach

uart5queue = xQueueCreate(32, sizeof(uint8_t));

einen Breakpoint setzen und den Wert von uart5queue überprüfen?


Gruß, Stefan

von Philipp (Gast)


Lesenswert?

Vielen Dank für deine Antwort.

Habe das ganze jetzt mal simulieren lassen, dazu habe ich einen 
Breakpoint in der Zeile nach der xQueueCreate Funkion erstellt.
Lasse ich das Programm bis dort hin laufen, zeigt er mir als 
QueueHandle_t für die uart5queue einen Wert von 0x20004820<ucHeap+16352> 
an.

von Philipp (Gast)


Lesenswert?

Habe den Fehler mittlerweile gefunden,
in der c-File, in der die Queue empfangen wird, muss der Queuehandler 
mit extern ... bekannt gemacht werden. Jetzt funktioniert zumindest 
diese Funkion.

Trotzdem vielen Dank für eure Hilfe!

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.