Photon ADC_IRQHandler

I’m trying to setup ADC interrupt on Photon, put everything in place but it seems like ADC_IRQHandler is never being called but instead it goes to ‘Default_Handler’ set in bootloader causing watchdog to reset the system.

A simple interrupt like this won’t work either.

attachInterrupt(D0, blink, CHANGE);

Any thoughts?

@mojtabacazi and @kennethlimcp, @mdma and I (mostly Mat!) have been working on making hardware timer interrupts available to users. Because of the separated system/user firmware architecture, interrupts must be managed through the HAL. A lot of the work is going on in the timer_interrupt branch and is not yet merged with develop. I’ll discuss with @mdma to see where he’s at with this. :smile:

1 Like

Hi @mojtabacazi! Thanks for the issue report. I’d like to try to reproduce this and fix - do you have some code I can use as a test case?

Cheers :smile:

I think I know where the problem is. In bootloader, startup_stm32f2xx.S Sets all the IRQ handlers. It sets the unused one to a Default_Handler which is defined as Infinite_Loop. In core you had startup_stm32f1xx.S which is doing the same but it was compiled/linked against user code so if you put like EXTI0_IRQHandler in user code linker will find it and set that as the. But in photon startup file is linked once in bootloader. So even if you put EXTI0_IRQHandler in your code it won’t get linked.

I’ve spend like a day figuring out what’s going on so let me know if you need more information.

I’m afraid your conclusion is incorrect. While it’s true interrupt vectors are assigned in the bootloader, they are only in affect while the bootloader is running. They are reassigned in main firmware. First, by WICED, which sets the SCB->VTOR pointer to it’s own interrupt block, and then again by our code, which moves the ISR block to RAM so we can hook some of the interrupts.

Overriding the interrupts using weak function overrides requires static linking. On the Photon, the user firmware is dynamically linked to the system firmware, so this method of function overriding won’t work. (Also it’s quite fragile, dependent upon the order that modules are passed to the linker, so I’m pleased we have escaped that potential trap.)

This PR is set to provide an API to allow user code to hook system interrupts. Initial focus is on timer interrupts, although all interrupt sources will be considered, including the ADC interrupt above.


Are you disabling all IRQ before doing SCB->VTOR = (unsigned long)isrs; ? How do I know when it’s safe to override?

The assignment is atomic, and the handlers are already set up, so it’s always safe to override.