cancel
Showing results for 
Search instead for 
Did you mean: 

CPU stuck in HAL_NVIC_EnableIRQ

armdude
Associate

Hi, this is my first post so I will try to provide as much information as possible. Any help is greatly appreciated! I will try to provide any missing details.

What I'm Trying To Do

  • I am trying to erase sector 1 using the HAL provided APIs
  • Tried HAL_FLASHEx_Erase(&p_erase_init, &page_error);
  • Tried FLASH_Erase_Sector(uint32_t Sector, uint32_t Banks, uint32_t VoltageRange)
  • Just for testing, I am attempting to erase sector 1 just before the while(1) loop in main
  • I am using a debug LED to indicate if my program is successful (enteres the while(1) loop)

Context

  • Target MCU is the STM32H755
  • A custom bootloader Cortex-M7 application that lives in FLASH in 0x08000000
  • The custom bootloader Cortex-M4 appliction is gutted out and runs a while (1) {} 

Problem

  • The CPU hangs when this function is called HAL_NVIC_EnableIRQ(pSpiIoCfg->IntrIrq);

Note

  • I am unlocking the FLASH and locking FLASH afer erasing sector 1

Sample Code

 

 

 

FLASH_EraseInitTypeDef p_erase_init = {0};
uint32_t page_error;

p_erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
p_erase_init.Banks = FLASH_BANK_1;
p_erase_init.Sector = 1;
p_erase_init.NbSectors = 1U;
p_erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_3;
HAL_FLASHEx_Erase(&p_erase_init, &page_error);

...

#if AL_EVENT_ENABLED
	/* Configure GPIO as SPI interrupt input */
	HW_GPIO_ClkSource(pSpiIoCfg->pIntrPort, ENABLE);	
	GPIO_InitStructure.Pin = pSpiIoCfg->IntrPin;
	GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(pSpiIoCfg->pIntrPort, &GPIO_InitStructure);
	
	/* Enable SPI interrupt source at NVIC */
	HAL_NVIC_SetPriorityGrouping(HW_NVIC_PRIORITY_GROUP);
	HAL_NVIC_SetPriority(pSpiIoCfg->IntrIrq, pSpiIoCfg->IntrPrePrio, pSpiIoCfg->IntrSubPrio);

	// CPU hangs when calling this function
	HAL_NVIC_EnableIRQ(pSpiIoCfg->IntrIrq);
	HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, 0);
#endif


...

 

 

 

 

Pin and Clock Configuration

Clock Tree

 

armdude_1-1736819053460.png

NVIC1 Settings

armdude_3-1736819102471.png

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
armdude
Associate

Okay I did some more testing and realized that the init function from our BSP was enabling the SPI interrupts BEFORE the SPI peripheral was initialized. My guess is that an interrupt was being fired as soon as the SPI interrupts were enabled and because the SPI peripheral wasn't even initialized yet, it caused the CPU to hang. So I guess the lesson is don't blindly trust your vendor BSP's init functions.

 

	/* Configure SPI peripheral */
	pSpiHandle->Instance = pSpiIoCfg->pInstance;

	/* Reset the SPI memory interface */	
	pSpiHandle->Init.Mode = SPI_MODE_MASTER;
	pSpiHandle->Init.Direction = SPI_DIRECTION_2LINES;
	pSpiHandle->Init.DataSize = SPI_DATASIZE_8BIT;	
	pSpiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;		
	pSpiHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
	pSpiHandle->Init.NSS = SPI_NSS_SOFT;	
	pSpiHandle->Init.BaudRatePrescaler = pSpiIoCfg->Baudrate;
	pSpiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB;
	pSpiHandle->Init.TIMode = SPI_TIMODE_DISABLE;	
	pSpiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	pSpiHandle->Init.CRCPolynomial = 0;
	pSpiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
	pSpiHandle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_04DATA;
	
	/* Enable SPI periphral */
	if (HAL_SPI_Init(pSpiHandle) != HAL_OK)
	{
		return -1;
	}
	
