Atmel Avr Tcpip Atmel-crystal.asm

 .include "M103def.inc"
 .list
 .listmac
 .eseg
 .db "Copyright 1998-1999 Gary T. Desrosiers. All Rights Reserved.",0
 .cseg
 .org 0
 jmp start
;-----------------------------------------------------------------------+
; ATmega103 <===> Crystal Interconnects. |
;-----------------------------------------------------------------------+
; |
;PORTA - Unconnected. Because external SRAM enable bit set in MCUCR, |
;		 this port becomes the data port (AD0-7). |
; |
;PORTB - Connected to SA0-SA3 of Crystal board. PB4-PB7 is unconnected |
; |
;PORTC - Unconnected. Because external SRAM enable bit set in MCUCR, |
; this port becomes the high order address bus (A8-A15). |
; |
;PORTD - Connected to SD0-SD7 of the Crystal board (Crystal Data Bus). |
; |
;PORTE - Tied to PE0-->>/RD, PE1-->>/WR, PE2-->>/CHIPSEL, |
; and PE3<<--INTR on the Crystal board. |
; |
; Note: When using the STK300 development board, remove the PORTB, |
; PORTD, and PORTE jumpers. |
; |
;-----------------------------------------------------------------------+
; Note: When using the STK300 development board, perform the following: |
; |
; * Remove the PORTB jumpers (all 8) |
; * Remove the PORTD jumpers (all 8) |
; * Remove PORTE jumpers for RE0/RE1 |
; * Move J1 to J2 to disable 3.3v mode and enable 5.0v mode |
; * Optionally, connect the 16x1 or 2x8 LCD |
;-----------------------------------------------------------------------+
;
.equ CDB=PORTD ;Crystal Data Bus
.equ CAB=PORTB ;Crystal Address Bus
.equ CSIG=PORTE ;Crystal Signals
.equ IOR=0 ;Read
.equ IOW=1 ;Write
.equ CHIPSEL=2 ;Chip Select
.equ INTR=3 ;Interrupt signal
;
;
;
; *Change these* : Configuration equates. 
;
.equ ClkFreq = 4000000	 ;4 Mhz crystal
;
.equ IP1	 =	192 ;first octet of IP address
.equ IP2 = 168 ;second octet of IP address
.equ IP3 = 1 ;third octet of IP address
.equ IP4 = 2 ;fourth octet of IP address
;
.equ MAC1 = 0x00 ;\
.equ MAC2 = 0x00 ; \
.equ MAC3 = 0x00 ; \
.equ MAC4 = 0x12 ; 48 bit IEEE OUI (Organizationally Unique Identifier)
.equ MAC5 = 0x34 ; /
.equ MAC6 = 0x56 ;/
;
; Some useful macros
;
.macro ppRD ;Read PacketPage port at addr @0
 ldi offsetL,low(@0)
 ldi offsetH,high(@0)
 rcall ReadPP
.endmacro
;
.macro ppWR ;Write PacketPage port (addr,val)
 ldi offsetL,low(@0)
 ldi offsetH,high(@0)
 ldi valueL,low(@1)
 ldi valueH,high(@1)
 rcall WritePP
.endmacro
;
.macro Dinput
 clr wL ;Change the data bus to input
 out DDRD,wL
.endmacro
;
.macro Doutput 
 ser wL ;Change the data bus to output
 out DDRD,wL
.endmacro
;
.macro ior ;I/O port read at @0 
 ldi wL,@0
 rcall ioRead
.endmacro
;
.macro iow ;I/O port write at @0
 out CDB,wL
 ldi wL,@0
 out CAB,wL
 rcall ioWrite
