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