| ??? 10/29/01 16:37 Read: times |
#16125 - RE: I can not download !! |
// PicoWeb Project File
#define BANNER "rnPicoWeb UDP data acquisition tester.rn" #define EEPROM_IP /* use file "ip" for IP address */ #define NET_CONFIG_IP /* allow IP address reconfiguration via net */ #define ENABLE_WATCHDOG /* use Atmel watchdog timer hardware */ #undef DEBUGGER /* no debugger...we're using serial port */ //#define CLOCK 8000000 #define CLOCK 7372000 /* processor clock rate (Hz) */ #define BAUD_RATE 19200 /* serial port baud rate */ //#define SHOW_UDP_REQUESTS #define UDP_CHECKSUM_DONE #define UDP_CMD_PORT 99 // HTML and images udpdata.htm // home page // publix CGI routines sertest.cgi //------------------ included AVR assembly language follows --------------- #avr_reset clr r17 sts data_pkt_count,r17 ; reset packet counter #avr_slow #avr_fast rcall udp_loop_processing #avr_asm ;-------------------------------------------------------------- ; Project Notes: ; ; This sample is not really set up to run. It was used it to ; test UDP throughput to a PC using a special version of Perl ; which was hacked to do UDP transfers. For various reasons, ; we cannot distribute this version of Perl. ; ; The sample project takes a "trigger" UDP packet from the PC ; which tells the PicoWeb how much "dummy" data to send back ; using one or more UDP packets. The response UDP packets ; are limited to 1024 bytes of "payload" data. Therefore, ; if the PC sends a "trigger" packet requesting 16K bytes of ; data, then a total of 16 1024-byte UDP packets will be sent ; by the PicoWeb in quick succession. Using this setup, we ; determined the maximum sustained rate at which we could move ; UDP data from the PicoWeb to a laptop PC (running Windows NT) ; with a PCMCIA Ethernet card was 239 Kbytes/sec. ; ; As for a description of the various routines in this project: ; ; The routine "import_udp" gets called each time a UDP packet ; is received by the PicoWeb. This routine looks at the first ; two bytes of the incoming UDP packet and then saves this ; 16-bit number, the total amount of dummy UDP data to return. ; This routine then zeros the counter which keeps track of how ; much UDP data has been returned. Also, this routine calls ; "set_client" to remember the IP address and port of the ; incoming UDP packet. This information will be used to send ; back one or more response UDP data packets. ; ; The routine "udp_loop_processing" is called each time through ; the PicoWeb "fast idle" loop. It checks whether any UDP ; "response" data needs to be sent. If so, it uses a routine ; called "movedata" (see pcode instruction "pf2x") to setup for ; UDP data transfer and then build up the UDP packet''s data. ; The routine "udp_loop_processing" then calls the routine ; "mem_udp_send_client" to complete the checksum the UDP packet ; and to send the newly formed packet out on the network. ; ; The routine "set_client" records the IP address and port ; number from an incoming UDP packet for later use. ; ; The routine "movedata" is called to setup for creating the ; data for the UDP packet. UDP data is supplied two bytes ; at a time by a co-routine whose address is stored in the ; Z-register. This co-routine is named "movedata_next" in this ; sample project. Each time this "co-routine" is called it is ; expected to supply 16-bits of new UDP data in the Y-register ; (after first calling "f2x_checksum" to compute a running ; UDP checksum). ; ; Note that this project also can send data to the serial port ; using "parameters" supplied as part of a GET request URL line ; The string after "C=" in the URL is send out the serial port. ; Any data returned by the serial port (within 1 s) is output to ; the Web page. (See CGI routine "sertest".) This has nothing ; to do with the "UDP part" of the project. ;-------------------------------------------------------------- #include "tcpip.inc" #include "mempkt.asm" .section .bss client_ip: .skip 4 client_port: .skip 2 udp_byte_count: .skip 2 udp_pkt_seq: .skip 2 ; packet sequence # 0...N packet_header: .skip UDP_DATA ; ether/ip/udp headers data_pkt_count: .skip 2 ; incremented by 1 for every packet sent .cseg #define UDP_PKT_LEN 1024 #define MEM_ETH_DEST packet_header+0 #define MEM_ETH_SRC MEM_ETH_DEST+6 #define MEM_ETH_PT MEM_ETH_SRC+6 #define MEM_IPH MEM_ETH_PT+2 #define MEM_IP_HVTOS MEM_IPH+0 #define MEM_IP_LEN MEM_IPH+2 #define MEM_IP_ID MEM_IPH+4 #define MEM_IP_FFO MEM_IPH+6 #define MEM_IP_TTLP MEM_IPH+8 #define MEM_IP_CHKSUM MEM_IPH+10 #define MEM_IP_SRCADDR MEM_IPH+12 #define MEM_IP_DSTADDR MEM_IPH+16 #define MEM_IPD MEM_IPH+20 #define MEM_UDP_HEADER MEM_IPD+0 #define MEM_UDP_SP MEM_UDP_HEADER+0 #define MEM_UDP_DP MEM_UDP_HEADER+2 #define MEM_UDP_LEN MEM_UDP_HEADER+4 #define MEM_UDP_CHKSUM MEM_UDP_HEADER+6 #define MEM_UDP_DATA MEM_UDP_HEADER+8 ;+ ; **-udp-udp receive handler. ; ; return with ret. ;- #define UDP_FUNC UDP_DATA .global import_udp import_udp: rcall pcode pr2s buf,UDP_DP,2 ; get destination port pcmpwi buf,BSWAP(UDP_CMD_PORT) ; check if it matches pjumpne udp_bail pr2s udp_byte_count,UDP_DATA,2 ; byte count is first two bytes of data pmovwi udp_pkt_seq,0 ; zero sequence number pincw data_pkt_count #if defined(SHOW_UDP_REQUESTS) ppushn putcok,1 ppushn putc_b,1 pmovbi putcok,1 pmovbi putc_b,0 pprintr "UDP src",IP_SRCADDR,4 pprintr ":",UDP_DP,2 pprintv " len ",[udp_byte_count] pcrlf ppopn putc_b,1 ppopn putcok,1 #endif pcall set_client ; remember who to send data to! udp_bail: pend ret ;+ ; **-udp_loop_processing-fast loop hook. ; ; this routine is called every time through the "fast loop". it generates the ; next packet if there is more data to send. ; ; note: ; this routine is called via "rcall", and must return with "ret". ;- udp_loop_processing: rcall pcode pandwi udp_byte_count,0xffff ; check remaining byte count pjumpeq udp_bail #if defined(SHOW_UDP_REQUESTS) pprintv "pkt=",[udp_byte_count] #endif pmovwi MEM_UDP_LEN,UDP_PKT_LEN+2 ; set length (+2 for sequence #) pf2x UDP_DATA,movedata,UDP_PKT_LEN+2 ; move the data pcall mem_udp_send_client ; send it psubwi udp_byte_count,UDP_PKT_LEN ; minus bytes just moved (excluding seq #) pjumplo udp_stop pjumpeq udp_stop pjump udp_bail ; more to send udp_stop: pmovwi udp_byte_count,0 ; zero out count pjump udp_bail ;+ ; **-set_client-remember requestor as client for future autonomous sends. ; ; inputs: ; current receive packet contains client info ; ; outputs: ; appropriate info copied to memory packet buffer. ; ; caveats: ; called via pcall/pret ;- set_client: pr2s client_ip,IP_SRCADDR,4 ; remember client''s IP pr2s client_port,UDP_SP,2 ; and port number pr2s MEM_ETH_DEST,ETH_SRC,6 ; and client ether pmemcpy MEM_IP_SRCADDR,my_ip,4 ; source ip == me pmovwi MEM_UDP_SP,BSWAP(UDP_CMD_PORT) ; and port pmemcpy MEM_ETH_SRC,my_ether,6 ; and ether pmovwi MEM_ETH_PT,0x0008 ; set PT=IP pmovwi MEM_IP_HVTOS,0x0045 ; 4500 pmovwi MEM_IP_TTLP,0x1101 ; UDP proto and TTL=1 pmovwi MEM_IP_FFO,0 ; zero fragment stuff pret ;+ ; **-movedata-move data to packet. ; ; inputs: ; none ; ; outputs: ; data moved ; ; notes: ; demonstrates how to use pf2x with initial setup processing vs. ; "during the loop" processing. ;- movedata: movwi z,movedata_next clrw x ; reset the checksum ldsw y,udp_pkt_seq ; get packet sequence # rcall moveword ; "move" it incw y ; advance sequence # stsw udp_pkt_seq,y ; store it back lds yl,data_pkt_count ; get start of sequence mov yh,yl inc yh ret movedata_next: rcall moveword inc yl inc yl inc yh inc yh ret moveword: mov i0,yl mov i1,yh ; i0/i1 = next word of data f2x_checksum y,r10 ; accumulate checksum - r10 destroyed ret ;+ ; **-mem_udp_send-send a UDP datagram from ram. ; ; inputs: ; transmit buffer: ; MEM_UDP_DATA = user data to be sent ; MEM_UDP_LEN = native byte order length of data to send ; ; checksum algorithm: ; ; ip_chksum = 0 ; ; ip_chksum = ~checksum(IPH,IPHLEN) ; udp_chksum = 0 ; ph.src = ip.src ; ph.dst = ip.dst ; ph.mbzprot = 0|(ip.prot<<8) ; ph.len = udp_len (UDP data only, not header) ; ph_chksum = checksum(UDP_HDR,UDP_LEN+UDP_HEADER_LEN) ; udp_chksum = ~checksum(PH_HDR,PH_HEADER_LEN) ;- #define PH_HEADER rcv_hdr+en_rbuf_nhdr #define PH_SRCADDR PH_HEADER+0 #define PH_DSTADDR PH_HEADER+4 #define PH_MBZPROT PH_HEADER+8 #define PH_LEN PH_HEADER+10 #define PH_CHKSUM PH_HEADER+12 #define PH_HEADER_LEN 14 #define MOVW(x,y) pmovwi x,[y] #define UDP_CHECKSUM_DONE mem_udp_send_client: pmemcpy MEM_IP_DSTADDR,client_ip,4 ; destination = client pmovwi MEM_UDP_DP,[client_port] ; and client port mem_udp_send: #if defined(UDP_MEM_SEND_DEBUG) pprintv " MVCHK=",[chkacc] pclrw chkacc pmem_chksum MEM_UDP_DATA,[MEM_UDP_LEN] pprintv " UDPCHK=",[chkacc] #endif ; ; compute UDP length and store in UDP_LEN field and PH_LEN field. ; MOVW(buf,MEM_UDP_LEN) ; get length (native order) paddwi buf,UDP_HEADER_LEN ; total length MOVW(MEM_UDP_LEN,swap buf) ; set UDP length ; ; checksum UDP data, and store checksum (uncomplemented) in pseudoheader. ; pclrw MEM_UDP_CHKSUM ; zero UDP checksum #if defined(UDP_CHECKSUM_DONE) pmem_chksum MEM_UDP_HEADER,UDP_HEADER_LEN #else pclrw chkacc ; reset accumulator pmem_chksum MEM_UDP_HEADER,[buf] ; compute UDP checksum #endif MOVW(PH_CHKSUM,chkacc) ; store checksum in pseudoheader paddwi buf,IP_HEADER_LEN MOVW(MEM_IP_LEN,swap buf) ; set IP length ; ; the IP header should be ready, zero its checksum, checksum it, and ; store complemented checksum back in header. ; pclrw chkacc pclrw MEM_IP_CHKSUM ; zero IP header checksum pmem_chksum MEM_IPH,IP_HEADER_LEN ; checksum IP header pxorwi chkacc,-1 ; complement the ip checksum #if defined(LOG_MEM_CHKSUM) pprintv "IPCK ",[chkacc] #endif MOVW(MEM_IP_CHKSUM,chkacc) ; store in IP header ; ; finally, checksum the pseudoheader and store complemented checksum ; in UDP header. ; pmemcpy PH_SRCADDR,MEM_IP_SRCADDR,8 ; source/dest IP addrs pmovwi PH_MBZPROT,0x1100 ; UDP proto in PH MOVW(PH_LEN,MEM_UDP_LEN) ; store net order length in ph pclrw chkacc pmem_chksum PH_HEADER,PH_HEADER_LEN ; checksum pseudoheader pxorwi chkacc,-1 ; complement MOVW(MEM_UDP_CHKSUM,chkacc) ; store in UDP header checksum #if defined(LOG_MEM_CHKSUM) pprintv "PHCK ",[chkacc] #endif ; ; compute total packet size and send. ; MOVW(buf,swap MEM_IP_LEN) ; ip length total paddwi buf,6+6+2 ; compute length with ether header #if defined(UDP_CHECKSUM_DONE) ; ; if the checksum has already been computed, it also means the packet ; data is in the frame buffer, so just load the headers. ; ps2x 0,MEM_ETH_DEST,UDP_DATA ; ether, ip, udp headers #else ; ; load everything. ; ps2x 0,MEM_ETH_DEST,[buf] ; copy packet to board #endif xmit_frame [buf] ; out she goes #if defined(LOG_MEM_CHKSUM) pprintv "PKLEN ",[buf] #endif pret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;; serial device I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #define putchar_serial pmovbi putc_b,0 #define putchar_net pmovbi putc_b,1 #define serial_binary pser_mode 1 #define serial_normal pser_mode 0 .eseg ; ; sertest ; ; Send command from URL parameter string to serial port and ; output response back from serial port ; sertest: putchar_serial ; switch putchar to serial port serial_binary ; put serial port in binary mode pcall serdev_print_url_cmd ; send command from URL string get_response: putchar_net ; switch putchar back to ''net pcall serdev_copynet ; copy serial port input to net pret ; ; serdev_print_url_cmd ; ; print command string in URL after "C=" ; serdev_print_url_cmd: purlparm buf,"C=" ; search for command string pjumpne 1f ; exit if not found pprinturl buf,1 ; output command string (after C=) 1: pret ; ; serdev_copynet ; ; loop reading chars from the serial buffer and writing to ''net until ; LF encountered (or timeout) ; .cseg serdev_copynet: psgetcto buf,PSGETCTO_MSECS(1000) ; get char from UART with 1s timeout pjumpeq serdev_copydone ; no more chars! pcmpbi buf,0x0a ; check for LF (exit if found) pjumpeq serdev_copydone pputcb buf ; output character pjump serdev_copynet ; back for more serdev_copydone: pret |