.endmacro
;
; Crystal CS8900 PacketPage equates
;
.equ portRxTxData = 0x00 ;Receive/Transmit data (port 0)
.equ portRxTxData1 = 0x02 ;Receive/Transmit data (port 0)
.equ portTxCmd = 0x04 ;Transmit Commnad
.equ portTxLength = 0x06 ;Transmit Length
.equ portISQ = 0x08 ;Interrupt status queue
.equ portPtr = 0x0a ;PacketPage pointer
.equ portData = 0x0c ;PacketPage data (port 0)
.equ portData1 = 0x0e ;PacketPage data (port 1)
;
; CS8900 PacketPage Offsets 
;
.equ ppEISA = 0x0000 ;EISA Registration number of CS8900
.equ ppProdID = 0x0002 ;Product ID Number
.equ ppIOBase = 0x0020 ;I/O Base Address
.equ ppIntNum = 0x0022 ;Interrupt number (0,1,2, or 3)
.equ ppMemBase = 0x002C ;Memory Base address register (20 bit)
.equ ppRxCfg = 0x0102 ;Receiver Configuration
.equ ppRxCtl = 0x0104 ;Receiver Control
.equ ppTxCfg = 0x0106 ;Transmit Configuration
.equ ppBufCfg = 0x010A ;Buffer Configuration
.equ ppLineCtl = 0x0112 ;Line Control
.equ ppSelfCtl = 0x0114 ;Self Control
.equ ppBusCtl = 0x0116 ;Bus Control
.equ ppTestCtl = 0x0118 ;Test Control
.equ ppISQ = 0x0120 ;Interrupt status queue
.equ ppRxEvt = 0x0124 ;Receiver Event
.equ ppTxEvt = 0x0128 ;Transmitter Event
.equ ppBufEvt = 0x012C ;Buffer Event
.equ ppRxMiss = 0x0130 ;Receiver Miss Counter
.equ ppTxCol = 0x0132 ;Transmit Collision Counter
.equ ppLineSt = 0x0134 ;Line Status
.equ ppSelfSt = 0x0136 ;Self Status
.equ ppBusSt = 0x0138 ;Bus Status
.equ ppTxCmd = 0x0144 ;Transmit Command Request
.equ ppTxLength = 0x0146 ;Transmit Length
.equ ppIndAddr = 0x0158 ;Individual Address (IA)
.equ ppRxStat = 0x0400 ;Receive Status
.equ ppRxLength = 0x0402 ;Receive Length
.equ ppRxFrame = 0x0404 ;Receive Frame Location
.equ ppTxFrame = 0x0A00 ;Transmit Frame Location
;
; Register Numbers 
;
.equ REG_NUM_MASK = 0x003F
.equ REG_NUM_RX_EVENT = 0x0004
.equ REG_NUM_TX_EVENT = 0x0008
.equ REG_NUM_BUF_EVENT = 0x000C
.equ REG_NUM_RX_MISS = 0x0010
.equ REG_NUM_TX_COL = 0x0012
;
; Self Control Register
;
.equ SELF_CTL_RESET = 0x0040
.equ SELF_CTL_HC1E = 0x2000
.equ SELF_CTL_HCB1 = 0x8000
;
; Self Status Register 
;
.equ SELF_ST_INIT_DONE = 0x0080
.equ SELF_ST_SI_BUSY = 0x0100
.equ SELF_ST_EEP_PRES = 0x0200
.equ SELF_ST_EEP_OK = 0x0400
.equ SELF_ST_EL_PRES = 0x0800
;
; Bus Control Register 
;
.equ BUS_CTL_USE_SA = 0x0200
.equ BUS_CTL_MEM_MODE = 0x0400
.equ BUS_CTL_IOCHRDY = 0x1000
.equ BUS_CTL_INT_ENBL = 0x8000
;
; Bus Status Register 
;
.equ BUS_ST_TX_BID_ERR = 0x0080
.equ BUS_ST_RDY4TXNOW = 0x0100
;
; Line Control Register 
;
.equ LINE_CTL_RX_ON = 0x0040
.equ LINE_CTL_TX_ON = 0x0080
.equ LINE_CTL_AUI_ONLY = 0x0100
.equ LINE_CTL_10BASET = 0x0000
;
; Test Control Register 
;
.equ TEST_CTL_DIS_LT = 0x0080
.equ TEST_CTL_ENDEC_LP = 0x0200
.equ TEST_CTL_AUI_LOOP = 0x0400
.equ TEST_CTL_DIS_BKOFF = 0x0800
.equ TEST_CTL_FDX = 0x4000
;
; Receiver Configuration Register 
;
.equ RX_CFG_SKIP = 0x0040
.equ RX_CFG_RX_OK_IE = 0x0100
.equ RX_CFG_CRC_ERR_IE = 0x1000
.equ RX_CFG_RUNT_IE = 0x2000
.equ RX_CFG_X_DATA_IE = 0x4000
;
; Receiver Event Register 
;
.equ RX_EVENT_RX_OK = 0x0100
.equ RX_EVENT_IND_ADDR = 0x0400
.equ RX_EVENT_BCAST = 0x0800
.equ RX_EVENT_CRC_ERR = 0x1000
.equ RX_EVENT_RUNT = 0x2000
.equ RX_EVENT_X_DATA = 0x4000
;
;Receiver Control Register 
;
.equ RX_CTL_RX_OK_A = 0x0100
.equ RX_CTL_MCAST_A = 0x0200
.equ RX_CTL_IND_A = 0x0400
.equ RX_CTL_BCAST_A = 0x0800
.equ RX_CTL_CRC_ERR_A = 0x1000
.equ RX_CTL_RUNT_A = 0x2000
.equ RX_CTL_X_DATA_A = 0x4000
;
;Transmit Configuration Register 
;
.equ TX_CFG_LOSS_CRS_IE = 0x0040
.equ TX_CFG_SQE_ERR_IE = 0x0080
.equ TX_CFG_TX_OK_IE = 0x0100
.equ TX_CFG_OUT_WIN_IE = 0x0200
.equ TX_CFG_JABBER_IE = 0x0400
.equ TX_CFG_16_COLL_IE = 0x8000
.equ TX_CFG_ALL_IE = 0x8FC0
;
;Transmit Event Register 
;
.equ TX_EVENT_TX_OK = 0x0100
.equ TX_EVENT_OUT_WIN = 0x0200
.equ TX_EVENT_JABBER = 0x0400
.equ TX_EVENT_16_COLL = 0x1000
;
; Transmit Command Register
;
.equ TX_CMD_START_5 = 0x0000
.equ TX_CMD_START_381 = 0x0080
.equ TX_CMD_START_1021 = 0x0040
.equ TX_CMD_START_ALL = 0x00C0
.equ TX_CMD_FORCE = 0x0100
.equ TX_CMD_ONE_COLL = 0x0200
.equ TX_CMD_NO_CRC = 0x1000
.equ TX_CMD_NO_PAD = 0x2000
;
;Buffer Configuration Register 
;
.equ BUF_CFG_SW_INT = 0x0040
.equ BUF_CFG_RDY4TX_IE = 0x0100
.equ BUF_CFG_TX_UNDR_IE = 0x0200
;
;
; Register file assignments
;
.def count=r14
.def lcdPos=r15
.def wL=r16
.def wH=r17
.def offsetL=r18
.def offsetH=r19
.def valueL=r20
.def valueH=r21
.def tempL=r22
.def tempH=r23
.def flags=r24
.def scratch=r25
.def lengthL=r26
.def lengthH=r27
.def chksumL=r0
.def chksumM=r1
.def chksumH=r2
;
; start of packet data in sram
;
.equ packet = 0x60
;
; Packet offset equates
;
;
; Packet header
;
.equ pktLenH = 0x00
.equ pktLenL = 0x01
.equ pktDest0H= 0x02
.equ pktDest0L= 0x03
.equ pktDest1H= 0x04
.equ pktDest1L= 0x05
.equ pktDest2H= 0x06
.equ pktDest2L= 0x07
.equ pktSrc0H = 0x08
.equ pktSrc0L = 0x09
.equ pktSrc1H = 0x0a
.equ pktSrc1L = 0x0b
.equ pktSrc2H = 0x0c
.equ pktSrc2L = 0x0d
.equ pktTypeH = 0x0e
.equ pktTypeL = 0x0f
;
; ARP
;
.equ ar_hwtype= 0x10 ;hardware type
.equ ar_prtype= 0x12 ;protocol type
.equ ar_hwlen = 0x14 ;hardware address length
.equ ar_prlen = 0x15 ;protocol address length
.equ ar_op = 0x16 ;ARP operation (1=request, 2=reply)
.equ ar_sha = 0x18 ;senders hardware address
.equ ar_spa = 0x1e ;senders IP address
.equ ar_tha = 0x22 ;target hardware address
.equ ar_tpa = 0x28 ;target IP address
;
; IP header
;
.equ ip_verlen= 0x10 ;IP version and header length(in longs)
.equ ip_tos = 0x11 ;IP type of service
.equ ip_len = 0x12 ;packet length (length-header_length)
.equ ip_id = 0x14 ;datagram id
.equ ip_fragoff= 0x16 ;fragment offset
.equ ip_ttl = 0x18 ;time to live (in gateway hops)
.equ ip_proto = 0x19 ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17)
.equ ip_cksum = 0x1a ;header checksum
.equ ip_src = 0x1c ;IP address of source
.equ ip_dst = 0x20 ;IP addess of destination
.equ ip_data = 0x24
;
; IP value equates
;
.equ IPT_ICMP = 1 ;protocol type for ICMP packets
.equ IPT_TCP = 6 ;protocol type for TCP packets
.equ IPT_EGP = 8 ;protocol type for EGP packets
.equ IPT_UDP = 0x11 ;protocol type for UDP packets
;
; ICMP header
;
.equ ic_type = ip_data ;0=reply, 8=request, others=who-cares
.equ ic_code = ic_type+1 ;code
.equ ic_cksum = ic_code+1 ;checksum of header+data
.equ ic_id = ic_cksum+2 ;message id
.equ ic_seq = ic_id+2 ;sequence number
;
; UDP Header
;
.equ u_src = ip_data ;source udp port number
.equ u_dst = u_src+2 ;destination UDP port number
.equ u_len = u_dst+2 ;length of UDP header+data
.equ u_cksum = u_len+2 ;checksum (see note)
.equ u_data = u_cksum+2 ;start of data
;
; Note: checksum is calculated by taking the 16 bit sums of the ip_src, ip_dst,
; ip_proto, u_len, and the sum starting at u_src for a length of u_len
; yes, this means that u_len is taken twice! u_cksum is zero during the calc.
; The sum is then one's complemented. This is the checksum
;
;
start:
 ldi wL,low(RAMEND)
 out SPL,wL
 ldi wL,high(RAMEND)		 ;setup the stack
 out SPH,wL
		ldi wL,$c0		 ;Setup for external
		out MCUCR,wL		 ; SRAM Enable and Wait State Enable
 ldi wL,0b11110111 ;PORTE INTR signal input all others output
 out DDRE,wL 
 sbi CSIG,IOR ;no read
 sbi CSIG,IOW ;no write
 sbi CSIG,CHIPSEL ;don't select chip
 ser wL
 out DDRB,wL ;PORTB (Crystal Address Bus) output
 clr count ;packet counter
 Dinput
 ldi scratch,255 ;wait
 rcall wait
 
 rcall lcd_reset ;reset LCD
 rcall VerChip ;make sure that the CS8900 is connected, Z set if true
 ldi wL,'>' ;success indicator
 breq VerOK
 ldi wL,'<' ;failure indicator on LCD
