6 – conditional returns, 8 – handling interrupts, Ds4830a user’s guide – Maxim Integrated DS4830A Optical Microcontroller User Manual
Page 199
DS4830A User’s Guide
199
If opting to preload the loop address to an internal 16-bit register, the most time and code efficient means is by
performing the load in the instruction just prior to the top of the loop:
move LC[1], #10h
; Set loop counter to 16
move LC[0], IP
; Set loop address to the next address
LoopTop:
; loop addr not relative to djnz LC[n],src
...
23.7.6 – Conditional Returns
Similar to the conditional jumps, the DS4830A microcontroller also supports a set of conditional return operations.
Based upon the value of one of the status flags, the CPU can conditionally pop the stack and begin execution at the
address popped from the stack. If the condition is not true, the conditional return instruction does not pop the stack
and does not change the instruction pointer. The following conditional return operations are supported:
RET C
; if C=1, a RET is executed
RET NC
; if C=0, a RET is executed
RET Z
; if Z=1 (Acc=00h), a RET is executed
RET NZ
; if Z=0 (Acc<>00h), a RET is executed
RET S
; if S=1, a RET is executed
23.8
–
Handling Interrupts
Handling interrupts in the DS4830A microcontroller is a three-part process.
First, the location of the interrupt handling routine must be set by writing the address to the 16-bit Interrupt Vector
(IV) register. This register defaults to 0000h on reset, but this will usually not be the desired location since this will
often be the location of reset / power-up code.
move IV, IntHandler
; move PFX[0], #high(IntHandler)
; move IV, #low(IntHandler)
; PFX[0] write not needed if IntHandler addr=0023h
Next, the interrupt must be enabled. For any interrupts to be handled, the IGE bit in the Interrupt and Control register
(IC) must first be set to 1. Next, the interrupt itself must be enabled at the module level and locally within the module
itself. The module interrupt enable is located in the Interrupt Mask register, while the location of the local interrupt
enable will vary depending on the module in which the interrupt source is located.
Once the interrupt handler receives the interrupt, the Interrupt in Service (INS) bit will be set by hardware to block
further interrupts, and execution control is transferred to the interrupt service routine. Within the interrupt service
routine, the source of the interrupt must be determined. Since all interrupts go to the same interrupt service routine,
the Interrupt Identification Register (IIR) must be examined to determine which module initiated the interrupt. For
example, the II0 (IIR.0) bit will be set if there is a pending interrupt from module 0. These bits cannot be cleared
directly; instead, the appropriate bit flag in the module must be cleared once the interrupt is handled.
INS is set automatically on entry to the interrupt handler and cleared automatically on exit (RETI).
IntHandler:
push PSF
; save C since used in identification process
move C, IIR.X
; check highest priority flag in IIR
jump C, ISR_X
; if IIR.X is set, interrupt from module X
move C, IIR.Y
; check next highest priority int source
jump C, ISR_Y
; if IIR.Y is set, interrupt from module Y
...
ISR_X:
...
reti
To support high priority interrupts while servicing another interrupt source, the IMR register may be used to create a
user-defined prioritization. The IMR mask register should not be utilized when the highest priority interrupt is being
serviced because the highest priority interrupt should never be interrupted. This is default condition when a hardware
branch is made the Interrupt Vector address (INS is set to 1 by hardware and all other interrupt sources are blocked).
The code below demonstrates how to use IMR to allow other interrupts.
ISR_Z:
pop PSF
; restore PSF
push IMR
; save current interrupt mask
move IMR, #int_mask
; new mask to allow only higher priority ints
move INS, #0
; re-enable interrupts