Chapter 5 - Interrupts

advertisement
Chapter 5 - Interrupts
Interrupts and Exceptions
Exception Source
Reset and NMI
On Chip Debug
Memory Region
Program
Program
Cache Error
TLB Refill
RAM or Program
RAM or Program
General Exception
Interrupt
RAM or Program
RAM or Program
Di Jasio - Programming 32-bit Microcontrollers in C
Description
Normal Reset and Non Maskable Interrupt entry point.
Used by the ICD and EJTAG interfaces to enable in
circuit debugging features.
Error condition specific to the cache mechanism.
Not used on PIC32 as a fixed address translation
scheme (FMT) is used is place of a full MMU.
All other types of exceptions.
The proper interrupt vector.
Interrupt Service Functions
Interrupt service functions are not supposed
to return any value (use type void).
 No parameter can be passed to the function
(use parameter void).
 They cannot be called directly by other
functions.
 Ideally, they should not call any other
function.

Di Jasio - Programming 32-bit Microcontrollers in C
Sources of Interrupt
Among the external sources available for the PIC32MX3, there are:
 5 x External pins with level trigger detection
 22 x External pins connected to the Change Notification module
 5 x Input Capture modules
 5 x Output Compare modules
 2 x Serial port interfaces (UARTs)
 4 x Synchronous serial interfaces (SPI and I2C)
 1 x Parallel Master Port
Among the internal sources we count:
 1 x 32 internal (core) timer
 5 x 16-bit Timers
 1 x Analog-to-Digital Converter
 1 x Analog Comparators module
 1 x Real Time Clock and Calendar
 1 x Flash controller
 1 x Fail Safe Clock Monitor
 2 x Software interrupts
 4 x DMA channels
Di Jasio - Programming 32-bit Microcontrollers in C
Interrupt Flags & Priorities

The Interrupt Enable bit (typically represented with the name of the interrupt source
peripheral followed by the suffix –IE in the device datasheet), a single bit of data:




The Interrupt Flag (typically represented with a suffix -IF), a single bit of data: is set
each time the specific trigger event is activated, independently of the status of the
enable bit.


Notice how, once set, it must be cleared (manually) by the user. In other words it must be cleared before
exiting the interrupt service routine, or the same interrupt service routine will be immediately called again.
The Group Priority Level (typically represented with a suffix -IP). Interrupts can have up
to 7 levels of priority (from ipl1 to ipl7). Should two interrupt events occur at the same
time, the highest priority event will be served first.




When cleared, the specific trigger event is prevented from generating interrupts.
When set, it allows the interrupt to be processed.
At power on, all interrupt sources are disabled by default.
Three bits encode the priority level of each interrupt source.
At any given point in time, the PIC32 execution priority level value is kept in the MIPS core status-register.
Interrupts with a priority level lower than the current value will be ignored.
At power on, all interrupt sources are assigned a default level of ipl0, once more assuring all interrupts are
disabled.
The Sub-priority Level. Two more bits are allocated to define four more possible levels
of priority within a priority group. If two events of the same priority level occur
simultaneously, the one with the highest sub-priority will be selected first.

