Harmony Interrupt System Services provide a set of APIs allowing system developers to monitor and control the operation of peripheral interrupts.
The elements controlled by the Interrupt System Services include:
- Enabling / Disabling an individual interrupt
- Setting a Peripheral's Interrupt Priority and Sub-Priority
- Clearing an interrupt flag
- Assigning an ISR to a Peripheral with a Dynamic Driver
Interrupts are controlled by Harmony's Interrupt System Services, but they are defined when the individual peripheral drivers are selected. To effectively implement interrupts, the system developer must work with both Interrupt System Services and the individual peripheral setup. This page demonstrates Interrupt System Services.
Enabling Interrupt System Services
To enable Interrupt System Services from MHC select the box "Use Interrupt System Service?" under
Harmony Framework Configuration ▶ System Services ▶ Interrupts
When the "Generate" button is pushed, MHC will add the source files to the project to enable Interrupt System Services.
Peripheral Interrupt Setup
Peripheral interrupts are setup under the Driver section of Microchip Harmony Configurator (MHC). For each peripheral capable of generating an interrupt, MHC will present the user the option of enabling the interrupt. When configuring the interrupt in MHC the user has the opportunity to set the initial priority level of the individual interrupt.
When the project is generated, MHC inserts code to:
- Initialize the MCU interrupt system SYS_INT_Initialize()
- Enable Global Interrupts SYS_INT_Enable()
- Set the selected interrupt priority levels
- Enable the peripheral interrupts
- Create "Stub" Interrupt Service routines for either Static or Dynamic Drivers
Enabling and Disabling an Interrupt
Individual peripheral interrupts can be enabled or disabled by calling the functions SYS_INT_SourceEnable() and SYS_INT_SourceDisable()
void SYS_INT_SourceEnable(INT_SOURCE source);
void SYS_INT_SourceDisable(INT_SOURCE#* source);
. . .
green|/ Enable interrupts from Timer 3##
// Disable interrupts from ADC 1
The data type for the input parameter for these functions, INT_SOURCE, is an enumeration defined in the processor's Harmony interrupt header file.
Setting an ISR Priority
Application programs can change the priority, and sub-priority, of individual peripherals using the functions SYS_INT_VectorPrioritySet and SYS_INT_VectorSubprioritySet
void SYS_INT_VectorPrioritySet( INT_VECTOR vector,
void SYS_INT_VectorSubprioritySet( INT_VECTOR vector,
INT_PRIORITY_LEVEL2); // Set UART1's interrupt priority level to 2
INT_SUBPRIORITY_LEVEL1); // Set UART1's interrupt SUB priority level to 1
The data types for the input parameters to these functions, INT_VECTOR, ]INT_PRIORITY and INT_SUBPRIORITY_LEVEL are enumerations defined in the processor's Harmony interrupt header file.
Clearing an interrupt's request flag
Peripherals announce an interrupt condition by setting the Peripheral Interrupt Request flag associated with the peripheral. The interrupt request flags are located in the MCU's special function registers (SFRs). The ISR needs to clear the request flag before returning control to the main program. The Harmony supplied function to clear the flags is SYS_INT_SourceStatusClear
void SYS_INT_SourceStatusClear( INT_SOURCE source);
// Clear Timer1 interrupt request
The data type for the input parameter, INT_SOURCE, is an enumeration defined in the processor's Harmony interrupt header file.
Dynamic vs Static Drivers
Peripherals are configured with either a Static or Dynamic driver. MHC provides the developer the ability to select the driver type to use from a pull-down menu.
Static drivers are intended to be used in applications in which the peripheral's parameters remain unchanged (i.e. static), and in applications where the peripheral is not shared with multiple tasks. Dynamic Drivers offer the system developer the ability to easily alter the peripheral's performance at run-time. One of the features which can be changed for Dynamic Drivers is the Interrupt Service Routine (ISR). Changing the ISR at run-time can be essential in sharing one peripheral among several tasks.
For Static Drivers, Harmony inserts a "stub" ISR at the interrupt vector. The Harmony supplied static ISR contains code to clear the Peripheral Interrupt Request flag. The user will need to complete the ISR by adding code to the ISR function.
For Dynamic Drivers, Harmony inserts a call to a Harmony-supplied Peripheral Task function at the interrupt vector. The Peripheral Task does some parameter testing then calls, via a function pointer, the ISR to handle the interrupt.
Implementing an ISR for a Static Driver
When a peripheral is configured to use an interrupt MHC creates a file called system_interrupt.c. This file is placed in the current project. For peripherals with static drivers a stub Interrupt Service Routine (ISR) is created.
To implement application specific ISR the developer will insert code directly into the stub ISR.
Implementing an ISR for a Dynamic Driver
ISRs for dynamic drivers are implemented using call-back functions. MHC places a call to a Peripheral-Task into the interrupt vector for each peripheral defined with a dynamic driver. There is one Peripheral-Task function for each peripheral type. The Peripheral Task functions have names such as DRV_TMR_Tasks_ISR for Timers and DRV_USART_TasksTransmit for the UART transmit function, etc…
The lone parameter passed to the Peripheral-Task function is a pointer to a data structure containing the information for the individual peripheral. (This data structure is commonly called a System Object.) One of the parameters in the System Object data structure is the address of the designated interrupt service routine.
The peripheral-task function performs some error checking then invokes the functions specified in the System Object data structure. Loading the System Object with the address of the ISR establishes which user-written function will eventually be executed upon an interrupt.
The default selection of the ISR for a peripheral with a dynamic driver varies among the peripherals. For basic I/O peripherals such as SPI, MHC inserts a call to the specific transfer functions based upon whether or not the enhanced buffer is being used. The SPI interrupt handler ensures the data is transferred to and from the SPI SFRs and the user designated data buffer.
The default ISR for interrupts requiring user-written function is NULL. For peripherals where the developer needs to insert specific code, Harmony provides two support functions: SYS_INT_DynamicRegister and SYS_INT_DynamicDeregister. These functions allow the application developer to either set or remove their custom function as the ISR callback function.
void SYS_INT_DynamicDeregister( INT_SOURCE source);
void SYS_INT_DynamicRegister( INT_SOURCE source, ISR_POINTER,
// Deregisters the ISR for Timer_4 interrupt
/* Sets the user-written MyISR as the interrupt service routine for Timer 1 where Timer 1 has been set as Timer instance 0 */
SYS_INT_DynamicRegister(INT_SORCE_TIMER_1, MyISR , sysObj.drvTmr0);
Early versions of Harmony do not support nor include SYS_INT_DynamicRegister or SYS_INT_DynamicDeregister.
Some peripheral drivers, such as Timers, offer their own functions to set their ISRs. Refer to the Harmony peripheral documentation for how to set or clear the dynamic ISR for the peripheral you are working with.