Topic : Redirecting IRQs for IAP

Forum : ST7/STM8

Original Post
Post Information Post
October 26, 2009 - 3:57pm
Raisonance Support Team

Hi all,

We got an interesting request concerning in-application programming: As the STM8 protects the flash on a number of blocks of memory starting at address 0x8000 (configurable through option bytes), the interrupt vector table located at address 0x8000 is read-only in IAP mode.

So what happens to your interrupts when you need to support In-Application Programming (IAP)?

ST recommends that you relocate your interrupt vectors at a different address, for instance 0x9000. This can be done in your C files through the INTVECTOR(0x9000) directive.

Here is an example file that declares such a "leaping" IRQ vector table.
It works as follows:
[=*]

  • Interrupt n occurs.[/*]
  • The STM8 transfers execution to the IRQ n handler in the table at addres 0x8000[/*]
  • The interrupt vector does nothing, except transferring execution to its sibling interrupt handler but in the table at address 0x9000[/*]
  • The interrupt handler (which can be in the IAP bootstrap or in the user code) handles the code[/*]
  • Upon IRET, the execution restores back to its initial point[/*]
  • [/]

    The following C file will define the initial interrupt vector table. Feel free to use it in your projects.

    Regards,
    Bruno

    //------------------------------------------------------------------------------
    // redirect_irq_table.c
    //
    // When writing In-Application Programming (IAP) using the STM8, it may
    // be necessary to define a second interrupt vector table. This is because
    // the STM8 interrupt vectors are at addresses 0x8000-0x8080, which is
    // part of the Flash that may be write-protected (in order to protect
    // the User Boot Code from erasure). This write protection is made through
    // STM8 option bytes
    // In case the interrupt vectors are write-protected, it will be necessary
    // to redirect them to an area which can be reprogrammed.
    // This file will create a redirection vector table.
    //
    // Notes:
    // - The USER_INTERRUPT_TABLE_ADDRESS macro must contain the address of the
    // actual vector table you will be using.
    // - The INTVECTOR Compiler directive will have to be used for the user
    // application in order to remap the user interrupt table.
    // For example, INTVECTOR(0x9000) will relocate vectors starting at 0x9000.
    //
    //------------------------------------------------------------------------------
    // Copyright (c) Raisonance S.A.S, 2009.
    //------------------------------------------------------------------------------
    
    
    // Define the ISR type, which is a pointer to an interrupt function
    typedef char far* ISR;       // far* is necessary for 3-bytes address
    
    // Change the USER_INTERRUPT_TABLE_ADDRESS macro to point to the actual
    // vector table you will be using.
    #define USER_INTERRUPT_TABLE_ADDRESS 0x9000
    
    // At absolute address (0x8008 + interruptNumber * 4) place a 0x82 byte,
    // then the 3-bytes address of the handler
    at 0x8008 code unsigned char vect0_head = 0x82;
    at 0x8009 code ISR vect0  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x08);
    at 0x800C code unsigned char vect1_head = 0x82;
    at 0x800D code ISR vect1  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x0C);
    at 0x8010 code unsigned char vect2_head = 0x82;
    at 0x8011 code ISR vect2  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x10);
    at 0x8014 code unsigned char vect3_head = 0x82;
    at 0x8015 code ISR vect3  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x14);
    at 0x8018 code unsigned char vect4_head = 0x82;
    at 0x8019 code ISR vect4  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x18);
    at 0x801C code unsigned char vect5_head = 0x82;                      
    at 0x801D code ISR vect5  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x1C);
    at 0x8020 code unsigned char vect6_head = 0x82;                      
    at 0x8021 code ISR vect6  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x20);
    at 0x8024 code unsigned char vect7_head = 0x82;                      
    at 0x8025 code ISR vect7  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x24);
    at 0x8028 code unsigned char vect8_head = 0x82;
    at 0x8029 code ISR vect8  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x28);
    at 0x802C code unsigned char vect9_head = 0x82;                      
    at 0x802D code ISR vect9  = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x2C);
    at 0x8030 code unsigned char vect10_head = 0x82;                     
    at 0x8031 code ISR vect10 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x30);
    at 0x8034 code unsigned char vect11_head = 0x82;                     
    at 0x8035 code ISR vect11 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x34);
    at 0x8038 code unsigned char vect12_head = 0x82;                     
    at 0x8039 code ISR vect12 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x38);
    at 0x803C code unsigned char vect13_head = 0x82;                     
    at 0x803D code ISR vect13 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x3C);
    at 0x8040 code unsigned char vect14_head = 0x82;                     
    at 0x8041 code ISR vect14 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x40);
    at 0x8044 code unsigned char vect15_head = 0x82;                     
    at 0x8045 code ISR vect15 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x44);
    at 0x8048 code unsigned char vect16_head = 0x82;
    at 0x8049 code ISR vect16 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x48);
    at 0x804C code unsigned char vect17_head = 0x82;                     
    at 0x804D code ISR vect17 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x4C);
    at 0x8050 code unsigned char vect18_head = 0x82;                     
    at 0x8051 code ISR vect18 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x50);
    at 0x8054 code unsigned char vect19_head = 0x82;                     
    at 0x8055 code ISR vect19 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x54);
    at 0x8058 code unsigned char vect20_head = 0x82;                     
    at 0x8059 code ISR vect20 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x58);
    at 0x805C code unsigned char vect21_head = 0x82;                     
    at 0x805D code ISR vect21 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x5C);
    at 0x8060 code unsigned char vect22_head = 0x82;                     
    at 0x8061 code ISR vect22 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x60);
    at 0x8064 code unsigned char vect23_head = 0x82;                     
    at 0x8065 code ISR vect23 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x64);
    at 0x8068 code unsigned char vect24_head = 0x82;                     
    at 0x8069 code ISR vect24 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x68);
    at 0x806C code unsigned char vect25_head = 0x82;                     
    at 0x806D code ISR vect25 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x6C);
    at 0x8070 code unsigned char vect26_head = 0x82;                     
    at 0x8071 code ISR vect26 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x70);
    at 0x8074 code unsigned char vect27_head = 0x82;                     
    at 0x8075 code ISR vect27 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x74);
    at 0x8078 code unsigned char vect28_head = 0x82;                     
    at 0x8079 code ISR vect28 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x78);
    at 0x807C code unsigned char vect29_head = 0x82;                     
    at 0x807D code ISR vect29 = (ISR)(USER_INTERRUPT_TABLE_ADDRESS + 0x7C);