VerOK: rcall lcd_write
 rcall ResetChip ;reset CS8900
 rcall InitChip ;initialize CS8900
;
; We already did this in VerChip but get the signature bytes for the CS8900 and display
; them on the LCD. Should be 3000 630E 0500
;
 Dinput
 ior portPtr+1 ;read PacketPage Ptr for high order byte
 mov valueH,wL ;save high low
 ior portPtr ;read PacketPage Ptr for high order byte
 mov valueL,wL ;save high low
 rcall outHL
 ppRD ppEISA ;get the EISA number whoch should be 0x630E
 rcall outHL
 ppRD ppProdID ;get the Product ID which should be 000x xxxx 0000 0000
 rcall outHL
 clr flags ;Packet flags
loop:
 sbis PINE,INTR ;wait for interrupt
 rjmp loop
 rcall ProcessISQ ;process the queue
 sbrs flags,0 ;received frame flag
 rjmp loop
 cbr flags,1 ;clear the receive flag
;
; We're going to display on the LCD, t: CC LLLL FFFF
; Where t=r for recieved frame, a=arp request, p=ping request
; CC=count of frames received so far
; LLLL=length of this frame
; FFFF=frame type. For example 0800 for IP, 0806 for ARP
;
 rcall lcd_clear
 clr lcdPos 
 inc lcdPos ;start in second LCD position
 ldi wL,':'
 rcall lcd_write
		mov		wL,count
 rcall toHexH
		rcall lcd_write
 mov		wL,count ;display the count of received frames
 rcall toHexL
 rcall lcd_write
 ldi wL,' '
 rcall lcd_write
 lds valueH,packet+pktLenH ;display the packet length
 lds valueL,packet+pktLenL
 rcall outHL
 lds valueH,packet+pktTypeH ;and the packet type
 lds valueL,packet+pktTypeL
 rcall outHL
 sbrc flags,1 ;bit set when valid arp
 rjmp ArpRequest
 sbrc flags,2 ;bit set when valid UDP Request on port 7
 rjmp UDP7Request
 sbrc flags,3 ;bit set when valid ICMP Ping request received
 rjmp PingRequest
 clr lcdPos
 ldi wL,'r'
 rcall lcd_write
 rjmp loop
