Forum: Mikrocontroller und Digitale Elektronik [STM32F217 + freeRTOS] xPortStartFirstTask runs into HardFault_Handler


von Christian B. (Gast)


Lesenswert?

Hallo an zusammen,

ich habe hier ein Board mit einem STM32F217. GPIOs, 
Serielle-Schnittstelle habe ich als erstes in Betrieb genommen und das 
funktioniert soweit. Als nächstes wollte ich freeRTOS zum laufen 
bringen.

Version: FreeRTOS.org V6.0.1
 + STM32F2xx standard peripherals library 1.0.0

Mein Problem ist, dass mein Scheduler beim Starten des ersten Threads in 
den HardFault_Handler läuft. Im Debugger konnte ich bis zum SVC_Handler 
folgen. Hat jemand eine Idee und kann mir einen Tipp geben?

Gruß,
Christian

main.c:
1
 
2
SystemInit();
3
4
/* Set the Vector Table base address at 0x08000000 */
5
NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );
6
7
/* Configure HCLK clock as SysTick clock source. */
8
SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
9
NVIC_SetPriority( SysTick_IRQn, 15 );
10
NVIC_SetPriority( RTC_Alarm_IRQn, 12 );
11
12
xTaskCreate( mainTask, ( signed portCHAR * ) "Main", configMINIMAL_STACK_SIZE + 200, NULL, 1, &mainTaskHandle );
13
14
/* Start the scheduler. */
15
vTaskStartScheduler();

port.c
1
 
2
portBASE_TYPE xPortStartScheduler( void )
3
{
4
  /* Make PendSV, CallSV and SysTick the same priroity as the  
5
           kernel. */
6
  *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
7
  *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
8
9
  /* Start the timer that generates the tick ISR.  
10
           Interrupts are disabled
11
      here already. */
12
  prvSetupTimerInterrupt();
13
14
  /* Initialise the critical nesting count ready for the first task.
15
           */
16
  uxCriticalNesting = 0;
17
18
  /* Start the first task. */
19
  vPortStartFirstTask();
20
21
  /* Should not get here! */
22
  return 0;
23
}
1
 
2
void vPortStartFirstTask( void )
3
{
4
  asm volatile(
5
          " ldr r0, =0xE000ED08   \n" /* Use the NVIC offset register to locate the stack. */
6
          " ldr r0, [r0]       \n"
7
          " ldr r0, [r0]       \n"
8
          " cpsie i               \n"
9
          " msr msp, r0      \n" /* Set the msp back to the start of the stack. */
10
          " svc 0          \n" /* System call to start first task. */
11
        );
12
}
13
#endif
1
void vPortSVCHandler( void )
2
{
3
  __asm volatile (
4
          "  ldr  r3, pxCurrentTCBConst2    \n" /* Restore the context. */
5
          "  ldr r1, [r3]          \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
6
          "  ldr r0, [r1]          \n" /* The first item in pxCurrentTCB is the task top of stack. */
7
          "  ldmia r0!, {r4-r11}        \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
8
          "  msr psp, r0            \n" /* Restore the task stack pointer. */
9
          "  mov r0, #0             \n"
10
          "  msr  basepri, r0          \n"
11
          "  orr r14, #0xd          \n"
12
          "  bx r14              \n"
13
          "                  \n"
14
          "  .align 2            \n"
15
          "pxCurrentTCBConst2: .word pxCurrentTCB        \n"
16
        );
17
}
von Lasse S. (cowz) Benutzerseite


Lesenswert?

Hallo,

ich weiß nicht, ob freeRTOS das nicht sowieso macht, aber bei meinem 
Scheduler hatte ich den Hardfault immer dann, wenn ich mit 
EXC_RETURN=0xFFFFFFFD zurückspringen wollte, der Rücksprung aber wieder 
in einen IRQ-Handler gehen sollte. Daher muss der PendSV die geringste 
Priorität haben und immer in den Threadmode springen wollen.

Das bedeutet insbesondere auch, dass der SVC höher priorisiert sein 
muss.

Gruß
Lasse

PS: Ansonsten mal wirklich single steppen und vor branches die 
Sprungadressen checken, ob der Stack da passt.
von holger (Gast)


Lesenswert?

>/* Configure HCLK clock as SysTick clock source. */
>SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
>NVIC_SetPriority( SysTick_IRQn, 15 );

Als erstes lässt du mal die Finger vom Systick.
Der wird vom FreeRTOS belegt. Und HardFault
bedeutet dein Controller springt in den Wald.
Das liegt irgendwo in den Tiefen deines unbekannten
Programmes verborgen. Kann man also nix zu sagen.
von Christian B. (Gast)


Lesenswert?

Danke für die beiden Antworten. Das OS stürtzt inzwischen nicht mehr ab. 
Ich habe das OS jetzt als erstes in main intialisiert, noch vor der 
seriellen Schnittstelle und anderen Devices. Die anderen Sachen habe ich 
dann in die mainTask verschoben und hatte von nun an keine Probleme 
mehr.

main.c
1
SystemInit();
2
3
xTaskCreate( mainTask, ( signed portCHAR * ) "Main", configMINIMAL_STACK_SIZE + 200, NULL, 1, &mainTaskHandle );
4
5
/* Start the scheduler. */
6
vTaskStartScheduler();
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.