Gömülü ethernet, mikrodenetleyici tabanlı projelerin ağ üzerinden paket gönderip almasını sağlar. 10BaseT iletişimini etkinleştirmek için gereken tüm devreleri içerir. Kart, mikrodenetleyicilerle arayüz oluşturmak için gereken pin sayısını en aza indirecek şekilde tasarlanmıştır. 8 bitlik bir veri yolu, 4 bitlik bir adres yolu ve isteğe bağlı bir kesme sinyali ile birlikte üç kontrol sinyali (15 sinyal), kartı kontrol etmek için gereken tek şeydir. Bu, 8 bit modunda çalışan Crystal CS8900 ethernet alıcı-verici kullanılarak mümkün olmuştur.
Ethernet üzerinden TCP/IP iletişimini gerçekleştirmek için gerekli tüm bilgiler, şemalar ve kaynak kodları bu sayfada detaylandırılmıştır. Bu projede bir Microchip PIC16C74 denetleyici kullanıyorum ancak, yeterli port kapasitesine sahip herhangi bir denetleyici de çalışacaktır. Bu, popüler Motarola 68HC11’i içerir.
Burada açıklanan proje iki bölümden oluşmaktadır. Gerçek gömülü ethernet kartı ve PIC16C74’ü kullanan test devresi. PIC üzerinde çalışan kod, kart için gerekli sürücüleri ve ağ üzerinde iletişim kurmak için gerekli TCP/IP katmanlarını içerir.
Crystal CS8900’e Genel Bakış
Crystal CS8900, yalnızca bir izolasyon transformatörü ve bazı pasif bileşenler kullanarak doğrudan 10BaseT ethernet’in analog tarafına arabirim oluşturabilen tek çipli bir çözümdür. CS8900, mikrodenetleyiciye eşzamansız paketleri alıp göndermesine izin veren 4K entegre belleğe sahiptir. Bu, normalde mevcut olabilecek herhangi bir zamanlama sorununu ortadan kaldırır ve en yavaş mikrodenetleyicinin bile ethernet üzerinden konuşmasına izin verir. CS8900’ün kendisi 20Mhz’de çalışıyor ve harici bir kristal gerektiriyor. Çoğu ethernet alıcı-vericisi doğrudan ISA veriyolu üzerinde çalışır ve gelen ve giden paketler ve kontrol bilgileri için harici RAM’e erişmek üzere DMA’yı kullanır.
Kristal kısım da bu modda çalışır ancak 8 bitlik bir moda da sahiptir. Bu modu kullanmak, PC mimarisindeki bağlantı noktalarını kontrol etmeye benzer. Bir yazma işlemi için adres, örneğin 0x300 olmak üzere adres yoluna yerleştirilir, veriler veri yoluna yerleştirilir ve ardından /IOW sinyali değiştirilir. Adres kod çözme mantığı, panolardan birindeki port adresinin (0x300) orada olduğunu “görür” ve ardından veri yolundan verileri alır.
Bir okuma işlemi için, adres veri yoluna 0x300 adresi yerleştirilir ve /IOR sinyali değiştirilir, bu adrese sahip kart veriyi “in” komutunun okunması için veri yoluna yerleştirir. CS8900 bu şekilde 8 bit modunda çalışır ve port erişimi için varsayılan başlangıç adresi 0x300’dür ve 0x30F olarak devam eder. Tüm kayıt konumlarını adreslemek için adres yolunda gerçekten sadece 4 bitin gerekli olduğuna dikkat edin. Diğer adres yolu pinleri ya yüksek ya da düşük bağlanır. Bu 16 kayıt konumunu değiştirerek, PacketPage belleği olarak bilinen 4K dahili belleğin tamamını kontrol edebilirsiniz.
Temel olarak, CS8900, parça üzerinde çok daha geniş bir 4K dahili bellek alanını kontrol etmek için dolaylı bir dizi kayıt içerir. Örneğin belgeler, alınan çerçevenin uzunluğunun 0x0402 ve 0x0403 konumunda olduğunu belirtir (CS8900 her zaman 16 bit değerler kullanır), bu nedenle 0x0402 değerini PacketPage işaretçi konumuna (0xa ve 0xb) yerleştirir ve verileri PacketPage veri konumu (0xc ve 0xd). Okumakta olduğunuz gerçek veriler, PacketPage belleğindeki 0x0402 ve 0x0403 konumlarından gelmektedir. Bu teknik, Crystal uygulama notu AN112’de daha eksiksiz anlatılmıştır.
Bu kart ExpressPCB kullanılarak tasarlanmıştır. Pano düzeni tasarımı için yazılım, web sitelerinden ücretsiz olarak indirilebilir ve panoların siparişi, yazılım paketi aracılığıyla otomatikleştirilir.
CS8900 yalnızca 100 pinli QFP yüzeye montaj paketinde mevcut olduğundan, bu proje için profesyonelce tasarlanmış bir anakart kullanmanız gerekeceği belirtilmelidir.
Mikroçip PIC16C74, CS8900’ü sürmek ve bazı temel TCP/IP işlevlerini uygulamak için kullanılır. Test devresi, ethernet omurgasına bağlandıktan sonra başka bir düğümden pinglenebilir. Ayrıca, UDP bağlantı noktası 7’yi (eko) dinleyen test devresine bağlanan bir Windows Sockets programı dahildir. Yankı hizmeti aldığı tüm verileri geri gönderir.
Programların tümü, 192.168.1.2 IP adresini ve 00:00:00:12:34:56 Ethernet adresini (OUI-Kuruluşsal Olarak Benzersiz Tanımlayıcı olarak da adlandırılır) kullanacak şekilde ayarlanmıştır. Bunlar hayali rakamlar olduğu için değiştirmeniz gerekebilir. Değişiklik gerektiren iki yer, PIC üzerinde çalışan program bu değerler için eşitliklere sahiptir ve IP adresi testudp.c programında sabit olarak kodlanmıştır.
Bunları değiştirmezseniz ve NT (önerilen) altında test ediyorsanız, route add 192.168.1.2 your.ip.gateway.address komutunu kullanarak statik bir rota eklemeniz gerekebilir. Bu, panoya giden tüm trafiğin yerel makinenizin varsayılan ağ geçidinden geçmesine neden olur.
Assembly yazılımı
list p=pic16c74 __config h'3ffa' ;HS crystal, 20Mhz include; ; *Change these* : Configuration equates. ; IP1 equ d'192' ;first octet of IP address IP2 equ d'168' ;second octet of IP address IP3 equ d'1' ;third octet of IP address IP4 equ d'2' ;fourth octet of IP address ; MAC1 equ 0x00 ;\ MAC2 equ 0x00 ; \ MAC3 equ 0x00 ; \ MAC4 equ 0x12 ; 48 bit IEEE OUI (Organizationally Unique Identifier) MAC5 equ 0x34 ; / MAC6 equ 0x56 ;/ ; ; Some useful macros ; ppRD macro addr ;Read PacketPage port movlw addr&0xff movwf offsetL movlw addr>>8 movwf offsetH call ReadPP endm ; ppWR macro addr,val ;Write PacketPage port movlw addr&0xff movwf offsetL movlw addr>>8 movwf offsetH movlw val&0xff movwf valueL movlw val>>8 movwf valueH call WritePP endm ; Dinput macro ;Change the data bus to input bsf STATUS,RP0 movlw 0xff movwf TRISB bcf STATUS,RP0 endm ; Doutput macro ;Change the data bus to output bsf STATUS,RP0 clrf TRISB bcf STATUS,RP0 endm ; ior macro port ;I/O port read movlw port call ioRead endm ; iow macro port ;I/O port write movwf PORTB movlw port movwf PORTA call ioWrite endm ; ; Crystal CS8900 PacketPage equates ; portRxTxData equ 0x00 ;Receive/Transmit data (port 0) portRxTxData1 equ 0x02 ;Receive/Transmit data (port 0) portTxCmd equ 0x04 ;Transmit Commnad portTxLength equ 0x06 ;Transmit Length portISQ equ 0x08 ;Interrupt status queue portPtr equ 0x0a ;PacketPage pointer portData equ 0x0c ;PacketPage data (port 0) portData1 equ 0x0e ;PacketPage data (port 1) ; ; CS8900 PacketPage Offsets ; ppEISA equ 0x0000 ;EISA Registration number of CS8900 ppProdID equ 0x0002 ;Product ID Number ppIOBase equ 0x0020 ;I/O Base Address ppIntNum equ 0x0022 ;Interrupt number (0,1,2, or 3) ppMemBase equ 0x002C ;Memory Base address register (20 bit) ppRxCfg equ 0x0102 ;Receiver Configuration ppRxCtl equ 0x0104 ;Receiver Control ppTxCfg equ 0x0106 ;Transmit Configuration ppBufCfg equ 0x010A ;Buffer Configuration ppLineCtl equ 0x0112 ;Line Control ppSelfCtl equ 0x0114 ;Self Control ppBusCtl equ 0x0116 ;Bus Control ppTestCtl equ 0x0118 ;Test Control ppISQ equ 0x0120 ;Interrupt status queue ppRxEvt equ 0x0124 ;Receiver Event ppTxEvt equ 0x0128 ;Transmitter Event ppBufEvt equ 0x012C ;Buffer Event ppRxMiss equ 0x0130 ;Receiver Miss Counter ppTxCol equ 0x0132 ;Transmit Collision Counter ppLineSt equ 0x0134 ;Line Status ppSelfSt equ 0x0136 ;Self Status ppBusSt equ 0x0138 ;Bus Status ppTxCmd equ 0x0144 ;Transmit Command Request ppTxLength equ 0x0146 ;Transmit Length ppIndAddr equ 0x0158 ;Individual Address (IA) ppRxStat equ 0x0400 ;Receive Status ppRxLength equ 0x0402 ;Receive Length ppRxFrame equ 0x0404 ;Receive Frame Location ppTxFrame equ 0x0A00 ;Transmit Frame Location ; ; Register Numbers ; REG_NUM_MASK equ 0x003F REG_NUM_RX_EVENT equ 0x0004 REG_NUM_TX_EVENT equ 0x0008 REG_NUM_BUF_EVENT equ 0x000C REG_NUM_RX_MISS equ 0x0010 REG_NUM_TX_COL equ 0x0012 ; ; Self Control Register ; SELF_CTL_RESET equ 0x0040 SELF_CTL_HC1E equ 0x2000 SELF_CTL_HCB1 equ 0x8000 ; ; Self Status Register ; SELF_ST_INIT_DONE equ 0x0080 SELF_ST_SI_BUSY equ 0x0100 SELF_ST_EEP_PRES equ 0x0200 SELF_ST_EEP_OK equ 0x0400 SELF_ST_EL_PRES equ 0x0800 ; ; Bus Control Register ; BUS_CTL_USE_SA equ 0x0200 BUS_CTL_MEM_MODE equ 0x0400 BUS_CTL_IOCHRDY equ 0x1000 BUS_CTL_INT_ENBL equ 0x8000 ; ; Bus Status Register ; BUS_ST_TX_BID_ERR equ 0x0080 BUS_ST_RDY4TXNOW equ 0x0100 ; ; Line Control Register ; LINE_CTL_RX_ON equ 0x0040 LINE_CTL_TX_ON equ 0x0080 LINE_CTL_AUI_ONLY equ 0x0100 LINE_CTL_10BASET equ 0x0000 ; ; Test Control Register ; TEST_CTL_DIS_LT equ 0x0080 TEST_CTL_ENDEC_LP equ 0x0200 TEST_CTL_AUI_LOOP equ 0x0400 TEST_CTL_DIS_BKOFF equ 0x0800 TEST_CTL_FDX equ 0x4000 ; ; Receiver Configuration Register ; RX_CFG_SKIP equ 0x0040 RX_CFG_RX_OK_IE equ 0x0100 RX_CFG_CRC_ERR_IE equ 0x1000 RX_CFG_RUNT_IE equ 0x2000 RX_CFG_X_DATA_IE equ 0x4000 ; ; Receiver Event Register ; RX_EVENT_RX_OK equ 0x0100 RX_EVENT_IND_ADDR equ 0x0400 RX_EVENT_BCAST equ 0x0800 RX_EVENT_CRC_ERR equ 0x1000 RX_EVENT_RUNT equ 0x2000 RX_EVENT_X_DATA equ 0x4000 ; ;Receiver Control Register ; RX_CTL_RX_OK_A equ 0x0100 RX_CTL_MCAST_A equ 0x0200 RX_CTL_IND_A equ 0x0400 RX_CTL_BCAST_A equ 0x0800 RX_CTL_CRC_ERR_A equ 0x1000 RX_CTL_RUNT_A equ 0x2000 RX_CTL_X_DATA_A equ 0x4000 ; ;Transmit Configuration Register ; TX_CFG_LOSS_CRS_IE equ 0x0040 TX_CFG_SQE_ERR_IE equ 0x0080 TX_CFG_TX_OK_IE equ 0x0100 TX_CFG_OUT_WIN_IE equ 0x0200 TX_CFG_JABBER_IE equ 0x0400 TX_CFG_16_COLL_IE equ 0x8000 TX_CFG_ALL_IE equ 0x8FC0 ; ;Transmit Event Register ; TX_EVENT_TX_OK equ 0x0100 TX_EVENT_OUT_WIN equ 0x0200 TX_EVENT_JABBER equ 0x0400 TX_EVENT_16_COLL equ 0x1000 ; ; Transmit Command Register ; TX_CMD_START_5 equ 0x0000 TX_CMD_START_381 equ 0x0080 TX_CMD_START_1021 equ 0x0040 TX_CMD_START_ALL equ 0x00C0 TX_CMD_FORCE equ 0x0100 TX_CMD_ONE_COLL equ 0x0200 TX_CMD_NO_CRC equ 0x1000 TX_CMD_NO_PAD equ 0x2000 ; ;Buffer Configuration Register ; BUF_CFG_SW_INT equ 0x0040 BUF_CFG_RDY4TX_IE equ 0x0100 BUF_CFG_TX_UNDR_IE equ 0x0200 ; ; PORTA pin assignments (Crystal address bus) ; SA0 equ 0 SA1 equ 1 SA2 equ 2 SA3 equ 3 ;RA4 equ 4 ;not used (ST) ;RA5 equ 5 ;not used (TTL) ; ; PORTB pin assignments (Crystal data bus) ; SD0 equ 0 SD1 equ 1 SD2 equ 2 SD3 equ 3 SD4 equ 4 SD5 equ 5 SD6 equ 6 SD7 equ 7 ; ; PORTC pin assignments (Crystal signals CHIPSEL/IOW/IOR) ; IOR equ 0 ;active low signal to initiate I/O read operation IOW equ 1 ;active low signal to initiate I/O write operation CHIPSEL equ 2 ;active low signal to select the CS8900 chip INTR equ 3 ;active HIGH interrupt pending signal. Auto cleared after read of ISQ ;RC4 equ 4 ;not used (ST) ;RC5 equ 5 ;not used (ST) ;RC6 equ 6 ;not used (ST) ;RC7 equ 7 ;not used (ST) ; ; PORTD pin assignments ; ;RD0 equ 0 ;not used ;RD1 equ 1 ;not used ;RD2 equ 2 ;not used ;RD3 equ 3 ;not used ;RD4 equ 4 ;not used ;RD5 equ 5 ;not used ;RD6 equ 6 ;not used ;RD7 equ 7 ;not used ; ; PORTE pin assignments (LCD control) ; ;RE0 equ 0 ;not used ;RE1 equ 1 ;not used ;RE2 equ 2 ;not used ; ; Register file assignments ; tempH equ 0x20 tempL equ 0x21 loops equ 0x22 loops2 equ 0x23 loops3 equ 0x24 char equ 0x25 cnt_low equ 0x26 cnt_mid equ 0x27 cnt_hi equ 0x28 bcd1 equ 0x29 bcd2 equ 0x2a bcd3 equ 0x2b valueH equ 0x2c valueL equ 0x2d offsetH equ 0x2e offsetL equ 0x2f flags equ 0x30 hextemp equ 0x31 lengthH equ 0x32 lengthL equ 0x33 packet equ 0x34 ;the highest register file location is 3F because we need 64 bytes after this. ; ; Packet offset equates ; ; ; Packet header ; pktLenH equ 0x00 pktLenL equ 0x01 pktDest0H equ 0x02 pktDest0L equ 0x03 pktDest1H equ 0x04 pktDest1L equ 0x05 pktDest2H equ 0x06 pktDest2L equ 0x07 pktSrc0H equ 0x08 pktSrc0L equ 0x09 pktSrc1H equ 0x0a pktSrc1L equ 0x0b pktSrc2H equ 0x0c pktSrc2L equ 0x0d pktTypeH equ 0x0e pktTypeL equ 0x0f ; ; ARP ; ar_hwtype equ 0x10 ;hardware type ar_prtype equ 0x12 ;protocol type ar_hwlen equ 0x14 ;hardware address length ar_prlen equ 0x15 ;protocol address length ar_op equ 0x16 ;ARP operation (1=request, 2=reply) ar_sha equ 0x18 ;senders hardware address ar_spa equ 0x1e ;senders IP address ar_tha equ 0x22 ;target hardware address ar_tpa equ 0x28 ;target IP address ; ; IP header ; ip_verlen equ 0x10 ;IP version and header length(in longs) ip_tos equ 0x11 ;IP type of service ip_len equ 0x12 ;packet length (length-header_length) ip_id equ 0x14 ;datagram id ip_fragoff equ 0x16 ;fragment offset ip_ttl equ 0x18 ;time to live (in gateway hops) ip_proto equ 0x19 ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17) ip_cksum equ 0x1a ;header checksum ip_src equ 0x1c ;IP address of source ip_dst equ 0x20 ;IP addess of destination ip_data equ 0x24 ; ; IP value equates ; IPT_ICMP equ 1 ;protocol type for ICMP packets IPT_TCP equ 6 ;protocol type for TCP packets IPT_EGP equ 8 ;protocol type for EGP packets IPT_UDP equ 0x11 ;protocol type for UDP packets ; ; ICMP header ; ic_type equ ip_data ;0=reply, 8=request, others=who-cares ic_code equ ic_type+1 ;code ic_cksum equ ic_code+1 ;checksum of header+data ic_id equ ic_cksum+2 ;message id ic_seq equ ic_id+2 ;sequence number ; ; UDP Header ; u_src equ ip_data ;source udp port number u_dst equ u_src+2 ;destination UDP port number u_len equ u_dst+2 ;length of UDP header+data u_cksum equ u_len+2 ;checksum (see note) u_data equ 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 ; org 0 goto start ; org 4 retfie ; start bsf STATUS,RP0 movlw 0xff ;make all RA/RE movwf ADCON1 ;pins digital I/O clrf TRISA ;crystal address bus output clrf TRISB ;crystal data bus output clrf TRISC ;crystal control signals output bcf STATUS,RP0 bsf PORTC,IOR ;no read on crystal bsf PORTC,IOW ;no write on crystal bsf PORTC,CHIPSEL ;address enable clrf PORTA ;clear address bus call VerChip call ResetChip call InitChip clrf flags loop btfss PORTC,INTR ;wait for interrupt goto loop call ProcessISQ btfss flags,0 ;received frame flag goto loop bcf flags,0 ;clear the receive flag btfss flags,1 ;bit set when valid arp goto loop bcf flags,1 ;clear the valid arp request flag call SendARP goto loop ; ; wait for W milliseconds ; wait movwf loops wait0 movlw 5 movwf loops2 wait1 movlw .110 movwf loops3 wait2 nop nop nop nop nop nop decfsz loops3,1 goto wait2 decfsz loops2,1 goto wait1 decfsz loops,1 goto wait0 return ; ; Compare two 16 bit numbers and return the result in STATUS,C ; If C=0, valueH/valueL is less than tempH/tempL ; if C=1, then valueH/valueL is greater than or equal to tempH/tempL ; valueH/valueH are destroyed in the process. cmp16 movf tempL,0 ;get low subwf valueL,1 btfsc STATUS,C ;C=0 means its neg goto cmpH ;C=1, valueL is >= 0x7f movlw 1 subwf valueH,1 ;decrement high btfss STATUS,C ;if it goes neg, then goto cmpIsLess ; value is less than 0x7f cmpH movf tempH,0 ;0x00 part of 0x007f subwf valueH,1 ;subtract btfss STATUS,C goto cmpIsLess bsf STATUS,C ; valueH/valueL is greater or equal to tempH/tempL return cmpIsLess bcf STATUS,C ;valueH/valueL is less than 0x007F return ;************************************************************************ ;* C S 8 9 0 0 D r i v e r F u n c t i o n s * ;************************************************************************ ; ; SendARP - Send a response ARP to the requestor ; SendARP Doutput movlw TX_CMD_START_ALL iow portTxCmd movlw 0 iow portTxCmd+1 movlw d'42' ;length of ARP response frame iow portTxLength movlw 0 iow portTxLength+1 RTGetStat ppRD ppBusSt ;get BusStatus btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit) goto RTGetStat ;no, wait for it Doutput ; Send dest (6) movf packet+pktSrc0H,0 iow portRxTxData movf packet+pktSrc0L,0 iow portRxTxData+1 movf packet+pktSrc1H,0 iow portRxTxData movf packet+pktSrc1L,0 iow portRxTxData+1 movf packet+pktSrc2H,0 iow portRxTxData movf packet+pktSrc2L,0 iow portRxTxData+1 ; Send src (6) movlw MAC1 iow portRxTxData movlw MAC2 iow portRxTxData+1 movlw MAC3 iow portRxTxData movlw MAC4 iow portRxTxData+1 movlw MAC5 iow portRxTxData movlw MAC6 iow portRxTxData+1 ; Send type (2) movlw 0x08 iow portRxTxData movlw 0x06 iow portRxTxData+1 ; Send hwtype (2) movlw 0x00 iow portRxTxData movlw 0x01 iow portRxTxData+1 ; Send prtype (protocol type) (2) movlw 0x08 iow portRxTxData movlw 0x00 iow portRxTxData+1 ; Send hardware and protocol address lengths (2) movlw 0x06 iow portRxTxData movlw 0x04 iow portRxTxData+1 ; Send operation (response) (2) movlw 0x00 iow portRxTxData movlw 0x02 iow portRxTxData+1 ; Send Senders HW address (6) movlw MAC1 iow portRxTxData movlw MAC2 iow portRxTxData+1 movlw MAC3 iow portRxTxData movlw MAC4 iow portRxTxData+1 movlw MAC5 iow portRxTxData movlw MAC6 iow portRxTxData+1 ; Send Senders IP (4) movlw IP1 iow portRxTxData movlw IP2 iow portRxTxData+1 movlw IP3 iow portRxTxData movlw IP4 iow portRxTxData+1 ; Send Target HW address (6) movf packet+pktSrc0H,0 iow portRxTxData movf packet+pktSrc0L,0 iow portRxTxData+1 movf packet+pktSrc1H,0 iow portRxTxData movf packet+pktSrc1L,0 iow portRxTxData+1 movf packet+pktSrc2H,0 iow portRxTxData movf packet+pktSrc2L,0 iow portRxTxData+1 ; Send Target IP (4) movf packet+ar_spa,0 iow portRxTxData movf packet+ar_spa+1,0 iow portRxTxData+1 movf packet+ar_spa+2,0 iow portRxTxData movf packet+ar_spa+3,0 iow portRxTxData+1 return ; ; ; ; Receive Event ; Input with RxEvent in valueH ; ReceiveEvent Dinput ;make data bus input ; ; It's important to read the status and length high-order ; byte first. ; ior portRxTxData+1 ;read and discard status ior portRxTxData ;read and discard status movlw packet+2 ;set indirect movwf FSR ; address ior portRxTxData+1 ;get length high movwf packet+pktLenH ;save in header area movwf lengthH ; and in lengthH movwf valueH ;save for compare ior portRxTxData ;get length low movwf packet+pktLenL ;save in header area movwf lengthL ; and in lengthL movwf valueL ;save for compare ReadFrame movlw 0x7f-packet ;this is the max packet length addlw packet subwf FSR,0 btfsc STATUS,C goto RFCont ;done ; if C=0 (FSR-packet+64 is neg) then we have not received max bytes yet so write to register file ior portRxTxData ;read from CS8900 movwf INDF ;write it to file register incf FSR,1 ;increment file location ior portRxTxData+1 ;read from CS8900 movwf INDF ;write it to file register incf FSR,1 ;increment file location goto RFCont ;continue RFCont movlw 2 subwf lengthL,1 btfsc STATUS,C ;see if negative (C=0) goto RF1 ;C set so result is zero or better movlw 1 subwf lengthH,1 ;decrement high btfss STATUS,C goto ReadDone ;high went neg, we're done RF1 movf lengthL,0 ;get low btfss STATUS,Z goto ReadFrame ;not zero, continue movf lengthH,0 btfss STATUS,Z goto ReadFrame ;not zero, continue ReadDone movlw 1 iorwf flags,1 ;flag frame read movlw 0x08 ;check if subwf packet+pktTypeH,0 ; packet type btfss STATUS,Z ; is 0x0806 (ARP) goto ChkIP ;no, check IP movlw 0x06 subwf packet+pktTypeL,0 btfsc STATUS,Z goto DoArp ChkIP movlw 0x08 ;check if subwf packet+pktTypeH,0 ; packet type btfss STATUS,Z ; is 0x0800 (IP) return ;no, just return movf packet+pktTypeL,0 btfsc STATUS,Z goto DoIP ;process IP packet return discard ppRD ppRxCfg movlw RX_CFG_SKIP iorwf valueL,1 call WritePP ;discard frame return ; ; 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 movlw 0x01 ;make sure it's 1 subwf packet+ar_hwtype+1,0 ;compare to low btfss STATUS,Z return ;exit, bad request movlw 0x08 ;make sure it's 0x0800 subwf packet+ar_prtype,0 ;compare to high btfss STATUS,Z return ;exit, bad request movlw 0 ;make sure it's 0x0800 subwf packet+ar_prtype+1,0 ;compare to low btfss STATUS,Z return ;exit, bad request movlw 0x06 ;make sure it's 6 for hwlen subwf packet+ar_hwlen,0 ;compare to high btfss STATUS,Z return ;exit, bad request movlw 0x04 ;make sure it's 4 for protocol length subwf packet+ar_prlen,0 ;compare to low btfss STATUS,Z return ;exit, bad request movlw 0x01 ;make sure it's 0x0001 for arp request subwf packet+ar_op+1,0 ;compare to low btfss STATUS,Z return ;exit, bad request movlw IP1 ;First IP octet subwf packet+ar_tpa,0 btfss STATUS,Z return ;exit, bad request movlw IP2 ;second IP octet subwf packet+ar_tpa+1,0 btfss STATUS,Z return ;exit, bad request movlw IP3 ;Third IP octet subwf packet+ar_tpa+2,0 btfss STATUS,Z return ;exit, bad request movlw IP4 ;fourth IP octet subwf packet+ar_tpa+3,0 btfss STATUS,Z return ;exit, bad request ; If we got to here, then we have a valid ARP request for our IP address movlw 2 iorwf flags,1 return ; ; Process IP packet for ICMP or UDP requests ; DoIP movlw IPT_ICMP ;get protocol number for ICMP subwf packet+ip_proto,0 ;compare to this packet's proto btfsc STATUS,Z ;if zero, then it's ICMP goto DoICMP ;go process ICMP packet movlw IPT_UDP ;get protocol number for UDP subwf packet+ip_proto,0 ;compare to this packet's proto btfss STATUS,Z ;if zero, then it's ICMP return ;just return, we dont process this type DoUDP movlw 7 ;port we're listing for requests on subwf packet+u_dst+1,0 ;compare to UDP packet btfss STATUS,Z ;if zero, then it's echo port return ;otherwise, just return clrf packet+ip_cksum ;clear clrf packet+ip_cksum+1 ; checksum movf packet+ip_src,0 ;move movwf packet+ip_dst ; ip movf packet+ip_src+1,0 ; of movwf packet+ip_dst+1 ; source movf packet+ip_src+2,0 ; to movwf packet+ip_dst+2 ; dest movf packet+ip_src+3,0 movwf packet+ip_dst+3 movlw IP1 ;move movwf packet+ip_src ; our movlw IP2 ; ip movwf packet+ip_src+1 ; address movlw IP3 ; to movwf packet+ip_src+2 ; source movlw IP4 movwf packet+ip_src+3 movf packet+pktSrc0H,0 ;move movwf packet+pktDest0H ; mac src to dest movf packet+pktSrc0L,0 movwf packet+pktDest0L movf packet+pktSrc1H,0 ;move movwf packet+pktDest1H ; mac src to dest movf packet+pktSrc1L,0 movwf packet+pktDest1L movf packet+pktSrc2H,0 ;move movwf packet+pktDest2H ; mac src to dest movf packet+pktSrc2L,0 movwf packet+pktDest2L movlw MAC1 ;move movwf packet+pktSrc0H ; our movlw MAC2 ; MAC movwf packet+pktSrc0L ; address movlw MAC3 ; to movwf packet+pktSrc1H ; source movlw MAC4 movwf packet+pktSrc1L movlw MAC5 movwf packet+pktSrc2H movlw MAC6 movwf packet+pktSrc2L movlw d'20' movwf lengthL clrf lengthH movlw packet+ip_verlen call cksum movf valueH,0 movwf packet+ip_cksum ;save new checksum movf valueL,0 movwf packet+ip_cksum+1 movf packet+u_src,0 ;get src port movwf tempL movf packet+u_dst,0 ;put dest port movwf packet+u_src ;in source movf tempL,0 movwf packet+u_dst ;put source port in dest movf packet+u_src+1,0 ;get src port movwf tempL movf packet+u_dst+1,0 ;put dest port movwf packet+u_src+1 ;in source movf tempL,0 movwf packet+u_dst+1 ;put source port in dest clrf packet+u_cksum ;clear UDP checksum for new calc clrf packet+u_cksum+1 ;clear byte two clrf cnt_low clrf cnt_mid ;clear checksum accum clrf cnt_hi movlw packet+ip_src movwf FSR movlw d'8' ;IP_ALEN*2 call UDPCkSum movf packet+ip_proto,0 ;get protocol (1 byte) addwf cnt_low,1 ;add to accum btfss STATUS,C goto ProtoDone movlw 1 addwf cnt_mid,1 btfsc STATUS,C incf cnt_hi,1 ProtoDone movlw packet+u_len ;add in UDP len movwf FSR movlw d'2' call UDPCkSum movlw packet+u_src movwf FSR movf packet+u_len+1,0 call UDPCkSum movf cnt_hi,0 addwf cnt_low,1 btfsc STATUS,C incf cnt_mid,1 comf cnt_mid,0 movwf packet+u_cksum comf cnt_low,0 movwf packet+u_cksum+1 Doutput movlw TX_CMD_START_ALL iow portTxCmd movlw 0 iow portTxCmd+1 movf packet+pktLenL,0 ;length of ARP response frame iow portTxLength movf packet+pktLenH,0 iow portTxLength+1 UDPGetStat ppRD ppBusSt ;get BusStatus btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit) goto UDPGetStat ;no, wait for it Doutput btfss packet+pktLenL,0 goto WriteEven ;even # of bytes movf packet+pktLenL,0 ;get length addlw packet movwf FSR clrf INDF ;clear byte WriteEven movlw packet+2 movwf FSR movf packet+pktLenL,0 movwf tempL ;save length of send in temp WriteUDP movf INDF,0 iow portRxTxData incf FSR,1 movf INDF,0 iow portRxTxData+1 incf FSR,1 movlw 2 subwf tempL,1 btfsc STATUS,Z goto UDPDone btfsc STATUS,C goto WriteUDP UDPDone return ; ; Calc (cumulative) checksum of UDP header/data ; UDPCkSum movwf tempL ;save length of buffer bcf STATUS,C ;clear carry rrf tempL,1 ;/2 cuz we process 2 bytes at a time UDPCklp movf INDF,0 ;get next byte high movwf valueH ;save it incf FSR,1 ;increment to low byte movf INDF,0 ;get low incf FSR,1 ;increment addwf cnt_low,1 ;add to accum btfss STATUS,C goto UDPLcarry movlw 1 addwf cnt_mid,1 btfsc STATUS,C incf cnt_hi,1 UDPLcarry movf valueH,0 ;get the high again addwf cnt_mid,1 btfsc STATUS,C incf cnt_hi,1 decfsz tempL,1 goto UDPCklp return ; ; Process ICMP (ping) requests ; DoICMP ;we might want to check in the future for IA or broadcast requests clrf packet+ip_cksum clrf packet+ip_cksum+1 ;clear checksum movf packet+ip_src,0 ;move movwf packet+ip_dst ; ip movf packet+ip_src+1,0 ; of movwf packet+ip_dst+1 ; source movf packet+ip_src+2,0 ; to movwf packet+ip_dst+2 ; dest movf packet+ip_src+3,0 movwf packet+ip_dst+3 movlw IP1 ;move movwf packet+ip_src ; our movlw IP2 ; ip movwf packet+ip_src+1 ; address movlw IP3 ; to movwf packet+ip_src+2 ; source movlw IP4 movwf packet+ip_src+3 clrf packet+ic_cksum ;clear ICMP clrf packet+ic_cksum+1 ; checksum clrf packet+ic_type ;make type a reply clrf packet+ic_code ;clear code movf packet+pktSrc0H,0 ;move movwf packet+pktDest0H ; mac src to dest movf packet+pktSrc0L,0 movwf packet+pktDest0L movf packet+pktSrc1H,0 ;move movwf packet+pktDest1H ; mac src to dest movf packet+pktSrc1L,0 movwf packet+pktDest1L movf packet+pktSrc2H,0 ;move movwf packet+pktDest2H ; mac src to dest movf packet+pktSrc2L,0 movwf packet+pktDest2L movlw MAC1 ;move movwf packet+pktSrc0H ; our movlw MAC2 ; MAC movwf packet+pktSrc0L ; address movlw MAC3 ; to movwf packet+pktSrc1H ; source movlw MAC4 movwf packet+pktSrc1L movlw MAC5 movwf packet+pktSrc2H movlw MAC6 movwf packet+pktSrc2L movlw d'20' ;length of IP header movwf lengthL ;set length of clrf lengthH ; checksum calculation movlw packet+ip_verlen ;displacement to start of IP header call cksum ;calculate the checksum movf valueH,0 movwf packet+ip_cksum ;set new checksum movf valueL,0 movwf packet+ip_cksum+1 movf packet+ip_len,0 ;get length high movwf lengthH movlw d'20' ;ip header length subwf packet+ip_len+1,0 ;calc length of ICMP header+data movwf lengthL btfss STATUS,C decf lengthH,1 ;if prev sub went neg then dec high movlw packet+ic_type ;start of ICMP header call cksum movf valueH,0 ;set new checksum movwf packet+ic_cksum movf valueL,0 movwf packet+ic_cksum+1 Doutput movlw TX_CMD_START_ALL iow portTxCmd movlw 0 iow portTxCmd+1 movf packet+pktLenL,0 ;length of ICMP response frame iow portTxLength ; is the same as movf packet+pktLenH,0 ; the request. iow portTxLength+1 ICMPGetStat ppRD ppBusSt ;get BusStatus btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit) goto ICMPGetStat ;no, wait for it Doutput movlw packet+pktDest0H movwf FSR movf packet+pktLenL,0 ;length movwf lengthL ; to movf packet+pktLenH,0 ; send movwf lengthH WritePing movf INDF,0 ;get next byte incf FSR,1 iow portRxTxData movf INDF,0 ;get next byte incf FSR,1 iow portRxTxData+1 movlw 2 ;subtract subwf lengthL,1 ; two byte from length btfsc STATUS,C ;see if negative (C=0) goto WP1 ;C set so result is zero or better movlw 1 subwf lengthH,1 ;decrement high btfss STATUS,C ;c=0 means negative goto ICMPDone ;high went neg, we're done WP1 movf lengthL,0 ;get low btfss STATUS,Z goto WritePing ;not zero, continue movf lengthH,0 btfss STATUS,Z goto WritePing ;not zero, continue ICMPDone return ; ; Calc checksum. Reads packet at offset W for ; LengthH/LengthL bytes and calculates the checksum ; in valueH/valueL. ; cksum movwf FSR clrf cnt_low ;we do the arithmetic clrf cnt_mid ; using a 24 clrf cnt_hi ; bit area cksuml movf INDF,0 ;get high byte of 16-bit word movwf valueH ;save it incf FSR,1 movf INDF,0 incf FSR,1 addwf cnt_low,1 ;add to accum btfss STATUS,C goto noLcarry movlw 1 addwf cnt_mid,1 btfsc STATUS,C incf cnt_hi,1 noLcarry movf valueH,0 ;get the high again addwf cnt_mid,1 btfsc STATUS,C incf cnt_hi,1 ; movlw 2 ;subtract subwf lengthL,1 ; two byte from length btfsc STATUS,C ;see if negative (C=0) goto CK1 ;C set so result is zero or better movlw 1 subwf lengthH,1 ;decrement high btfss STATUS,C ;c=0 means negative goto CkDone ;high went neg, we're done CK1 movf lengthL,0 ;get low btfss STATUS,Z goto cksuml ;not zero, continue movf lengthH,0 btfss STATUS,Z goto cksuml ;not zero, continue ; CkDone movf cnt_hi,0 ;get the third byte of 24 bit area addwf cnt_low,1 ;any carries into this are added in btfsc STATUS,C ;if that caused a carry, then incf cnt_mid,1 ; increment the middle byte comf cnt_low,0 ;get and ones complement movwf valueL ;save it to low comf cnt_mid,0 ;get and ones complement movwf valueH ;save as high return ; ; Transmit Event ; TransmitEvent return ; ; Processes the pending interrupt requests from the Interrupt Status Queue ; ProcessISQ ; Read the ISQ NextEvt Dinput ior portISQ ;read interrupt status queue movwf valueL ;save value low ior portISQ+1 ;read interrupt status queue high movwf valueH ;save value high movf valueL,0 ;get val btfsc STATUS,Z return ;if zero, then done movlw REG_NUM_RX_EVENT subwf valueL,0 ;RxEvent? btfsc STATUS,Z goto evtRecv movlw REG_NUM_TX_EVENT subwf valueL,0 ;TxEvent? btfsc STATUS,Z ;Ingore BufEvent, RxMiss, and TxCol call TransmitEvent goto NextEvt evtRecv call ReceiveEvent goto NextEvt ; ; 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 bsf valueH,7 ;enable irq call WritePP ;write it back ppRD ppLineCtl ;get Line Control bsf valueL,6 ;set SerRxOn bsf valueL,7 ;set SerTxOn call WritePP ;write it back return ; ; Resets the CS8900 ; ResetChip ppWR ppSelfCtl,SELF_CTL_RESET ;issue a reset to the chip ResetWait movlw d'1' ;wait for call wait ;a millisecond ppRD ppSelfCtl ;get the Self Control status btfsc valueL,6 ;see it bit 6 (RESET) was cleared goto ResetWait ;no, then still in reset, wait some more ppRD ppSelfSt ;get self status btfss valueL,7 ;bit 7 is INITD goto ResetWait ; when set, initialization of the CS8900 is done return ; ; 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 movwf valueL ;save value low ior portPtr+1 ;read PacketPage Ptr for high order byte movwf PORTA ;set the address bus movwf valueH ;save high low movf valueL,0 ;get low value btfss STATUS,Z ;should be 0 (i.e. 0x3000 low is 0x00) goto VerBad movlw 0x30 ;high part of 0x3000 subwf valueH,0 ;subtract from value obtained btfss STATUS,Z ;see if compared okay goto VerBad ppRD ppEISA ;get the EISA number whoch should be 0x630E movlw 0x63 subwf valueH,0 ;compare to 0x63 btfss STATUS,Z goto VerBad movlw 0x0e ;compare to 0x0e subwf valueL,0 btfss STATUS,Z goto 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 movf valueL,0 ;set return status VerBad return ;return with status,z indicating success (Z) or not set for failure ; ; Writes the value at valueH/valueL to the PagePacket register who's ; address is in offsetH/offsetL ; WritePP Doutput ;make the data bus output movf offsetL,0 ;get the low order byte iow portPtr ;write to PacketPage Ptr movf offsetH,0 ;get the high order byte iow portPtr+1 ;write to PacketPage ptr movf valueL,0 ;get low order value to write iow portData ;write to PacketPage data movf valueH,0 ;get high order data iow portData+1 ;write to PacketPage data return ; ; Reads the PagePacket at offsetH/offsetL and returns the result in ; valueH/valueL. ; ReadPP Doutput ;make the data bus output movf offsetL,0 ;get the offset to read iow portPtr ;write to PacketPage Ptr movf offsetH,0 ;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 movwf valueL ;save value low ior portData+1 ;read the high order byte movwf valueH ;save the high order byte value return ioRead movwf PORTA bcf PORTC,CHIPSEL bcf PORTC,IOR nop movf PORTB,0 bsf PORTC,IOR bsf PORTC,CHIPSEL return ; ioWrite bcf PORTC,CHIPSEL bcf PORTC,IOW nop bsf PORTC,IOW bsf PORTC,CHIPSEL return end
C Yazılımı
#include#include #include #include int main(int argc, char **argv) { char szBuf[256]; struct sockaddr_in sin; WSADATA wsaData; SOCKET s; int rc,i; if (WSAStartup(0x101,&wsaData) == SOCKET_ERROR) { printf("WSAStartup() failed, rc=%d\n",WSAGetLastError()); WSACleanup(); return -1; } sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2"); sin.sin_family = AF_INET; sin.sin_port = htons(7); s = socket(AF_INET,SOCK_DGRAM,0); if(s<0) { printf("Couldn't get a socket, rc=%d\n",WSAGetLastError()); WSACleanup(); return -1; } if(connect(s,(struct sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR) { printf("connect() failed, rc=%d\n",WSAGetLastError()); WSACleanup(); return -1; } for(i=0;i<5;i++) { wsprintf(szBuf,"Test %d",i+1); rc = send(s,szBuf,strlen(szBuf),0); if (rc == SOCKET_ERROR) { printf("send() failed,rc=%d\n",WSAGetLastError()); WSACleanup(); return -1; } printf("Sent Data [%s]\n",szBuf); rc = recv(s,szBuf,sizeof(szBuf),0 ); if (rc == SOCKET_ERROR) { printf("recv() failed, rc=%d\n",WSAGetLastError()); closesocket(s); WSACleanup(); return -1; } if (rc == 0) { printf("Server closed connection\n"); closesocket(s); WSACleanup(); return -1; } printf("Received %d bytes, data [%s] from the board\n",rc,szBuf); } closesocket(s); WSACleanup(); }
Şifre-Pass: 320volt.com
Yayım tarihi: 2009/02/02 Etiketler: crystal cs8900, embedded ethernet, eternet, microchip pic projeleri, PIC16C74