![]() |
![]() |
Interacts with the Cortex-M NVIC controller for configuring interrupts. More...
Macros | |
#define | INT_PRIORITY_MASK ((0xFF << (8 - NUM_PRIORITY_BITS)) & 0xFF) |
#define | NUM_PRIORITY 8 |
#define | NVIC_APINT_PRIGROUP_M 0x00000700 |
#define | NVIC_APINT_PRIGROUP_7_1 0x00000000 |
#define | NVIC_APINT_PRIGROUP_6_2 0x00000100 |
#define | NVIC_APINT_PRIGROUP_5_3 0x00000200 |
#define | NVIC_APINT_PRIGROUP_4_4 0x00000300 |
#define | NVIC_APINT_PRIGROUP_3_5 0x00000400 |
#define | NVIC_APINT_PRIGROUP_2_6 0x00000500 |
#define | NVIC_APINT_PRIGROUP_1_7 0x00000600 |
#define | NVIC_APINT_PRIGROUP_0_8 0x00000700 |
#define | NVIC_SYS_PRI1_R 0xE000ED18 |
#define | NVIC_SYS_PRI2_R 0xE000ED1C |
#define | NVIC_SYS_PRI3_R 0xE000ED20 |
#define | NVIC_PRI0_R 0xE000E400 |
#define | NVIC_PRI1_R 0xE000E404 |
#define | NVIC_PRI2_R 0xE000E408 |
#define | NVIC_PRI3_R 0xE000E40C |
#define | NVIC_PRI4_R 0xE000E410 |
#define | NVIC_PRI5_R 0xE000E414 |
#define | NVIC_PRI6_R 0xE000E418 |
#define | NVIC_PRI7_R 0xE000E41C |
#define | NVIC_PRI8_R 0xE000E420 |
#define | NVIC_PRI9_R 0xE000E424 |
#define | NVIC_PRI10_R 0xE000E428 |
#define | NVIC_PRI11_R 0xE000E42C |
#define | NVIC_PRI12_R 0xE000E430 |
#define | NVIC_PRI13_R 0xE000E434 |
#define | NVIC_PRI14_R 0xE000E438 |
#define | NVIC_PRI15_R 0xE000E43C |
#define | NVIC_EN0_R 0xE000E100 |
#define | NVIC_EN1_R 0xE000E104 |
#define | NVIC_DIS0_R 0xE000E180 |
#define | NVIC_DIS1_R 0xE000E184 |
#define | NVIC_PEND0_R 0xE000E200 |
#define | NVIC_PEND1_R 0xE000E204 |
#define | NVIC_UNPEND0_R 0xE000E280 |
#define | NVIC_UNPEND1_R 0xE000E284 |
Functions | |
bool | Interrupt_enableMaster (void) |
bool | Interrupt_disableMaster (void) |
void | Interrupt_registerInterrupt (uint32_t interruptNumber, void(*intHandler)(void)) |
void | Interrupt_unregisterInterrupt (uint32_t interruptNumber) |
void | Interrupt_setPriorityGrouping (uint32_t bits) |
uint32_t | Interrupt_getPriorityGrouping (void) |
void | Interrupt_setPriority (uint32_t interruptNumber, uint8_t priority) |
uint8_t | Interrupt_getPriority (uint32_t interruptNumber) |
void | Interrupt_enableInterrupt (uint32_t interruptNumber) |
void | Interrupt_disableInterrupt (uint32_t interruptNumber) |
bool | Interrupt_isEnabled (uint32_t interruptNumber) |
void | Interrupt_pendInterrupt (uint32_t interruptNumber) |
void | Interrupt_unpendInterrupt (uint32_t interruptNumber) |
void | Interrupt_setPriorityMask (uint8_t priorityMask) |
uint8_t | Interrupt_getPriorityMask (void) |
void | Interrupt_setVectorTableAddress (uint32_t addr) |
uint32_t | Interrupt_getVectorTableAddress (void) |
void | Interrupt_enableSleepOnIsrExit (void) |
void | Interrupt_disableSleepOnIsrExit (void) |
Interacts with the Cortex-M NVIC controller for configuring interrupts.
The NVIC provides global interrupt masking, prioritization, and handler dispatching. Individual interrupt sources can be masked, and the processor interrupt can be globally masked as well (without affecting the individual source masks).
The NVIC is tightly coupled with the Cortex-M microprocessor. When the processor responds to an interrupt, the NVIC supplies the address of the function to handle the interrupt directly to the processor. This action eliminates the need for a global interrupt handler that queries the interrupt controller to determine the cause of the interrupt and branch to the appropriate handler, reducing interrupt response time.
The interrupt prioritization in the NVIC allows higher priority interrupts to be handled before lower priority interrupts, as well as allowing preemption of lower priority interrupt handlers by higher priority interrupts. Again, this helps reduce interrupt response time (for example, a 1 ms system control interrupt is not held off by the execution of a lower priority 1 second housekeeping interrupt handler).
Sub-prioritization is also possible; instead of having N bits of preemptable prioritization, the NVIC can be configured (via software) for N - M bits of preemptable prioritization and M bits of sub-priority. In this scheme, two interrupts with the same preemptable prioritization but different sub-priorities do not cause a preemption; tail chaining is used instead to process the two interrupts back-to-back.
If two interrupts with the same priority (and sub-priority if so configured) are asserted at the same time, the one with the lower interrupt number is processed first. The NVIC keeps track of the nesting of interrupt handlers, allowing the processor to return from interrupt context only once all nested and pending interrupts have been handled.
Interrupt handlers can be configured in one of two ways; statically at compile time or dynamically at run time. Static configuration of interrupt handlers is accomplished by editing the interrupt handler table in the application's startup code. When statically configured, the interrupts must be explicitly enabled in the NVIC via Interrupt_enableInterrupt() before the processor can respond to the interrupt (in addition to any interrupt enabling required within the peripheral itself). Statically configuring the interrupt table provides the fastest interrupt response time because the stacking operation (a write to SRAM) can be performed in parallel with the interrupt handler table fetch (a read from Flash), as well as the prefetch of the interrupt handler itself (assuming it is also in Flash).
Alternatively, interrupts can be configured at run-time using Interrupt_registerInterrupt() (or the analog in each individual driver). When using Interrupt_registerInterrupt(), the interrupt must also be enabled as before; when using the analogue in each individual driver, Interrupt_enableInterrupt() is called by the driver and does not need to be called by the application. Run-time configuration of interrupts adds a small latency to the interrupt response time because the stacking operation (a write to SRAM) and the interrupt handler table fetch (a read from SRAM) must be performed sequentially.
Run-time configuration of interrupt handlers requires that the interrupt handler table be placed on a 1-kB boundary in SRAM (typically this is at the beginning of SRAM). Failure to do so results in an incorrect vector address being fetched in response to an interrupt. The vector table is in a section called ``vtable'' and should be placed appropriately with a linker script.
Each interrupt source can be individually enabled and disabled via Interrupt_enableInterrupt() and Interrupt_disableInterrupt(). The processor interrupt can be enabled and disabled via Interrupt_enableMaster() and Interrupt_disableMaster(); this does not affect the individual interrupt enable states. Masking of the processor interrupt can be used as a simple critical section (only an NMI can interrupt the processor while the processor interrupt is disabled), although masking the processor interrupt can have adverse effects on the interrupt response time.
The priority of each interrupt source can be set and examined via Interrupt_setPriority() and Interrupt_getPriority(). The priority assignments are defined by the hardware; the upper N bits of the 8-bit priority are examined to determine the priority of an interrupt (for the MSP432 family, N is 3). This protocol allows priorities to be defined without knowledge of the exact number of supported priorities; moving to a device with more or fewer priority bits is made easier as the interrupt source continues to have a similar level of priority. Smaller priority numbers correspond to higher interrupt priority, so 0 is the highest priority.
Below is a very brief code example showing how to configure interrupt priorities. For a set of more detailed code examples, please refer to the code examples in the examples/ directory of the MSPWare release:
#define INT_PRIORITY_MASK ((0xFF << (8 - NUM_PRIORITY_BITS)) & 0xFF) |
#define NUM_PRIORITY 8 |
Referenced by Interrupt_getPriorityGrouping(), and Interrupt_setPriorityGrouping().
#define NVIC_APINT_PRIGROUP_M 0x00000700 |
Referenced by Interrupt_getPriorityGrouping().
#define NVIC_APINT_PRIGROUP_7_1 0x00000000 |
#define NVIC_APINT_PRIGROUP_6_2 0x00000100 |
#define NVIC_APINT_PRIGROUP_5_3 0x00000200 |
#define NVIC_APINT_PRIGROUP_4_4 0x00000300 |
#define NVIC_APINT_PRIGROUP_3_5 0x00000400 |
#define NVIC_APINT_PRIGROUP_2_6 0x00000500 |
#define NVIC_APINT_PRIGROUP_1_7 0x00000600 |
#define NVIC_APINT_PRIGROUP_0_8 0x00000700 |
#define NVIC_SYS_PRI1_R 0xE000ED18 |
#define NVIC_SYS_PRI2_R 0xE000ED1C |
#define NVIC_SYS_PRI3_R 0xE000ED20 |
#define NVIC_PRI0_R 0xE000E400 |
#define NVIC_PRI1_R 0xE000E404 |
#define NVIC_PRI2_R 0xE000E408 |
#define NVIC_PRI3_R 0xE000E40C |
#define NVIC_PRI4_R 0xE000E410 |
#define NVIC_PRI5_R 0xE000E414 |
#define NVIC_PRI6_R 0xE000E418 |
#define NVIC_PRI7_R 0xE000E41C |
#define NVIC_PRI8_R 0xE000E420 |
#define NVIC_PRI9_R 0xE000E424 |
#define NVIC_PRI10_R 0xE000E428 |
#define NVIC_PRI11_R 0xE000E42C |
#define NVIC_PRI12_R 0xE000E430 |
#define NVIC_PRI13_R 0xE000E434 |
#define NVIC_PRI14_R 0xE000E438 |
#define NVIC_PRI15_R 0xE000E43C |
#define NVIC_EN0_R 0xE000E100 |
#define NVIC_EN1_R 0xE000E104 |
#define NVIC_DIS0_R 0xE000E180 |
#define NVIC_DIS1_R 0xE000E184 |
#define NVIC_PEND0_R 0xE000E200 |
#define NVIC_PEND1_R 0xE000E204 |
#define NVIC_UNPEND0_R 0xE000E280 |
#define NVIC_UNPEND1_R 0xE000E284 |
bool Interrupt_enableMaster | ( | void | ) |
Enables the processor interrupt.
This function allows the processor to respond to interrupts. This function does not affect the set of interrupts enabled in the interrupt controller; it just gates the single interrupt from the controller to the processor.
Referenced by PCM_gotoLPM0InterruptSafe(), and PCM_gotoLPM3InterruptSafe().
bool Interrupt_disableMaster | ( | void | ) |
Disables the processor interrupt.
This function prevents the processor from receiving interrupts. This function does not affect the set of interrupts enabled in the interrupt controller; it just gates the single interrupt from the controller to the processor.
References CPU_cpsid().
Referenced by PCM_gotoLPM0InterruptSafe(), and PCM_gotoLPM3InterruptSafe().
void Interrupt_registerInterrupt | ( | uint32_t | interruptNumber, |
void(*)(void) | intHandler | ||
) |
Registers a function to be called when an interrupt occurs.
interruptNumber | specifies the interrupt in question. |
intHandler | is a pointer to the function to be called. |
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
Referenced by ADC14_registerInterrupt(), AES256_registerInterrupt(), COMP_E_registerInterrupt(), CS_registerInterrupt(), DMA_registerInterrupt(), FlashCtl_registerInterrupt(), GPIO_registerInterrupt(), I2C_registerInterrupt(), MPU_registerInterrupt(), PCM_registerInterrupt(), PSS_registerInterrupt(), RTC_C_registerInterrupt(), SPI_registerInterrupt(), SysTick_registerInterrupt(), Timer32_registerInterrupt(), Timer_A_registerInterrupt(), UART_registerInterrupt(), and WDT_A_registerInterrupt().
void Interrupt_unregisterInterrupt | ( | uint32_t | interruptNumber | ) |
Unregisters the function to be called when an interrupt occurs.
interruptNumber | specifies the interrupt in question. |
This function is used to indicate that no handler should be called when the given interrupt is asserted to the processor. The interrupt source is automatically disabled (via Interrupt_disableInterrupt()) if necessary.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
Referenced by ADC14_unregisterInterrupt(), AES256_unregisterInterrupt(), COMP_E_unregisterInterrupt(), CS_unregisterInterrupt(), DMA_unregisterInterrupt(), FlashCtl_unregisterInterrupt(), GPIO_unregisterInterrupt(), I2C_unregisterInterrupt(), MPU_unregisterInterrupt(), PCM_unregisterInterrupt(), PSS_unregisterInterrupt(), RTC_C_unregisterInterrupt(), SPI_unregisterInterrupt(), SysTick_unregisterInterrupt(), Timer32_unregisterInterrupt(), Timer_A_unregisterInterrupt(), UART_unregisterInterrupt(), and WDT_A_unregisterInterrupt().
void Interrupt_setPriorityGrouping | ( | uint32_t | bits | ) |
Sets the priority grouping of the interrupt controller.
bits | specifies the number of bits of preemptable priority. |
This function specifies the split between preemptable priority levels and sub-priority levels in the interrupt priority specification. The range of the grouping values are dependent upon the hardware implementation; on the MSP432 family, three bits are available for hardware interrupt prioritization and therefore priority grouping values of three through seven have the same effect.
References ASSERT, NUM_PRIORITY, and SCS_AIRCR_VECTKEY__M.
uint32_t Interrupt_getPriorityGrouping | ( | void | ) |
Gets the priority grouping of the interrupt controller.
This function returns the split between preemptable priority levels and sub-priority levels in the interrupt priority specification.
References NUM_PRIORITY, and NVIC_APINT_PRIGROUP_M.
void Interrupt_setPriority | ( | uint32_t | interruptNumber, |
uint8_t | priority | ||
) |
Sets the priority of an interrupt.
interruptNumber | specifies the interrupt in question. |
priority | specifies the priority of the interrupt. |
This function is used to set the priority of an interrupt. When multiple interrupts are asserted simultaneously, the ones with the highest priority are processed before the lower priority interrupts. Smaller numbers correspond to higher interrupt priorities; priority 0 is the highest interrupt priority.
The hardware priority mechanism only looks at the upper N bits of the priority level (where N is 3 for the MSP432 family), so any prioritization must be performed in those bits. The remaining bits can be used to sub-prioritize the interrupt sources, and may be used by the hardware priority mechanism on a future part. This arrangement allows priorities to migrate to different NVIC implementations without changing the gross prioritization of the interrupts.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
uint8_t Interrupt_getPriority | ( | uint32_t | interruptNumber | ) |
Gets the priority of an interrupt.
interruptNumber | specifies the interrupt in question. |
This function gets the priority of an interrupt. See Interrupt_setPriority() for a definition of the priority value.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
void Interrupt_enableInterrupt | ( | uint32_t | interruptNumber | ) |
Enables an interrupt.
interruptNumber | specifies the interrupt to be enabled. |
The specified interrupt is enabled in the interrupt controller. Other enables for the interrupt (such as at the peripheral level) are unaffected by this function.
Valid values will vary from part to part, so it is important to check the device specific datasheet, however for MSP432 101 the following values can be provided:
References ASSERT.
Referenced by ADC14_registerInterrupt(), AES256_registerInterrupt(), COMP_E_registerInterrupt(), CS_registerInterrupt(), DMA_registerInterrupt(), FlashCtl_registerInterrupt(), GPIO_registerInterrupt(), I2C_registerInterrupt(), MPU_enableInterrupt(), PCM_registerInterrupt(), PSS_registerInterrupt(), RTC_C_registerInterrupt(), SPI_registerInterrupt(), Timer32_registerInterrupt(), Timer_A_registerInterrupt(), UART_registerInterrupt(), and WDT_A_registerInterrupt().
void Interrupt_disableInterrupt | ( | uint32_t | interruptNumber | ) |
Disables an interrupt.
interruptNumber | specifies the interrupt to be disabled. |
The specified interrupt is disabled in the interrupt controller. Other enables for the interrupt (such as at the peripheral level) are unaffected by this function.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
Referenced by ADC14_unregisterInterrupt(), AES256_unregisterInterrupt(), COMP_E_unregisterInterrupt(), CS_unregisterInterrupt(), DMA_unregisterInterrupt(), FlashCtl_unregisterInterrupt(), GPIO_unregisterInterrupt(), I2C_unregisterInterrupt(), MPU_disableInterrupt(), PCM_unregisterInterrupt(), PSS_unregisterInterrupt(), RTC_C_unregisterInterrupt(), SPI_unregisterInterrupt(), Timer32_unregisterInterrupt(), Timer_A_unregisterInterrupt(), UART_unregisterInterrupt(), and WDT_A_unregisterInterrupt().
bool Interrupt_isEnabled | ( | uint32_t | interruptNumber | ) |
Returns if a peripheral interrupt is enabled.
interruptNumber | specifies the interrupt to check. |
This function checks if the specified interrupt is enabled in the interrupt controller.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
void Interrupt_pendInterrupt | ( | uint32_t | interruptNumber | ) |
Pends an interrupt.
interruptNumber | specifies the interrupt to be pended. |
The specified interrupt is pended in the interrupt controller. Pending an interrupt causes the interrupt controller to execute the corresponding interrupt handler at the next available time, based on the current interrupt state priorities. For example, if called by a higher priority interrupt handler, the specified interrupt handler is not called until after the current interrupt handler has completed execution. The interrupt must have been enabled for it to be called.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
void Interrupt_unpendInterrupt | ( | uint32_t | interruptNumber | ) |
Un-pends an interrupt.
interruptNumber | specifies the interrupt to be un-pended. |
The specified interrupt is un-pended in the interrupt controller. This will cause any previously generated interrupts that have not been handled yet (due to higher priority interrupts or the interrupt no having been enabled yet) to be discarded.
See Interrupt_enableInterrupt for details about the interrupt parameter
References ASSERT.
void Interrupt_setPriorityMask | ( | uint8_t | priorityMask | ) |
Sets the priority masking level
priorityMask | is the priority level that is masked. |
This function sets the interrupt priority masking level so that all interrupts at the specified or lesser priority level are masked. Masking interrupts can be used to globally disable a set of interrupts with priority below a predetermined threshold. A value of 0 disables priority masking.
Smaller numbers correspond to higher interrupt priorities. So for example a priority level mask of 4 allows interrupts of priority level 0-3, and interrupts with a numerical priority of 4 and greater are blocked.
The hardware priority mechanism only looks at the upper N bits of the priority level (where N is 3 for the MSP432 family), so any prioritization must be performed in those bits.
References CPU_basepriSet().
uint8_t Interrupt_getPriorityMask | ( | void | ) |
Gets the priority masking level
This function gets the current setting of the interrupt priority masking level. The value returned is the priority level such that all interrupts of that and lesser priority are masked. A value of 0 means that priority masking is disabled.
Smaller numbers correspond to higher interrupt priorities. So for example a priority level mask of 4 allows interrupts of priority level 0-3, and interrupts with a numerical priority of 4 and greater are blocked.
The hardware priority mechanism only looks at the upper N bits of the priority level (where N is 3 for the MSP432 family), so any prioritization must be performed in those bits.
References CPU_basepriGet().
void Interrupt_setVectorTableAddress | ( | uint32_t | addr | ) |
Sets the address of the vector table. This function is for advanced users who might want to switch between multiple instances of vector tables (perhaps between flash/ram).
addr | is the new address of the vector table. |
uint32_t Interrupt_getVectorTableAddress | ( | void | ) |
Returns the address of the interrupt vector table.
void Interrupt_enableSleepOnIsrExit | ( | void | ) |
Enables the processor to sleep when exiting an ISR. For low power operation, this is ideal as power cycles are not wasted with the processing required for waking up from an ISR and going back to sleep.
void Interrupt_disableSleepOnIsrExit | ( | void | ) |
Enables the processor to sleep when exiting an ISR. For low power operation, this is ideal as power cycles are not wasted with the processing required for waking up from an ISR and going back to sleep.