Hallo, ich habe mich heute in in das FreeRTOS auf den STM32F4 Controllern eingarbeitet. Ich habe einen Task der eine LED 100x blinken lassen soll. Dies funktioniert auch ganz gut. Nur wenn der Task zu Ende ist (nach 100x) LED blinken lassen) wird der Default-Handler in startup_stm32f4xx.c aufgerufen. Eig. gibt es doch den IDLE-TASK der aufgerufen wird wenn keine anderen Tasks vorhanden sind. Oder? Weiß jemand was genaueres dazu? Moritz
>Ich habe einen Task der eine LED 100x blinken lassen soll. Dies >funktioniert auch ganz gut. Nur wenn der Task zu Ende ist (nach 100x) >LED blinken lassen) wird der Default-Handler in startup_stm32f4xx.c >aufgerufen. Dann hast du wohl einen der drei Interruptvektoren die man FreeRTOS zuweisen muss nicht in die Interrupttabelle eingetragen.
Hallo, welche Interrupt Vektoren? Sind das: vPortSVCHandler -> SVCHandler xPortPendSVHandler -> PendSV_Handler xPortSysTickHandler -> SysTick_Handler Moritz
Das hängt von der Implementierung von FreeRTOS ab. Deine Beschreibung klingt danach, dass keine Endlosschleife in dem LED-Task verwendet wird und damit die Task-Funktion verlassen wird. Ich kenne den Kernel jetzt nicht genau, allerdings gehe ich davon aus, dass bei FreeRTOS jeder Task in einer Endlosschleife laufen muss. Wird der Task verlassen, so landet der Program Counter an irgendeiner nicht definierten Adresse. MfG
>Dann hast du wohl einen der drei Interruptvektoren >die man FreeRTOS zuweisen muss nicht in die Interrupttabelle >eingetragen. So, noch mal schnell nachgesehen. Die drei Handler heissen vPortSVCHandler, /* SVCall Handler */ xPortPendSVHandler, /* PendSV Handler */ xPortSysTickHandler, /* SysTick Handler */ Die musst du in der Startup Datei in die Interrupttabelle eintragen.
Hallo, Sorry aber ist das hier die Interrupt Tabelle?:
1 | /**
|
2 | *@brief The minimal vector table for a Cortex M3. Note that the proper constructs
|
3 | * must be placed on this to ensure that it ends up at physical address
|
4 | * 0x00000000.
|
5 | */
|
6 | __attribute__ ((section(".isr_vector"))) |
7 | void (* const g_pfnVectors[])(void) = |
8 | {
|
9 | /*----------Core Exceptions------------------------------------------------ */
|
10 | (void *)&pulStack[STACK_SIZE-1], /*!< The initial stack pointer */ |
11 | Reset_Handler, /*!< Reset Handler */ |
12 | NMI_Handler, /*!< NMI Handler */ |
13 | HardFault_Handler, /*!< Hard Fault Handler */ |
14 | MemManage_Handler, /*!< MPU Fault Handler */ |
15 | BusFault_Handler, /*!< Bus Fault Handler */ |
16 | UsageFault_Handler, /*!< Usage Fault Handler */ |
17 | 0,0,0,0, /*!< Reserved */ |
18 | SVC_Handler, /*!< SVCall Handler */ |
19 | DebugMon_Handler, /*!< Debug Monitor Handler */ |
20 | 0, /*!< Reserved */ |
21 | PendSV_Handler, /*!< PendSV Handler */ |
22 | SysTick_Handler, /*!< SysTick Handler */ |
23 | |
24 | /*----------External Exceptions---------------------------------------------*/
|
25 | WWDG_IRQHandler, /*!< 0: Window WatchDog */ |
26 | PVD_IRQHandler, /*!< 1: PVD through EXTI Line detection */ |
27 | TAMP_STAMP_IRQHandler, /*!< 2: Tamper and TimeStamps through the EXTI line*/ |
28 | RTC_WKUP_IRQHandler, /*!< 3: RTC Wakeup through the EXTI line */ |
29 | FLASH_IRQHandler, /*!< 4: FLASH */ |
30 | RCC_IRQHandler , /*!< 5: RCC */ |
31 | EXTI0_IRQHandler, /*!< 6: EXTI Line0 */ |
32 | EXTI1_IRQHandler, /*!< 7: EXTI Line1 */ |
33 | EXTI2_IRQHandler, /*!< 8: EXTI Line2 */ |
34 | EXTI3_IRQHandler, /*!< 9: EXTI Line3 */ |
35 | EXTI4_IRQHandler, /*!< 10: EXTI Line4 */ |
36 | DMA1_Stream0_IRQHandler, /*!< 11: DMA1 Stream 0 */ |
37 | DMA1_Stream1_IRQHandler, /*!< 12: DMA1 Stream 1 */ |
38 | DMA1_Stream2_IRQHandler, /*!< 13: DMA1 Stream 2 */ |
39 | DMA1_Stream3_IRQHandler, /*!< 14: DMA1 Stream 3 */ |
40 | DMA1_Stream4_IRQHandler, /*!< 15: DMA1 Stream 4 */ |
41 | DMA1_Stream5_IRQHandler, /*!< 16: DMA1 Stream 5 */ |
42 | DMA1_Stream6_IRQHandler, /*!< 17: DMA1 Stream 6 */ |
43 | ADC_IRQHandler, /*!< 18: ADC1, ADC2 and ADC3s */ |
44 | CAN1_TX_IRQHandler, /*!< 19: CAN1 TX */ |
45 | CAN1_RX0_IRQHandler, /*!< 20: CAN1 RX0 */ |
46 | CAN1_RX1_IRQHandler, /*!< 21: CAN1 RX1 */ |
47 | CAN1_SCE_IRQHandler, /*!< 22: CAN1 SCE */ |
48 | EXTI9_5_IRQHandler, /*!< 23: External Line[9:5]s */ |
49 | TIM1_BRK_TIM9_IRQHandler, /*!< 24: TIM1 Break and TIM9 */ |
50 | TIM1_UP_TIM10_IRQHandler, /*!< 25: TIM1 Update and TIM10 */ |
51 | TIM1_TRG_COM_TIM11_IRQHandler,/*!< 26: TIM1 Trigger and Commutation and TIM11*/ |
52 | TIM1_CC_IRQHandler, /*!< 27: TIM1 Capture Compare */ |
53 | TIM2_IRQHandler, /*!< 28: TIM2 */ |
54 | TIM3_IRQHandler, /*!< 29: TIM3 */ |
55 | TIM4_IRQHandler, /*!< 30: TIM4 */ |
56 | I2C1_EV_IRQHandler, /*!< 31: I2C1 Event */ |
57 | I2C1_ER_IRQHandler, /*!< 32: I2C1 Error */ |
58 | I2C2_EV_IRQHandler, /*!< 33: I2C2 Event */ |
59 | I2C2_ER_IRQHandler, /*!< 34: I2C2 Error */ |
60 | SPI1_IRQHandler, /*!< 35: SPI1 */ |
61 | SPI2_IRQHandler, /*!< 36: SPI2 */ |
62 | USART1_IRQHandler, /*!< 37: USART1 */ |
63 | USART2_IRQHandler, /*!< 38: USART2 */ |
64 | USART3_IRQHandler, /*!< 39: USART3 */ |
65 | EXTI15_10_IRQHandler, /*!< 40: External Line[15:10]s */ |
66 | RTC_Alarm_IRQHandler, /*!< 41: RTC Alarm (A and B) through EXTI Line */ |
67 | OTG_FS_WKUP_IRQHandler, /*!< 42: USB OTG FS Wakeup through EXTI line */ |
68 | TIM8_BRK_TIM12_IRQHandler, /*!< 43: TIM8 Break and TIM12 */ |
69 | TIM8_UP_TIM13_IRQHandler, /*!< 44: TIM8 Update and TIM13 */ |
70 | TIM8_TRG_COM_TIM14_IRQHandler,/*!< 45:TIM8 Trigger and Commutation and TIM14*/ |
71 | TIM8_CC_IRQHandler, /*!< 46: TIM8 Capture Compare */ |
72 | DMA1_Stream7_IRQHandler, /*!< 47: DMA1 Stream7 */ |
73 | FSMC_IRQHandler, /*!< 48: FSMC */ |
74 | SDIO_IRQHandler, /*!< 49: SDIO */ |
75 | TIM5_IRQHandler, /*!< 50: TIM5 */ |
76 | SPI3_IRQHandler, /*!< 51: SPI3 */ |
77 | UART4_IRQHandler, /*!< 52: UART4 */ |
78 | UART5_IRQHandler, /*!< 53: UART5 */ |
79 | TIM6_DAC_IRQHandler, /*!< 54: TIM6 and DAC1&2 underrun errors */ |
80 | TIM7_IRQHandler, /*!< 55: TIM7 */ |
81 | DMA2_Stream0_IRQHandler, /*!< 56: DMA2 Stream 0 */ |
82 | DMA2_Stream1_IRQHandler, /*!< 57: DMA2 Stream 1 */ |
83 | DMA2_Stream2_IRQHandler, /*!< 58: DMA2 Stream 2 */ |
84 | DMA2_Stream3_IRQHandler, /*!< 59: DMA2 Stream 3 */ |
85 | DMA2_Stream4_IRQHandler, /*!< 60: DMA2 Stream 4 */ |
86 | ETH_IRQHandler, /*!< 61: Ethernet */ |
87 | ETH_WKUP_IRQHandler, /*!< 62: Ethernet Wakeup through EXTI line */ |
88 | CAN2_TX_IRQHandler, /*!< 63: CAN2 TX */ |
89 | CAN2_RX0_IRQHandler, /*!< 64: CAN2 RX0 */ |
90 | CAN2_RX1_IRQHandler, /*!< 65: CAN2 RX1 */ |
91 | CAN2_SCE_IRQHandler, /*!< 66: CAN2 SCE */ |
92 | OTG_FS_IRQHandler, /*!< 67: USB OTG FS */ |
93 | DMA2_Stream5_IRQHandler, /*!< 68: DMA2 Stream 5 */ |
94 | DMA2_Stream6_IRQHandler, /*!< 69: DMA2 Stream 6 */ |
95 | DMA2_Stream7_IRQHandler, /*!< 70: DMA2 Stream 7 */ |
96 | USART6_IRQHandler, /*!< 71: USART6 */ |
97 | I2C3_EV_IRQHandler, /*!< 72: I2C3 event */ |
98 | I2C3_ER_IRQHandler, /*!< 73: I2C3 error */ |
99 | OTG_HS_EP1_OUT_IRQHandler, /*!< 74: USB OTG HS End Point 1 Out */ |
100 | OTG_HS_EP1_IN_IRQHandler, /*!< 75: USB OTG HS End Point 1 In */ |
101 | OTG_HS_WKUP_IRQHandler, /*!< 76: USB OTG HS Wakeup through EXTI */ |
102 | OTG_HS_IRQHandler, /*!< 77: USB OTG HS */ |
103 | DCMI_IRQHandler, /*!< 53: DCMI */ |
104 | CRYP_IRQHandler, /*!< 53: CRYP crypto */ |
105 | HASH_RNG_IRQHandler, /*!< 53: Hash and Rng */ |
106 | FPU_IRQHandler /*!< 53: FPU */ |
107 | |
108 | };
|
>Sorry aber ist das hier die Interrupt Tabelle?:
Jipp.
Tausch sie genau so aus wie du oben schon geschrieben hast.
vPortSVCHandler -> SVCHandler
xPortPendSVHandler -> PendSV_Handler
xPortSysTickHandler -> SysTick_Handler
Vor die Tabelle legst du noch Prototypen damit der Compiler
weiss wie die Funktionen aussehen:
void WEAK vPortSVCHandler(void);
void WEAK xPortPendSVHandler(void);
void WEAK xPortSysTickHandler(void);
Hallo, vielen Dank erstmal! Jetzt hab ich das Problem das der Default Handler gleich am anfang aufgerufen wird, wenn ich den Scheduler mit vTaskStartScheduler() starten möchte. Moritz
Hallo nochmal! Ich poste mal das ganze Projekt. Vielleicht kann jemand mal rein gucken. Moritz
>Ich poste mal das ganze Projekt. Vielleicht kann jemand mal rein gucken. Also was da jetzt schief läuft weiss ich auch nicht. Aber folge besser mal dem Rat von Dietrich: >Deine Beschreibung klingt danach, dass keine Endlosschleife in dem >LED-Task verwendet wird und damit die Task-Funktion verlassen wird. Lass den Quatsch beim Task1 mit dem DeleteTask mal. Und nimm erst mal nur einen Task der auf keinen Fall verlassen wird.
Hallo, vielen Dank! Aber gibt es irgendeine Möglichkeit einen Task zu Beenden? Gleich wenn der Scheduler gestartet wird, wird in den Default -Handler gesprungen. Anscheinen war das also vorher schon Richtig mit den Handlern. Moritz
>Gleich wenn der Scheduler gestartet wird, wird in den Default -Handler >gesprungen. Anscheinen war das also vorher schon Richtig mit den >Handlern. Ich denke auch. Nimm noch mal deinen ersten Code und vergiss die Änderungen von mir. Und wie gesagt: Bring erst mal einen Task zum laufen. Und den lässt du dann laufen. Wenn das klappt kann man weitere Sachen ausprobieren.
Hallo, das mit einem/zwei/drei Task klappt super. Auch einen Task anhalten mit TaskDelay() ist kein Problem. Nur möchte ich jetzt auch gerne die Möglichkeit haben Tasks zu Beenden und nicht in einen While(1) Schleife laufen zu lassen. Schließlich kann es ja auch mal Task geben die z.B nur am Anfang gebraucht werden und dann nicht den Rest der Laufzeit Sinnlos in einen While(1) Schleife laufen müssen. Auf der Setie von FreeRTOS steht: [1]"The idle task is created automatically when the RTOS scheduler is started to ensure there is always at least one task that is able to run. It is created at the lowest possible priority to ensure it does not use any CPU time if there are higher priority application tasks in the read state. The idle task is responsible for freeing memory allocated by the RTOS to tasks that have since been deleted. It is therefore important in applications that make use of the vTaskDelete() function to ensure the idle task is not starved of processing time. The idle task has no other active functions so can legitimately be starved of microcontroller time under all other conditions. It is possible for application tasks to share the idle task priority (tskIDLE_PRIORITY). See the configIDLE_SHOULD_YIELD configuration parameter for information on how this behaviour can be configured." Daraus schließe ich eigentlich das man gar keinen Task laufen lassen kann und sich der µC nicht aufhängt. Es wird dann halt der IdleTask ausgeführt. [1] http://www.freertos.org/RTOS-idle-task.html
Hallo, vielen Dank! Jetzt geht es! mit vTaskDelete(NULL) den Aktuellen Task löschhen und mit vTaskDelete(hTask) einen anderen Task löschen. Vielen DANK an alle :) Moritz
Hi ich ebenfalls ein Problem mit den drei FreeRTOS spezifischen Interrupt Handlern. (Zumindestens vermute ich das da ich die nötigen Interrupthandler nicht in die Tabelle eingetragen hatte). Wenn ich debugge komme ich aus xTaskCreate(...) nicht mehr heraus. Letzendlich wird an einer Stelle memset(...) aufgerufen und dann lande ich im default handler für unerwartet interrupts. Im SourceForge Forum wird das als Lösung angegeben:
1 | Add to FreeRTOSConfig.h: |
2 | |
3 | #define vPortSVCHandler SVC_Handler |
4 | #define xPortPendSVHandler PendSV_Handler |
5 | #define vPortSVCHandler SVC_Handler |
6 | #define xPortSysTickHandler SysTick_Handler |
Das hat bei mir aber keinen Erfolg gebracht, außerdem verstehe ich nicht ganz was die defines ändern. "Biegen" die den namen der FreeRTOS-Handler korrekt oder soll das den Eintrag in der Tabelle beeinflussen? Da es mir unklar ist habe ich versucht (wie Holger auch schrieb) sie direkt in die startup_stm32f4xx.S einzubingen: holger schrieb: > Tausch sie genau so aus wie du oben schon geschrieben hast. > > vPortSVCHandler -> SVCHandler > xPortPendSVHandler -> PendSV_Handler > xPortSysTickHandler -> SysTick_Handler Wenn ich das mache bekomme ich undefined reference Fehler wie:
1 | ./startup_stm32f4xx.o:(.isr_vector+0x2c): undefined reference to `vPortSVCHandler' |
Mir ist soweit klar dass ihm die Handler an dieser Stelle nicht bekannt sind, aber folgendes funktioniert bei mir nicht: > Vor die Tabelle legst du noch Prototypen damit der Compiler > weiss wie die Funktionen aussehen: > > void WEAK vPortSVCHandler(void); > void WEAK xPortPendSVHandler(void); > void WEAK xPortSysTickHandler(void); Wenn ich das mache bekomme ich ein "bad instruction":
1 | ../startup_stm32f4xx.S:134: Error: bad instruction `void WEAK vPortSVCHandler(void)' |
Allerdings sieht meine startup_stm32f4xx.S auch prinzipiell anders aus wie Moritz startup_stm32f4xx.c. Ich habe sie mal angehängt. Ich weiß garnicht wo und wie ich die Funktionsdefinitionen in die .S Datei korrekt einfüge. Ich weiß nicht so recht wie ich die FreeRTOS Handler mit der InterruptTabelle verheiraten soll.
Peter Pfanne schrieb: > Ich weiß nicht so recht wie ich die FreeRTOS Handler mit der > InterruptTabelle verheiraten soll. Einfach alles zusammen linken. Gruß Oliver
Ich habe mich nochmal hingesetzt und bin weitegekommen. Noch drei Fragen/Probleme: 1) Jedes Mal wenn ich memset oder strncpy aufgerufen wird lande ich im handler für unerwartet interrupts. Wenn ich die Aufrufe der Funktionen durch xTaskCreate auskommentiere kann ich mehrer Tasks starten. Allerdings führt z.b. xQueueSend auch zu strncpy. Ich habe keine Ahnung warum diese Funktionen zu Fehlern führen. 2) Unabhängig ob ich die Interrupt Vektoren richtig verküpfe (#defines vorhanden oder nicht) lande ich bei einem Preakpoint in xPortSysTickHandler. mit den #defines läuft alles aber schneller. (Wie) kann das sein? 3) generell ist da ein zeitproblem denn ein vTaskDelay( 500 / portTICK_RATE_MS) dauert ca. 1.5 Sekunden. Die Taktfrequent von 168Mhz (aus system_stm32f4xx.c) müsste stimmen, der Timer Config Code im freertos port für den M4 (prvSetupTimerInterrupt) wird wohl auch stimmen. Die Funktion SystemInit der die System Clock, PLL etc configuriert wird ebenfalls aufgerufen.
Ok Punkt 2 hat sich erledigt. Ich hatte die #defines doppelt. Ohne komme ich , wie erwartet, nicht mehr in xPortSysTickHandler an.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.