Handling Data Conflict in Interrupt Vector Table Shared by Bootloader and Application

Introduction:

The common method to download the application firmware of a Microcontroller (MC) is to use a specific programmer for that particular microcontroller. Another alternative is to use the Bootloader, which is a small non-erasable program that resides in the flash area of MC which empowers it with self-reprogramming capability. The Bootloader receives the application program through any of the communication interfaces such as USB, UART etc. and re-programs the application.

What is an Interrupt Vector Table?

An Interrupt vector Table (IVT) is responsible for handling the interrupts, when it occurs. This is done by directing the interrupts to its respective interrupt service routine (ISR). IVT plays a major role in microcontroller programming.

In recent days, modern MC’s (eg.dsPic33EP512MU814) have an auxiliary Flash, the Bootloader code shall reside in that auxiliary flash and shall use the auxiliary interrupt vector table(AIVT) to handle the interrupts. The application code shall reside in the usual Flash memory and shall use the IVT to handle the interrupts.

Problem Description:

Few Controllers (eg.dsPIC33EP512GM706) do not have an auxiliary flash memory or an AIVT, so the Bootloader and the Application rely upon a Single IVT and Flash memory. This becomes barrier to use common Interrupts in the bootloader and the application code, thus making self- reprogramming a tedious task. Objective of this article is to brief about the challenges faced due to the above scenario and the solution to overcome it.

Challenges faced:

It is certain to have two separate workspaces for the Bootloader and the application code, and combining the two workspaces generates a unified Hex file. In our case considering the controller that do not an auxiliary flash memory or an AIVT, if the same interrupt is being used in both the codes it will result in an interrupt overlap issue or data conflict as shown in Figure 1. This data conflict is due to the fact that the bootloader and the application are trying to access the same IVT address of that particular common interrupt in their respective linker files.

Figure 1: Error screen when the Bootloader & Application workspaces are compiled to generate an Unified hex file

As shown in Figure 1, the address at which the data conflict has occurred is the address of an interrupt in the IVT. Now the challenge is to combine the two workspaces without any data conflict

Solution to overcome the above challenge:

Step 1:

In order to overcome this issue, the Bootloader.gld linker script should keep the IVT. Remove the Interrupt Vector Table (.ivt section) from the Application.gld linker script.

Step 2:

Ensure that the bootloader and the application codes are not using the same interrupts. E.g. If the Bootloader uses Timer 2 interrupt then the Application should not use the same interrupt, instead it can use Timer 1 or Timer 3 interrupt

Step 3:

The ISRs of the application code has to be defined in a known address. This can be done by using the address attribute as follows:

void __attribute__((interrupt,auto_psv,address(0x0036AC))) _T1Interrupt( void )

By using the above address attribute the compiler places the ISR of the Timer 1 interrupt in a known location that is 0x0036AC.

Step 4:

Create dispatch ISR’s for the all interrupts used in the application. The dispatch ISR should be written in the Bootloader code

E.g. Dispatch ISR of the timer 1 interrupt

void __attribute__((interrupt,auto_psv)) _T1Interrupt( void ){void (*fptr)(void);fptr = (void (*)(void))0x0036AC;fptr();}

Thus, if an interrupt related to the application occurs the bootloader’s ivt directs it to its respective dispatch ISR which in-turn redirects it to the application’s ISR by specifying the address. Also if an interrupt related to the Bootloader occurs it shall be serviced just like any other normal ISR by the bootloader itself. The interrupt handling flow between the bootloader and the application is depicted below in Figure 2.

Figure 2: Interrupt handling flow between Bootloader and Application Code

Step 5:

Combine the two projects and compile the code to create a unified hex file without any data conflict or interrupt overlap issues.

Dependencies:

It is necessary to identify all the required interrupts in the application code and create a dispatch ISRs in the bootloader code beforehand. Enough memory should be allocated for the application ISRs as we are defined their addresses and not the compiler.

Tools used to prove the above concept:

Controller : dsPIC33EP512GM706

IDE (Integrated development environment : MPLAB XIDE

Compiler : MPLAB C30

Conclusion:

Thus by deploying the above method, a unified hex file was created without any data conflict issue.

Figure 3. The build window showing the unified hex file creation without any data conflict

The Bootloader’s functionality of erasing and re-programming the application code was implemented and tested successfully. The build window is shown in Figure 3.