Sie sind auf Seite 1von 58

Interrupt Basics

Exceptions and Interrupts Interrupts Handlers vs. Subroutines Accept or hold Pending: Priority control Exception vector table Example Karl-Ragmar Riemschneider

Exceptions in H8S/2357

Example for IRQ Input

Interrupt Controller

Interrupt Controller

Two interrupt control Mode 0 or Mode 2: 2 interrupt control modes can be set INTM1 and INTM0 bits in the system control register (SYSCR). Priorities settable with IPR Interrupt priority register (IPR) is provided for setting interrupt priorities. 8 priority levels can be set for all interrupts except NMI. NMI is assigned the highest priority level of 8, and can be accepted at all times. Independent vector addresses All interrupt sources are assigned independent vector addresses No need for interrupt handling routine to determine the source of interrupts.
Comfortable but NOT typical !! Often the handler has to find out the source of the interrupt, see daisy chain principles in the literature of other processors.)

Nine external interrupts IRQ_7 to IRQ_0 + NMI Edge of interrupt signal is selectable:
IRQ_7 to IRQ_0: falling edge, rising edge, or both edge detection, or level sensing. NMI: Rising edge or falling edge.

Interrupt Request (IRQ) Enable Register - IER

Additional switch to enable/disable the IRQ lines Remark: before use one IRQ you have enable this

Interrupt Request (IRQ) Sense Control Registers ISCRH, ISCRL defines the effective event or state on IRQ Pins (falling, rising edge both edges or low level)

Decision Chain in Mode 0

System Control Register SYSCR

System Control Register SYSCR

Bit NMIEG sets the active edge (falling/rising) of the Signal which effects non maskable interrupts NMI

NMI

Interrupt Controller - discussed until now

System Control Register SYSCR


Interrupt Control Mode 0 or 2 is set by INTM1 (and INTM0)

System Control Register SYSCR - Interrupt Control Mode 0 or 2

Setting of Interrupt Control Mode 0 INTM1=0 and INTM0=0 Interrupt acceptance will controlled by One single bit (I bit) in Status Register CCR [Condition Control Register] Function:
I bit set to 1 = allowed interrupts I bit reset to 0 = interrupts not allowed

Setting of Interrupt Control Mode 2 INTM1=1 and INTM0=0 8 interrupt priorities for:
8 external interrupts sources ( = IRQ interrupts) and 16 internal interrupts sources (on-chip supporting module interrupts).

Interrupt control mode 2 is described in the following

Current Status with respect to Exceptions

System Byte

Extended Control Registe

Status Register(s)
Code Condition Register

User Byte

Current Status with respect to Exceptions

Used in Trace Mode resetted in Interrupt handlers

System Byte

Contains the current masked priority set by program (incl. handlers)

Extended Control Registe

Status Register(s)
Code Condition Register

User Byte
Used in Interrupt Control Mode 0

Handling in Interrupt Mode 0

Feature of Exceptions

Each exception is associated with a vector number. This vector number gives the address of an exception vector table entry. An exception vector table is an array of the type long (short jump addresses). The address of an exception vector table entry is the vector number multiplied by 4. Address of an Entry in EVT = Vector number (Index of EVT) x 4.

All the H8S/2357 exception handler start addresses are stored in a table of 92 longwords. This table is reaching from address 0x00 0000 to 0x00 0016F.

Exception Vector Table

Content of Exception Vector Table (summarized)

Priority of Exception Types

11 Interrupt Priority Registers IPRx to set the Priority Level of 21 Exceptions Sources

Initialized to 0x77 that means

set highest Prio-lev

Block of 3 Bit => Prio-level 0 to 7

Block of 3 Bit => Prio-level 0 to 7

Correspondence between interrupt sources and settings in the 11 Interupt Priority Registers IPRx

Interrupt Controller - discussed until now

Phase of Exception Handling

Flowchart of Interrupt Phase 1 (HW


Result: ... ? or ... ?

Two functions: ... ?

and ... ?

Flowchart of Interrupt Phase 1 (HW


Result: Accepted (starting handler) or Held pending (do not start handler)

Two functions: 1) Highest Priority will be at started first (if there more then one with different Priorities) 2) Priority equal or or lower is not accepted (the source is set to held pending)

How handling Interrupts with same Priorities happens at the same time ?

List abridged see Manual if more Info necessary

Interrupt Controller - discussed until now

Interrupt Request Status Register ISR


IRQ Status Register ISR indicates the Status of an IRQ

ISR flag clearing: Cleared by reading IRQnF flag when IRQnF = 1, then writing 0 to IRQnF flag. When interrupt exception handling is executed AND low-level detection is set (IRQnSCB = IRQnSCA = 0) AND IRQn input is high (again). When IRQn interrupt exception handling is executed AND falling, rising, or both edge detection is set (IRQnSCB=1 and/or IRQnSCA = 1). These Flags block the re-entry of the own handler !

ISR Flag clearing

Memory Map in the Evaluation-Board (EVB) in Lab


Firmware (download, upload, serial communication, debugg ...)

Not allowed to write there

C Areas

Example of Shadow EVT

Phase as Result of Rotation Direction

One Page Example -Task

Task: Detect the Direction of Rotation ! Input: one the digital light barrier signal for interrupting the other digital light barrier signal will be polled Output: output clockwise rotation with one LED output counterclockwise rotation with one other LED Control: stop with one manual switched High Level on one Pin

One Page Example

S1, S0 Digital Input Signals

P4(2) Stop manual switch

Port(1) and P5(0) Output to LED

One Page Example - Rules I


#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }
pre-definitions in header files ....

else

direction = 1;