ArpRequest:
 cbr flags,2 ;clear the valid arp request flag
 clr lcdPos
 ldi wL,'a'
 rcall lcd_write
 rcall WriteARP ;respond to the ARP request with our IP/MAC
 rjmp loop
PingRequest:
 cbr flags,8 ;clear the valid ICMP ping request flag
 clr lcdPos
 ldi wL,'p'
 rcall lcd_write
 rcall WritePing ;respond to the ping
 rjmp loop
UDP7Request:
 cbr flags,4 ;clear the valid UDP port 7 request flag
 clr lcdPos
 ldi wL,'u'
 rcall lcd_write
 rcall WriteUDP ;echo reply
 rjmp loop
;
; Converts the valueH/valueL to hex and displays it on the LCD
;
outHL:
		mov		wL,valueH
 rcall toHexH
		rcall	lcd_write
 mov		wL,valueH
 rcall toHexL
 rcall lcd_write
 mov		wL,valueL
 rcall toHexH
		rcall	lcd_write
		mov		wL,valueL
 rcall toHexL
 rcall lcd_write
 ldi wL,' '
 rcall lcd_write
 ret
toHexL:
		andi	wL,0x0f
		ori		wL,0x30
		cpi		wL,0x3a
		brlo	thlX
 ldi wH,7
		add 	wL,wH
thlX: ret
toHexH:
		lsr		wL
		lsr		wL
		lsr		wL
		lsr		wL
		ori		wL,0x30
		cpi		wL,0x3a
		brlo	thhX
 ldi wH,7
		add	 wL,wH
thhX: ret
;
; Send the reset sequence to the LCD's HD44780 controller. 
;
lcd_reset:
 ldi scratch,20 ;wait 20 milliseconds
 rcall wait
		ldi		wL,30ドル				;Spec said to send this init sequence
		sts		8000,ドルwL
 ldi scratch,4
		rcall	wait 			;Wait 4ms
		ldi		wL,30ドル				;Spec said to send this init sequence
		sts		8000,ドルwL			;Send init sequence again
		rcall	delay100us			;Wait 100us
		ldi		wL,30ドル				;Spec said to send this init sequence
		sts		8000,ドルwL			;and one last time
		rcall	delay100us			;Wait 100us
		ldi		wL,3ドルF				;Display off
		sts		8000,ドルwL
 ldi scratch,4
		rcall	wait 			;Wait 4ms
		ldi		wL,0ドルF				;Display on
		sts		8000,ドルwL
 ldi scratch,4
		rcall	wait 			;Wait 4ms
		ldi		wL,06ドル				;Entry Mode Set
		sts		8000,ドルwL
 ldi scratch,4
		rcall	wait 			;Wait 4ms
 rcall lcd_clear ;clear display
 clr lcdPos ;position of character on LCD
		ret
;
; Clear the LCD display
;
lcd_clear:
		ldi		wL,01ドル				;Clear Display
		sts		8000,ドルwL
 ldi scratch,4
		rcall	wait 			;Wait 4ms
 clr lcdPos ;position of character on LCD
 ret
		
;
; Sends the character in r16 to the LCD. The register "lcdPos" is
; incremented to the next position. The register value is a modulous 8
; and the LCD is broken into two sections (as is typical for HD44780 based LCDs),
; position 0-7 on LCD1 and 0-7 on LCD2.
;
lcd_write:
		mov		r17,lcdPos	
		sbrs	r17,3
		rjmp 	lcd_1
 andi r17,0x07
		ori		r17,0x40
 rjmp lcd_2
lcd_1:	andi r17,0x07
lcd_2: ori		r17,0x80
		sts		8000,ドルr17
		rcall	delay40us
		sts		$C000,r16
		rcall	delay40us
		inc		lcdPos
		ret	
		
delay40us:
 push wL
		ldi		wL,40ドル
loop3:	dec		wL		
		brne	loop3	
 pop wL	
		ret
delay100us:
 push wL
		ldi		wL,88ドル
loop4:	dec		wL		
		brne	loop4
 pop wL		
		ret
 
;
; wait for W milliseconds
;
;delay the given number of milliseconds using a software loop
;	Enter:	scratch = number of milliseconds to delay
;	Exit:	scratch,wL,wH = undefined
wait:
wait1: ldi	 wH,high((ClkFreq / 1000) / 4)
	 ldi wL,low((ClkFreq / 1000) / 4)
wait2:	subi	wL,1			;(1)
	 sbci	wH,0			;(1)
	 brne	wait2			;(2)
	 dec	 scratch
	 brne	wait1
	 ret
;************************************************************************
;* C S 8 9 0 0 D r i v e r F u n c t i o n s *
;************************************************************************
;
; WriteARP - Send a response ARP to the requestor 
;
WriteARP:
 ldi zL,low(packet)
 ldi zH,high(packet) ;load the z reg with the packet address
 clr wL
 st z,wL
 ldi wL,42 				 ;length of ARP response frame
 std z+2,wL
