Net Burner 5282 MCF 5282 Cold Fire Micro
Net. Burner 5282 MCF 5282 Cold. Fire Micro. Controller Interrupt System
Net. Burner Mod 5282 Memory Map
TRAP Instruction
RTE Instruction
Stack (SP)-4 --> Register storage begins here ^ ------(SP) --> Format/Offset {7, 6, 5, 4}={1111}, {3, 2, 1, 0}=vector (? ) (SP)+2 --> SR - Status Register (SP)+6 --> PC - Program Counter ------(SP)+10 --> Top of Stack before TRAP ----High Memory
Typical Interrupt System Model CPU with: Interrupt Request Arbitration and Interrupt Acknowledgement Cycle Runs in supervisor mode during the execution of the ISR I/O Device(s) with BUS Communication Support Registers, e. g. 8 bit Data Register 8 bit Control Register with: Ready/Done bit Interrupt Enable bit 8 bit Vector Register with: ISR (interrupt Service Routine) Vector Number Main program that sets up: I/O Control Register Vector Register with address of ISR program, that ends with an RTE instruction
MCF 5282 Interrupt System Software: Main Program Interrupt Service Routine (ISR) Hardware: Device that can initiate an Interrupt (e. g. an A/D Converter) Edge Port Module (EPORT) {Chap 11 – MCF 5282 User’s Manual} Contains the interrupt support control register data Arbitrates interrupt requests, Interrupt Control Module(s) { Chap 10 – MCF 5282 User’s Manual} Provides the equivalent of the TRAP functionality, and Provides CPU with ISR address Support functions: Set. Intc( ) – Sets up the Interrupt Control Module INTERRUPT macro – Provides the messy code for the service routine
Procedure for Interrupt handling Application • Review your system architecture and determine which interrupt level (1 -7) is appropriate. Level 1 is the lowest priority, level 7 is the highest. Use caution with level 7, since it is unique in that it is a non-maskable interrupt. If you use level 7, the ISR cannot call any u. COS functions, or use the INTERRUPT( ) macro. • Write an Interrupt Service Routine (ISR). If you are using IRQ 1 – 6, use the INTERRUPT( ) macro to make coding the ISR easier. If you are using the level 7 unmaskable IRQ, then you must write the program code to save and restore the CPU registers. • Call the Set. Intc( ) function to set up the interrupt vector, level and priority. The function should be called prior to any interrupts occurring.
Edge Port Module (From MCF 5282 User’s Manual)
Interrupt Control Module (From: MCF 5282 User’s Manual) etc.
Net. Burner Hardware
Example program – IRQ Pushbuttom activates IRQ 1 #include #include "predef. h" <stdio. h> <ctype. h> <startnet. h> <autoupdate. h> <dhcpclient. h> <. . /mod 5282/system/sim 5282. h> <cfinter. h> /* An interrupt setup helper defined in bsp. c */ extern "C" { void Set. Intc(int intc, long func, int vector, int level, int prio ); } OS_SEM Irq. Post. Sem; /* Function sets up the 5282 interrupt controller */ /* Semaphore to communicate between the IRQ 1 pin ISR and the main application */ /* Declare our interrupt procedure. . name: our_irq 1_pin_isr masking level (The value of the Cold. Fire SR during the interrupt: use 0 x 2700 to mask all interrupts. 0 x 2500 to mask levels 1 -5 etc. . . 0 x 2100 to mask level 1 */ INTERRUPT(out_irq 1_pin_isr, 0 x 2100 ) { /* WARNING Only a very limited set of RTOS functions can be called from within an interrupt service routine. Basically, only OS POST functions and LED functions should be used. No I/O (read, write or printf may be called), since they can block. */ sim. eport. epfr=0 x 02; /* Clear the interrupt edge 0 0 0 1 0 */ OSSem. Post(&Irq. Post. Sem); }
Example program – IRQ Pushbuttom activates IRQ 1 (cont) extern "C" { void User. Main(void * pd); void putdisp(unsigned short w); } /* Helper function to display a decimal number */ void Put. Disp. Decimal(WORD val, BOOL blank_zero ) { WORD w; w = (val / 1000) * 0 x 1000; if ((w == 0) && (blank_zero)) w = 0 x. F 000; w += ((val / 100)% 10) * 0 x 0100; if (w == 0 x. F 000) w = 0 x. FF 00; w += ((val / 10)% 10) * 0 x 0010; if (w == 0 x. FF 00) w = 0 x. FFF 0; w += ((val )% 10) * 0 x 0001; putdisp(w); }
Example program – IRQ Pushbuttom activates IRQ 1 (cont) void User. Main(void * pd) { Initialize. Stack(); if (Ethernet. IP==0)Get. DHCPAddress(); OSChange. Prio(MAIN_PRIO); Enable. Auto. Update(); DWORD isr_count=0; /* Count how many times the switch was hit */ /* Initialize the semaphore we are using */ OSSem. Init(&Irq. Post. Sem, 0); /* First set up the Eport module to use IRQ 1 as a falling-edge active IRQ pin (See the 5282 UM chapter 11). Set the pin assignment register irq 1 pin falling edge sensitive. */ sim. eport. eppar=0 x 0008; /* 00 00 00 10 00 see table 11 -3 in UM */ sim. eport. epddr=0 x 0; /* All edge port pins as inputs */ sim. eport. epier = 0 x 0002; /* Enable IRQ 1 only 0 0 0 1 0 */ /* Now enable the actual interrupt controller. See users manual chapter 10 for more information. We are going to use the BSP helper function declared above and implemented in BSP. c */ Set. Intc(0, /* The first interrupt controller */ (long)&out_irq 1_pin_isr, /* Our interrupt function */ 1, /* The vector number from the users manual table 10 -13 */ 1, /* Set this to priority 1 but any value from 1 to 6 would be valid. */ 1 /* The priority within the gross levels; see chapter 10, any value from 0 to 7 is ok */ ); iprintf("Application startedn"); iprintf("Press the IRQ button on the development board. n"); while (1) { OSSem. Pend(&Irq. Post. Sem, 0 /* Wait forever */); Put. Disp. Decimal(++isr_count, true); iprintf("The interrupt Switch was hit %ld timesrn", isr_count); } }
Set up 5282 Controller extern “C” { /* This function sets up the 5282 interrupt controller */ void Set. Intc(int intc, long func, int vector, int level, int prio); }
INTERRUPT macro is provided in the header: #include <cfinter. h> You can add some unique functionality to it.
SR - Status Register
Edge Port Module Names and Addresses (From Header File: #include <. . /mod 5282/system/sim 5282. h>) #define MBASE 0 x 40000000 /* Module Base Address*/. . typedef struct { /* edge port module */ vuword eppar; vubyte epddr; vubyte epier; vubyte epdr; vubyte epfr; } eportstruct ; . . /* /* /* 130000 ->130001 130002 ->130002 130003 ->130003 130004 ->130004 130005 ->130005 130006 ->130006 eport eport pin assignment register */ data direction register */ interrupt enable register */ data register */ pin data register */ flag register */
Edge Port Module
Flag Register
Pin Assignment Register
Data Direction Register
Interrupt Enable Register
Set up 5282 Controller extern “C” { /* This function sets up the 5282 interrupt controller */ void Set. Intc(int intc, long func, int vector, int level, int prio); }
Example of Level 7 Interrupt Service Routine /* The extern directive If you are crating a extern "C" { void NMI_C_Part(); void NMI_ASM_Part(); } is only needed if you are creating this code in a. cpp file; . c file, do not include the extern section. */ // The part of the ISR written in C/C++ // The part of the ISR written in Assembly /* The "Function_Holder()" is just a place holder so we can create some inline assembly language code. */ void Function_Holder() { __asm__ (". global NMI_ASM_Part"); // export the label for ASM part __asm__ (". extern NMI_C_Part"); // label for the C part of the ISR __asm__ (“NMI_ASM_Part: ”); // label for the assembly part of the ISR __asm__ (" move. w #0 x 2700, %sr "); // set the IRQ mask to mask all __asm__ (" lea -60(%a 7), %a 7 "); // make space on the system stack __asm__ (" movem. l %d 0 -%d 7/%a 0 -%a 6, (%a 7) "); // save all registers __asm__ (" jsr NMI_C_Part "); __asm__ (" movem. l (%a 7), %d 0 -%d 7/%a 0 -%a 6 "); __asm__ (" lea 60(%a 7), %a 7 "); __asm__ (" rte"); } /* This is the C/C++ part of the ISR that is called from the assembly code */ void NMI_C_Part() { // Your C/C++ application code goes here }
- Slides: 25