void main(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ changes independent 0x00; /* initialize Output Clockwise = Countercl. = 0 */ P5DR= of program flow => instruction to compiler SYSCR|= 0x20; /* Interrupt mode 2 */ nothing to optimize IPRA = 0x30; /* Priority 3 for IRQ_0 */ ISCRL = 0x02; /* Rising edge of IRQ_0 */ SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ and_exr(0xF8); /* Mask level = 0 */ IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signal */ IER & = 0xF; /* Disable IRQ_0 interrupt */ }

define a global buffer to communicate between main() and IRQ0hnd

One Page Example - Rules II


#include <mpp1.h> volatile unsigned char direction;
free indentifier name

interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }


no return value

no parameters !

else

direction = 1;

void interrupt pragmamain(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ P5DR= 0x00; /* initialize Output Clockwise = Countercl. = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ IPRA = 0x30; /* Priority 3 for IRQ_0 */ ISCRL = 0x02; /* Rising edge of IRQ_0 */ SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ and_exr(0xF8); /* Mask level = 0 */ IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signal */ IER & = 0xF; /* Disable IRQ_0 interrupt */ }

One Page Example - Rules III


#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }
Two bits as Outputs

No output at first

else

direction = 1;

void main(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ P5DR= 0x00; /* initialize Output Clockwise = Countercl. = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ IPRA = 0x30; /* Priority 3 for IRQ_0 */ ISCRL = 0x02; /* Rising edge of IRQ_0 */ SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ and_exr(0xF8); /* Mask level = 0 */ IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signal */ IER & = 0xFE; /* Disable IRQ_0 interrupt */ }

One Page Example - Rules III


#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }
Interrupt mode 2 = prioritized Interrupts Give the signal IRQ3 the priority 3

else

Determine the direction = 1; active edge of IRQ0

void main(void) { Entry pointer (start address) P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ of a self defined handler P5DR= 0x00; /* initialize Output Clockwise = Countercl. EVT (SVT) in Shadow = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ at IRQ_O number ! IPRA = 0x30; /* Priority 3 for IRQ_0 */ write the Opcode of unconditional ISCRL = 0x02; /* Rising edge of IRQ_0 */ Jump Opcode SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ before the start addresses SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ and_exr(0xF8); /* Mask level = 0 */ IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise 0*/EXR Bit 2, Bit 1, Bit 0 Write in without changes of the other bits ! /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signal */ IER & = 0xF; /* Disable IRQ_0 interrupt */ Last step of initialization: Enable the IRQ_0 signal }

One Page Example - Rules IV


#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }

else

Start busy waiting & output direction = 1; loop

Test the content of the global buffer void main(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ P5DR= 0x00; /* initialize Output Clockwise = Countercl. = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ IPRA = 0x30; /* Priority 3 for IRQ_0 */ Output P5DR = 0000 0010 (binary) ISCRL = 0x02; /* Rising edge of IRQ_0 */ SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ Output P5DR = 0000 0001 (binary) and_exr(0xF8); /* Mask level = 0 */ Check one Pin: P4(2) IER |=0x01; /* Enable IRQ_0 interrupt */ if high leave the loop do { else loop again if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ of using interrupts is Last step disabling /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signalprevents not wished handler */ starts for the future IER & = 0xF; /* Disable IRQ_0 interrupt */ (here disable the IRQ_0) }

One Page Example - Rules IV

#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }
Start busy waiting & output loop

else

direction = 1;

void main(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ Test the content of the global buffer P5DR= 0x00; /* initialize Output Clockwise = Countercl. = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ IPRA = 0x30; /* Priority 3 for IRQ_0 */ Output P5DR = 0000 0010 (binary) ISCRL = 0x02; /* Rising edge of IRQ_0 */ Output SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ P5DR = 0000 0001 (binary) SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ Check one Pin: P4(2) and_exr(0xF8); /* Mask level = 0 */ if high leave the loop else loop again IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ /* ... */ /* Execute additional tasks*/ Last step of using interrupts is disabling } while(PORT4 & 0x04 == 0); /* while no stop signal */
(here disable the IRQ_0)

One Page Example - Completed


#include <mpp1.h> volatile unsigned char direction; interrupt void IRQ0hnd(void) { if(PORT4 & 0x01 == 0) direction = 0; }

else

direction = 1;

void main(void) { P5DDR= 0x03; /* P5(1) and P5(0) as outputs */ P5DR= 0x00; /* initialize Output Clockwise = Countercl. = 0 */ SYSCR|= 0x20; /* Interrupt mode 2 */ IPRA = 0x30; /* Priority 3 for IRQ_0 */ ISCRL = 0x02; /* Rising edge of IRQ_0 */ SHADOW_IH(IRQ_0) = IRQ0hnd; /* Update shadow EVT */ SHADOW_JMP(IRQ_0)= OPCODE_JMP; /* Add the JMP instruction */ and_exr(0xF8); /* Mask level = 0 */ IER |=0x01; /* Enable IRQ_0 interrupt */ do { if (direction == 0) P5DR= 0x02; /* Clockwise */ else P5DR = 0x01; /* Counterclockwise */ /* ... */ /* Execute additional tasks*/ } while(PORT4 & 0x04 == 0); /* while no stop signal */ IER & = 0xF; /* Disable IRQ_0 interrupt */ }

Golden Rules for Exception Handler Writing

Dont modify any general purpose register CPU pushes no registers automatically for interrupts ! Assembler: Push the needed registers
(and pop them at end - under all circumstances)

C: Use local Variables only if really needed (Interrupt latency time !!) Keep Handlers short ! Avoid Nested Interrupts ! => Priority /Level change in Handler could be dangerous Dont forget Re-enable or Unmask Interrupts !!! Assembler : Use the proper Return instruction RTE => NOT RTS !! Stop Interrupts if not more in use