cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_Delay stuck SysTick not triggered, workaround for stm32f105

UMP-Dan
Associate II

Hi,
I have scoured the web for a solution to this problem, but I cannot find one, typically the replies are the same, but the solution is never found. I have tried every other solution you will find.

I was playing around with the cube mx trying to solve my problem with this, and I'm not sure what changed, but the cube mx generated a program which actually made HAL_Delay work correctly.
I have used the STM32CubeIDE with CubeMX generated code for many projects in the past with relatively no issues.

  • STM32F105
  • STLINK_V3
  • Firmware Package: STM32Cube FW_F1 V1.8.5
  • STM32CubeIDE version 1.13.0
  • MXCube Version 6.9

The Problem:

To summarise the problem, the application will freeze at HAL_Delay();  
The reason for this is because within the file stm32f1xx_t.c , the SysTick_Handler will not be called, and hence HAL_IncTick(); will also never increment the uwTick counter.  Clearly the Systick Interrupt isn't being triggered.

 

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

 

The following call stack will be shown when you try and Step-Over HAL_Delay(); while debugging.

 

Thread #1 [main] 1 [core: 0] (Suspended : Signal : SIGTRAP:Trace/breakpoint trap)	
	uwTickPrio() at 0x20000004	
	<signal handler called>() at 0xfffffff9	
	HAL_GetTick() at stm32f1xx_hal.c:307 0x8000806	
	HAL_Delay() at stm32f1xx_hal.c:382 0x800083c	
	main() at main.c:98 0x8000546	

 

Work Around:

I have found that for whatever reason the file system_stm32f1xx.c (located in Core/Src is related.  In my working.rar  which I have attached you will find that the system_stm32f1xx.c file is different to the not working.rar

If I copy the system_stm32f1xx.c file from the working project into the not working project, it will compile and debug correctly.  There is major differences between the files but I do not understand them. 

Perhaps someone with more experience with the inners of how the ST generation behaves can shed some light on why this would happen.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

The issue is likely related to the vector table address. Here's what happens in the "working" scenario:

 

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif

 

Here's what happens in the "not working" scenario:

 

#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#endif /* USER_VECT_TAB_ADDRESS */

 

But this is never executed since USER_VECT_TAB_ADDRESS isn't defined.

This was a decision made by ST. There have been at least a couple threads on it, and someone from ST said it was deliberate. I and others here said it was a mistake and would cause users hard to find problems. Will link the thread if I can find it.

And in case it isn't clear, here's what you need to add in your system startup file:

 

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

 

or uncomment the line that defines USER_VECT_TAB_ADDRESS.

So SysTick is happening, it's just not at a useful address.

There's a chance I'm wrong here as well. There's also a bug in GCC where "weak" definitions aren't properly overridden by strong definitions. Not sure if it's fixed in the latest compiler CubeIDE is using.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

7 REPLIES 7
TDK
Guru

The issue is likely related to the vector table address. Here's what happens in the "working" scenario:

 

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif

 

Here's what happens in the "not working" scenario:

 

#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#endif /* USER_VECT_TAB_ADDRESS */

 

But this is never executed since USER_VECT_TAB_ADDRESS isn't defined.

This was a decision made by ST. There have been at least a couple threads on it, and someone from ST said it was deliberate. I and others here said it was a mistake and would cause users hard to find problems. Will link the thread if I can find it.

And in case it isn't clear, here's what you need to add in your system startup file:

 

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

 

or uncomment the line that defines USER_VECT_TAB_ADDRESS.

So SysTick is happening, it's just not at a useful address.

There's a chance I'm wrong here as well. There's also a bug in GCC where "weak" definitions aren't properly overridden by strong definitions. Not sure if it's fixed in the latest compiler CubeIDE is using.

If you feel a post has answered your question, please click "Accept as Solution".

Here's one thread about it, there are others:

https://community.st.com/t5/stm32cubemx-mcu/stm32cubeide-1-7-mcu-package-l4-series-1-17-vtor-is-not/m-p/220563

 

If you feel a post has answered your question, please click "Accept as Solution".

Hello, thank you very much for your reply and helpful insight,
I uncommented the #define USER_VECT_TAB_ADDRESS line as you say, and the project now works with no problems.

Definitely a strange choice by ST, especially as I had generated this project without any complexity... 
So clearly in the working project I must have generated it under a different version where this wasn't a thing yet?

Hopefully this post can at least help some lost souls in finding a solution.  I uncommented this line within system_stm32f1xx.c

/* Note: Following vector table addresses must be defined in line with linker
         configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
     anywhere in Flash or Sram, else the vector table is kept at the automatic
     remap of boot address selected */
 #define USER_VECT_TAB_ADDRESS



gsibley
Associate

Hello I hope someone at ST is reading this issue -- it took me quite a while to figure this out today.  Only hope was finding this thread.  I love STM32s but this kind of experience will drive people away as it kills out-of-the-box "hello world" type demos.

It is truly bizarre that a tool like CubeMX which is designed to create simple programs with a few clicks does all pin initialization, clock initialization, peripheral calls, linker script, etc and yet when it comes to the vector table they say "oh no, the user definitely knows what's best there, let's just not change it".

And it was a decision made partway through the CubeMX project with little announcement to those using the tool.

If you feel a post has answered your question, please click "Accept as Solution".
mcagriaksoy
Associate II

Hello, I tried both possibilities, relocate vector table on "SRAM" or "FLASH" but in both ways, behave same. Do you know any third option or possible another workaround? I am using the STM32G4 series MCU.

Uncomment that not worked to me, instead of using this:
 

#define DELAY_US(us) \
    do { \
         uint32_t start = SysTick->VAL; \
         uint32_t ticks = (us * SYSTICK_LOAD)-SYSTICK_DELAY_CALIB;  \
         while((start - SysTick->VAL) < ticks); \
    } while (0)

I used this delay_us1(). I calculated for a 480Mhz micro:

void delay_us1(uint16_t us)  //depende de optimizaciones
{
	for (uint16_t i=0;i<us;i++)
		{
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();

			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();			__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
		}
}