The interrupt part of ARM Cortex M MCUs is described in CMSIS. The interrupt controller of ARM Cortex M MCUs is called NVIC. The NVIC is part of CMSIS and is decribed at the CMSIS website: https://www.keil.com/pack/doc/CMSIS/Core/html/group__NVIC__gr.html
In general ARM Cortex M based MCUs having two types of IRQs: Core peripheral IRQs and MCU peripheral IRQs. Core Peripherals are ARM Cortex M specific like SysTick and the Fault IRQs. MCU peripherals are peripherals provided by the MCU vendor like UART, Timers, etc.
Core Peripherals – SysTick
To initialize the SysTick core peripheral with the IRQ handle SysTick_Handler is pretty easy:
First of all the system clock must be updated to deliver the correct clock-speed in the global variable SystemCoreClock:
SystemCoreClockUpdate(); //update clock variable SystemCoreClock (defined by CMSIS)
Now the SysTick can be configured:
SysTick_Config(SystemCoreClock / 1000); //setup 1ms SysTick (defined by CMSIS)
The interrupt service routine looks like the following code:
static volatile uint32_t u32Counter; //ms counter
void SysTick_Handler(void)
{
u32Counter++;
}
See also SysTick in CMSIS: https://www.keil.com/pack/doc/CMSIS/Core/html/group__SysTick__gr.html
MCU Peripherals – Ambiq Micro Apollo MCU external IRQ
For MCU peripherals the available IRQs are defined in the typedef enum IRQn_Type in the MCU header file. For Ambiq Micro in the “apollo1.h” or “apollo2.h” header file. For example the GPIO interrupt handler of Apollo 1 can be found as “GPIO_IRQn”. The same way is the handler defined in the startup assembler or C file, but instead of IRQn the handler is named “Handler”.
Example:
GPIO_IRQn => GPIO_Handler
To initialize the interrrupt, first of all the peripheral must be configured and after that the NVIC (example GPIO0):
/* peripheral setup */
GPIO->INT0EN &= ~(1 << 0); //disable IRQ before configurating
GPIO->PADKEY = 0x00000073; //unlock GPIO setup
GPIO->PADREGA_b.PAD0FNCSEL = 0x3; //use as GPIO0
GPIO->PADREGA_b.PAD0INPEN = 1; //enable input
GPIO->CFGA_b.GPIO0INTD = 1; //set falling-edge
GPIO->CFGA_b.GPIO0INCFG = 1; //use as GPIO0 as input
GPIO->PADKEY = 0x00000000; //lock GPIO setup
GPIO->INT0EN |= (1 << 0); //enable IRQ in peripheral setup
//see also http://blog.io-expert.com/using-gpios-of-ambiq-micros-apollo1-and-apollo2-mcus
/* NVIC setup */
NVIC_ClearPendingIRQ(GPIO_IRQn); //clear pending flag
NVIC_EnableIRQ(GPIO_IRQn); //enable IRQ
NVIC_SetPriority(GPIO_IRQn,1); //set priority, smaller value means higher priority
At last the IRQ handler must be written:
void GPIO_IRQHandler(void)
{
uint32_t u32Status;
u32Status = GPIO->INT0STAT;
if(u32Status & (1 << 0))
{
//do the IRQ handling here…
}
GPIO->INT0CLR = u32Status; //clear IRQ flags
}
Run the Code
The complete example is workable with MCU Templates for Apollo1 and Apollo2 from FEEU http://www.fujitsu.com/feeu or by contacting FEEU directly info.feeu@de.fujitsu.com
See also MCU Templates