Direct writing ISR address to vector table at run time?

Post here first, or if you can't find a relevant section!
Post Reply
tiger762
Posts: 22
Joined: Tue Jan 26, 2016 11:40 pm

Direct writing ISR address to vector table at run time?

Post by tiger762 » Sun Feb 26, 2017 11:20 pm

I need to add an ADC interrupt handler for my stm32f103c8t6. I might be overthinking this a little, but can I do this:

*((volatile long *)0x88) = &adc_isr;

at run time? I would still set the NVIC registers for priority / subpriority, etc.

adc_isr() is my candidate interrupt service routine. I would make the assignment during initialization, before the ADC is put into service.

I just need to catch the EOC interrupt and I have given up on trying to decipher the StdPeripheralLibrary. A rat's nest of #defines with some secret methodology of usage I am not privy to.

devan
Posts: 45
Joined: Sat May 14, 2016 1:45 am

Re: Direct writing ISR address to vector table at run time?

Post by devan » Mon Feb 27, 2017 12:33 am

Assuming you're running from flash, you won't be able to overwrite the vector table directly without erasing and rewriting the entire first page of flash, which is probably not what you want.

A common approach to modify the vector table at runtime is to:
  • Make a new vector table somewhere in RAM, usually initialized from the vector table in flash
  • Overwrite the entry in your RAM vector table with the ISR handler you want
  • Update the SCB VTOR register to point to your vector table in RAM
You can see an example of this approach in the mbed library:

Code: Select all

#define NVIC_RAM_VECTOR_ADDRESS   (0x20000000)  // Vectors positioned at start of RAM
#define NVIC_FLASH_VECTOR_ADDRESS (0x08000000)  // Initial vector position in flash

void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
    uint32_t *vectors = (uint32_t *)SCB->VTOR;
    uint32_t i;

    // Copy and switch to dynamic vectors if the first time called
    if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS) {
        uint32_t *old_vectors = vectors;
        vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;
        for (i=0; i<NVIC_NUM_VECTORS; i++) {
            vectors[i] = old_vectors[i];
        }
        SCB->VTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS;
    }
    vectors[IRQn + NVIC_USER_IRQ_OFFSET] = vector;
}

victor_pv
Posts: 1607
Joined: Mon Apr 27, 2015 12:12 pm

Re: Direct writing ISR address to vector table at run time?

Post by victor_pv » Mon Feb 27, 2017 1:31 am

tiger762 wrote:I need to add an ADC interrupt handler for my stm32f103c8t6. I might be overthinking this a little, but can I do this:

*((volatile long *)0x88) = &adc_isr;

at run time? I would still set the NVIC registers for priority / subpriority, etc.

adc_isr() is my candidate interrupt service routine. I would make the assignment during initialization, before the ADC is put into service.

I just need to catch the EOC interrupt and I have given up on trying to decipher the StdPeripheralLibrary. A rat's nest of #defines with some secret methodology of usage I am not privy to.
There is a function in the core that allows you to attach an interrupt handler for different ADC events, adc_attach_interrupt, check the file adc_f1.c

stevestrong
Posts: 1514
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Direct writing ISR address to vector table at run time?

Post by stevestrong » Mon Feb 27, 2017 1:30 pm

Wouldn't

Code: Select all

adc_attach_interrupt(adc_dev *dev, uint8 interrupt, voidFuncPtr handler)
do the trick?

Post Reply