Open changtimwu opened 9 years ago
CPU Attached mode
using the NO_CPU_CONFIG
pin._ first 11 bytes of eeprom -- 9 bytes are easy to understand
ram 0x0000 裡面第一行指令一定是 jp 80, 因為前面要放很多東西包括 isr table application 0x80~0xe000
.org 0x0000 ;start of SRAM space - interrupt tables
rst0:
jp start ;
.org 0x0080 ;start of code space - enter code here
start:
the memory layout of first 128 bytes
;====================================================================
; restart table
;
; The restart table must start at address 0x0000 as this is where the
; rst x commands call to.
;====================================================================
int040: ;org 0x0040
call h_defInt ;default handler w/caller ID on the stack (i.e., old PC)
This implies
<I reg>
== 0jp
instruction takes 3 bytes.
so
0x0040 就形成了類似傳統的 memory-based interrupt vector table. intnmi: ;org 0x0066
call h_defInt ;default handler w/caller ID on the stack (i.e., old PC)
z80 nmi ISR 固定要放在 0x0066
0x58 ~ 0x63 沒浪費, 放了 Manufacturer modifiable parameters , code 會讀來用?
; ;org 0x0058
s_smiDevAddr: .db 0x00 ;1 byte SMI Device Addr for s_tbl2switch routine
;b7=P, 1=phy 0=switch
; if b7=1: b6=C22, 1=Clause 22, 0=Clause 45
; if b7=1: b5=Ext, 1=external, 0=internal
;b4:0=SMI Dev Addr
;
miscInfo: .db 0x01 ;Device Features Control Byte
;b7:2=reserved
;b1=Enable EEE on AVB ports with reservations
;b0=Enable EEE
switchMac0: .dw 0x0050 ;1st two bytes of the switch's MAC address
switchMac2: .dw 0x4300 ;2nd two bytes of the switch's MAC address
switchMac4: .dw 0x0003 ;3rd two bytes of the switch's MAC address
stpPorts: .dw 0xF7FF ;b15:12 - CLI enabled on port(s), 0xF=disabled, 0xE=all ports
;b11 - reserved
;b10:0 - bit vector of active switch ports for STP
ptpPorts: .dw 0xFFFF ;b15:12 - forced Slave Port if <> 0xF
;b11 - 1=Grand Master capable
;b10:0 - bit vector of active switch ports for PTP
srpPorts: .dw 0x07FF ;b15:11 - reserved
;b10:0 - bit vector of active switch ports for SRP
0x67 ~ 0x7f 沒用, 未來可以放
CPU interrupt mode 都是用 mode 2, 用 im 2
指令達成.
I/O registers related to interrupts: 0x07 -- interrupt source 0x08~0x0e -- act registers, interrupt vector table 固定在這
NMI 就是不能mask掉, 連 DI(disable interrupt)指令也不能關掉
In mode 2, ISR 可以在 ram 內的任何 address, I REG
決定 high byte, act register 決定
meaning of ack register
0 -- disable this interrupt
1 -- it's NMI and ISR is fixed at <I REG>0066
2~0xff -- low byte of ISR entry point. This also defines priority. The lower address the higher priority.
two level interrupts: When serving a interrupt( running inside of an ISR), all other INTs are masked(不會觸發) out except NMI. NMI 永遠不會被遮罩.
所有 ISRs 的 code 不能超過 256 byte( in the same page)? No, the page which <I REG>
assigns would be just a JUMP table. or (Branch table)
;====================================================================
; Z80 mode 2 interrupt table
;
; Z80 Mode 2 interrupts support a jump table that can be anywhere as long as the
; entire table is in the same page (i.e., the upper 8 addr bits are the same).
; This table is placed here so the previously listed restarts can be used for
; code size optimization (if needed). For this to work the interrupt
; controller needs to put the Z80 into Mode 2 & configure the I-Reg
; & interrupt controller to point to these addresses (it is the job of each
; interrupt from the controller to supply the lower 8 addr bits).
;
; input: nothing
; output: Top of Stack=value indicating the interrupt # (these are calls)
; effect: nothing destroyed
; note: before the interrupt service routine returns it must
; pop all the saved registers off the stack (like this extra call)
; 0x0066 - 0x0069 Z80 NMI branch table
; 0x0058 - 0x0065 Manufacturer modifiable parameter table from EEPROM
; 0x0040 - 0x0057 Z80 Mode 2 Interrupt branch table
; Use this to support all 8 interrupts w/separate vectors
;
http://z80-heaven.wikidot.com/interrupts
main:
bcall(_ClrLCDFull) ; 清除螢幕
; disable interrupts while we're install ours
di
; set up the interrupt jump table to jump to $9A9A
ld a,$9A ; 把 0x9a 填滿整個 mem 0x99xx
ld ($9900),a
ld hl,$9900
ld de,$9901
ld bc,256
ldir
; copy our interrupt to $9A9A ; ISR copy 到 9a9a
ld hl,interruptStart
ld de,$9A9A
ld bc,interruptEnd - interruptStart
ldir
; set $99 into I ; 日後 isr routine entry 都是 0x99xx
ld a,$99
ld I,a
; set interrupt mode 2
im 2
loop:
; re-enable interrupts
ei
; rest of our program ; 一直印 counter 看看timer interrupt 是不是真的固定把它累加.
ld hl,0
ld (curRow),hl
ld hl,(counter)
bcall(_DispHl)
jr loop
interruptStart:
; disable interrupts during our interrupt
di
; swap registers
ex AF,AF'
exx
; our interrupt code
ld hl,(counter)
inc hl
ld (counter),hl
; swap back registers
ex AF,AF'
exx
; re-enable interrupts and return
ei
ret
interruptEnd:
counter:
.dw 0
ISR 最後一行要下 ei !!
RST 稱之為 Restart, sometimes are referred as software interrupt, 前面 0x00~0x3f 放的是 restart table, 一個 rst 指令就可以進去, 跟call指令的差別在, rst 只需要 1 byte,適合拿來放frequently called routines.
trace the ethernet command of impMonMain.s
to save memory the monitor program use table to store reg read/writes. How much can this save when comparing with directly read write with instruction?
halInitTbl: ;halInit switch configuration
; ;Enable below commands for debugging
; .db setDisout ;enable debug messages
; .db 0x00 ;with this zero byte
; ;Do Global 2 work
.db smiDevOp+G2 ;modify Global 2
; ;Set GPIO 12 to be output
.db regWtOp+0x1A ;modify Global 2 offset 0x1A
.dw 0xE3EF ;sets GPIO 12 to output
; the above equals to WriteReg( 0x1c, 0x1a, 0xe3ef)
; ;Set features (only works on unprogrammed parts)
.db regWtOp+0x1A ;modify Global 2 offset 0x1A
.dw 0xF940 ;override the automotive mode
;the above equals to WriteReg( 0x1c, 0x1a, 0xf940)
; ;and set PHYs Auto-neg (only needed on unprogrammed parts)
.db mulWtOp+v8 ;multiple dev write
.db v7to1 ;on ports 8 to 1
.db phyOp+c22int+0x00 ;to internal C22 PHYs offset 0x00
.dw 0x9100 ;reset the PHY w/Auto-neg enabled
; the above equals to
; for (i=1;i<=8;i++)
; WritePhy( i, 0, 0x9100);
; ;Turn on the LEDs (they are off while fast booting)
.db smiDevOp+p0 ;modify Port 0
.db regWtOp+0x16 ;offset 0x16
.dw 0x8000 ;turn on the LEDs
;the above equals to WriteReg( 0x00, 0x16, 0x8000);
.db stop ;end of this command list
;
;
c_ePairTbl:
; ;Enable below commands for debugging
; .db setDisout ;enable debug messages
; .db 0x00 ;with this zero byte
;Turn off learning on Ports 0 to 9
.db mulWtOp+v8+v9 ;write to multiple ports
.db v7to0 ;ports 0 to 9
.db swOp+0x0B ;write to Switch Port offset 0x0B ;
.dw 0x0000 ;value to turn off learning
; equals to
; for (i=0;i<=9;i++){
; WriteReg( i, 0x0b, 0x0000);
; }
; ;Configure Ports 0 to 9 to trap SA Misses
.db mulWtOp+v8+v9 ;write to multiple ports
.db v7to0 ;ports 0 to 9
.db swOp+0x0D ;write to Switch Port offset 0x0D
.dw 0x0040 ;value to trap SA Misses
; equals to
; for (i=0;i<=9;i++){
; WriteReg( i, 0x0d, 0x0040);
; }
; ;Configure IMP port for Header+ETDSA+Forwarding
.db smiDevOp+IMP ;configure the IMP's port
.db regWtOp+0x04 ;write to Port offset 0x04
.dw 0x0B7F ;value for Header+ETDSA+Forwarding
; this equals to WriteReg( 0x1e, 0x04, 0x0b7f)
; ;Configure CPUDest ==> IMP port
.db smiDevOp+G1 ;modify Global 1
.db regWtOp+0x1A ;offset 0x1A
.dw 0xB0FE ;value to point CPUDest to port 0x1E (the IMP)
; this equals to WriteReg( 0x1b, 0x1a, 0xb0fe)
.db stop ;end of the table
device table
p0 = 0x00 ;SMI Dev vector for Port 0
p1 = 0x01 ;SMI Dev vector for Port 1
p2 = 0x02 ;SMI Dev vector for Port 2
p3 = 0x03 ;SMI Dev vector for Port 3
p4 = 0x04 ;SMI Dev vector for Port 4
p5 = 0x05 ;SMI Dev vector for Port 5
p6 = 0x06 ;SMI Dev vector for Port 6
p7 = 0x07 ;SMI Dev vector for Port 7
p8 = 0x08 ;SMI Dev vector for Port 8
p9 = 0x09 ;SMI Dev vector for Port 9
p10 = 0x0A ;SMI Dev vector for Port 10
p11 = 0x0B ;SMI Dev vector for Port 11
G1 = 0x1B ;SMI Dev for Global 1
G2 = 0x1C ;SMI Dev for Global 2
IMP = 0x1E ;SMI Dev for Z80 CPU
tcam = 0x1F ;SMI Dev for the TCAM
setPhyMd = 0x01 ;Set PHY Access mode opcode
setDisout = 0x02 ;Set c_disout mode opcode
setSingStep = 0x03 ;Set single step mode opcode
smiDevOp = 0x20 ;Set SMI Dev Addr opcode
c45WtAddr = 0x40 ;Set Clause 45 register address
regWtOp = 0x60 ;Register Write opcode
mulWtOp = 0x80 ;Multiple Device Write opcode
phyOp = 0x80 ;indicates operation is to a PHY reg
rmwOp = 0xC0 ;Read Modify Write opcode
waitOp = 0xE0 ;Wait on Bit opcode
swOp = 0x40 ;indicates operation is to a Switch reg
;
c22int = 0x40 ;PHY access mode value for Clause 22 Internal access
c22ext = 0x60 ;PHY access mode value for Clause 22 Internal access
c45int = 0x00 ;PHY access mode value for Clause 45 Internal access
c45ext = 0x20 ;PHY access mode value for Clause 45 Internal access
;
The internal PHY and SERDES registers are only accessible via the SMI PHY command and Data registers(Global 2, offset 0x18 & 0x19) using SMIFunc set for Internal Access mode. The internal Port 1 to Port 8 PHYs are mapped at SMI device address 0x01 to 0x08 respectively. The internal SERDES on Ports 9 and Port 10 are mapped at SMI device addreses 0x09 and 0x0a respectively.
Table 136, Index: 0x30 of Monitor & MGMT Control _Many modes of frame processing need to know where the CPU is located. Theses modes are
page 39, Table 24: Port Control Register, Offset 0x04
Field SA Filtering Description(key field for 802.1x)
Source Address Filtering controls
These bits select the SA filtering method to be used on the port
0x03 = Drop to CPU.
Ingressing frames will be mapped to the CPUDest(Global offset 0x1a) if their SA field is in the ATU's address database as a Static entry with a port vector of all zeros and the frame is not otherwise filtered. Otherwise, the frames will be discarded if their SA field is not in the ATU's address database(i.e., it's a new or unknown source address).
This mode is a form of MAC based 802.1X where some frames can be forced to the CPU for further authentication prior to full authorization.
page 58 Port E Type offset 0x0f
page 29 Port control offset 0x04
G2(0x1b) offset 0x1c , page 134
G1(0x1b) offset 0x1a, index 0x30, page 131
the value 0xb0fe
The extra data placed in the frame is needed to support the Spanning Tree Protocol(STP) as well as cross-chip features like LAGs, Mirrors. etc. Ports that are interconnected together to form a larger switch ports connected to the management CPU must use this mode.
所以 STD DSA mode 是指, 只有control packet才會塞DSA?
https://github.com/contiki-os/contiki/blob/master/doc/pt-doc.txt A protothread runs within a single C function and cannot span over other functions.
even though having such a limitation, contiki still intensively use protothread in his net implementation ex. https://github.com/contiki-os/contiki/blob/master/core/net/http-socket/http-socket.c
it also demonstrate how to use multiple pt
when thread has deep calls.e
sdcc seems implement setjmp/longjmp for z80.
out a lot coroutine implementations out there
http://www.codemud.net/~thinker/GinGin_CGI.py/show_id_doc/489
http://fanf.livejournal.com/105413.html
https://github.com/adamdunkels/uip uip 1.0 has integrated tuntap.