; Target HW address MAC (6)
 lds wL,packet+pktSrc0H
 sts packet+ar_tha,wL
 sts packet+pktDest0H,wL
 lds wL,packet+pktSrc0L
 sts packet+ar_tha+1,wL
 sts packet+pktDest0L,wL
 lds wL,packet+pktSrc1H
 sts packet+ar_tha+2,wL
 sts packet+pktDest1H,wL
 lds wL,packet+pktSrc1L
 sts packet+ar_tha+3,wL
 sts packet+pktDest1L,wL
 lds wL,packet+pktSrc2H
 sts packet+ar_tha+4,wL
 sts packet+pktDest2H,wL
 lds wL,packet+pktSrc2L
 sts packet+ar_tha+5,wL
 sts packet+pktDest2L,wL
; Target IP (4)
 lds wL,packet+ar_spa
 sts packet+ar_tpa,wL
 lds wL,packet+ar_spa+1
 sts packet+ar_tpa+1,wL
 lds wL,packet+ar_spa+2
 sts packet+ar_tpa+2,wL
 lds wL,packet+ar_spa+3
 sts packet+ar_tpa+3,wL
; Senders IP (4)
 ldi wL,IP1
 sts packet+ar_spa,wL
 ldi wL,IP2
 sts packet+ar_spa+1,wL
 ldi wL,IP3
 sts packet+ar_spa+2,wL
 ldi wL,IP4
 sts packet+ar_spa+3,wL
; Src HW Address MAC (6)
 ldi wL,MAC1
 sts packet+ar_sha,wL
 sts packet+pktSrc0H,wL
 ldi wL,MAC2
 sts packet+ar_sha+1,wL
 sts packet+pktSrc0L,wL
 ldi wL,MAC3 
 sts packet+ar_sha+2,wL
 sts packet+pktSrc1H,wL
 ldi wL,MAC4
 sts packet+ar_sha+3,wL
 sts packet+pktSrc1L,wL
 ldi wL,MAC5
 sts packet+ar_sha+4,wL
 sts packet+pktSrc2H,wL
 ldi wL,MAC6
 sts packet+ar_sha+5,wL
 sts packet+pktSrc2L,wL
; Packet type (2)
 ldi wL,0x08
 sts packet+pktTypeH,wL
 ldi wL,0x06
 sts packet+pktTypeL,wL
; Hardware type (2)
 ldi wL,0x00
 sts packet+ar_hwtype,wL
 ldi wL,0x01 
 sts packet+ar_hwtype+1,wL
; Protocol type (2)
 ldi wL,0x08
 sts packet+ar_prtype,wL
 ldi wL,0x00
 sts packet+ar_prtype+1,wL
; Hardware and protocol address lengths (2)
 ldi wL,0x06
 sts packet+ar_hwlen,wL
 ldi wL,0x04
 sts packet+ar_prlen,wL
; Operation (response) (2)
 ldi wL,0x00
 sts packet+ar_op,wL
 ldi wL,0x02
 sts packet+ar_op+1,wL
 rcall WritePacket
 ret