Once an interrupt of a given priority group is selected though, any following interrupts of the same level (even
if of higher sub-priority) will be ignored until the current interrupt (flag) has been cleared.
Di Jasio - Programming 32-bit Microcontrollers in C
Interrupt Vectors Table
Natural Order
0 (highest)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
…
56 (lowest)
Macro
Abbreviation
CT
CS0
CS1
INT0
T1
IC1
OC1
INT1
T2
IC2
OC2
INT2
T3
IC3
OC3
INT3
T4
IC4
OC4
INT4
T5
IC5
OC5
SPI1E
SPI1TX
SPI1RX
U1E
U1RX
U1TX
I2C1B
I2C1S
I2C1M
CN
AD1
PMP
CMP1
CMP2
SPI2E
SPI2TX
SPI2RX
U2E
U2RX
U2TX
I2C2B
I2C2S
I2C2M
FSCM
RTCC
DMA0
DMA1
DMA2
DMA3
Di Jasio - Programming 32-bit Microcontrollers in C
FCE
IRQ Symbol
Description
_CORE_TIMER_IRQ
_CORE_SOFTWARE_0_IRQ
_CORE_SOFTWARE_1_IRQ
_EXTERNAL_0_IRQ
_TIMER_1_IRQ
_INPUT_CAPTURE_1_IRQ
_OUTPUT_COMPARE_1_IRQ
_EXTERNAL_1_IRQ
_TIMER_2_IRQ
_INPUT_CAPTURE_2_IRQ
_OUTPUT_COMPARE_2_IRQ
_EXTERNAL_2_IRQ
_TIMER_3_IRQ
_INPUT_CAPTURE_3_IRQ
_OUTPUT_COMPARE_3_IRQ
_EXTERNAL_3_IRQ
_TIMER_4_IRQ
_INPUT_CAPTURE_4_IRQ
_OUTPUT_COMPARE_4_IRQ
_EXTERNAL_4_IRQ
_TIMER_5_IRQ
_INPUT_CAPTURE_5_IRQ
_OUTPUT_COMPARE_5_IRQ
_SPI1_ERR_IRQ
_SPI1_TX_IRQ
_SPI1_RX_IRQ
_UART1_ERR_IRQ
_UART1_RX_IRQ
_UART1_TX_IRQ
_I2C1_BUS_IRQ
_I2C1_SLAVE_IRQ
_I2C1_MASTER_IRQ
_CHANGE_NOTICE_IRQ
_ADC_IRQ
_PMP_IRQ
_COMPARATOR_1_IRQ
_COMPARATOR_2_IRQ
_SPI2_ERR_IRQ
_SPI2_TX_IRQ
_SPI2_RX_IRQ
_UART2_ERR_IRQ
_UART2_RX_IRQ
_UART2_TX_IRQ
_I2C2_BUS_IRQ
_I2C2_SLAVE_IRQ
_I2C2_MASTER_IRQ
_FAIL_SAFE_MONITOR_IRQ
_RTCC_IRQ
_DMA0_IRQ
_DMA1_IRQ
_DMA2_IRQ
_DMA3_IRQ
Core Timer Interrupt
Core Software Interrupt 0
Core Software Interrupt 1
External Interrupt 0
Timer 1 Interrupt
Input Capture 1 Interrupt
Output Compare 1 Interrupt
External Interrupt 1
Timer 2 Interrupt
Input Capture 2 Interrupt
Output Compare 2 Interrupt
External Interrupt 2
Timer 3 Interrupt
Input Capture 3 Interrupt
Output Compare 3 Interrupt
External Interrupt 3
Timer 4 Interrupt
Input Capture 4 Interrupt
Output Compare 4 Interrupt
External Interrupt 4
Timer 5 Interrupt
Input Capture 5 Interrupt
Output Compare 5 Interrupt
SPI 1 Fault
SPI 1 Transfer Done
SPI 1 Receiver Done
UART 1 Error
UART 1 Receiver
UART 1 Transmitter
I2C 1 Bus Collision Event
I2C 1 Slave Event
I2C 1 Master Event
Input Change Interrupt
ADC Convert Done
Parallel Master Port Interrupt
Comparator 1 Interrupt
Comparator 2 Interrupt
SPI 2 Fault
SPI 2 Transfer Done
SPI 2 Receiver Done
UART 2 Error
UART 2 Receiver
UART 2 Transmitter
I2C 2 Bus Collision Event
I2C 2 Slave Event
I2C 2 Master Event
Fail-safe Clock Monitor Interrupt
Real Time Clock Interrupt
DMA Channel 0 Interrupt
DMA Channel 1 Interrupt
DMA Channel 2 Interrupt
DMA Channel 3 Interrupt
_FLASH_CONTROL_IRQ
Flash Control Event
Interrupt Handlers in C
You can declare an Interrupt handler function in C
using one of two syntax options:
 Example using attributes syntax:
void __attribute__ (( interrupt(ipl1),vector(0)))
InterruptHandler( void)
{
// your interrupt service routine code here...
} // interrupt handler

Example using pragma syntax:
#pragma interrupt InterruptHandler ipl1 vector 0
void InterruptHandler( void)
{
// interrupt service routine code here...
} // interrupt handler
Di Jasio - Programming 32-bit Microcontrollers in C
Interrupt Service Macro

A more compact alternative using the predefined macro:
__ISR( v, ipl)

Example:
void __ISR( 0, ipl1) InterruptHandler (void)
{
// interrupt service routine code here...
} // interrupt handler
Di Jasio - Programming 32-bit Microcontrollers in C
“int.h” Support Functions & Macros

INTEnableSystemSingleVectoredInt();


INTEnableSystemMultiVectoredInt();


Same as the above, but enables the vectored interrupt
management mode of the PIC32.
mXXSetIntPriority( x);



This function follows a precise sequence of initialization of the
interrupt control module (as prescribed in the device datasheet)
so to enable the basic interrupt management mode of the PIC32.
This is actually just a placeholder for a long list of similar macros
(replace the XX with the interrupt source abbreviations from
Interrupt Vector Table to obtain each macro name).
It assigns a given priority level (from 0 to 7) to the chosen
interrupt source.
mXXClearIntFlag();

