Interrupts
The FT90x interrupt controller handles 32 interrupt inputs. When an interrupt occurrs, the Interrupt Service Route (ISR) will process this event via the CPU.
The ISR vector range is from 0 to 31, which corresponds to interrupt 0 to 31.
Each interrupt shall be assigned the interrupt vector number and priority before using. By default, the highest priority interrupt is interrupt 0, and the lowest is interrupt 31.
However, the interrupt priority can be rearranged by register settings and also allows multiple interrupts at the same priority.
Nested interrupts are allowed if enabled (by default they are disabled). Up to 16 levels of nesting is allowed which defaults to only 1 level if nesting is enabled.
When nesting is enabled, only interrupts with higher priorities can interrupt the current interrupt. Interrupts of same or lower priorities will be queued as long as the interrupt sources are not cleared.
Peripheral of Interrupt | Interrupt Vector Index | Default Priority |
---|---|---|
Power Management | 0 | 0 (Non-Maskable) |
EHCI Host Controller | 1 | 1 |
USB2.0 Peripheral Controller | 2 | 2 |
Ethernet Controller | 3 | 3 |
SD Host Controller | 4 | 4 |
CAN Bus 0 | 5 | 5 |
CAN Bus 1 | 6 | 6 |
Camera | 7 | 7 |
SPI Master | 8 | 8 |
SPI Slave 0 | 9 | 9 |
SPI Slave 1 | 10 | 10 |
I2C 0 | 11 | 11 |
I2C 1 | 12 | 12 |
UART 0 | 13 | 13 |
UART 1 | 14 | 14 |
I2S Bus | 15 | 15 |
PWM | 16 | 16 |
Timers | 17 | 17 |
GPIO | 18 | 18 |
RTC | 19 | 19 |
ADC | 20 | 20 |
DAC | 21 | 21 |
Slow Clock Timer | 22 | 22 |
UNUSED | 23-31 | 23-31 |
FT90x default interrupt and priority table
Interrupt Service Routine
Interrupt service routine is defined in this way :
void interrupt() iv IVT_TIMERS_IRQ ics ICS_OFF { // Interrupt service routine code }
where :
iv
- reserved word that inform the compiler that it is an interrupt service routine.IVT_TIMERS_IRQ
- appropriate Interrupt Vector.ics
Interrupt Context Saving; Interrupt Context Saving can be performed in several ways :ICS_OFF
- No context savingICS_AUTO
- Compiler chooses whether the context saving will be perfomed or not.
User can explicitly declare starting interrupt routine address using org
directive :
void interrupt() org 0x0288 iv IVT_TIMERS_IRQ ics ICS_OFF { // Interrupt service routine code }
Function Calls from Interrupt
Calling functions from within the interrupt routine is possible. The compiler takes care about the registers being used, both in "interrupt" and in "main" thread, and performs "smart" context-switching between two of them, saving only the registers that have been used in both threads. It is not recommended to use a function call from interrupt. In case of doing that take care of stack depth.
Disable Context Saving
Use the #pragma disablecontextsaving
to instruct the compiler not to automatically perform context-switching.
This means that no register will be saved/restored by the compiler on entrance/exit from interrupt service routine.
This enables the user to manually write code for saving registers upon entrance and to restore them before exit from interrupt.
Interrupt Example
Here is a simple example of handling the interrupts from TimerA
(if no other interrupts are allowed):
volatile char val; // Timer interrupt function void Timer_Interrupt() iv IVT_TIMERS_IRQ{ // Toggle led value val = ~val; GPIO_PIN60_bit = val; GPIO_PIN17_bit = val; // Clear Timer A interrupt TIMER_INT.B0 = 1; } void main() { // Initialize LD1 as digital output GPIO_Pin_Digital_Output(_GPIO_PIN_NUM_60); // Initialize LD2 as digital output GPIO_Pin_Digital_Output(_GPIO_PIN_NUM_17); GPIO_PIN60_bit = 0; GPIO_PIN17_bit = 0; val = 0; // Enable the Timer module TIMER_CONTROL_0 = 2; // Select Timer A TIMER_SELECT = 0; // Write prescaler for Timer A TIMER_PRESC_LS = 10000; TIMER_PRESC_MS = 10000 >> 8; // Write start value TIMER_WRITE_LS = 10000; TIMER_WRITE_MS = 10000 >> 8; // Set continuous mode and direction down TIMER_CONTROL_3 = 0; // Trigger clearing timer A and prescaler TIMER_CONTROL_4 = 0x11; // Enable prescaler for Timer A TIMER_CONTROL_2 = 0x10; // Enable Timer A interrupt TIMER_INT.B1 = 1; // Enable global interrupts FT900_INTR_CTRL.B31 = 0; // Start timer A TIMER_CONTROL_1 = 1; while(1) ; }
What do you think about this topic ? Send us feedback!