| |
serudp.pwp
// PicoWeb Project File
#undef BANNER
#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 DEBUGGER
#define SERIAL_ALWAYS_BINARY
//#define CLOCK 8000000
#define CLOCK 7372000 /* processor clock rate (Hz) */
#define BAUD_RATE 19200 /* serial port baud rate */
#define SEEPROM_CLIENT_ADDR 0x3000
#define PKT_SIZE 256 /* one page */
#define UDP_SOURCE_PORT 99
#define UDP_DEST_PORT 99 /* port on remote host */
#define CLIENT_MAC_UNKNOWN 0xffff
// HTML and images
serudp.htm // home page
// public CGI routines
//------------------ included AVR assembly language follows ---------------
#avr_reset
#include "udpsend.h"
pbegin
pcall reset_client
pmovwi pkt_index,UDP_DATA+2 ; reset packet index
pend
#avr_slow
pbegin
pcmpwi MEM_ETH_DEST,CLIENT_MAC_UNKNOWN
pjumpne 99f ; we know the client MAC, waive on
psee2s MEM_IP_DSTADDR,SEEPROM_CLIENT_ADDR,4
pmemcpy buf,MEM_IP_DSTADDR,4 ; set IP to ARP for
pcall arp_request ; ARP for that baby...
99:
pend
#avr_fast
pbegin
pcmpwi MEM_ETH_DEST,CLIENT_MAC_UNKNOWN
pjumpeq 99f ; client mac unknown - bail out
ppushn xmit_page,1 ; save current page
pmovb xmit_page,my_enet ; map my page
;
; drain chars from serial buffer into packet until newline or until
; packet fills, then send.
;
10:
pser_getc buf ; get next char
pjumpeq 97f ; no more - bail
ps2x [pkt_index],buf,1 ; store char to packet
pincw pkt_index
pandwi buf,0xff
pcmpwi buf,'\n' ; newline?
pjumpeq 20f ; yep - send
pcmpwi pkt_index,PKT_SIZE ; did it fill
pjumplo 10b ; no - go for more
20:
pcall send_and_reset ; send it and reset index
pjump 10b ; go for more
97:
ppopn xmit_page,1 ; restore transmit page
99:
pend
#avr_asm
.pushsection .bss
pkt_hdr: .skip 2 ; 2-byte header for every packet sent
pkt_index: .skip 2 ; current packet index - UDP_DATA ... PKT_SIZE
packet_header: .skip UDP_DATA ; ether/ip/udp headers
.popsection
.pushsection .data
;
; this is a massive kludge. this is the last page of the transmit buffer
; that is canonically reserved during initialization of the PicoWeb kernel.
;
; in a future update of the firmware, this buffer can be reserved properly
; so that it cannot be overwritten by a large (> 5*256 byte) transmit
; frame. for now, as long as no web pages are too big, there is not a
; problem.
;
my_enet: .byte 0x45 ; my ethernet page
.popsection
send_and_reset:
pincw pkt_hdr
ps2x UDP_DATA,pkt_hdr,2 ; store packet header
pmovwi MEM_UDP_LEN,[pkt_index] ; compute
psubwi MEM_UDP_LEN,UDP_DATA ; the length
pjumphis 10f
pclrw MEM_UDP_LEN ; < 0 bytes - send zero.
10:
pcall udp_send ; send the packet
xmit_reset:
pmovwi pkt_index,UDP_DATA+2 ; reset packet index
pret
;+
; **-udp-udp receive handler.
;
; return with ret.
;-
.global import_udp
import_udp:
pbegin
pr2s buf,UDP_DP,2 ; get destination port
pcmpwi buf,BSWAP(UDP_SOURCE_PORT) ; see if it is our source port
pjumpne 99f ; nope - ignore it
;
; send the data to the serial port.
;
#define PKTP (buf)
#define PKTL (buf+2)
#define PKTC (buf+4)
pr2s PKTL,UDP_LEN,2 ; get net order UDP length
pmovwi PKTL,[swap PKTL] ; swap it
psubwi PKTL,UDP_HEADER_LEN ; minus size of UDP header
pjumplo 99f ; nothing there
pmovwi PKTP,UDP_DATA ; data pointer
10:
pr2s PKTC,[PKTP],1 ; get next char
pputcb PKTC
pincw PKTP
pdecw PKTL
pjumpeq 99f ; we''re done
pjumphis 10b ; back for more
99:
pasmret
#undef PKTP
#undef PKTL
#undef PKTC
;+
; **-reset_client-forget about our current client.
;-
reset_client:
pclrw pkt_hdr
pmovwi MEM_ETH_DEST,CLIENT_MAC_UNKNOWN
pret
;+
; **-arp_test_reply-test arp reply.
;
; inputs:
; MEM_ETH_DEST(word) == CLIENT_MAC_UNKNOWN if we are ARPing
; arp packet in current receive buffer
;
; outputs:
; client MAC potentially acquired
;-
arp_test_reply:
pcmpwi MEM_ETH_DEST,CLIENT_MAC_UNKNOWN ; were we arping?
pjumpne 99f ; no - toss that baby
pcmp4 buf,MEM_IP_DSTADDR ; is it a reply for the right address?
pjumpne 99f ; no - toss it
pr2s MEM_ETH_DEST,AH_SRCETH,6 ; store the MAC
pcall xmit_reset ; flush the buffer
pjump setup_header ; set up static header fields
99:
pret
;+
; **-setup_header-set up static header fields.
;-
setup_header:
pmemcpy MEM_IP_SRCADDR,my_ip,4 ; source ip == me
pmovwi MEM_UDP_SP,BSWAP(UDP_SOURCE_PORT) ; and source port
pmovwi MEM_UDP_DP,BSWAP(UDP_DEST_PORT) ; and dest port
pmemcpy MEM_ETH_SRC,my_ether,6 ; and ether
pmovwi MEM_ETH_PT,0x0008 ; set PT=IP
pmovwi MEM_IP_HVTOS,0x0045 ; V=4, H=5(*4), TOS=00
pmovwi MEM_IP_TTLP,0x1101 ; UDP proto and TTL=1
pmovwi MEM_IP_FFO,0 ; zero fragment stuff
pret
;+
; **-icmp_test_destaddr-test if specified address is my client.
;
; pcode routine, exit with flags Z=1 if match
;-
icmp_test_destaddr:
pcmp4 MEM_IP_DSTADDR,buf ; compare it
pret
;+
; **-udp_port_unreachable
;
; inputs:
; buf = network order UDP port that is unreachable.
;-
udp_port_unreachable:
pcmpwi buf,BSWAP(UDP_DEST_PORT) ; is it for my destination port?
pjumpeq reset_client ; yes - forget this dude!
pret
#include "arp.asm"
#include "udpsend.asm"
#include "icmp.asm"
Back
|
|
|