Not Recommended for Use, but demonstrates raw API of LwIP. Needs mbed library 26
Dependencies: lwip-mbed-2010 mbed
main.cpp@0:dbb5ecae258f, 2013-08-21 (annotated)
- Committer:
- RodColeman
- Date:
- Wed Aug 21 06:40:16 2013 +0000
- Revision:
- 0:dbb5ecae258f
Original, on mbed library 26
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RodColeman | 0:dbb5ecae258f | 1 | #include "mbed.h" |
RodColeman | 0:dbb5ecae258f | 2 | #include "lwip/opt.h" |
RodColeman | 0:dbb5ecae258f | 3 | #include "lwip/stats.h" |
RodColeman | 0:dbb5ecae258f | 4 | #include "lwip/sys.h" |
RodColeman | 0:dbb5ecae258f | 5 | #include "lwip/pbuf.h" |
RodColeman | 0:dbb5ecae258f | 6 | #include "lwip/udp.h" |
RodColeman | 0:dbb5ecae258f | 7 | #include "lwip/tcp.h" |
RodColeman | 0:dbb5ecae258f | 8 | #include "lwip/dns.h" |
RodColeman | 0:dbb5ecae258f | 9 | #include "lwip/dhcp.h" |
RodColeman | 0:dbb5ecae258f | 10 | #include "lwip/init.h" |
RodColeman | 0:dbb5ecae258f | 11 | #include "lwip/netif.h" |
RodColeman | 0:dbb5ecae258f | 12 | #include "netif/etharp.h" |
RodColeman | 0:dbb5ecae258f | 13 | #include "netif/loopif.h" |
RodColeman | 0:dbb5ecae258f | 14 | #include "device.h" |
RodColeman | 0:dbb5ecae258f | 15 | |
RodColeman | 0:dbb5ecae258f | 16 | Ethernet ethernet; |
RodColeman | 0:dbb5ecae258f | 17 | DigitalOut ledLink(p30); |
RodColeman | 0:dbb5ecae258f | 18 | DigitalOut ledActivity(p29); |
RodColeman | 0:dbb5ecae258f | 19 | DigitalOut ledStage0 (LED1); |
RodColeman | 0:dbb5ecae258f | 20 | DigitalOut ledStage1 (LED2); |
RodColeman | 0:dbb5ecae258f | 21 | DigitalOut ledStage2 (LED3); |
RodColeman | 0:dbb5ecae258f | 22 | DigitalOut ledTCP80 (LED4); |
RodColeman | 0:dbb5ecae258f | 23 | Serial pc(USBTX, USBRX); |
RodColeman | 0:dbb5ecae258f | 24 | volatile char stage = 0; |
RodColeman | 0:dbb5ecae258f | 25 | |
RodColeman | 0:dbb5ecae258f | 26 | Ticker stage_blinker; |
RodColeman | 0:dbb5ecae258f | 27 | |
RodColeman | 0:dbb5ecae258f | 28 | struct netif netif_data; |
RodColeman | 0:dbb5ecae258f | 29 | |
RodColeman | 0:dbb5ecae258f | 30 | const char testPage[] = "HTTP/1.1 200 OK\r\n" |
RodColeman | 0:dbb5ecae258f | 31 | "Content-Type: text/html\r\n" |
RodColeman | 0:dbb5ecae258f | 32 | "Connection: Close\r\n\r\n" |
RodColeman | 0:dbb5ecae258f | 33 | "<html>" |
RodColeman | 0:dbb5ecae258f | 34 | "<head>" |
RodColeman | 0:dbb5ecae258f | 35 | "<title>mbed test page</title>" |
RodColeman | 0:dbb5ecae258f | 36 | "<style type='text/css'>" |
RodColeman | 0:dbb5ecae258f | 37 | "body{font-family:'Arial, sans-serif', sans-serif;font-size:.8em;background-color:#fff;}" |
RodColeman | 0:dbb5ecae258f | 38 | "</style>" |
RodColeman | 0:dbb5ecae258f | 39 | "</head>" |
RodColeman | 0:dbb5ecae258f | 40 | "<body>%s</body></html>\r\n\r\n"; |
RodColeman | 0:dbb5ecae258f | 41 | |
RodColeman | 0:dbb5ecae258f | 42 | char buffer[1024]; |
RodColeman | 0:dbb5ecae258f | 43 | char temp[1024]; |
RodColeman | 0:dbb5ecae258f | 44 | err_t recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { |
RodColeman | 0:dbb5ecae258f | 45 | struct netif *netif = &netif_data; |
RodColeman | 0:dbb5ecae258f | 46 | ledTCP80 = true; |
RodColeman | 0:dbb5ecae258f | 47 | printf("TCP callback from %d.%d.%d.%d\r\n", ip4_addr1(&(pcb->remote_ip)),ip4_addr2(&(pcb->remote_ip)),ip4_addr3(&(pcb->remote_ip)),ip4_addr4(&(pcb->remote_ip))); |
RodColeman | 0:dbb5ecae258f | 48 | char *data; |
RodColeman | 0:dbb5ecae258f | 49 | /* Check if status is ok and data is arrived. */ |
RodColeman | 0:dbb5ecae258f | 50 | if (err == ERR_OK && p != NULL) { |
RodColeman | 0:dbb5ecae258f | 51 | /* Inform TCP that we have taken the data. */ |
RodColeman | 0:dbb5ecae258f | 52 | tcp_recved(pcb, p->tot_len); |
RodColeman | 0:dbb5ecae258f | 53 | data = static_cast<char *>(p->payload); |
RodColeman | 0:dbb5ecae258f | 54 | /* If the data is a GET request we can handle it. */ |
RodColeman | 0:dbb5ecae258f | 55 | if (strncmp(data, "GET ", 4) == 0) { |
RodColeman | 0:dbb5ecae258f | 56 | printf("Handling GET request...\r\n"); |
RodColeman | 0:dbb5ecae258f | 57 | printf("Request:\r\n%s\r\n", data); |
RodColeman | 0:dbb5ecae258f | 58 | |
RodColeman | 0:dbb5ecae258f | 59 | //generate the test page |
RodColeman | 0:dbb5ecae258f | 60 | time_t seconds = time(NULL); |
RodColeman | 0:dbb5ecae258f | 61 | sprintf(temp, "<h1>Congratulations!</h1>If you can see this page, your mbed is working properly." |
RodColeman | 0:dbb5ecae258f | 62 | "<h2>mbed Configuration</h2>" |
RodColeman | 0:dbb5ecae258f | 63 | "mbed RTC time:%s<br/>" |
RodColeman | 0:dbb5ecae258f | 64 | "mbed HW address: %02x:%02x:%02x:%02x:%02x:%02x<br/>" |
RodColeman | 0:dbb5ecae258f | 65 | "mbed IP Address: %s<br/>", |
RodColeman | 0:dbb5ecae258f | 66 | ctime(&seconds), |
RodColeman | 0:dbb5ecae258f | 67 | (char*) netif->hwaddr[0], |
RodColeman | 0:dbb5ecae258f | 68 | (char*) netif->hwaddr[1], |
RodColeman | 0:dbb5ecae258f | 69 | (char*) netif->hwaddr[2], |
RodColeman | 0:dbb5ecae258f | 70 | (char*) netif->hwaddr[3], |
RodColeman | 0:dbb5ecae258f | 71 | (char*) netif->hwaddr[4], |
RodColeman | 0:dbb5ecae258f | 72 | (char*) netif->hwaddr[5], |
RodColeman | 0:dbb5ecae258f | 73 | inet_ntoa(*(struct in_addr*)&(netif->ip_addr)) |
RodColeman | 0:dbb5ecae258f | 74 | ); |
RodColeman | 0:dbb5ecae258f | 75 | sprintf(buffer, testPage, temp); |
RodColeman | 0:dbb5ecae258f | 76 | if (tcp_write(pcb, (void *)buffer, strlen(buffer), 1) == ERR_OK) { |
RodColeman | 0:dbb5ecae258f | 77 | tcp_output(pcb); |
RodColeman | 0:dbb5ecae258f | 78 | printf("Closing connection...\r\n"); |
RodColeman | 0:dbb5ecae258f | 79 | tcp_close(pcb); |
RodColeman | 0:dbb5ecae258f | 80 | } |
RodColeman | 0:dbb5ecae258f | 81 | } |
RodColeman | 0:dbb5ecae258f | 82 | else |
RodColeman | 0:dbb5ecae258f | 83 | { |
RodColeman | 0:dbb5ecae258f | 84 | printf("Non GET request...\r\nRequest:\r\n%s\r\n", data); |
RodColeman | 0:dbb5ecae258f | 85 | } |
RodColeman | 0:dbb5ecae258f | 86 | |
RodColeman | 0:dbb5ecae258f | 87 | pbuf_free(p); |
RodColeman | 0:dbb5ecae258f | 88 | } |
RodColeman | 0:dbb5ecae258f | 89 | |
RodColeman | 0:dbb5ecae258f | 90 | else { |
RodColeman | 0:dbb5ecae258f | 91 | /* No data arrived */ |
RodColeman | 0:dbb5ecae258f | 92 | /* That means the client closes the connection and sent us a packet with FIN flag set to 1. */ |
RodColeman | 0:dbb5ecae258f | 93 | /* We have to cleanup and destroy out TCPConnection. */ |
RodColeman | 0:dbb5ecae258f | 94 | printf("Connection closed by client.\r\n"); |
RodColeman | 0:dbb5ecae258f | 95 | pbuf_free(p); |
RodColeman | 0:dbb5ecae258f | 96 | } |
RodColeman | 0:dbb5ecae258f | 97 | /* Don't panic! Everything is fine. */ |
RodColeman | 0:dbb5ecae258f | 98 | ledTCP80 = false; |
RodColeman | 0:dbb5ecae258f | 99 | return ERR_OK; |
RodColeman | 0:dbb5ecae258f | 100 | } |
RodColeman | 0:dbb5ecae258f | 101 | /* Accept an incomming call on the registered port */ |
RodColeman | 0:dbb5ecae258f | 102 | err_t accept_callback(void *arg, struct tcp_pcb *npcb, err_t err) { |
RodColeman | 0:dbb5ecae258f | 103 | LWIP_UNUSED_ARG(arg); |
RodColeman | 0:dbb5ecae258f | 104 | /* Subscribe a receive callback function */ |
RodColeman | 0:dbb5ecae258f | 105 | tcp_recv(npcb, &recv_callback); |
RodColeman | 0:dbb5ecae258f | 106 | /* Don't panic! Everything is fine. */ |
RodColeman | 0:dbb5ecae258f | 107 | return ERR_OK; |
RodColeman | 0:dbb5ecae258f | 108 | } |
RodColeman | 0:dbb5ecae258f | 109 | |
RodColeman | 0:dbb5ecae258f | 110 | void stageblinker() |
RodColeman | 0:dbb5ecae258f | 111 | { |
RodColeman | 0:dbb5ecae258f | 112 | switch (stage) |
RodColeman | 0:dbb5ecae258f | 113 | { |
RodColeman | 0:dbb5ecae258f | 114 | case 0: |
RodColeman | 0:dbb5ecae258f | 115 | ledStage0 = !ledStage0; |
RodColeman | 0:dbb5ecae258f | 116 | ledStage1 = false; |
RodColeman | 0:dbb5ecae258f | 117 | ledStage2 = false; |
RodColeman | 0:dbb5ecae258f | 118 | break; |
RodColeman | 0:dbb5ecae258f | 119 | case 1: |
RodColeman | 0:dbb5ecae258f | 120 | ledStage0 = true; |
RodColeman | 0:dbb5ecae258f | 121 | ledStage1 = !ledStage1; |
RodColeman | 0:dbb5ecae258f | 122 | ledStage2 = false; |
RodColeman | 0:dbb5ecae258f | 123 | break; |
RodColeman | 0:dbb5ecae258f | 124 | case 2: |
RodColeman | 0:dbb5ecae258f | 125 | ledStage0 = true; |
RodColeman | 0:dbb5ecae258f | 126 | ledStage1 = true; |
RodColeman | 0:dbb5ecae258f | 127 | ledStage2 = true; |
RodColeman | 0:dbb5ecae258f | 128 | stage_blinker.detach(); |
RodColeman | 0:dbb5ecae258f | 129 | break; |
RodColeman | 0:dbb5ecae258f | 130 | } |
RodColeman | 0:dbb5ecae258f | 131 | } |
RodColeman | 0:dbb5ecae258f | 132 | |
RodColeman | 0:dbb5ecae258f | 133 | int main() { |
RodColeman | 0:dbb5ecae258f | 134 | pc.baud(115200); |
RodColeman | 0:dbb5ecae258f | 135 | printf("mBed Ethernet Tester 1.0\r\nStarting Up...\r\n"); |
RodColeman | 0:dbb5ecae258f | 136 | stage = 0; |
RodColeman | 0:dbb5ecae258f | 137 | struct netif *netif = &netif_data; |
RodColeman | 0:dbb5ecae258f | 138 | struct ip_addr ipaddr; |
RodColeman | 0:dbb5ecae258f | 139 | struct ip_addr netmask; |
RodColeman | 0:dbb5ecae258f | 140 | struct ip_addr gateway; |
RodColeman | 0:dbb5ecae258f | 141 | Ticker tickFast, tickSlow, tickARP, eth_tick, dns_tick, dhcp_coarse, dhcp_fine; |
RodColeman | 0:dbb5ecae258f | 142 | stage_blinker.attach_us(&stageblinker, 1000*500); |
RodColeman | 0:dbb5ecae258f | 143 | |
RodColeman | 0:dbb5ecae258f | 144 | char *hostname = "my-mbed"; |
RodColeman | 0:dbb5ecae258f | 145 | |
RodColeman | 0:dbb5ecae258f | 146 | printf("Configuring device for DHCP...\r\n"); |
RodColeman | 0:dbb5ecae258f | 147 | /* Start Network with DHCP */ |
RodColeman | 0:dbb5ecae258f | 148 | IP4_ADDR(&netmask, 255,255,255,255); |
RodColeman | 0:dbb5ecae258f | 149 | IP4_ADDR(&gateway, 0,0,0,0); |
RodColeman | 0:dbb5ecae258f | 150 | IP4_ADDR(&ipaddr, 0,0,0,0); |
RodColeman | 0:dbb5ecae258f | 151 | /* Initialise after configuration */ |
RodColeman | 0:dbb5ecae258f | 152 | lwip_init(); |
RodColeman | 0:dbb5ecae258f | 153 | netif->hwaddr_len = ETHARP_HWADDR_LEN; |
RodColeman | 0:dbb5ecae258f | 154 | device_address((char *)netif->hwaddr); |
RodColeman | 0:dbb5ecae258f | 155 | netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, device_init, ip_input); |
RodColeman | 0:dbb5ecae258f | 156 | netif->hostname = hostname; |
RodColeman | 0:dbb5ecae258f | 157 | netif_set_default(netif); |
RodColeman | 0:dbb5ecae258f | 158 | dhcp_start(netif); // <-- Use DHCP |
RodColeman | 0:dbb5ecae258f | 159 | |
RodColeman | 0:dbb5ecae258f | 160 | /* Initialise all needed timers */ |
RodColeman | 0:dbb5ecae258f | 161 | tickARP.attach_us( ðarp_tmr, ARP_TMR_INTERVAL * 1000); |
RodColeman | 0:dbb5ecae258f | 162 | tickFast.attach_us(&tcp_fasttmr, TCP_FAST_INTERVAL * 1000); |
RodColeman | 0:dbb5ecae258f | 163 | tickSlow.attach_us(&tcp_slowtmr, TCP_SLOW_INTERVAL * 1000); |
RodColeman | 0:dbb5ecae258f | 164 | dns_tick.attach_us(&dns_tmr, DNS_TMR_INTERVAL * 1000); |
RodColeman | 0:dbb5ecae258f | 165 | dhcp_coarse.attach_us(&dhcp_coarse_tmr, DHCP_COARSE_TIMER_MSECS * 1000); |
RodColeman | 0:dbb5ecae258f | 166 | dhcp_fine.attach_us(&dhcp_fine_tmr, DHCP_FINE_TIMER_MSECS * 1000); |
RodColeman | 0:dbb5ecae258f | 167 | stage = 1; |
RodColeman | 0:dbb5ecae258f | 168 | while (!netif_is_up(netif)) { |
RodColeman | 0:dbb5ecae258f | 169 | ledLink = ethernet.link(); |
RodColeman | 0:dbb5ecae258f | 170 | device_poll(); |
RodColeman | 0:dbb5ecae258f | 171 | } |
RodColeman | 0:dbb5ecae258f | 172 | |
RodColeman | 0:dbb5ecae258f | 173 | /* |
RodColeman | 0:dbb5ecae258f | 174 | while (!(netif->dhcp->state == DHCP_BOUND || netif->dhcp->state == DHCP_PERMANENT)) |
RodColeman | 0:dbb5ecae258f | 175 | { |
RodColeman | 0:dbb5ecae258f | 176 | ledLink = ethernet.link(); |
RodColeman | 0:dbb5ecae258f | 177 | device_poll(); |
RodColeman | 0:dbb5ecae258f | 178 | //printf("Waiting for DHCP response, state = %d\r\n", netif->dhcp->state); |
RodColeman | 0:dbb5ecae258f | 179 | //wait_ms(100); |
RodColeman | 0:dbb5ecae258f | 180 | } |
RodColeman | 0:dbb5ecae258f | 181 | */ |
RodColeman | 0:dbb5ecae258f | 182 | stage = 2; |
RodColeman | 0:dbb5ecae258f | 183 | printf("Interface is up, local IP is %s\r\n", |
RodColeman | 0:dbb5ecae258f | 184 | inet_ntoa(*(struct in_addr*)&(netif->ip_addr))); |
RodColeman | 0:dbb5ecae258f | 185 | |
RodColeman | 0:dbb5ecae258f | 186 | printf("Starting Web Server...\r\n"); |
RodColeman | 0:dbb5ecae258f | 187 | |
RodColeman | 0:dbb5ecae258f | 188 | /* Bind a function to a tcp port */ |
RodColeman | 0:dbb5ecae258f | 189 | struct tcp_pcb *pcb = tcp_new(); |
RodColeman | 0:dbb5ecae258f | 190 | if (tcp_bind(pcb, IP_ADDR_ANY, 80) == ERR_OK) { |
RodColeman | 0:dbb5ecae258f | 191 | pcb = tcp_listen(pcb); |
RodColeman | 0:dbb5ecae258f | 192 | tcp_accept(pcb, &accept_callback); |
RodColeman | 0:dbb5ecae258f | 193 | } |
RodColeman | 0:dbb5ecae258f | 194 | |
RodColeman | 0:dbb5ecae258f | 195 | printf("Waiting for connection...\r\n"); |
RodColeman | 0:dbb5ecae258f | 196 | while(1) { |
RodColeman | 0:dbb5ecae258f | 197 | device_poll(); |
RodColeman | 0:dbb5ecae258f | 198 | ledLink = ethernet.link(); |
RodColeman | 0:dbb5ecae258f | 199 | } |
RodColeman | 0:dbb5ecae258f | 200 | } |