;
; WriteUDP - Send a response to the port 7 UDP echo request
;
WriteUDP:
 clr wL
 sts packet+ip_cksum,wL ;clear
 sts packet+ip_cksum+1,wL ; checksum
 lds wL,packet+ip_src ;move
 sts packet+ip_dst,wL ; ip
 lds wL,packet+ip_src+1 ; of 
 sts packet+ip_dst+1,wL ; source
 lds wL,packet+ip_src+2 ; to
 sts packet+ip_dst+2,wL ; dest
 lds wL,packet+ip_src+3 
 sts packet+ip_dst+3,wL
 
 ldi wL,IP1 ;move
 sts packet+ip_src,wL ; our
 ldi wL,IP2 ; ip
 sts packet+ip_src+1,wL ; address
 ldi wL,IP3 ; to
 sts packet+ip_src+2,wL ; source
 ldi wL,IP4 
 sts packet+ip_src+3,wL
 lds wL,packet+pktSrc0H ;move
 sts packet+pktDest0H,wL ; mac src to dest
 lds wL,packet+pktSrc0L 
 sts packet+pktDest0L,wL 
 lds wL,packet+pktSrc1H ;move
 sts packet+pktDest1H,wL ; mac src to dest
 lds wL,packet+pktSrc1L 
 sts packet+pktDest1L,wL 
 lds wL,packet+pktSrc2H ;move
 sts packet+pktDest2H,wL ; mac src to dest
 lds wL,packet+pktSrc2L 
 sts packet+pktDest2L,wL
 ldi wL,MAC1 ;move
 sts packet+pktSrc0H,wL ; our
 ldi wL,MAC2 ; MAC
 sts packet+pktSrc0L,wL ; address
 ldi wL,MAC3 ; to 
 sts packet+pktSrc1H,wL ; source
 ldi wL,MAC4
 sts packet+pktSrc1L,wL
 ldi wL,MAC5
 sts packet+pktSrc2H,wL
 ldi wL,MAC6
 sts packet+pktSrc2L,wL
 ldi lengthL,20 ;length of IP header
 clr lengthH
 ldi zL,low(packet+ip_verlen)
 ldi zH,high(packet+ip_verlen)
 rcall cksum
 sts packet+ip_cksum,valueH ;save new IP checksum
 sts packet+ip_cksum+1,valueL
 lds wH,packet+u_src ;get src port
 lds wL,packet+u_dst ;put dest port 
 sts packet+u_src,wL ;in source
 sts packet+u_dst,wH ;put source port in dest
 lds wH,packet+u_src+1 ;get src port
 lds wL,packet+u_dst+1 ;put dest port 
 sts packet+u_src+1,wL ;in source
 sts packet+u_dst+1,wH ;put source port in dest
 clr wL
 sts packet+u_cksum,wL ;clear UDP checksum for new calc
 sts packet+u_cksum+1,wL ;clear byte two
 ldi zl,low(packet+ip_src)
 ldi zh,high(packet+ip_src)
 lds lengthH,packet+ip_len
 lds lengthL,packet+ip_len+1
 ldi wL,20-8 ;ip_len-20+8 (20 is the length of an IP header.
 clr wH ; 8 is the length of the two IP fields (ip_src/ip_dst)
 sub lengthL,wL
 sbc lengthH,wH
 rcall cksum
 clr wH
 lds wL,packet+ip_proto ;get protocol (1 byte)
 sub valueL,wL ;add to accum
 sbc valueH,wH
 lds wH,packet+u_len ;add in UDP len
 lds wL,packet+u_len+1
 sub valueL,wL
 sbc valueH,wH
 sts packet+u_cksum,valueH
 sts packet+u_cksum+1,valueL
 rcall WritePacket
 ret
;
; WritePing - Send a ICMP Ping response
;
WritePing:
 ;we might want to check in the future for IA or broadcast requests
 clr wL
 sts packet+ip_cksum,wL
 sts packet+ip_cksum+1,wL ;clear checksum
 lds wL,packet+ip_src ;move
 sts packet+ip_dst,wL ; ip
 lds wL,packet+ip_src+1 ; of 
 sts packet+ip_dst+1,wL ; source
 lds wL,packet+ip_src+2 ; to
 sts packet+ip_dst+2,wL ; dest
 lds wL,packet+ip_src+3 
 sts packet+ip_dst+3,wL 
 ldi wL,IP1 ;move
 sts packet+ip_src,wL ; our
 ldi wL,IP2 ; ip
 sts packet+ip_src+1,wL ; address
 ldi wL,IP3 ; to
 sts packet+ip_src+2,wL ; source
 ldi wL,IP4 
 sts packet+ip_src+3,wL
 clr wL
 sts packet+ic_cksum,wL ;clear ICMP
 sts packet+ic_cksum+1,wL ; checksum
 sts packet+ic_type,wL ;make type a reply
 sts packet+ic_code,wL ;clear code
 lds wL,packet+pktSrc0H ;move
 sts packet+pktDest0H,wL ; mac src to dest
 lds wL,packet+pktSrc0L 
 sts packet+pktDest0L,wL 
 lds wL,packet+pktSrc1H ;move
 sts packet+pktDest1H,wL ; mac src to dest
 lds wL,packet+pktSrc1L 
 sts packet+pktDest1L,wL 
 lds wL,packet+pktSrc2H ;move
 sts packet+pktDest2H,wL ; mac src to dest
 lds wL,packet+pktSrc2L 
 sts packet+pktDest2L,wL
 ldi wL,MAC1 ;move
 sts packet+pktSrc0H,wL ; our
 ldi wL,MAC2 ; MAC
 sts packet+pktSrc0L,wL ; address
 ldi wL,MAC3 ; to 
 sts packet+pktSrc1H,wL ; source
 ldi wL,MAC4
 sts packet+pktSrc1L,wL
 ldi wL,MAC5
 sts packet+pktSrc2H,wL
 ldi wL,MAC6
 sts packet+pktSrc2L,wL
 ldi lengthL,20 ;set length of
 clr lengthH ; checksum calculation = length of IP header
 ldi zL,low(packet+ip_verlen);displacement to start of IP header
 ldi zH,high(packet+ip_verlen)
 rcall cksum ;calculate the checksum
 sts packet+ip_cksum,valueH ;set new checksum
 sts packet+ip_cksum+1,valueL
 lds lengthH,packet+ip_len ;get length high
 lds lengthL,packet+ip_len+1 ;calc length of ICMP header+data
 subi lengthL,20 ;-length of IP header
 sbci lengthH,0
 ldi zL,low(packet+ic_type) ;start of ICMP header
 ldi zH,high(packet+ic_type) ;start of ICMP header
 rcall cksum
 sts packet+ic_cksum,valueH ;set new checksum
 sts packet+ic_cksum+1,valueL
 rcall WritePacket
ICMPDone:
 ret
;----------------------------------------------------------------------
; Receive Event
; Input with RxEvent in valueH
;
ReceiveEvent:
;
; It's important to read the status and length high-order
; byte first. 
;
 Dinput ;make data bus input
 ior portRxTxData+1 ;read and discard status
 ior portRxTxData ;read and discard status
 ldi yL,low(packet) ;set indirect
 ldi yH,high(packet)
 ior portRxTxData+1 ;get length high
 st y+,wL ;save in header
 mov lengthH,wL ; and in lengthH
 ior portRxTxData ;get length low
 st y+,wL ;save in header area
 mov lengthL,wL ; and in lengthL
 sbrc lengthL,0 ;odd length?
 adiw lengthL,1 ;yes, increment lengthL/lengthH by 1
 lsr lengthH ;divide high by 2 and set carry appropriately
 ror lengthL ;rotate carry into lower and divide by 2
ReadFrame:
 ior portRxTxData ;read from CS8900
 st y+,wL ;write it to sram
 ior portRxTxData+1 ;read from CS8900
 st y+,wL ;write it to sram
 sbiw lengthL,1 ;decrement lengthL/lengthH
 brpl ReadFrame
 inc count ;increment packet counter
 sbr flags,1 ;flag frame read
 lds wL,packet+pktTypeH ;check if packet type
 cpi wL,0x08 ; is 0x0806 (ARP)
 brne ChkIP 
 lds wL,packet+pktTypeL
 cpi wL,0x06
 breq DoArp 
ChkIP:
 lds wL,packet+pktTypeH ;check if packet type
 cpi wL,0x08 ; is 0x0806 (ARP)
 brne REReturn 
 lds wL,packet+pktTypeL
 cpi wL,0x00
 breq DoIP 
REReturn:
 ret
;
; It's an arp request, Could be a request or a response.
; ARP packets are small so the whole thing is always in
; the register file.
;
DoArp:
 lds wL,packet+ar_hwtype+1 ;make sure it's 1
 cpi wL,0x01
 brne DoArpX
 lds wL,packet+ar_prtype ;compare to high
 cpi wL,0x08 ;make sure it's 0x0800
 brne DoArpX
 lds wL,packet+ar_prtype+1 ;compare to high
 cpi wL,0x00 ;make sure it's 0x0800
 brne DoArpX
 lds wL,packet+ar_hwlen ;make sure it's 6 for hwlen
 cpi wL,0x06 ;compare to high
 brne DoArpX
 lds wL,packet+ar_prlen ;make sure it's 4 for protocol length
 cpi wL,0x04 ;compare to low
 brne DoArpX
 lds wL,packet+ar_op+1 ;make sure it's 0x0001 for arp request
 cpi wL,0x01 ;compare to low
 brne DoArpX
 lds wL,packet+ar_tpa
 cpi wL,IP1
 brne DoArpX 
 lds wL,packet+ar_tpa+1
 cpi wL,IP2
 brne DoArpX 
 lds wL,packet+ar_tpa+2
 cpi wL,IP3
 brne DoArpX 
 lds wL,packet+ar_tpa+3
 cpi wL,IP4
 brne DoArpX 
; If we got to here, then we have a valid ARP request for our IP address
 sbr flags,2 ;set ARP flag
DoArpX:
 ret
;
; Process IP packet for ICMP or UDP requests
;
DoIP:
 lds wL,packet+ip_proto ;compare to this packet's proto
 cpi wL,IPT_ICMP ; to ICMP?
 breq DoICMP ;go process the ICMP packet
 cpi wL,IPT_UDP ; to UDP?
 breq DoUDP ;go process the UDP packet
 ret ;just return, we dont process this type
;
; Process UDP Port 7 echo requests
;
DoUDP:
 lds wL,packet+u_dst+1 ;compare to UDP packet
 cpi wL,7 ;port we're listing for requests on
 brne DoUDPDone
 sbr flags,4 ;we have a request for our port 7
DoUDPDone:
 ret
;
; Process ICMP (ping) requests
;
DoICMP:
 sbr flags,8 ;set flag to indicate ICMP ping request
 ret
;
; Calc checksum. Reads packet at offset zL/zH for
; lengthH/lengthL bytes and calculates the checksum
; in valueH/valueL.
;
cksum: clr chksumL ;we do the arithmetic
 clr chksumM ; using a 24
 clr chksumH ; bit area
	 sbrs lengthL,0		 ;odd length?
	 rjmp	cksumC
	 mov	 yL,zL
	 mov	 yH,zH
	 add	 yL,lengthL
	 adc	 yH,lengthH
 	clr	 wL
	 st	 y,wL		 	;clear byte after last
	 adiw	lengthL,1
cksumC: lsr	 lengthH
 	ror	 lengthL
cksuml: ld wH,z+ ;get high byte of 16-bit word
 ld wL,z+
 add chksumL,wL ;add to accum
 brcc noLcarry
 ldi wL,1
 add chksumM,wL
 brcc noLcarry
 add chksumH,wL
noLcarry:
 add chksumM,wH ;add in the high byte
 brcc noHcarry
 inc chksumH
noHcarry:
 subi lengthL,1
 sbci lengthH,0
 clr wL
 cpi lengthL,0
 cpc lengthH,wL
 breq CkDone
 brpl cksuml 
CkDone: add chksumL,chksumH ;add in the third byte of 24 bit area
 brcc CkDone1
 inc chksumM
CkDone1:mov valueL,chksumL
	 com	 valueL
 mov valueH,chksumM
	 com	 valueH
 ret
;
; Transmit Event
;
TransmitEvent:
 ret
;
; Processes the pending interrupt requests from the Interrupt Status Queue
;
ProcessISQ:
 ; Read the ISQ
NextEvt:
 Dinput
 ior portISQ ;read interrupt status queue
 mov valueL,wL ;save value low
 ior portISQ+1 ;read interrupt status queue high
 mov valueH,wL ;save value high
 tst valueL ;get val
 breq EvtRet
 cpi valueL,REG_NUM_RX_EVENT 
 breq evtRecv
 cpi valueL,REG_NUM_TX_EVENT 
 breq evtTran ;Ingore BufEvent, RxMiss, and TxCol
 rjmp NextEvt
evtRecv:
 rcall ReceiveEvent
 rjmp NextEvt
evtTran:
 rcall TransmitEvent
 rjmp NextEvt
EvtRet: ret
;
; Initializes the chip 
;
InitChip:
 ppWR ppLineCtl,LINE_CTL_10BASET ;set to 10BaseT
 ppWR ppTestCtl,TEST_CTL_FDX ;set to full duplex
 ppWR ppRxCfg,RX_CFG_RX_OK_IE ;enable RxOK interrupt
 ppWR ppRxCtl,(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A)
 ppWR ppTxCfg,TX_CFG_ALL_IE
;
; Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff
;
 ppWR ppIndAddr,(MAC2<<8|MAC1) ;0xbbaa Write
 ppWR ppIndAddr+2,(MAC4<<8|MAC3) ;0xddcc out
 ppWR ppIndAddr+4,(MAC6<<8|MAC5) ;0xffee 48 bit IA
 ppWR ppIntNum,0x00 ;INT is on INTRQ0
 ppRD ppBusCtl ;get Bus Control
 sbr valueH,0x80 ;enable irq
 rcall WritePP
 ppRD ppLineCtl ;get Line Control
 sbr valueL,0xc0 ;set SerRxOn and SerTxOn
 rcall WritePP
 ret
;
; Resets the CS8900
;
ResetChip: 
 ppWR ppSelfCtl,SELF_CTL_RESET ;issue a reset to the chip
ResetWait:
 ldi scratch,1 ;wait for
 rcall wait ;a millisecond
 ppRD ppSelfCtl ;get the Self Control status
 sbrc valueL,6 ;see it bit 6 (RESET) was cleared
 rjmp ResetWait ;no, then still in reset, wait some more
 ppRD ppSelfSt ;get self status
 sbrs valueL,7 ;bit 7 is INITD 
 rjmp ResetWait ; when set, initialization of the CS8900 is done
 ret
 
;
; Verifies that the CS8900 is attached and sets the STATUS,Z flag to
; indicate success or not set if failure.
;
VerChip:
 Dinput ;make the data bus input
 ; first, get the signature at portPtr which should be 0x3000
 ior portPtr ;read PacketPage Ptr
 mov valueL,wL ;save value low
 ior portPtr+1 ;read PacketPage Ptr for high order byte
 mov valueH,wL ;save high low
 tst valueL ;should be 0 (i.e. 0x3000 low is 0x00)
 brne VerBad
 cpi valueH,0x30 ;high part of 0x3000
 brne VerBad
 ppRD ppEISA ;get the EISA number whoch should be 0x630E
 cpi valueL,0x0e
 brne VerBad
 cpi valueH,0x63
 brne VerBad
 ppRD ppProdID ;get the Product ID which should be 000x xxxx 0000 0000
 ;where x xxxx = 0 0011 for rev E and 0 0101 for rev F
 tst valueL ;set return status
VerBad: ret ;return with Z indicating success or not.
;
; Writes the packet for lengthL/lengthH
;
WritePacket:
 Doutput
 ldi wL,TX_CMD_START_ALL
 iow portTxCmd
 clr wL
 iow portTxCmd+1
 lds wL,packet+pktLenL ;length 
 iow portTxLength ; of packet 
 lds wL,packet+pktLenH ; to send
 iow portTxLength+1
WPGetStat:
 ppRD ppBusSt ;get BusStatus
 sbrs valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit)
 rjmp WPGetStat ;no, wait for it
 Doutput
 ldi zL,low(packet+pktDest0H)
 ldi zH,high(packet+pktDest0H)
 lds lengthH,packet+pktLenH
 lds lengthL,packet+pktLenL
 sbrs lengthL,0 ;odd length?
 rjmp PacketEven ;nope, continue
 adiw lengthL,1 ;increment length
