180 likes | 288 Views
ECE 353 Introduction to Microprocessor Systems. Discussion 11. Topics. Interrupts and Exceptions Q&A. Interrupts and Exceptions. The ADuC7026 defines locations for each exception vector – the code must put the proper instructions there to handle each exception. Table 2-4
E N D
ECE 353Introduction to Microprocessor Systems Discussion 11
Topics • Interrupts and Exceptions • Q&A
Interrupts and Exceptions • The ADuC7026 defines locations for each exception vector – the code must put the proper instructions there to handle each exception. Table 2-4 • ADuc7026.s places the address of the IRQ handler in the proper vector location. • Exception.s contains the actual exception handler routines. • The interrupt checklist posted on the course web page gives guidelines of what needs to be done to correctly handle interrupts. • The ADuC7026 has 23 sources of interrupts. Table 72
Interrupt Problem • Assume that the CPU is being clocked at 41.78MHz (32768Hz x 1275). Set up timer #1 to generate a periodic interrupt at a frequency of 3.2kHz. Produce an output on pin 4.0 that will have a duty cycle given by duty/32, where duty is a byte memory variable. The ISR can only make one change to the P4.0 state in each invocation. Only use the five least significant bits of duty.
Answer • Requirements: • Timer – setup to give a 3.2 kHz periodic interrupt • Timer ISR – use to handle generating the proper output • Variables – Count (for timer period tracking) and Duty (for setting the duty cycle) • Output pin – P4.0
Answer • In Main, we need: • Setup GPIO for P4.0 • Setup Timer1 • Setup ISR • Initialize variables • In ISR, we need: • Update count • Update output
Answer • Variables: • Count – to get duty cycle increments of 1/32, we need to keep track of Timer ISR occurrences – Count will need values of 1-31. • Each execution of the Timer ISR will need to increment or decrement Count, and if it reaches the limit, reload the start count. • Duty – Duty will be set in main – will determine how many of the 32 occurrences of the Timer ISR in one period will need to set the output high. (Timer ISR will not modify this variable.)
Answer • Timer1 config: • System clock at 41.7792 MHz means clock period of 23.935 ns. • Timer frequency of 3.2 kHz means timer period of 312.5 us. • Using divide by one, we need a T1LD value of 312.5 us/23.935 ns = 13056 • ISR config: • CLR Timer 1 IRQ • Enable Timer 1 IRQ • Enable global IRQ bit in CPSR (use MSR and MRS instructions) • GPIO config: • Set GPIO P4.0 as GPIO, output • Initialize P4.0 to zero
Answer • ISR details: • Get Count and Duty variables • Test: if Count < Duty, then P4.0 = 1, else P4.0 = 0 • If Count == 0, then Count = 31, else Count = Count - 1 • Store updated Count
ConcepTest • What is the frequency of the output waveform? • 3.2 kHz / 32 = 100 Hz • What is the minimum average value? • 0 • What is the maximum average value? • 31/32 = 0.96875 • To achieve 1.0, we would need to relax the restriction on the bits of Duty to allow using 6-bits so we could go 0 – 32.
Answer Code: Main.s • ; Filename: main11.s • ; Author: ECE 353 Staff • ; Description: main program file for discussion 11 • ARM ;use ARM instruction set • EXPORT __main • EXPORT Count • EXPORT Duty • INCLUDE aduc7026.inc • ;count down, periodic, binary, source/1 • T1CON_VALUE EQU 0x000000C0 • ;need interrupt every 312.5 us with 41.7792 MHz clock • T1_PERIOD EQU 13056 • ;timer1 interrupt • TMR1_IRQ_EN EQU 0x00000008 • AREA SRAM, DATA, READWRITE • ; variables for timerISR • DCount DCD 0x0 ;timer ISR counter • DDuty DCD 0x0 ;duty cycle parameter
Answer Code: Main.s (cont.) • AREA FLASH, CODE, READONLY • __main • ; setup GPIO pin 4.0 as output, initially zero • LDR R7, =(GPIO_MMR_BASE) ;MMR base address • MOV R0, #0x00 • LDR R1, [R7, #GP4CON] ;get P4 as GPIO • BIC R1, R1, #3 ; • STR R1, [R7, #GP4CON] ;set P4.0 as GPIO • LDR R1, [R7, #GP4DAT] ;get P4 as GPIO • ORR R1, R1, #0x01000000 ;set P4.0 as output • BIC R1, R1, #0x00010000 ;set P4.0 as zero • STR R1, [R7, #GP4DAT] • ; intitialize variables • LDR R7, =(DCount) ;count address • MOV R0, #31 • STR R0, [R7] ;store initial count value • LDR R7, =(DDuty) ;duty cycle variable address • MOV R0, #20 • STR R0, [R7] ;store initial duty cycle value
Answer Code: Main.s (cont.) • ; setup timer1 • LDR R7, =(TIMER_MMR_BASE) ;register base • LDR R0, =(T1_PERIOD) • STR R0, [R7, #T1LD] ;set timer period • LDR R0, =(T1CON_VALUE) • STR R0, [R7, #T1CON] ;configure timer • ; setup interrupt • LDR R7, =(IRQCON_MMR_BASE) ;register base • MOV R0, #TMR1_IRQ_EN • STR R0, [R7, #IRQCLR] ;clear timer1 interrupt • STR R0, [R7, #IRQEN] ;enable timer1 interrupt • MRS R1, CPSR ; read CPSR • BIC R1, R1, #0x80 ;clear bit7 - IRQ disable bit • MSR CPSR_c, R1 ; enable IRQs • spin • B spin • Count DCD DCount • Duty DCD DDuty • END
Answer Code: Exception.s • INCLUDE ADuC7026.inc ;MMR definitions • IMPORT Duty • IMPORT Count • IRQ_Handler • PUSH {R0-R4} ;context save • LDR R2, Duty • LDR R0, [R2] ;get current duty cycle • LDR R2, Count • LDR R1, [R2] ;get current count • LDR R3, =(GPIO_MMR_BASE) • LDR R4, [R3, #GP4DAT] ;get P4 as GPIO • CMP R1, R0 ; Count less than Duty - put out one • BICPL R4, R4, #0x00010000 ;set P4.0 to zero • ORRMI R4, R4, #0x00010000 ;set P4.0 to one • STR R4, [R3, #GP4DAT] • MOVS R1, R1 ;set flags • MOVEQ R1, #31 ;count at zero - reload • SUBNE R1, R1, #1 ;count not zero - decrement • STR R1, [R2] ;store updated count • ;interrupt stuff • LDR R3, =(TIMER_MMR_BASE) ;timer MMR base address • MOV R1, #0xFF • STRB R1, [R3, #T1CLRI] ;reset timer1 interrupt • POP {R0-R4} ;context restore • SUBS PC, LR, #4 ;interrupt return