cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Hang unewpectedly (NVIC suspected)

SSchm.5
Associate III

Hello,

I've designed a board based on an STM32F091CBU.

I needed CAN bus support, one SPI and one I2C and a timer interrupt.

When I tested my program, it hanged during the initialization of the IMU (an LSM6DSM) due to HAL_delays I ordinary set between SPI messages (paranoïd habit I must admit).

I've read on this forum that HAL_delay could hang due to a bad NVIC priority parameter. So after some tries, I decided to get rid of HAL_delays and the program was finally able to finish initialisation of the IMU. Then I activate an Interuption on a GPIO to know when data is available.

The program was supposed to send CAN frames every second through a CAN-PHY component so I've linked a CAN shield from seedstudio to it to monitor what is happening there. Dead silence.

After some checks with breakpoints, I discovered that my program never go inside the infinite loop. I've checked every peripherial interrupt handler with breakpoints and no-one seem to be called. And I suppose that my NVIC priorities could be responsible for that.

I would be very happy if someone could check my NVIC priorities and tell me if I did wrong.

Thank you.

4 REPLIES 4

Error_Handler and HardFault_Handler are silent places to die.

If it doesn't get to main() check SystemInit()

Would recommend getting a UART to work early in Reset_Handler, and output characters along the way to see where it passes through or where it hangs up.

An uncleared interrupt with loop indefinitely, blocking foreground code.

Stop in the debugger, see where the processor is currently executing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
SSchm.5
Associate III

Hello Clive and thank you for your answer.

I finally had the time to come back to this project and decided to set Breakpoints at every interrupt handler.

It was inefficient, so I used the "step into" button to understand where does it hang.

The program turned mad when reaching the while(1) loop. I got:

Reading all registers

Performing single step...

...Breakpoint reached @ address 0x08005946

Reading all registers

Performing single step...

In loop until I paused the program. Then I saw the arrow just in front of the "while(1)".

So I took a look at disassembly:

127         LSM6_INIT();
0800593c:   bl      0x8005d18 <LSM6_INIT>
129         HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
08005940:   movs    r0, #7
08005942:   bl      0x800114e <HAL_NVIC_EnableIRQ>
135         while (1)
08005946:   b.n     0x8005946 <main+46>
149       {
          SystemClock_Config:
08005948:   push    {r4, r7, lr}
0800594a:   sub     sp, #100        ; 0x64
0800594c:   add     r7, sp, #0
150         RCC_OscInitTypeDef RCC_OscInitStruct = {0};
0800594e:   movs    r4, #44 ; 0x2c
08005950:   adds    r3, r7, r4
08005952:   movs    r0, r3
08005954:   movs    r3, #52 ; 0x34
08005956:   movs    r2, r3
08005958:   movs    r1, #0
0800595a:   bl      0x8006928 <memset>
151         RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

The arrow is in front of the line 7. I didn't studied assembly instrutions much, but "b.n" instruction looked particularly odd. So I checked and someone on a forum say it's a non maskable interrupt.

Still investigating at the moment...

Pavel A.
Evangelist III

b.n is your while(1) loop.

> So I checked and someone on a forum say it's a non maskable interrupt.

Yeah. they write a lot of stupid things out there.

-- pa

SSchm.5
Associate III

Hello,

Yes Pavel, indeed. I posted my message a little bit too fast and figured out what b.n mean minutes after.

So after constating that my GPIO interrupt handler never fire (the LSM6 should send something on INT2 due to his FIFO), I've put a reading of the amount of stored values inside the IMU. This reading happen everytime the main loop happen. With a breakpoint to check the retrieved value.

	uint8_t addresse[2];
	uint8_t quantity[2];
	uint16_t quant_maxi = 0;
 
	addresse[0]= 0X3A | 0b10000000; //FIFO_STATUS1 read
  
while (1)
  {
    /* USER CODE END WHILE */
	  //HAL_Delay(50);
		//On demande combien de bytes sont stockés
		HAL_GPIO_WritePin(CS_IMU_GPIO_Port, CS_IMU_Pin, RESET);
		HAL_SPI_Transmit(&hspi1, (uint8_t*)addresse, 1, HAL_MAX_DELAY);
		HAL_SPI_Receive(&hspi1, (uint8_t *)quantity, 2, HAL_MAX_DELAY);
		HAL_GPIO_WritePin(CS_IMU_GPIO_Port, CS_IMU_Pin, SET);
 
		quant_maxi = (quantity[0] << 8) + quantity[1];
    /* USER CODE BEGIN 3 */
  }

First turn, quant_maxi = 0. Nothing really surprising. My ODR is pretty slow (26 Hz)

Second turn quant_maxi = 16. Pretty believable. But i get 16 at every check. Whatever time I spend betweend the "Resume debugging". Isn't the IMU supposed to live by himself? So I could get a higher number when I wait longer to resume?

Third turn: quant_maxi = 16 again???. That's when I'm lost.

Fourth turn: the program hang.

Still loking for paths to follow. I've already "breakpointed" every interrupt handlers and nothing suspicious seem to get out of the burrow.