#if AL_EVENT_ENABLED
	/* Configure GPIO as SPI interrupt input */
	HW_GPIO_ClkSource(pSpiIoCfg->pIntrPort, ENABLE);	
	GPIO_InitStructure.Pin = pSpiIoCfg->IntrPin;
	GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(pSpiIoCfg->pIntrPort, &GPIO_InitStructure);
	
	/* Enable SPI interrupt source at NVIC */
	HAL_NVIC_SetPriorityGrouping(HW_NVIC_PRIORITY_GROUP);
	HAL_NVIC_SetPriority(pSpiIoCfg->IntrIrq, pSpiIoCfg->IntrPrePrio, pSpiIoCfg->IntrSubPrio);

	// CPU hangs when calling this function
	HAL_NVIC_EnableIRQ(pSpiIoCfg->IntrIrq);
#endif

 

View solution in original post

5 REPLIES 5
Pavel A.
Evangelist III

Hello and welcome to the forum!

So you want to erase a sector in the internal flash of STM32H755.

SPI is not related to this so there's no any sense in enabling its interrupt (and what is "SPI interrupt source" at all?)

Remove or comment out lines 24, 27. Will it work?

 

 

 

 

Hangs where? If you stop the MCU in debugger where is it?

Hard Fault or perpetually locked in IRQ Handler trying and failing to clear the source.

You Erase a sector with live code in it?

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

Ah sorry for not providing the context for the SPI. For our project, the SPI is used to communicate with an EtherCAT slave controller subsystem to it is required. The code above for initializing the SPI interrupts are from our vendor BSP.

Commenting our lines 24,27 does indeed work and does not cause the MCU to hang. 

 

 

It hangs on this line

 

// CPU hangs when calling this function
HAL_NVIC_EnableIRQ(pSpiIoCfg->IntrIrq);

 

The interesting thing is when I step through debug the MCU, it does not hang on this line and this is true for both STM32CubeIDE and VSCode's Cortex-debug extension with our cmake project.

 

Hard Fault or perpetually locked in IRQ Handler trying and failing to clear the source.


Oh I see this is a good point, I will try to see if I can catch a hard fault or stuck in an IRQ handler without the debugger with the user led

 


You Erase a sector with live code in it?


No, the sector is cleared with 0xFF

Sorry derp, yes the sector has live code in it as in our application code lives in that sector. So just to broaden the context here, we need to clear this sector to prepare for an incoming firmware image to be written to that sector.

armdude
Associate

Okay I did some more testing and realized that the init function from our BSP was enabling the SPI interrupts BEFORE the SPI peripheral was initialized. My guess is that an interrupt was being fired as soon as the SPI interrupts were enabled and because the SPI peripheral wasn't even initialized yet, it caused the CPU to hang. So I guess the lesson is don't blindly trust your vendor BSP's init functions.

 

	/* Configure SPI peripheral */
	pSpiHandle->Instance = pSpiIoCfg->pInstance;

	/* Reset the SPI memory interface */	
	pSpiHandle->Init.Mode = SPI_MODE_MASTER;
	pSpiHandle->Init.Direction = SPI_DIRECTION_2LINES;
	pSpiHandle->Init.DataSize = SPI_DATASIZE_8BIT;	
	pSpiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;		
	pSpiHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
	pSpiHandle->Init.NSS = SPI_NSS_SOFT;	
	pSpiHandle->Init.BaudRatePrescaler = pSpiIoCfg->Baudrate;
	pSpiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB;
	pSpiHandle->Init.TIMode = SPI_TIMODE_DISABLE;	
	pSpiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	pSpiHandle->Init.CRCPolynomial = 0;
	pSpiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
	pSpiHandle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_04DATA;
	
	/* Enable SPI periphral */
	if (HAL_SPI_Init(pSpiHandle) != HAL_OK)
	{
		return -1;
	}
	
#if AL_EVENT_ENABLED
	/* Configure GPIO as SPI interrupt input */
	HW_GPIO_ClkSource(pSpiIoCfg->pIntrPort, ENABLE);	
	GPIO_InitStructure.Pin = pSpiIoCfg->IntrPin;
	GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
	GPIO_InitStructure.Pull = GPIO_PULLUP;
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(pSpiIoCfg->pIntrPort, &GPIO_InitStructure);
	
	/* Enable SPI interrupt source at NVIC */
	HAL_NVIC_SetPriorityGrouping(HW_NVIC_PRIORITY_GROUP);
	HAL_NVIC_SetPriority(pSpiIoCfg->IntrIrq, pSpiIoCfg->IntrPrePrio, pSpiIoCfg->IntrSubPrio);

	// CPU hangs when calling this function
	HAL_NVIC_EnableIRQ(pSpiIoCfg->IntrIrq);
#endif