prvPortStartFirstTask() fails at SVC 0

With all the issues seen around prvPortStartFirstTask() at SVC 0 on all forums, there is no precise solution mentioned in any of them that works.

Created a STM32 Project using STMCubeMX with FreeRTOS enabled. The application has 2 dummy tasks.

whats the missing piece here. looking for quick resolution.

Have you tried the recommendation in this post? xPortStartScheduler fails because BASEPRI is non-zero - #2 by jefftenney

CubeMX or other init software might be setting SVC to the wrong priority.

You didn’t say what problem you are facing, so it’s hard to suggest a solution. However, often reports of the svc 0 failing turn out to be that svc successfully starts a task, and the task crashes, but the debugger is still pointing at the svc instruction making it appear as if it was that instruction that failed.

“on all forums” this is why we try and keep this forum the focus point for FreeRTOS support, as this is where the developers, consultants, trainers, tenured users, etc can pass on their FreeRTOS expertise.

you can add an __asm("bkpt ") instruction at the beginning of your svc isr to ensure that your isr is correctly anchored in the ivt.

Did you check the return values of your task creation calls? Could your memory allocator be broken or you do not have enough heap set aside?

Thanks for quick reply!
Yes , I had a look into this post as well. in my case it has priority zero.
image

Attached screenshot of the register 0xE000ED1C just before executing prvPortStartFirstTask();

Thanks for the quick reply. Appreciate your efforts here.

Yes, that is the common answer. But, shouldn’t be in my case else I would be damned.
My tasks are pretty lame, infact the default one that is created by CubeMX. infact loop with waits on 1 Systick

Giving more details to help me resolve faster.

static void prvPortStartFirstTask( void )
{
	/* Start the first task.  This also clears the bit that indicates the FPU is
	in use in case the FPU was used before the scheduler was started - which
	would otherwise result in the unnecessary leaving of space in the SVC stack
	for lazy saving of FPU registers. */
	__asm volatile(
					" ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */
					" ldr r0, [r0] 			\n"
					" ldr r0, [r0] 			\n"
					" msr msp, r0			\n" /* Set the msp back to the start of the stack. */
					" mov r0, #0			\n" /* Clear the bit that indicates the FPU is in use, see comment above. */
					" msr control, r0		\n"
					" cpsie i				\n" /* Globally enable interrupts. */
					" cpsie f				\n"
					" dsb					\n"
					" isb					\n"
					" svc 0					\n" /* System call to start first task. */
					" nop					\n"
				);
}

The application crashes after executing svc 0.
The SVC_handler in my project points to vPortSVCHandler() in my case and is not redefined by the STM32 HAL.
The prvPortStartFirstTask() points to address 0x1FF09800 to locate the stack
image

General Registers General Purpose and FPU Register Group
r0 0x0
r1 0xf00000
r2 0xe000ef34
r3 0xc0000000
r4 0x2404ffc8
r5 0x8004ce0
r6 0x0
r7 0x2404ff60
r8 0x0
r9 0x0
r10 0x0
r11 0x0
r12 0x0
sp 0x24003f40
lr 0x80044fd
pc 0x80043da
xpsr 0x61000000
d0 0x0
d1 0x0
d2 0x0
d3 0x0
d4 0x0
d5 0x0
d6 0x0
d7 0xffffffff00000000
d8 0x0
d9 0x0
d10 0x0
d11 0x0
d12 0x0
d13 0x0
d14 0x0
d15 0xffffffff00000000
fpscr 0x0
msp 0x24003f40
psp 0x0
primask 0x0
basepri 0x50
faultmask 0x0
control 0x0
s0 0x0
s1 0x0
s2 0x0
s3 0x0
s4 0x0
s5 0x0
s6 0x0
s7 0x0
s8 0x0
s9 0x0
s10 0x0
s11 0x0
s12 0x0
s13 0x0
s14 0x0
s15 0xffffffff
s16 0x0
s17 0x0
s18 0x0
s19 0x0
s20 0x0
s21 0x0
s22 0x0
s23 0x0
s24 0x0
s25 0x0
s26 0x0
s27 0x0
s28 0x0
s29 0x0
s30 0x0
s31 0xffffffff

Does this issue ring a bell and with numerous posts around the same issue looks like it a very common issue faced?

Btw, using STM Cube IDE 1.3.1 with STMCubeMx 6.2.1

Thanks for your reply.
No I do not hit his breakpoint in my SVC handler. Here is the call trace
image

So when you dump your ivt, what is the entry in the place where the service interrupt should be? Does your eco system simply fail to register the isr?