This represents an entire class of macros that allow us to clear
the interrupt flag (–IF bit) of the chosen interrupt source.
Di Jasio - Programming 32-bit Microcontrollers in C
Single.c Example
/*
** Single vector Interrupt test
*/
#include <plib.h>
int count;
void __ISR( 0, ipl1) InterruptHandler( void)
{
count++;
mT2ClearIntFlag();
} // interrupt handler
main()
{
// 1. init timers
PR2 = 15;
T2CON = 0x8030;
// 2. init interrupts
mT2SetIntPriority( 1);
INTEnableSystemSingleVectoredInt();
mT2IntEnable( 1);
// 3. main loop
while( 1);
} // main
Di Jasio - Programming 32-bit Microcontrollers in C
Simulating “single.c”
Di Jasio - Programming 32-bit Microcontrollers in C
Nesting.c Example
/*
** Single Vector Interrupt Nesting
*/
#include <plib.h>
int count;
void __ISR( 0, ipl1) InterruptHandler( void)
{
// 1. re-enable interrupts immediately (nesting)
asm("ei");
// 2. check and serve the highest priority first
if ( mT3GetIntFlag())
{
count++;
// clear the flag and exit
mT3ClearIntFlag();
} // _T3
// 3. check and serve the lower priority
else if ( mT2GetIntFlag())
{
// spend a LOT of time here!
while( 1);
// before clearing the flag and exiting
mT2ClearIntFlag();
} // _T2
} // Interrupt Handler
Di Jasio - Programming 32-bit Microcontrollers in C
Nesting.c Example (cont.)
main()
{
// 4.
PR3 =
PR2 =
T3CON
T2CON
init timers
20;
15;
= 0x8030;
= 0x8030;
// 5. init interrupts
mT2SetIntPriority( 1);
mT3SetIntPriority( 3);
INTEnableSystemSingleVectoredInt();
mT2IntEnable( 1);
mT3IntEnable( 1);
// main loop
while( 1);
} // main
Di Jasio - Programming 32-bit Microcontrollers in C
Interrupt Vector Table
Vector
Number
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
…
44
Vector Symbol
_CORE_TIMER_VECTOR
_CORE_SOFTWARE_0_VECTOR
_CORE_SOFTWARE_1_VECTOR
_EXTERNAL_0_VECTOR
_TIMER_1_VECTOR
_INPUT_CAPTURE_1_VECTOR
_OUTPUT_COMPARE_1_VECTOR
_EXTERNAL_1_VECTOR
_TIMER_2_VECTOR
_INPUT_CAPTURE_2_VECTOR
_OUTPUT_COMPARE_2_VECTOR
_EXTERNAL_2_VECTOR
_TIMER_3_VECTOR
_INPUT_CAPTURE_3_VECTOR
_OUTPUT_COMPARE_3_VECTOR
_EXTERNAL_3_VECTOR
_TIMER_4_VECTOR
_INPUT_CAPTURE_4_VECTOR
_OUTPUT_COMPARE_4_VECTOR
_EXTERNAL_4_VECTOR
_TIMER_5_VECTOR
_INPUT_CAPTURE_5_VECTOR
_OUTPUT_COMPARE_5_VECTOR
_SPI1_VECTOR
_UART1_VECTOR
_I2C1_VECTOR
_CHANGE_NOTICE_VECTOR
_ADC_VECTOR
_PMP_VECTOR
_COMPARATOR_1_VECTOR
_COMPARATOR_2_VECTOR
_SPI2_VECTOR
_UART2_VECTOR
_I2C2_VECTOR
_FAIL_SAFE_MONITOR_VECTOR
_RTCC_VECTOR
_DMA0_VECTOR
_DMA1_VECTOR
_DMA2_VECTOR
_DMA3_VECTOR
_FCE_VECTOR
Di Jasio - Programming 32-bit Microcontrollers in C
Notes
Groups all three SPI1 interrupts
Groups all three UART1 interrupts
Groups all I2C1 interrupts
Groups all three SPI2 interrupts
Groups all three UART2 interrupts
Groups all I2C2 interrupts
Multiple.c Example
/*
** Multiple Vector Interrupt
*/
#include <plib.h>
int count;
void __ISR( _TIMER_3_VECTOR, ipl7) T3InterruptHandler( void)
{
// 1. T3 handler is responsible for incrementing count
count++;
// 2. clear the flag and exit
mT3ClearIntFlag();
} // T3 Interrupt Handler
void __ISR( _TIMER_2_VECTOR, ipl1) T2InterruptHandler( void)
{
// 3. re-enable interrupts immediately (nesting)
asm("ei");
// 4. T2 handler code here
while( 1);
// 5. clear the flag and exit
mT2ClearIntFlag();
} // T2 Interrupt Handler
Di Jasio - Programming 32-bit Microcontrollers in C
Multiple.c Example (cont.)
main()
{
// 5.
PR3 =
PR2 =
T3CON
T2CON
init timers
20;
15;
= 0x8030;
= 0x8030;
// 6. init interrupts
mT2SetIntPriority( 1);
mT3SetIntPriority( 7);
INTEnableSystemMultiVectoredInt();
mT2IntEnable( 1);
mT3IntEnable( 1);
// 7. main loop
while( 1);
} // main
Di Jasio - Programming 32-bit Microcontrollers in C
A Real Time Clock
/*
** A real time clock
**
*/
#include <plib.h>
int dSec = 0;
int Sec = 0;
int Min = 0;
// 1. Timer1 interrupt service routine
void __ISR( 0, ipl1) T1Interrupt( void)
{
// 1.1 increment the tens of a second counter
dSec++;
if ( dSec > 9)
// 10 tens in a second
{
dSec = 0;
Sec++;
// increment the seconds counter
if ( Sec > 59) // 60 seconds make a minute
{
Sec = 0;
Min++;
// increment the minute counter
if ( Min > 59)// 59 minutes in an hour
Min = 0;
} // minutes
} // seconds
// 1.2 clear the interrupt flag
mT1ClearIntFlag();
} //T1Interrupt
Di Jasio - Programming 32-bit Microcontrollers in C
main()
{
// 2.1 init I/Os
DDPCONbits.JTAGEN = 0; // disable JTAG port
TRISA = 0xff00;
// set PORTA LSB as output
// 2.2 configure Timer1 module
PR1 = 25000-1; // set the period register
T1CON = 0x8030;
// enabled, prescaler 1:256, internal clock
// 2.3 init interrupts
mT1SetIntPriority( 1);
mT1ClearIntFlag();
INTEnableSystemSingleVectoredInt();
mT1IntEnable( 1);
// 2.4. main loop
while( 1)
{
// your main code here
PORTA = Sec;
} // main loop
} // main
Di Jasio - Programming 32-bit Microcontrollers in C
Clock.c Simulation
Di Jasio - Programming 32-bit Microcontrollers in C
Using the Secondary Oscillator
// 1. Timer1 interrupt service routine
void __ISR( 0, ipl1) T1Interrupt( void)
{
// 1.1
Sec++;
// increment the seconds counter
if ( Sec > 59) // 60 seconds make a minute
{
Sec = 0;
Min++;
// increment the minute counter
if ( Min > 59)// 59 minutes in an hour
Min = 0;
} // minutes
// 1.2 clear the interrupt flag
mT1ClearIntFlag();
} //T1Interrupt



