Sie sind auf Seite 1von 12

ELEC 3040/3050

Lab 4
Double Counters
Using Interrupt-Driven I/O

Goals of this lab exercise

Add an additional counter to count upon interruptdriven input/output (I/O)


Last week software controlled timing of data
transfers

CPU in an endless loop scanning the switches


Difficult to respond in the middle of delay loop

This week push-button should interrupt the CPU


when it is pressed

Allows CPU to do other tasks when the push-button is idle


Increment the ISR counter only when the PB is pressed

MC9S12C32 Interrupts

Two external interrupt pins on the MC9S12C32 are


tested after each instruction:

IRQ# (interrupt request)

Logically ANDed with I (interrupt flag) in the processors


Condition Code Register (CCR)
When I=1, IRQ# is masked or disabled
(this is the power-on condition)
When IF=0, IRQ# is unmasked or enabled
ANDCC #%11101111 clears I=0; C function EnableInterrupts;
ORCC #%00010000 sets I=1; C function DisableInterrupts;

XIRQ# (non-maskable interrupt)

Logically ANDed with X (non-maskable interrupt flag) in the


processors Condition Code Register (CCR)
Once X cleared to 0, to enable interrupts, it cannot be reset
again, so interupts cannot be disabled

IRQ# operation

IRQ# is active-low, and can be configured


as either level-sensitive or edge-triggered

Level-sensitive => signal must be at its active


level when checked by the CPU
Must be held active until acknowledged by the CPU
Must be deactivated when acknowledged to prevent
multiple interrupts
Momentary activations might go unnoticed
(including activations while I=0)

Edge-triggered => an active transition on the


signal sets a flip-flop in the CPU that remains
set until the CPU acknowledges the interrupt

CPU interrupt response


1.
2.
3.
4.

Suspend the current task


Save the state of the CPU (registers) on the stack
Set I=1 to mask additional interrupts
Fetch an interrupt vector from the interrupt vector
table to jump to interrupt service routine (ISR)

ISR deals with the interrupting device/event, and is unique to


each device/event type
Interrupt vector is the starting address of an ISR (PC value)
Interrupt vector table is stored in memory, ending at $FFFF

1.

Execute the ISR

1.

Resume the suspended task

HC12 Interrupt Vector Table


Vector Address

Interrupt Source

$FFFE

Reset

$FFFC

Clock monitor failure reset

$FFFA

COP failure reset

$FFF8

Unimplemented instruction trap

$FFF6

SWI

$FFF4

XIRQ

$FFF2

IRQ

$FFF0

Real time interrupt

$FFEE

Capture timer channel 0

etc.

Complete table in Cady text & MC9S12C32 ref manual (pg 61)

Guidelines for writing ISRs

Assembly language: HC12 automatically saves/restores


all CPU registers

Terminate ISR with RTI (return from interrupt) in


assembly language

Restores CPU registers from stack

Cannot predict what the CPU is doing when an interrupt


occurs, so data for an ISR must come from global
variables, and not from:

not necessarily so on other CPUs

CPU registers (used by interrupted program)


C variables local to an interrupted program (created in the stack)
Cannot always predict what program/subprogram might be
running

Can reset I=0 within an ISR to allow nested interrupts

Initialization for interrupt support

Recall that I=1 at power-on/reset


Create the interrupt vector table entry for all
Assembly language:
org $fff2
dc.w irq_routine

;address of IRQ# vector


;IRQ# vector

C: declare function as an ISR:

interrupt void IRQ_ISR(void) {}

C: add file isr_vectors.c to your project (from class web)


1. Add your function prototype(s) at top of file:
extern void near IRQ_ISR(void);
2. Change UnimplementedISR to your ISR function name
(IRQ_ISR) for each vector(s) used in your project

Initialize any data (globals) needed for isr


Enable interrupts when everything is ready

Assembly language: andcc #%11101111


C function: EnableInterrupts;

//EXAMPLE: isr_vectors.c file (excerpt)


extern void near _Startup(void);
extern void near SWI_ISR(void);

/* Startup routine */
/* My SWI ISR
*/

#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this


module. Placement will be in NON_BANKED area. */
__interrupt void UnimplementedISR(void)
{
/* Unimplemented ISRs trap.*/
asm BGND;
}
typedef void (*near tIsrFunc)(void);
const tIsrFunc _vect[] @0xFF80 = {
UnimplementedISR,

UnimplementedISR,
SWI_ISR,
UnimplementedISR,
UnimplementedISR,
UnimplementedISR,
//_Startup
};

/* Interrupt table */
/* vector 63 */
/* vector 05 */
/* vector 04 */ SWI is Vector 4
/* vector 03 */
/* vector 02 */
/* vector 01 */
/* Reset vector */ COMMENT OUT

Conventions for C in CodeWarrior


#include <hidef.h>
/* common defines and macros */
#include <mc9s12c32.h>
/* derivative information */
/* global variables definitions here */
/* Define the interrupt service routine */
interrupt void IRQ_ISR(void) {
... instructions for the interrupt service
}
/* Define the main program */
void main(void) {
... initialize variables/devices/registers
INTCR_IRQE = 1; /* edge-triggered interrupts */
EnableInterrupts;
/* enable interrupts */
... instructions for the main program
}

Lab Experiment

Modify HW to interrupt the CPU when PB1 is


pressed (I/O ports should be the same)

Use IRQ# interrupt input pin (Port E, bit 1)

SW should include a main program and the Push


Button ISR

The main program should do all initialization and then


enter an endless loop in which a count is written to the
7-segment display about once per second

Note that all column lines should be low until an interrupt


occurs

The ISR should increment in PB counter & display the


current value of it for 5 seconds on the 7-seg display.

Set a variable so the main program will not disturb the 7segment display for about 5 seconds after an interrupt

Debug suggestions

The ISR can write a unique pattern to LEDs or 7segment display to indicate that it was entered
Display the ISR counter on the other display to ensure it
is counting properly upon ISR execution
Global variables can be modified by the ISR to indicate
that the ISR was executed
An unimplemented ISR error, detected by the
debugger, indicates that there was no interrupt vector in
the vector table

Das könnte Ihnen auch gefallen