PacketEven:
 lsr lengthH ;divide high by 2 and set carry appropriately
 ror lengthL ;rotate carry into lower and divide by 2
PacketWriteLoop:
 ld wL,z+ ;get next byte
 iow portRxTxData
 ld wL,z+ ;get next byte
 iow portRxTxData+1
 sbiw lengthL,1 ;decrement lengthL/lengthH
 brpl PacketWriteLoop 
 ret
;
; Writes the value at valueH/valueL to the PagePacket register who's
; address is in offsetH/offsetL
;
WritePP:
 Doutput ;make the data bus output
 mov wL,offsetL ;get the low order byte
 iow portPtr ;write to PacketPage Ptr
 mov wL,offsetH ;get the high order byte
 iow portPtr+1 ;write to PacketPage ptr
 mov wL,valueL ;get low order value to write
 iow portData ;write to PacketPage data
 mov wL,valueH ;get high order data
 iow portData+1 ;write to PacketPage data
 ret
;
; Reads the PagePacket at offsetH/offsetL and returns the result in
; valueH/valueL.
;
ReadPP:
 Doutput ;make the data bus output
 mov wL,offsetL ;get the offset to read
 iow portPtr ;write to PacketPage Ptr
 mov wL,offsetH ;get the high order offset
 iow portPtr+1 ;PagePacket Pointer Register high byte
 Dinput ;make the data bus input
 ior portData ;read the PacketPage data
 mov valueL,wL ;save value low
 ior portData+1 ;read the high order byte
 mov valueH,wL ;save the high order byte value
 ret
ioRead:
 out CAB,wL
 cbi CSIG,CHIPSEL
 cbi CSIG,IOR 
 nop
 nop
 in wL,PIND 
 sbi CSIG,IOR 
 sbi CSIG,CHIPSEL
 ret
;
ioWrite:
 cbi CSIG,CHIPSEL
 cbi CSIG,IOW 
 nop
 sbi CSIG,IOW 
 sbi CSIG,CHIPSEL 
 ret

file: /Techref/atmel/avr/tcpip/atmel-crystal.asm, 43KB, , updated: 1999年6月4日 13:02, local time: 2025年9月9日 13:51,
40.74.122.252:LOG IN

©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/Techref/atmel/avr/tcpip/atmel-crystal.asm"> atmel avr tcpip atmel-crystal</A>

Did you find what you needed?

Welcome to massmind.org!

Welcome to massmind.org!

.

AltStyle によって変換されたページ (->オリジナル) /