I did a little testing and I can comment out the line to add the ISR and the CAC runs and the code works. I just can't attach the interrupt.
So I started learning a bit more about the interrupts here.
Based on this post I had a look at @susan-parker 's code and I noticed that she was attaching pin interrupts and then changing the interrupt source. I didn't understand at first.
It seems as though all the interrupts in IRQManager are added through FSP configurations. If you look, what actually gets set as the function pointer for the isr are all FSP functions. Then they are looking in the configuration structs to get the handler to call.
For instance the external pin interrupt is added in addPeripheral:
#if EXT_INTERRUPTS_HOWMANY > 0
/* **********************************************************************
PIN EXTERNAL INTERRUPT
********************************************************************** */
else if(p == IRQ_EXTERNAL_PIN && cfg != NULL) {
external_irq_cfg_t *p_cfg = (external_irq_cfg_t *)cfg;
if (p_cfg->irq == FSP_INVALID_VECTOR) {
p_cfg->ipl = EXTERNAL_PIN_PRIORITY;
p_cfg->irq = (IRQn_Type)last_interrupt_index;
*(irq_ptr + last_interrupt_index) = (uint32_t)r_icu_isr;
set_ext_link_event(last_interrupt_index, p_cfg->channel);
last_interrupt_index++;
}
}
#endif
The address that's put in the vector table is to r_icu_isr, not the interrupt handler from Interrupts.h . I can't find the implementation of that. It seems to be in the libfsp maybe.
In the case of the external pin interrupts this ends up calling from Interrupts.cpp:
/* -------------------------------------------------------------------------- */
static void IrqCallback(external_irq_callback_args_t * p_args) {
/* -------------------------------------------------------------------------- */
void * param = (void *)p_args->p_context;
uint32_t ch = p_args->channel;
CIrq *irq_context = nullptr;
if(ch < MAX_IRQ_CHANNEL) {
irq_context = IrqChannel.get(ch,false);
if(irq_context != nullptr) {
R_BSP_IrqClearPending(irq_context->cfg.irq);
if(irq_context->fnc_param != nullptr) {
irq_context->fnc_param(param);
}
else if(irq_context->fnc_void != nullptr) {
irq_context->fnc_void();
}
}
}
}
And then it determines which pin fired the interrupt and which handler to call. So it seems that at the base level, all the pin change ISRs are sharing one base handler and it's called by another handler that's actually the thing being attached.
I'm sure that there's some extra code in there that we need to be implementing in order for our interrupt to work. In the case of Susan's code, that's being handled by the external pin change isr. She's basically putting her handler into the external pin interrupt pool and then fooling the processor into calling that pin change isr for her interrupt by swapping the event code.
It's pretty smart.