.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,$3F ;Display off sts $8000,wL ldi scratch,4 rcall wait ;Wait 4ms ldi wL,$0F ;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: 2024/8/14 21:04,
18.190.239.122:LOG IN
|
©2024 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? <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! |
.