Change the period register to generate one interrupt every 32,768 cycles
PR1 = 32768-1; // set the period register
Change the Timer1 configuration word (the prescaler is not required anymore)
T1CON = 0x8002;
// enabled, prescaler 1:1, use secondary oscillator
NOTE: Unfortunately you will not be able to immediately test this new configuration
with the simulator since the secondary oscillator input is not fully supported by
MPLAB SIM.
Di Jasio - Programming 32-bit Microcontrollers in C
Using the RTCC module
main()
{
// 2.1 init I/Os
DDPCONbits.JTAGEN = 0; // disable JTAG port
TRISA = 0xff00;
// set PORTA LSB as output
// 2.2 configure RTCC module
RtccInit();
// inits the RTCC
// set present time
rtccTime tm; tm.sec=0x15; tm.min=0x30; tm.hour=01;
// set present date
rtccDate dt;
dt.wday=0; dt.mday=0x15; dt.mon=0x10; dt.year=0x07;
RtccSetTimeDate(tm.l, dt.l);
// set desired alarm to Feb 29th
dt.wday=0; dt.mday=0x29; dt.mon=0x2;
RtccSetAlarmTimeDate(tm.l, dt.l);
// 2.2 init interrupts,
mRTCCSetIntPriority( 1);
mRTCCClearIntFlag();
INTEnableSystemSingleVectoredInt();
mRTCCIntEnable( 1);
// 2.3. main loop
while( 1)
{
// your main code here
// ...
} // main loop
} // main
Di Jasio - Programming 32-bit Microcontrollers in C
Using the RTCC module (Cont.)
// 1. RTCC interrupt service routine
void __ISR( 0, ipl1) RTCCInterrupt( void)
{
// 1.1 your code here, will be executed only once a year
// or once every 365 x 24 x 60 x 60 x 16,000,000 MCU cycles
// that is once every 504,576,000,000,000 MCU cycles
// 1.2 clear the interrupt flag
mRTCCClearIntFlag();
} // RTCCInterrupt
Di Jasio - Programming 32-bit Microcontrollers in C
Download