Overriding Weak EXTI callback

I am trying to setup a GPIO pin as an interrupt pin. I believe I have the setup working with the HAL library but have not been able to confirm due to problems with the callback override. I am overriding HAL_GPIO_EXTI_Callback in my main file so it is a global function. I am using the build task provided when building a project in VSCode.

When I try to debug the project and place a break point in the callback the break point is moved past the function as soon as it starts. This gave me the idea that the function was not in the final program. I confirmed this by doing an objdump on the .elf file.

When running objdump on libdaisy.a and 'target.o, HAL_GPIO_EXTI_Callback` is in both with the expected attributes.

Any idea on how to stop this function from being dropped by the compiler?

#include "daisy_seed.h"
#include "daisysp.h"
#include "interrupt.h"
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_gpio.h"


daisy::DaisySeed hw;
bool stuff;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	UNUSED(GPIO_Pin);
	hw.SetLed(true);
	hw.PrintLine("Interrupt");
}

int main(void)
{
	hw.Init();
	hw.StartLog();
	hw.PrintLine("Start Log");

	daisy::Interrupt int1;
	int1.Init(daisy::seed::D0);

	hw.PrintLine("Start Loop");
	while(1) {
		if (stuff)
		{
		hw.PrintLine("Beep");
		}
		else
		{
		hw.PrintLine("Boop");
		}
		stuff = !stuff;
		daisy::System::Delay(1000);
	}
}

HAL is written in C and code in C++ has different linkage (i.e. includes name mangling to support features like classes, namespaces, etc.). To override a weak C function in C++ file you should place your function in extern "C" {...} block to make it use C linkage for that function.

1 Like

Thank you for the response!

I had that in an earlier version but it had no effect. I tried again I have the same result, function is in individual .o/.a files and it is not in the final .elf. I think it might have to do with the override happening as a dynamic link as opposed to a static link. But I haven’t found any info if that is a limitation of the arm compiler

Actually, before you can use interrupt handling callbacks, you need to make a few extra steps.

First of all, one of EXTIXXX_IRQHandler(void) IRQ handlers get called by hardware interrupt based on pointer in specific address of ISR vector

Their default implementations are considered unhandled interrupts and they just raise a hardware fault. They are defined as weak functions and intended to be replaced by strong functions like that dispatch function call to a single handle and pass it the GPIO pin that you’re actually want to use:

void EXTIXXX_IRQHandler(void)
{
 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_XXX);
}

Not sure if you do this somewhere.

Next, interrupt handler clears pending interrupts and calls the callback function: libDaisy/stm32h7xx_hal_gpio.c at b65a1bad880f5d6ca5194d7162652757c6f4fcc5 · electro-smith/libDaisy · GitHub

Simply overriding the handler callback is insufficient, because your interrupt callback won’t be calling the handler that calls it unless you replace the default IRQ handler.

In addition to that, those functions are fairly simple and you don’t even have to use HAL to the full extend. You could just set pointer to arbitrary function you define in correct place of ISR vector. The only requirement is to clear pending interrupts in your handler like HAL_GPIO_EXTI_IRQHandler does. So you can bypass the whole weak/strong function issues from static libraries in case if you actually implement full IRQ handling workflow with HAL and get it. In this case you should set your custom IRQ handler before initializing the PIN as EXTI interrupt.