
...the world's most energy friendly microcontrollers
2013-09-16 - an0039_Rev1.04 12 www.silabs.com
4.3 Sleep-on-Exit
The sleep_on_exit example project sets up TIMER0 in Up/Count mode to give overflow interrupts every
second. The SLEEPONEXIT bit is set and the device is put in EM1. Execution will then not return to
main until SLEEPONEXIT is cleared. The ISR increments an interrupt counter which is shown on the
LCD every time it is run. After 5 interrupts the SLEEPONEXIT bit is cleared in the ISR and the CPU
returns to main where "DONE" is written to the LCD.
4.4 Sub Priority
In the sub_priority example project, TIMER0 and TIMER1 are set up to start at the same time and count
to 1000, triggering their overflow interrupts in the same cycle. PRIGROUP is configured so all interrupt
bits are used to set sub priority. Initially both interrupts have the same default sub priority and TIMER0
ISR will then be executed first as it has the lowest numbered IRQ. Before the TIMERs reach their second
overflow interrupts (also in the same cycle), the sub priority for the TIMER0 ISR has been decreased
and the TIMER1 ISR will then be executed first. Both ISRs will concatenate a "0" (for TIMER0) or a
"1" (for TIMER1) to a string every time they are called. The string is printed at the end of the program
to show the order the ISRs were executed in.
4.5 Preempt Priority
In the preempt_priority example project, TIMER0 and TIMER1 are set up to trigger overflow interrupts,
butthey are not enabled.TheTIMER0overflowinterruptis then triggeredbysettingtheoverflowinterrupt
flag in SW. In the TIMER0 ISR, the TIMER1 overflow interrupt is triggered in the same way. PRIGROUP
is configured so all interrupt bits are used to set preempt priority. Initially both interrupts have the same
default preempt priority and the TIMER1 interrupt triggered in the TIMER0 ISR will then wait until the
TIMER0 ISR finishes before starting.
Before TIMER0 overflow is triggered a second time, the preempt priority for the TIMER0 ISR has been
decreased. The TIMER1 ISR will then start immediately when triggered in the TIMER0 ISR and the rest
of the TIMER0 ISR will complete after the TIMER1 ISR is finished. The TIMER1 ISR will concatenate
a "0" to a string every time it is called. The TIMER0 ISR will concatenate an "A" to the string before
triggering the TIMER1 overflow interrupt and a "B" after. The string is printed then printed at the end
of the program to show the order the ISRs were executed in. Figure 1.2 (p. 3) shows the simplified
execution order of a nested interrupt.
4.6 Interrupt Disable
The interrupt_disable example project shows a how to disable interrupts temporarily to allow several
evaluations to be done in one atomic operation, without the risk of an interrupt hitting in between to
corrupt the process. In this example enabling the LFRCO and waiting for the interrupt to trigger when it
is stable. In the ISR, a global variable (lfrcoReady) is set to true which is then checked in main. While
this variable is false, the device is sent repeatedly to EM1. The repeated check ensures that no other
interrupt triggering will incorrectly cause the program to proceed without LFRCO being ready. If this
check was done without disabling the interrupts first, an LFRCO-ready interrupt firing after the check for
lfrcoReady, but before the sleep instructions, could lock the whole program indefinitely as there might
not be any subsequent interrupts to wake the device from sleep.
To disable and enable interrupts safely the em_int.h library is used. The library uses a lock level
counter to keep track of how many times INT_Disable() and INT_Enable() has been called.
INT_Disable() disables interrupts and increments the counter while INT_Enable() decrements the
counter and enables interrupts only if the counter reached zero. This ensures that interrupts will not be
enabled prematurely if nested disabling and enabling of interrupts is used. Notice that the CPU wakes
up when the interrupt is set pending even though the global interrupts have been disabled. The ISR is
however not entered until the lock level counter is decremented to zero.