Forum: Mikrocontroller und Digitale Elektronik FreeRTOS IDLE-Task


von Moritz M. (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von Moritz M. (Gast)


Lesenswert?

Hallo,

welche Interrupt Vektoren? Sind das:
vPortSVCHandler -> SVCHandler
xPortPendSVHandler -> PendSV_Handler
xPortSysTickHandler -> SysTick_Handler

Moritz

von Dietrich (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von Moritz M. (Gast)


Lesenswert?

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
};

von holger (Gast)


Lesenswert?

>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);

von Moritz M. (Gast)


Lesenswert?

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

von Moritz M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo nochmal!

Ich poste mal das ganze Projekt. Vielleicht kann jemand mal rein gucken.

Moritz

von holger (Gast)


Lesenswert?

>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.

von Moritz M. (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von Moritz M. (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

Nicht so

  vTaskDelete(&hTASK1);

sondern so

  vTaskDelete(hTASK1);

von Moritz M. (Gast)


Lesenswert?

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

von Peter P. (ichbineinepfanne) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

von Oliver J. (skriptkiddy)


Lesenswert?

Peter Pfanne schrieb:
> Ich weiß nicht so recht wie ich die FreeRTOS Handler mit der
> InterruptTabelle verheiraten soll.

Einfach alles zusammen linken.

Gruß Oliver

von Peter P. (ichbineinepfanne) Benutzerseite


Lesenswert?

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.

von Peter P. (ichbineinepfanne) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.