1.8.1 Interrupt Vector Table Only Devices

Most dsPIC33 devices only have a single IVT table when CodeGuard(tm) is disabled. For devices with a single IVT table, interrupts that the application need must be forwarded from the hardware IVT to the application. One way to accomplish this is to replicate the IVT table in the application space and forward the IVT interrupts to that application remapping table.

A predefined Application Interrupt Remap Table is created in the user application space at a fixed address. Each entry in the table contains a GOTO instruction that jumps to the actual application interrupt handler for the interrupt. Then each interrupt in the bootloader IVT would be programmed with the address of the corresponding table entry in the remap table. The Application Interrupt Remap Table can now be built when the application is built and the location and size or location of the actual Application interrupt handlers are no longer an issue. The interrupts will automatically get forwarded to the handler function when they occur.

Below is the flow of an interrupt and how it ends up in the applications interrupt handler:
  1. An interrupt occurs.

  2. The PC branches to the address specified in the hardware interrupt vector table (0x4000 in the example below). This is a fixed location in the application interrupt remapping table.

  3. The application interrupt remapping has a GOTO instruction to the actual application interrupt handler function.

 

 

One drawback of the interrupt forwarding methodology above is that it can be more costly in terms of program memory space. Each interrupt requires 2 instructions on the PIC24/dsPIC devices (6 bytes). There are between 118-256 interrupts on any given device. At 6 bytes of memory each to forward, this method can require over 1KB of memory.  

In addition, most application code only uses a few interrupt sources and, in that case, the unused interrupt entries in the Application Interrupt Remap Table are just wasting space. One way to "compress" or "reduce" the size of the table would be to identify what interrupts are going to be or could be used in the family of products for the design, and only create entries in the Application Interrupt Remap Table and place these entries in contiguous locations starting at the beginning of the Application Interrupt Remap Table. With this "list" of interrupts this application could support, the bootloader can take the list and for the interrupts identified, program their interrupts in the IVT with the address of the corresponding entry in the reduced Application Interrupt Remap Table. In addition, a "Default Interrupt Handler" in the application space can be created for the unused interrupts and an entry in the Application Interrupt Remap Table and a ISR for the default. This will forward all of the other interrupts to to the application via the default interrupt handler. That way if an application decides later that it needs a new interrupt that it didn't need before, it can still have access to that interrupt through the remapped default handler.

The selection of which interrupts to forward to their own ISR and which to forward to the default ISR can be a difficult task because the bootloader firmware owner may not know which ones are or could be used. In addition, with the life cycle of products being measured in years, the product features could change over time. So if flash space is not a primary consideration, then if there is even the smallest chance that the application may want an independent ISR for a peripheral, the bootloader should forward it to an independent ISR, and only forward peripherals to the default ISR if they are 100 percent sure the peripheral will never be used, or never need to use an interrupt or that using the default ISR for the interrupt is okay to use.

Using this methodology, the Final Interrupt Forwarding scheme is shown below. In this example, the application needs just two dedicated ISR routines, UART1 and SPI1.  

Each of these two units have a dedicated entry in the Application Interrupt Remap Table. The only other entry in the Application Interrupt Remap Table is the Default Interrupt ISR. All of the "unused" or peripherals that can share a common ISR, have their IVT entry pointing to this entry in the Application Interrupt Remap Table which also is the first address in the Remap Table. By using the default interrupt entry, we have reduced the size of the Application Interrupt Remap Table from approximately 256 flash words to 6 flash words.

 

 

In the example above, the peripherals A, B, and C are not used by the application, but their interrupts are forwarded to the application default handler just in case they are ever needed later.

In the case where the bootloader needs an interrupt, the IVT has to not forward that interrupt to the application (NOTE: on devices with Alternate Interrupt Tables - AIVTs - this is not required). In this case the bootloader would consume the interrupt from the IVT. In the example, below the bootloader needs UART2 in an interrupt mode. In this case the IVT doesn't forward the interrupt to the application but rather decides to keep the interrupt in the bootloader