1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
|
;**************************************************************************
; arch/z80/src/ez80/ez80_vectors.asm
;
; Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
; Author: Gregory Nutt <gnutt@nuttx.org>
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in
; the documentation and/or other materials provided with the
; distribution.
; 3. Neither the name NuttX nor the names of its contributors may be
; used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
; OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
;**************************************************************************
;**************************************************************************
; Constants
;**************************************************************************
NVECTORS EQU 64 ; max possible interrupt vectors
;* Bits in the Z80 FLAGS register *****************************************
EZ80_C_FLAG EQU 01h ; Bit 0: Carry flag
EZ80_N_FLAG EQU 02h ; Bit 1: Add/Subtract flag
EZ80_PV_FLAG EQU 04h ; Bit 2: Parity/Overflow flag
EZ80_H_FLAG EQU 10h ; Bit 4: Half carry flag
EZ80_Z_FLAG EQU 40h ; Bit 5: Zero flag
EZ80_S_FLAG EQU 80h ; Bit 7: Sign flag
;* The IRQ number to use for unused vectors
EZ80_UNUSED EQU 40h
;**************************************************************************
; Global Symbols Imported
;**************************************************************************
xref _ez80_startup
xref _up_doirq
;**************************************************************************
; Global Symbols Exported
;**************************************************************************
xdef _ez80_reset
xdef _ez80_initvectors
xdef _ez80_handlers
xdef _ez80_rstcommon
xdef _ez80_initvectors
xdef _ez80_vectable
;**************************************************************************
; Macros
;**************************************************************************
; Define one reset handler
; 1. Disable interrupts
; 2. Dlear mixed memory mode (MADL) flag
; 3. jump to initialization procedure with jp.lil to set ADL
rstvector: macro
di
rsmix
jp.lil _ez80_startup
endmac rstvector
; Define one interrupt handler
irqhandler: macro vectno
; Save AF on the stack, set the interrupt number and jump to the
; common reset handling logic.
; Offset 8: Return PC is already on the stack
push af ; Offset 7: AF (retaining flags)
ld a, #vectno ; A = vector number
jp _ez80_rstcommon ; Remaining RST handling is common
endmac irqhandler
;**************************************************************************
; Reset entry points
;**************************************************************************
define .RESET, space = ROM
segment .RESET
_ez80_reset:
_rst0:
rstvector
_rst8:
rstvector
_rst10:
rstvector
_rst18:
rstvector
_rst20:
rstvector
_rst28:
rstvector
_rst30:
rstvector
_rst38:
rstvector
ds %26
_nmi:
retn
;**************************************************************************
; Startup logic
;**************************************************************************
define .STARTUP, space = ROM
segment .STARTUP
.assume ADL=1
;**************************************************************************
; Interrupt Vector Handling
;**************************************************************************
; Symbol Val VecNo Addr
;----------------- --- ----- -----
_ez80_handlers:
irqhandler 0 ; EZ80_EMACRX_IRQ 0 0 0x040
handlersize equ $-_ez80handlers
irqhandler 1 ; EZ80_EMACTX_IRQ 1 1 0x044
irqhandler 2 ; EZ80_EMACSYS_IRQ 2 2 0x048
irqhandler 3 ; EZ80_PLL_IRQ 3 3 0x04c
irqhandler 4 ; EZ80_FLASH_IRQ 4 4 0x050
irqhandler 5 ; EZ80_TIMER0_IRQ 5 5 0x054
irqhandler 6 ; EZ80_TIMER1_IRQ 6 6 0x058
irqhandler 7 ; EZ80_TIMER2_IRQ 7 7 0x05c
irqhandler 8 ; EZ80_TIMER3_IRQ 8 8 0x060
irqhandler EZ80_UNUSED ; 9 0x064
irqhandler EZ80_UNUSED+1 ; 10 0x068
irqhandler 9 ; EZ80_RTC_IRQ 9 11 0x06C
irqhandler 10 ; EZ80_UART0_IRQ 10 12 0x070
irqhandler 11 ; EZ80_UART1_IRQ 11 13 0x074
irqhandler 12 ; EZ80_I2C_IRQ 12 14 0x078
irqhandler 13 ; EZ80_SPI_IRQ 13 15 0x07c
irqhandler 14 ; EZ80_PORTA0_IRQ 14 16 0x080
irqhandler 15 ; EZ80_PORTA1_IRQ 15 17 0x084
irqhandler 16 ; EZ80_PORTA2_IRQ 16 18 0x088
irqhandler 17 ; EZ80_PORTA3_IRQ 17 19 0x08c
irqhandler 18 ; EZ80_PORTA4_IRQ 18 20 0x090
irqhandler 19 ; EZ80_PORTA5_IRQ 19 21 0x094
irqhandler 20 ; EZ80_PORTA6_IRQ 20 22 0x098
irqhandler 21 ; EZ80_PORTA7_IRQ 21 23 0x09c
irqhandler 22 ; EZ80_PORTB0_IRQ 22 24 0x0a0
irqhandler 23 ; EZ80_PORTB1_IRQ 23 25 0x0a4
irqhandler 24 ; EZ80_PORTB2_IRQ 24 26 0x0a8
irqhandler 25 ; EZ80_PORTB3_IRQ 25 27 0x0ac
irqhandler 26 ; EZ80_PORTB4_IRQ 26 28 0x0b0
irqhandler 27 ; EZ80_PORTB5_IRQ 27 29 0x0b4
irqhandler 28 ; EZ80_PORTB6_IRQ 28 20 0x0b8
irqhandler 29 ; EZ80_PORTB7_IRQ 29 21 0x0bc
irqhandler 30 ; EZ80_PORTC0_IRQ 30 22 0x0c0
irqhandler 31 ; EZ80_PORTC1_IRQ 31 23 0x0c4
irqhandler 32 ; EZ80_PORTC2_IRQ 32 24 0x0c8
irqhandler 33 ; EZ80_PORTC3_IRQ 33 25 0x0cc
irqhandler 34 ; EZ80_PORTC4_IRQ 34 26 0x0d0
irqhandler 35 ; EZ80_PORTC5_IRQ 35 27 0x0d4
irqhandler 36 ; EZ80_PORTC6_IRQ 36 28 0x0d8
irqhandler 37 ; EZ80_PORTC7_IRQ 37 29 0x0dc
irqhandler 38 ; EZ80_PORTD0_IRQ 38 40 0x0e0
irqhandler 39 ; EZ80_PORTD1_IRQ 39 41 0x0e4
irqhandler 40 ; EZ80_PORTD2_IRQ 40 42 0x0e8
irqhandler 41 ; EZ80_PORTD3_IRQ 41 43 0x0ec
irqhandler 42 ; EZ80_PORTD4_IRQ 42 44 0x0f0
irqhandler 43 ; EZ80_PORTD5_IRQ 43 45 0x0f4
irqhandler 44 ; EZ80_PORTD6_IRQ 44 46 0x0f8
irqhandler 45 ; EZ80_PORTD7_IRQ 45 47 0x0fc
irqhandler EZ80_UNUSED+1 ; 48 0x100
irqhandler EZ80_UNUSED+2 ; 49 0x104
irqhandler EZ80_UNUSED+3 ; 50 0x108
irqhandler EZ80_UNUSED+4 ; 51 0x10c
irqhandler EZ80_UNUSED+5 ; 52 0x110
irqhandler EZ80_UNUSED+6 ; 53 0x114
irqhandler EZ80_UNUSED+7 ; 54 0x118
irqhandler EZ80_UNUSED+8 ; 55 0x11c
irqhandler EZ80_UNUSED+9 ; 56 0x120
irqhandler EZ80_UNUSED+10 ; 57 0x124
irqhandler EZ80_UNUSED+11 ; 58 0x128
irqhandler EZ80_UNUSED+12 ; 59 0x12c
irqhandler EZ80_UNUSED+13 ; 60 0x130
irqhandler EZ80_UNUSED+14 ; 61 0x134
irqhandler EZ80_UNUSED+15 ; 62 0x138
irqhandler EZ80_UNUSED+16 ; 63 0x13c
;**************************************************************************
; Common Interrupt handler
;**************************************************************************
_ez80_rstcommon:
; Create a register frame. SP points to top of frame + 4, pushes
; decrement the stack pointer. Already have
;
; Offset 8: Return PC is already on the stack
; Offset 7: AF (retaining flags)
;
; IRQ number is in A
push hl ; Offset 6: HL
ld hl, #(3*3) ; HL is the value of the stack pointer before
add hl, sp ; the interrupt occurred (3 for PC, AF, HL)
push hl ; Offset 5: Stack pointer
push iy ; Offset 4: IY
push ix ; Offset 3: IX
push de ; Offset 2: DE
push bc ; Offset 1: BC
; At this point, we know that interrupts were enabled (or we wouldn't be here
; so we can save a fake indicationn that will cause interrupts to restored when
; this context is restored
ld bc, #EZ80_PV_FLAG ; Parity bit. 1=parity odd, IEF2=1
push bc ; Offset 0: I with interrupt state in parity
di ; (not necessary)
; Call the interrupt decode logic. SP points to the beggining of the reg structure
ld hl, #0 ; Argument #2 is the beginning of the reg structure
add hl, sp ;
push hl ; Place argument #2 at the top of stack
ld bc, #0 ; BC = reset number
ld c, a ; Save the reset number in C
push bc ; Argument #1 is the Reset number
call _up_doirq ; Decode the IRQ
; On return, HL points to the beginning of the reg structure to restore
; Note that (1) the arguments pushed on the stack are not popped, and (2) the
; original stack pointer is lost. In the normal case (no context switch),
; HL will contain the value of the SP before the arguments were pushed.
ld sp, hl ; Use the new stack pointer
; Restore registers. HL points to the beginning of the reg structure to restore
ex af, af' ; Select alternate AF
pop af ; Offset 0: AF' = I with interrupt state in parity
ex af, af' ; Restore original AF
pop bc ; Offset 1: BC
pop de ; Offset 2: DE
pop ix ; Offset 3: IX
pop iy ; Offset 4: IY
exx ; Use alternate BC/DE/HL
pop hl ; Offset 5: HL' = Stack pointer after return
exx ; Restore original BC/DE/HL
pop hl ; Offset 6: HL
pop af ; Offset 7: AF
; Restore the stack pointer
exx ; Use alternate BC/DE/HL
pop de ; Offset 8: Return address
ld sp, hl ; Set SP = saved stack pointer value before return
push de ; Set up for reti
exx ; Restore original BC/DE/HL
; Restore interrupt state
ex af, af' ; Recover interrupt state
jp po, nointenable ; Odd parity, IFF2=0, means disabled
ex af, af' ; Restore AF (before enabling interrupts)
ei ; yes
reti
nointenable:
ex af, af' ; Restore AF
reti
;**************************************************************************
; Vector Setup Logic
;**************************************************************************
_ez80_initvectors:
; Initialize the vector table
ld iy, _ez80_vectable
ld ix, 4
ld bc, 4
ld b, NVECTORS
xor a, a ; Clear carry
ld hl, handlersize
ld de, _ez80_handlers
sbc hl, de ; Length of irq handler in hl
ld d, h
ld e, l
ld hl, _ez80_handlers ; Start of handlers in hl
ld a, 0
$1:
ld (iy), hl ; Store IRQ handler
ld (iy+3), a ; Pad to 4 bytes
add hl, de ; Point to next handler
push de
ld de, 4
add iy, de ; Point to next entry in vector table
pop de
djnz $1 ; Loop until all vectors have been written
; Select interrupt mode 2
im 2 ; Interrupt mode 2
; Write the address of the vector table into the interrupt vector base
ld hl, _ez80_vectable >> 8
ld i, hl
ret
;**************************************************************************
; Vector Table
;**************************************************************************
; This segment must be aligned on a 512 byte boundary anywhere in RAM
; Each entry will be a 3-byte address in a 4-byte space
define .IVECTS, space = RAM, align = 200h
segment .IVECTS
; The first 64 bytes are not used... the vectors actually start at +0x40
_ez80_vecreserve:
ds 64
_ez80_vectable:
ds NVECTORS * 4
|