well. I see the IVT table is populated.
But noticed one more behavior, on switching the Timebase Source in SYS to one of the timer (Timer 3 in my case), I see that the initialization of the timer itself fails?
Do we have issues with the generated code from CubeMX in some versions?

HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
  uint32_t tmpsmcr;

  /* Check the parameters */
  assert_param(IS_TIM_INSTANCE(htim->Instance));

  /* Check the TIM state */
  if (htim->State != HAL_TIM_STATE_READY)
  {
    return HAL_ERROR;
  }

  /* Set the TIM state */
  htim->State = HAL_TIM_STATE_BUSY;

  /* Enable the TIM Update interrupt */
  __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
  if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
  {
    tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
    if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
    {
      __HAL_TIM_ENABLE(htim); ---------> fails at this line
    }
  }
  else
  {
    __HAL_TIM_ENABLE(htim);
  }

  /* Return function status */
  return HAL_OK;
}

The application breaks at this line __HAL_TIM_ENABLE(htim);

Here is the call trace
image

Do we have issues with some release versions of STMCubeMX?
As I’m doing pretty basic stuff because getting into something complex.

Enabling freertos on STMCubeMX, creating two tasks and setting the SYS clock to Timer 3
I using STM32H725IGTx board.

I don’t know of any issues in cubemx that prevent freertos starting. Wondering if somehow your SCB->VTOR is not set correctly. Normally the startup code provided by ST sets it properly for you. It should point to your vector table.

You are right. Playing around with versions did not help much.
The IVT is defined as usual in the startup file

   .section  .isr_vector,"a",%progbits
  .type  g_pfnVectors, %object
  .size  g_pfnVectors, .-g_pfnVectors


g_pfnVectors:
  .word  _estack
  .word  Reset_Handler

  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler

@jefftenney @RAc any more suggestion that I can try?
Read the SVC interrupt priority it is set to 0 and basepri after registering the first task sets to a value 0x50.

The basepri value is populated by FreeRTOSConfig

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

Does this make sense as basepri will block SVC interrupt handling with the value it hold.

No need to worry about that when SVC uses priority 0. If BASEPRI is set to 0x50, then interrupts from 0x50 to 0xFF (or, as unshifted priorities, 5 through 15) are masked. Priority 0 (the highest priority) remains unmasked (and, in fact, cannot be masked by BASEPRI anyway).

The next thing for you to check is SCB->VTOR. Can you use the debugger to see if it is actually pointing to your vector table? You can determine the true location of your vector table in your linker file or in a map file, for example. Or, you can visually inspect the 32-bit words that start wherever VTOR points to see if they seem like reasonable vectors. You can put a breakpoint at the beginning of main to do this inspection.

If SCB->VTOR is not set correctly, the CPU will not lookup the correct interrupt vectors.

1 Like

To me it looks as if your logic never makes it as far as vTaskStartScheduler(), which would explain why your svc handler is not invoked and would in turn make interrupt configuration not a prime suspect.

One of my top gripes about the ST HAL is that it uses a timer interrupt for its own bookkeeping, meaning interrupts must be enabled for the HAL to work before FreeRTOS is started. Sure recipe for desaster. What priority is the HAL timer isr set to? Can you reconfigure it to be > MAX_SYSCALL and make sure that interrupts are enabled by the HAL only on a level > MAX_SYSCALL instead globally?

it does makes it prvPortStartFirstTask(); called in xPortStartScheduler() and executes till the asm call “svc 0” and then never invokes the SVCHandler() and hence the configured tasks don’t execute which makes sense.

I think the only issue to check why SVCHandler is not called. I strongly suspect the autogenerated FreeRTOSConfig.h file. Skinning the cat now with comments from Jeff

That does not look like a valid RAM address on the MCU?

Seems clear the problem is SCB->VTOR not being set correctly. Per the screenshots, SCB->VTOR is set to 0x1FF09800. The reference manual indicates that address is in “system” memory. So that isn’t right for your application.

You can try this statement at the beginning of main():

SCB->VTOR = 0x08000000;

There are a couple of assumptions in this value (0x08000000), but based on your other posts I think it is right.

Which hardware are you creating this project for? What steps did you follow to create this project? Also, can you share your complete project?

@rlobo From your earlier posts you are using STM32H725IGTx and you created the project from CubeMX 6.2.1. It would be interesting to see your project as @aggarg requested.

There may be an oversight in the ST startup code, not setting SCB->VTOR. The value 0x1FF09800 appears to be left over from the ST BSL, which starts the MCU from power-on reset under many circumstances.

Based on similar forum posts, I wonder if the port should verify the installation of the PendSV and SVCall handlers. In doing so, it would also verify VTOR is set properly. See this commit for example. Does this seem worth doing across the various Cortex M ports?