NVIC Stands for Nested vectored interrupt controller
The NVIC supports:
- up to 81 interrupts (depends on the STM32 device type, refer to the datasheets)
- A programmable priority level of 0-15 for each interrupt. A higher level corresponds to a lower priority, so level 0 is the highest interrupt priority
- Level and pulse detection of interrupt signals
- Dynamic reprioritization of interrupts
- Grouping of priority values into group priority and sub priority fields
- Interrupt tail-chaining
- An external Non-maskable interrupt (NMI)
1. Why need NVIC?
> You (Cortex -M Processor) are watch TV. At the same time, your phone is ringing; By the way, your clothes haven't clean yet; Your bike is broken. Except watching TV, You also have many things(exceptions) to do today. How you decide which one to do first and which one next. The NVIC will help you decide which one to do next if you have configured it correctly.
2. What is exception?
explain the technical terms in the picture.
what is software exception?
Software exception handling and the support provided by software tools differs somewhat from what is understood by exception handling in hardware.
What is synchronous and asynchronous exception?
An exception is described as synchronous if it is generated as a result of execution or attempted execution of the instruction stream, and where the return address provides details of the instruction that caused it. An asynchronous exception is not generated by executing instructions, while the return address might not always provide details of what caused the exception. The green area contain asynchronous and synchronous exceptions.
3. What's difference between exceptions and interrupt from register perspective?
The interrupt is quite simple, all of them are manipulated in NVIC registers.
But the exceptions are different. I make a table to understand the configuration with the style of NVIC's registers.
Most of peripherals's interrupt enabling only need to configure the NVIC register.
4. What's Difference between exceptions and interrupts in code.
To simplify the software layer, the CMSIS only uses IRQ numbers and therefore uses negative values for exceptions other than interrupts. The IPSR returns the Exception number.
5. How exceptions/interrupt works?
The steps are:
program -> 1. exception/interrupt request -> 2. set requestor's pending bit in NVIC register(exception state is Pending now) -> 3. is the highest priority of all pending exceptions ? -> 4. NVIC enable? -> 5. priority mask checking -> 6. (exception entry) stacking, in parallel to stacking operation, the processor performs a vector fetch that reads the exception handler start address from the vector table. -> 7. (exception state is active now) start executing ISR, at the same time, the processor writes an EXC_RETURN value to LR(indicates which stack pointer corresponds to the stack frame and what operation mode the processor was in before the exception entry) and automatically changes the status of the corresponding pending interrupt to active, Also the ISR_Number in IPSR change to current ISR_Number, Also automatically clear the Pending bit in NVIC register -> 8. exception return -> 9. EXC_RETURN is loaded into PC. The lowest 4 bits of EXC_RETURN provide information on the return stack and processor mode. The [31:4] bits indicates to the processor that the exception is complete -> 10. Returning the processor from an ISR(Exception return behavior) (unstacking) (exception state is inactive now) -> 11. restarting the interrupted program.
!!Attention: we should clear the interrupt triggering flag before exiting the ISR, otherwise, the processor will reenter the ISR immediately.
Let's make a real example.
The example is RCC. Here are the steps to make NVIC works.
1st. Config the RCC_IRQn in NVIC registers.
The RCC global interrupt is enabled.
2nd. Enable the interrupt for HSE ready (HSE RDYIE)
3rd. Enable the HSE oscilator, then the HSE RDY flag will be automatically generated when HSE is stable.
4th, HSE is stable now, the HSERDY flag is set by hardware.
the request signal is sending to the NVIC.
5th. Follow the NVIC processing steps
set requestor's pending bit in NVIC register -> is the highest priority of all pending exceptions ? -> NVIC enable? -> priority mask checking -> (exception entry) stacking, in parallel to stacking operation, the processor performs a vector fetch that reads the exception handler start address from the vector table. /* take a look at real stacking */
/* why LR is already written with EXC_RETURN, because my debugger is already at the beginning of ISR, I can't capture every single step */
/* the memory after stacking */
-> start executing ISR, at the same time, the processor writes an EXC_RETURN value to LR(indicates which stack pointer corresponds to the stack frame and what operation mode the processor was in before the exception entry) and automatically changes the status of the corresponding pending interrupt to active.
/* take a look in keil*/
-> exception return (trigger by BX lr)
/* take a look in keil */
-> EXC_RETURN is loaded into PC. The lowest 4 bits of EXC_RETURN provide information on the return stack and processor mode. The [31:4] bits indicates to the processor that the exception is complete -> Returning the processor from an ISR(Exception return behavior) (unstacking) -> restarting the interrupted program.
6. How interrupts are nested?
We can divide the exception into 3 parts, stacking, ISR, unstacking. as we know, the stacking and unstacking are overhead.
What will happen if another interrupt happens in stacking, or ISR, or, unstacking?
1st is the HIGHER group priority interrupt, 2nd is the LOWER group priority interrupt.
1st is the LOWER group priority interrupt, 2nd is the HIGHER group priority interrupt.
In normal, Stacking(push) and unstacking(pop) both need 12 cycles.
But ARM develops technique called Tail-chainning and Late arriving help shorten the interrupt latency.
Let's see how it works.
Tail-chaining is back-to-back processing of exceptions without overhead of state saving and restoration between interrupts. The processor skips the pop of 8 registers and push 8 registers when exiting one ISR and entering another because this has no effect on the stack contents.
The processor tail-chains if a pending interrupt has higher priority than all stacked exceptions and lower than the current active exception.
Speed UP with tail chaining.
A late-arriving interrupt can pre-empt a previous interrupt if the first instruction of the previous ISR has not entered the execute stage, and the late-arriving interrupt has a higher priority than the previous interrupt.
A late-arriving interrupt cause a new vector address fetch and ISR prefetch. State saving is not performed for the late-arriving interrupt because it has already been peroformed for the initial interrupt and so does not have to be repeated.
Speed UP with late-arriving.