'---------------------------------------------------------------------------------- ' Embedded UDP&WebServer - Atmega32 and RTL8019AS - Embedded UDP&WebServer '---------------------------------------------------------------------------------- ' ' Version 1 - April 1 2005 - Ben Zijlstra - Netherlands - https://benshobbycorner.nl/bzijlstra $crystal = 7372800 $regfile = "M32def.dat" $baud = 57600 Declare Sub Write_rtl8019as(byval Regaddr As Byte , Byval Regdata As Byte) Declare Sub Read_rtl8019as(byval Regaddr As Byte) Declare Sub Init_rtl8019as 'Declare Sub Showregs Declare Sub Getpacket Declare Sub Overrun Declare Sub Arp Declare Sub Udp Declare Sub Icmp Declare Sub Icmp_checksum Declare Sub Tcp Declare Sub Write_dest_mac Declare Sub Packetshape Declare Sub Echopacket Declare Sub Setipaddrs Declare Sub Ip_header_checksum Dim Myip(4) As Byte At &H64 Dim My_ip As Long At &H64 Overlay Dim Regaddr As Byte Dim Regdata As Byte 'Ethernet header layout Dim Hdr_chksum As Long Dim Byte_read As Byte Dim Hulp1 As Byte Dim Mymac(6) As Byte Dim I As Integer Dim Rxlen As Word Dim Hulp2 As Word Dim Hulp3 As Word Dim Hulp4 As Byte Dim Data_l As Byte Dim Data_h As Byte 'RTL8019AS Dim Txstart As Byte Dim Txlen As Word Dim I_header_length As Word Dim I_odd As Byte Dim I_chksum32 As Long Dim Hulp6 As Word At &HAF Dim Hulp6h As Byte At &HB0 Overlay Dim Hulp6l As Byte At &HAF Overlay Dim I_x As Word Dim I_hulp1 As Word Dim I_checksum16 As Word Dim I_temp16 As Word Dim I_value16 As Word At &HB1 Dim I_value16h As Byte At &HB2 Overlay Dim I_value16l As Byte At &HB1 Overlay Dim Ip_value16 As Word At &HB3 Dim Ip_value16h As Byte At &HB4 Overlay Dim Ip_value16l As Byte At &HB3 Overlay Dim Result16 As Word At &HB5 Dim Result16h As Byte At &HB6 Overlay Dim Result16l As Byte At &HB5 Overlay 'variables with overlays Dim Pageheader(4) As Byte At &HAB Dim T_enetpacketlenl As Byte At &HAD Overlay Dim T_enetpacketlenh As Byte At &HAE Overlay Dim Resend As Byte Dim T As Byte Dim Packet(1500) As Byte At &HC0 'Ethernet packet destination Dim T_enetpacketdest0 As Byte At &HC0 Overlay Dim T_enetpacketdest1 As Byte At &HC1 Overlay Dim T_enetpacketdest2 As Byte At &HC2 Overlay Dim T_enetpacketdest3 As Byte At &HC3 Overlay Dim T_enetpacketdest4 As Byte At &HC4 Overlay Dim T_enetpacketdest5 As Byte At &HC5 Overlay 'Ethernet packet source Dim T_enetpacketsrc0 As Byte At &HC6 Overlay Dim T_enetpacketsrc1 As Byte At &HC7 Overlay Dim T_enetpacketsrc2 As Byte At &HC8 Overlay Dim T_enetpacketsrc3 As Byte At &HC9 Overlay Dim T_enetpacketsrc4 As Byte At &HCA Overlay Dim T_enetpacketsrc5 As Byte At &HCB Overlay 'Ethernet packet type Dim T_enetpackettype As Word At &HCC Overlay Dim T_arp_hwtype1 As Byte At &HCF Overlay 'Arp Dim T_arp_prttype1 As Byte At &HD1 Overlay Dim T_arp_hwlen As Byte At &HD2 Overlay Dim T_arp_prlen As Byte At &HD3 Overlay Dim T_arp_op1 As Byte At &HD5 Overlay 'arp source ip address Dim T_arp_sipaddr0 As Byte At &HDC Overlay Dim T_arp_sipaddr1 As Byte At &HDD Overlay Dim T_arp_sipaddr2 As Byte At &HDE Overlay Dim T_arp_sipaddr3 As Byte At &HDF Overlay 'arp target IP address Dim T_arp_tipaddr As Long At &HE6 Overlay 'IP header layout IP version and header length Dim T_ip_vers_len As Byte At &HCE Overlay 'packet length Dim T_ip_pktlen0 As Byte At &HD0 Overlay Dim T_ip_pktlen1 As Byte At &HD1 Overlay 'protocol (ICMP=1, TCP=6, UDP=11) Dim T_ip_proto As Byte At &HD7 Overlay 'header checksum Dim T_ip_hdr_cksum0 As Byte At &HD8 Overlay Dim T_ip_hdr_cksum1 As Byte At &HD9 Overlay Dim T_ip_hdr_cksum As Word At &HD8 Overlay 'IP address of source Dim T_ip_srcaddr0 As Byte At &HDA Overlay Dim T_ip_srcaddr1 As Byte At &HDB Overlay Dim T_ip_srcaddr2 As Byte At &HDC Overlay Dim T_ip_srcaddr3 As Byte At &HDD Overlay Dim T_ip_srcaddr As Long At &HDA Overlay 'IP address of destination Dim T_ip_destaddr0 As Byte At &HDE Overlay Dim T_ip_destaddr1 As Byte At &HDF Overlay Dim T_ip_destaddr2 As Byte At &HE0 Overlay Dim T_ip_destaddr3 As Byte At &HE1 Overlay Dim T_ip_destaddr As Long At &HDE Overlay Dim T_icmp_type As Byte At &HE2 Overlay Dim T_icmp_code As Byte At &HE3 Overlay Dim T_icmp_cksum0 As Byte At &HE4 Overlay Dim T_icmp_cksum1 As Byte At &HE5 Overlay Dim T_icmp_cksum As Word At &HE4 Overlay Dim Tcp_srcporth As Byte At &HE2 Overlay Dim Tcp_srcportl As Byte At &HE3 Overlay Dim Tcp_destporth As Byte At &HE4 Overlay Dim Tcp_destportl As Byte At &HE5 Overlay Dim Tcp_seqnum3 As Byte At &HE6 Overlay Dim Tcp_seqnum2 As Byte At &HE7 Overlay Dim Tcp_seqnum1 As Byte At &HE8 Overlay Dim Tcp_seqnum0 As Byte At &HE9 Overlay Dim Tcp_acknum3 As Byte At &HEA Overlay Dim Tcp_acknum2 As Byte At &HEB Overlay Dim Tcp_acknum1 As Byte At &HEC Overlay Dim Tcp_acknum0 As Byte At &HED Overlay Dim Tcp_hdr As Byte At &HEE Overlay Dim Tcp_flags As Byte At &HEF Overlay Dim Tcp_cksumh As Byte At &HF2 Overlay Dim Tcp_cksuml As Byte At &HF3 Overlay Dim Tcp_cksum As Word At &HF2 Overlay 'UDP header Dim T_udp_srcport0 As Byte At &HE2 Overlay Dim T_udp_srcport1 As Byte At &HE3 Overlay Dim T_udp_destport0 As Byte At &HE4 Overlay Dim T_udp_destport1 As Byte At &HE5 Overlay Dim T_udp_destport As Word At &HE4 Overlay Dim T_udp_len0 As Byte At &HE6 Overlay Dim T_udp_len1 As Byte At &HE7 Overlay Dim T_udp_chksum0 As Byte At &HE8 Overlay Dim T_udp_chksum1 As Byte At &HE9 Overlay Dim T_udp_chksum As Word At &HE8 Overlay Dim T_udp_data As Byte At &HEA Overlay Const Debug = 0 ' put 1 for debug, 0 for no debug Const Rstport = &H18 Const Isr = &H07 Const Msg_initfail = "Init failed" Const Cr = &H00 Const Dcrval = &H58 Const Dcr = &H0E Const Rbcr0 = &H0A Const Rbcr1 = &H0B Const Rcr = &H0C Const Tpsr = &H04 Const Txtstart = &H40 Const Tcr = &H0D Const Pstart = &H01 Const Rxstart = &H46 Const Bnry = &H03 Const Pstop = &H02 Const Rxstop = &H60 Const Curr = &H07 Const Imr = &H0F Const Imrval = &H11 Const Tcrval = &H00 Const Rdmaport = &H10 Const Rsar0 = &H08 Const Rsar1 = &H09 Const Tbcr0 = &H05 Const Tbcr1 = &H06 'IP protocol types 'icmp Const Prot_icmp = &H01 'tcp Const Prot_tcp = &H06 'udp Const Prot_udp = &H11 'RTL8019AS ISR Register definitions Const Rdc = &H40 Config Int0 = Rising Mymac(1) = &H00 Mymac(2) = &H10 Mymac(3) = &H20 Mymac(4) = &H30 Mymac(5) = &H40 Mymac(6) = &H50 Myip(1) = 192 Myip(2) = 168 Myip(3) = 0 Myip(4) = 100 #if Debug = 1 Print "Hello world" #endif Databus Alias Porta _databus Alias Pina Rtldata Alias Porta Databus_ddr Alias Ddra Addrbus Alias Portb Addrbus_ddr Alias Ddrb Resetport Alias Portd Eeprom Alias Portd Ior_pin Alias Portd.6 Iow_pin Alias Portd.7 Resetport_ddr Alias Ddrd Inputport1 Alias Pinc Inputport2 Alias Portc Latch Alias Portd.3 Resetport_ddr = &HF8 ' leave RXD and TXD Call Init_rtl8019as 'Call Showregs 'Stop Enable Interrupts Enable Int0 On Int0 Rtl8019as_interrupt 'start the NIC Call Write_rtl8019as(cr , &H22) Do Loop End ' Routine to handle an interrupt on the RTL8019AS ' Rtl8019as_interrupt: #if Debug = 1 Print "Interrupt from RTL8019as" #endif Disable Int0 'read the interrupt status register Call Read_rtl8019as(isr) 'if the receive buffer has been overrun If Byte_read.4 = 1 Then Call Overrun End If 'if the receive buffer holds a good packet If Byte_read.0 = 1 Then Call Getpacket End If 'make sure the receive buffer ring is empty. If BNRY = CURR, the buffer is empty Call Read_rtl8019as(bnry) Data_l = Byte_read Call Write_rtl8019as(cr , &H62) Call Read_rtl8019as(curr) Data_h = Byte_read Call Write_rtl8019as(cr , &H22) 'buffer is not empty, get next packet If Data_l <> Data_h Then Call Getpacket End If 'reset the interrupts bits Call Write_rtl8019as(isr , &HFF) Call Write_rtl8019as(cr , &H22) Enable Int0 Return ' Routine to Write to NIC Control register ' Sub Write_rtl8019as(regaddr , Regdata) Addrbus = Regaddr Databus = Regdata Databus_ddr = &HFF nop Reset Iow_pin nop Set Iow_pin nop Databus_ddr = &H00 Databus = &HFF End Sub ' Routine to read from NIC Control register ' Sub Read_rtl8019as(regaddr) Databus_ddr = &H00 Databus = &HFF Addrbus = Regaddr Reset Ior_pin nop Byte_read = Pina nop Set Ior_pin nop End Sub ' Routine to initialise the RTL8019AS ethernetchip ' Sub Init_rtl8019as Databus_ddr = &H00 Databus = &HFF Addrbus_ddr = &HFF Addrbus = &H00 Resetport_ddr = &HF8 Reset Eeprom.5 Set Iow_pin Set Ior_pin Set Resetport.4 Waitms 2 Reset Resetport.4 Call Read_rtl8019as(rstport) Call Write_rtl8019as(rstport , Byte_read) Waitms 10 'check for good soft reset Call Read_rtl8019as(isr) If Byte_read.7 = 0 Then Print Msg_initfail End If Call Write_rtl8019as(cr , &H21) Waitms 2 Call Write_rtl8019as(dcr , Dcrval) Call Write_rtl8019as(rbcr0 , &H00) Call Write_rtl8019as(rbcr1 , &H00) Call Write_rtl8019as(rcr , &H04) Call Write_rtl8019as(tpsr , Txtstart) Call Write_rtl8019as(tcr , &H02) Call Write_rtl8019as(pstart , Rxstart) Call Write_rtl8019as(bnry , Rxstart) Call Write_rtl8019as(pstop , Rxstop) Call Write_rtl8019as(cr , &H61) Waitms 2 Call Write_rtl8019as(curr , Rxstart) For Hulp1 = 1 To 6 Call Write_rtl8019as(hulp1 , Mymac(hulp1)) Next Hulp1 Call Write_rtl8019as(cr , &H21) Call Write_rtl8019as(dcr , Dcrval) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(isr , &HFF) Call Write_rtl8019as(imr , Imrval) Call Write_rtl8019as(tcr , Tcrval) End Sub '( ' Routine show the contents of the RTL8019as registers ' Sub Showregs Local Cntr1 As Byte Local Cntr2 As Byte Call Write_rtl8019as(cr , &H21) Print Print "Realtek 8019AS Register dump" Print Print "REG Page0 Page1 Page2 Page3" Print For Cntr1 = 0 To 15 Cntr2 = Cntr1 Print Hex(cntr2); Print " "; Call Write_rtl8019as(cr , &H21) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &H61) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &HA1) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &HE1) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read) Next Cntr1 End Sub ') Sub Overrun Call Read_rtl8019as(cr) Data_l = Byte_read Call Write_rtl8019as(cr , &H21) Waitms 2 Call Write_rtl8019as(rbcr0 , &H00) Call Write_rtl8019as(rbcr1 , &H00) Hulp1 = Data_l And &H04 If Hulp1 <> 0 Then Resend = 0 Else If Hulp1 = 0 Then Call Read_rtl8019as(isr) Data_l = Byte_read Hulp1 = Data_l And &H02 Hulp4 = Data_l And &H08 Hulp3 = Hulp1 Or Hulp4 If Hulp3 > 0 Then Resend = 0 Else Resend = 1 End If End If End If Call Write_rtl8019as(tcr , &H02) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(bnry , Rxstart) Call Write_rtl8019as(cr , &H62) Call Write_rtl8019as(curr , Rxstart) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(isr , &H10) Call Write_rtl8019as(tcr , Tcrval) End Sub ' Routine to execute send packet command to retrieve the packet ' Sub Getpacket Call Write_rtl8019as(cr , &H1A) For I = 0 To 4 Call Read_rtl8019as(rdmaport) Pageheader(i + 1) = Byte_read Next I 'watch it. overlay variables Result16h = T_enetpacketlenh Result16l = T_enetpacketlenl Rxlen = Result16 Hulp2 = Rxlen + 1 For I = 1 To Hulp2 Call Read_rtl8019as(rdmaport) 'dump any bytes that will overrun the receive buffer If I < 1500 Then Packet(i + 1) = Byte_read End If Next I Hulp1 = Byte_read And Rdc If Hulp1 <> 64 Then Call Read_rtl8019as(isr) End If Call Write_rtl8019as(isr , &HFF) ' Routine to process an ARP packet ' If T_enetpackettype = &H0608 Then If T_arp_hwtype1 = &H01 Then If T_arp_prttype1 = &H00 Then If T_arp_hwlen = &H06 Then If T_arp_prlen = &H04 Then If T_arp_op1 = &H01 Then If My_ip = T_arp_tipaddr Then Call Arp End If End If End If End If End If End If End If ' Routine to go ahead with icmp or udp ' If T_enetpackettype = &H0008 Then If T_ip_destaddr = My_ip Then Select Case T_ip_proto Case Prot_icmp : Call Icmp Case Prot_tcp : Call Tcp Case Prot_udp : Call Udp End Select End If End If End Sub ' Routine to handle ARP-traffic ' Sub Arp 'Start the NIC Call Write_rtl8019as(cr , &H22) 'load beginning page for transmit buffer Call Write_rtl8019as(tpsr , Txtstart) 'set start address for remote DMA operation Call Write_rtl8019as(rsar0 , &H00) Call Write_rtl8019as(rsar1 , &H40) 'clear the interrupts Call Write_rtl8019as(isr , &HFF) 'load data byte count for remote DMA Call Write_rtl8019as(rbcr0 , &H3C) Call Write_rtl8019as(rbcr1 , &H00) 'do remote write operation Call Write_rtl8019as(cr , &H12) 'write destination MAC address Call Write_dest_mac 'write source address For I = 1 To 6 Call Write_rtl8019as(rdmaport , Mymac(i)) Next I 'arp target IP address 'arp_op1 = packet(&h16) Packet(&H16) = &H02 For I = 0 To 9 Hulp1 = &HCC + I T = Peek(hulp1) Call Write_rtl8019as(rdmaport , T) Next I 'write ethernet module mac address For I = 1 To 6 Call Write_rtl8019as(rdmaport , Mymac(i)) Next I 'write myip For I = 1 To 4 Call Write_rtl8019as(rdmaport , Myip(i)) Next I 'write remote mac address Call Write_dest_mac 'write remote IP address Call Write_rtl8019as(rdmaport , T_arp_sipaddr0) Call Write_rtl8019as(rdmaport , T_arp_sipaddr1) Call Write_rtl8019as(rdmaport , T_arp_sipaddr2) Call Write_rtl8019as(rdmaport , T_arp_sipaddr3) 'write som pad characters to fill out the packet to the minimum length For I = 0 To &H11 Call Write_rtl8019as(rdmaport , &H00) Next I 'make sure the DMA operation has succesfully completed Byte_read = 0 Do Hulp1 = Byte_read And Rdc Call Read_rtl8019as(isr) Loop Until Hulp1 = 0 'load numbers of bytes to be transmitted Call Write_rtl8019as(tbcr0 , &H3C) Call Write_rtl8019as(tbcr1 , &H00) 'send the contents of the transmit buffer onto the network Call Write_rtl8019as(cr , &H24) End Sub Sub Tcp End Sub Sub Udp End Sub Sub Write_dest_mac Call Write_rtl8019as(rdmaport , T_enetpacketsrc0) Call Write_rtl8019as(rdmaport , T_enetpacketsrc1) Call Write_rtl8019as(rdmaport , T_enetpacketsrc2) Call Write_rtl8019as(rdmaport , T_enetpacketsrc3) Call Write_rtl8019as(rdmaport , T_enetpacketsrc4) Call Write_rtl8019as(rdmaport , T_enetpacketsrc5) End Sub Sub Icmp 'set echo reply T_icmp_type = &H00 T_icmp_code = &H00 'setup the IP-header Call Setipaddrs Call Icmp_checksum Call Echopacket End Sub ' Routine to handle the source/destination address ' Sub Setipaddrs T_ip_destaddr = T_ip_srcaddr 'make ethernet module IP address source address T_ip_srcaddr = My_ip Call Packetshape Call Ip_header_checksum End Sub ' Routine to echo a complete packet ' Sub Echopacket Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(tpsr , Txtstart) Call Write_rtl8019as(rsar0 , &H00) Call Write_rtl8019as(rsar1 , &H40) Call Write_rtl8019as(isr , &HFF) Hulp1 = T_enetpacketlenl - 4 Call Write_rtl8019as(rbcr0 , Hulp1) Call Write_rtl8019as(rbcr1 , T_enetpacketlenh) Call Write_rtl8019as(cr , &H12) Result16h = T_enetpacketlenh Result16l = T_enetpacketlenl Result16 = Result16 - 4 Txlen = Result16 'write the complete packet to the RTL8019AS from packet(1) to packet(txlen+1) Hulp2 = Txlen + 1 For I = 1 To Hulp2 Call Write_rtl8019as(rdmaport , Packet(i)) Next I Byte_read = 0 While Hulp1 <> 0 Hulp1 = Byte_read And Rdc Call Read_rtl8019as(isr) Wend Hulp1 = T_enetpacketlenl - 4 Call Write_rtl8019as(tbcr0 , Hulp1) Call Write_rtl8019as(tbcr1 , T_enetpacketlenh) Call Write_rtl8019as(cr , &H24) End Sub Sub Packetshape 'move hardware source address to destination address T_enetpacketdest0 = T_enetpacketsrc0 T_enetpacketdest1 = T_enetpacketsrc1 T_enetpacketdest2 = T_enetpacketsrc2 T_enetpacketdest3 = T_enetpacketsrc3 T_enetpacketdest4 = T_enetpacketsrc4 T_enetpacketdest5 = T_enetpacketsrc5 ' 'Make ethernet module mac address the source address T_enetpacketsrc0 = Mymac(1) T_enetpacketsrc1 = Mymac(2) T_enetpacketsrc2 = Mymac(3) T_enetpacketsrc3 = Mymac(4) T_enetpacketsrc4 = Mymac(5) T_enetpacketsrc5 = Mymac(6) End Sub ' Routine to calculate a ICMP-checksum ' Sub Icmp_checksum 'clear the ICMP checksum T_icmp_cksum = &H00 'calculate the ICMP checksum I_header_length = T_ip_pktlen1 - 20 'I_header_length = I_header_length - 20 I_odd = I_header_length Mod 2 '14 for MAC-part '20 for IP-header 'start on 35 'ip_pktlen = 00 3c (60) 'icmp-packetlengte = ip_pktlen - ip_header I_chksum32 = 0 'Total packetlength - ip_header - 1 Hulp6h = T_ip_pktlen0 Hulp6l = T_ip_pktlen1 Hulp6 = Hulp6 + 13 For I_x = 35 To Hulp6 Step 2 I_value16h = Packet(i_x) I_hulp1 = I_x + 1 I_value16l = Packet(i_hulp1) I_value16 = Not I_value16 I_chksum32 = I_chksum32 + I_value16 Next I_x If I_odd = 1 Then I_value16h = Packet(i_x) I_value16l = 0 I_value16 = Not I_value16 I_chksum32 = I_chksum32 + I_value16 End If I_checksum16 = I_chksum32 I_temp16 = Highw(i_chksum32) I_checksum16 = I_checksum16 + I_temp16 T_icmp_cksum0 = High(i_checksum16) T_icmp_cksum1 = Low(i_checksum16) End Sub ' Routine to calculate a IP-header checksum ' Sub Ip_header_checksum Local Ip_x As Byte Local Ip_hulp1 As Byte Local Ip_chksum32 As Long Local Ip_checksum16 As Word Local Ip_temp16 As Word Local Ip_header_length As Byte 'calculate the IP header checksum T_ip_hdr_cksum = &H00 Hdr_chksum = 0 Ip_header_length = T_ip_vers_len And &H0F Ip_header_length = 4 * Ip_header_length Hulp1 = &H0E + Ip_header_length Ip_chksum32 = 0 For Ip_x = 15 To Hulp1 Step 2 Ip_value16h = Packet(ip_x) Ip_hulp1 = Ip_x + 1 Ip_value16l = Packet(ip_hulp1) Ip_value16 = Not Ip_value16 Ip_chksum32 = Ip_chksum32 + Ip_value16 Next Ip_x Ip_checksum16 = Ip_chksum32 Ip_temp16 = Highw(ip_chksum32) Ip_checksum16 = Ip_checksum16 + Ip_temp16 T_ip_hdr_cksum0 = High(ip_checksum16) T_ip_hdr_cksum1 = Low(ip_checksum16) End Sub '' hulp5 is hulp2 geworden