Stm32L4R5 GPIO Interrupt Enable causes issue.(FreeRTOS)

Hello Everyone,
Hope all are doing well.

I am currently working with a board based on STM32L4R5 in FreeRTOS environment.
I have two UARTS and some GPIO connected.
I have one task monitoring the UART data. Both UART have ISR and they place the received data onto a queue. This queue is accessed from the task to perform some action.

I have programmed one GPIO for Rising edge trigger interrupt.
But when I enable this interrupt, the application just stops working.
I have tried enabling the GPIO interrupt without FreeRTOS. I was able to detect the interrupts.

I have set the priority of all the three interrupts to 6. (Since I have #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5)

Can anybody please direct me if I am missing something.
Thank you.

Hi Pratham,

Do you have a debugger? Can you see what’s happening when “the application just stops working”? For example, is the CPU stuck in a forever loop due to an assertion failure? Is the CPU stuck in a forever loop in a fault handler? That will be an important clue.

You mention the GPIO interrupt works as expected without FreeRTOS. When you try it with FreeRTOS, are you adding anything into the ISR, for example a call to a FreeRTOS API function?

Hello Jeff,
Yes I am using a debugger. (Using it with the Cube IDE)
After vTaskStartScheduler(); The application never reached any of the thread.
When I try to pause and check where the application is at, it does not seem to be in a forever loop. Prompt(Break at address “0x1fff16d6” with no debug information available, or outside of program code.)

The ISR is just:

void EXTI15_10_IRQHandler( void )
{
	uint32_t pending = EXTI->PR1;

	if(pending & (1 << 13))
	{
		EXTI->PR1 |= 1 << 13;
	}

}

I do not have anything as of now in the ISR.

Thank you.

Hello,
Just one more, that the project does not use HAL drivers.
Thank you.

Can you clarify – your application works correctly (tasks run, UART data goes through your queues, a task processes the data, etc) as long as you don’t enable this GPIO interrupt?

Then as soon as you enable the interrupt, the application quits working, even before you get into the ISR even once?

Yes, If I don’t enable the GPIO IRQ: the application is able to run two tasks, tasks can read Data from the queue, UART ISR can place data onto the queue.

Yes. after initializing all peripherals and creating task, the application quits working. Does not even reach any Task or the ISR.

	initLEDButton();

	initUSART();

	initPWM();

	initDecoder( );

	initBluetooth();

	// Create task

	xTaskCreate( bluetoothTask, "BluetoothTask", 200 , ( void * ) NULL, 2, NULL );

	xTaskCreate( bluetoothTask2, "Task2", 200 , ( void * ) NULL, 2, NULL );

	vTaskStartScheduler();

Thanks for clarifying. Some ideas -

  • Can you post your FreeRTOSConfig.h file?
  • Can you post the code you use to configure and enable the GPIO interrupt?
  • Can you try to enable the GPIO interrupt from inside one of your tasks?
  • Can you step through vTaskStartScheduler(), with a breakpoint set at the beginning of vPortSVCHandler() so you can keep stepping from there when the breakpoint is hit. Maybe you’ll catch where things are going wrong when FreeRTOS is starting.
void testInitGPIOInterrupt( void )
{

	// PC 13
	uint8_t pinNumber;
	uint32_t temp;

	pinNumber = 13;

	RCC->AHB2ENR |= ( 1 << RCC_AHB2ENR_GPIOCEN_Pos );

	RCC->APB2ENR  |= ( 1 << RCC_APB2RSTR_SYSCFGRST_Pos );
	SYSCFG->EXTICR[(pinNumber/4)] &= ~(0xF << ((pinNumber % 4) * 4));
	SYSCFG->EXTICR[(pinNumber/4)] |=  (0x2 << ((pinNumber % 4) * 4));

	//enable the exti interrupt delivery using IMR Interrupt mask register 1
	EXTI->IMR1 |= ( 1 << pinNumber );
	//  Enable the 'rising edge' trigger
	EXTI->RTSR1 |= ( 1 << pinNumber );
	// Disable the 'falling edge' trigger
	EXTI->FTSR1 &= ~( 1 << pinNumber );

	GPIOC->MODER &= ~( 0x3 << ( pinNumber*2 ) );
	GPIOC->PUPDR &= ~( 0x3 << ( pinNumber*2 ) );
	GPIOC->PUPDR |= ( 0x0 << ( pinNumber*2 ) );

	// Enable IRQ
	NVIC_SetPriority( EXTI15_10_IRQn, 6 );
	NVIC_EnableIRQ ( EXTI15_10_IRQn );

}

I will try these suggestions.

FreeRTOSConfig.h (5.2 KB)

There’s a (harmless) typo here. I think you mean RCC_APB2ENR_SYSCFGEN_Pos. It’s harmless because both symbols equal zero (for bit zero).

However, be sure to delay a couple of clock cycles before attempting to address a peripheral after you’ve just enabled its bus clock. For example you could read the RCC register back, like this:

    RCC->APB2ENR  |= ( 1 << RCC_APB2ENR_SYSCFGEN_Pos);
    RCC->APB2ENR;  // Read back the (volatile) RCC register as a short delay.
    RCC->APB2ENR;  // Read back the (volatile) RCC register as a short delay.
    SYSCFG->EXTICR[(pinNumber/4)] &= ~(0xF << ((pinNumber % 4) * 4));

Nothing stands out to me in your FreeRTOSConfig.h.

It’s not the reason for the problem, but you should only clear the relevant pending EXTI IRQ by setting the corresponding bit e.g. in your case EXTI->PR1 = 1 << 13;
With EXTI->PR1 |= 1 << 13; you might clear some more pending IRQs not handled in this ISR. Also I think rechecking with pending = EXTI->PR1; is redundant/overhead if the IRQ handler is coupled with bit 13 in PR1.
Can you try to single single step the init sequence to narrow down the function/code causing the program to go wild ?

Thank you Hartmut for the advice.
I have made the changes to the IRQ:

void EXTI15_10_IRQHandler( void )
{
	EXTI->PR1 |= (1 << 13);
}

I am trying to single step in the init sequence and through the vTaskStartScheduler().

Hartmut’s most important suggestion was to change this:

to this:

EXTI->PR1 = (1 << 13);

Sorry my bad. I did not understand at first.
Correct me if I am wrong, this EXTI->PR1 = (1 << 13); will set all the bits(apart from the bit 13) to 0;
That will clear the relevant pending EXTI IRQ. If there are any other pending IRQ the handler will be called again?

What if I have multiple Interrupts say for EXTI12 or EXTI15. Should I have the if statement?

The if statement is good because that one ISR handles interrupts from 6 different sources. Even if you enable just the one, I like having some kind of code to indicate that to the developer. An if statement, or even an assert statement that none of the other relevant bits are set, or whatever works for the application.

And writing a 1 to PR1 clears the interrupt (clears the bit). Writing a 0 has no effect.

Did you have a chance to try enabling the interrupt from a task? In that test, you should see FreeRTOS start successfully I think.

Jeff

Testing calling the testInitGPIOInterrupt() from one task:
While testing I did encounter a weird issue. When I commented out this line

Both the task runs as expected. ( without GPIO ISR enabled )

But when I keep that line intact, The code does not even reach that line of coce( It does not start any task) and the application ends up in an unknown state.

So as soon as the interrupt is enabled the program breaks… :thinking:
Can you set breakpoints in EXTI15_10_IRQHandler and maybe also in the Dummy_Handler usually set as weak default handler for all undefined ISRs/exception handlers ?

Without the ST HAL, you’re on your own for establishing CPU clock speeds correctly as well as other settings that could impact stability. Any chance you’ve missed a setting, and now might be running the MCU outside its operational parameters? If you can put the repo on github I’d be happy to take a look.

Define “unknown state.” Do you end in a fault handler? If so, the instruction that caused the fault can be identified (but not necessarily the primary cause). Or what else is an “undefined state?” If your sytem is still running in that state and you break via the debugger, what piece of code is it executing?

Sorry for the late reply.
I was testing and found that these issues might not be related to the interrupt enabling.

I am sharing the location to the zip file where the project reside.
LINK

Thank you.

Would you mind telling the reason of the problem ?