Dependencies: FatFileSystem mbed WeatherMeters SDFileSystem
network.cpp@0:1a61c61d0845, 2012-04-03 (annotated)
- Committer:
- dcoban
- Date:
- Tue Apr 03 18:43:13 2012 +0000
- Revision:
- 0:1a61c61d0845
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dcoban | 0:1a61c61d0845 | 1 | /* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/) |
dcoban | 0:1a61c61d0845 | 2 | |
dcoban | 0:1a61c61d0845 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); |
dcoban | 0:1a61c61d0845 | 4 | you may not use this file except in compliance with the License. |
dcoban | 0:1a61c61d0845 | 5 | You may obtain a copy of the License at |
dcoban | 0:1a61c61d0845 | 6 | |
dcoban | 0:1a61c61d0845 | 7 | http://www.apache.org/licenses/LICENSE-2.0 |
dcoban | 0:1a61c61d0845 | 8 | |
dcoban | 0:1a61c61d0845 | 9 | Unless required by applicable law or agreed to in writing, software |
dcoban | 0:1a61c61d0845 | 10 | distributed under the License is distributed on an "AS IS" BASIS, |
dcoban | 0:1a61c61d0845 | 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
dcoban | 0:1a61c61d0845 | 12 | See the License for the specific language governing permissions and |
dcoban | 0:1a61c61d0845 | 13 | limitations under the License. |
dcoban | 0:1a61c61d0845 | 14 | */ |
dcoban | 0:1a61c61d0845 | 15 | /* Implementation of core lwIP ethernet functionality. */ |
dcoban | 0:1a61c61d0845 | 16 | #include <mbed.h> |
dcoban | 0:1a61c61d0845 | 17 | #include "lwip/init.h" |
dcoban | 0:1a61c61d0845 | 18 | #include "lwip/tcp_impl.h" |
dcoban | 0:1a61c61d0845 | 19 | #include "lwip/dns.h" |
dcoban | 0:1a61c61d0845 | 20 | #include "netif/etharp.h" |
dcoban | 0:1a61c61d0845 | 21 | #include "drv/eth/eth_drv.h" |
dcoban | 0:1a61c61d0845 | 22 | #include "network.h" |
dcoban | 0:1a61c61d0845 | 23 | #include "debug.h" |
dcoban | 0:1a61c61d0845 | 24 | |
dcoban | 0:1a61c61d0845 | 25 | |
dcoban | 0:1a61c61d0845 | 26 | /* Initializes the network stack. |
dcoban | 0:1a61c61d0845 | 27 | |
dcoban | 0:1a61c61d0845 | 28 | NOTE: Using DHCP to supply the IP addresses is the only supported scenario |
dcoban | 0:1a61c61d0845 | 29 | in this sample. |
dcoban | 0:1a61c61d0845 | 30 | |
dcoban | 0:1a61c61d0845 | 31 | Parameters: |
dcoban | 0:1a61c61d0845 | 32 | pNetwork is a pointer to the network object to be initialized. |
dcoban | 0:1a61c61d0845 | 33 | pIPAddress is a pointer to the string which specifies the static IP address |
dcoban | 0:1a61c61d0845 | 34 | of this node. Set to NULL for DHCP. |
dcoban | 0:1a61c61d0845 | 35 | pSubnetMask is a pointer to the string which specifies the subnet mask for |
dcoban | 0:1a61c61d0845 | 36 | static IP addresses. Set to NULL for DHCP. |
dcoban | 0:1a61c61d0845 | 37 | pGatewayAddress is a pointer to the string which specifies the static |
dcoban | 0:1a61c61d0845 | 38 | gateway IP address. Set to NULL for DHCP. |
dcoban | 0:1a61c61d0845 | 39 | pHostName is the host name to be used for representing this device to the |
dcoban | 0:1a61c61d0845 | 40 | DHCP server. |
dcoban | 0:1a61c61d0845 | 41 | |
dcoban | 0:1a61c61d0845 | 42 | Returns: |
dcoban | 0:1a61c61d0845 | 43 | 0 on success and a positive error code otherwise. |
dcoban | 0:1a61c61d0845 | 44 | */ |
dcoban | 0:1a61c61d0845 | 45 | int SNetwork_Init(SNetwork* pNetwork, |
dcoban | 0:1a61c61d0845 | 46 | const char* pIPAddress, |
dcoban | 0:1a61c61d0845 | 47 | const char* pSubnetMask, |
dcoban | 0:1a61c61d0845 | 48 | const char* pGatewayAddress, |
dcoban | 0:1a61c61d0845 | 49 | const char* pHostName) |
dcoban | 0:1a61c61d0845 | 50 | { |
dcoban | 0:1a61c61d0845 | 51 | int Return = 1; |
dcoban | 0:1a61c61d0845 | 52 | netif* pAddResult = NULL; |
dcoban | 0:1a61c61d0845 | 53 | ip_addr_t IpAddress; |
dcoban | 0:1a61c61d0845 | 54 | ip_addr_t NetMask; |
dcoban | 0:1a61c61d0845 | 55 | ip_addr_t GatewayAddress; |
dcoban | 0:1a61c61d0845 | 56 | Timer Timeout; |
dcoban | 0:1a61c61d0845 | 57 | |
dcoban | 0:1a61c61d0845 | 58 | // Must specify a network object to be initialized. |
dcoban | 0:1a61c61d0845 | 59 | assert ( pNetwork ); |
dcoban | 0:1a61c61d0845 | 60 | |
dcoban | 0:1a61c61d0845 | 61 | // Clear out the network object and fill it in during the initialization |
dcoban | 0:1a61c61d0845 | 62 | // process. |
dcoban | 0:1a61c61d0845 | 63 | memset(pNetwork, 0, sizeof(*pNetwork)); |
dcoban | 0:1a61c61d0845 | 64 | |
dcoban | 0:1a61c61d0845 | 65 | // Initialize the lwIP network stack. |
dcoban | 0:1a61c61d0845 | 66 | lwip_init(); |
dcoban | 0:1a61c61d0845 | 67 | |
dcoban | 0:1a61c61d0845 | 68 | // Set the initial IP addresses for the ethernet interface based on whether |
dcoban | 0:1a61c61d0845 | 69 | // DHCP is to be used or not. |
dcoban | 0:1a61c61d0845 | 70 | if (pIPAddress) |
dcoban | 0:1a61c61d0845 | 71 | { |
dcoban | 0:1a61c61d0845 | 72 | // For static IP, all strings must be set. |
dcoban | 0:1a61c61d0845 | 73 | assert ( pSubnetMask && pGatewayAddress ); |
dcoban | 0:1a61c61d0845 | 74 | |
dcoban | 0:1a61c61d0845 | 75 | ip4_addr_set_u32(&IpAddress, ipaddr_addr(pIPAddress)); |
dcoban | 0:1a61c61d0845 | 76 | ip4_addr_set_u32(&NetMask, ipaddr_addr(pSubnetMask)); |
dcoban | 0:1a61c61d0845 | 77 | ip4_addr_set_u32(&GatewayAddress, ipaddr_addr(pGatewayAddress)); |
dcoban | 0:1a61c61d0845 | 78 | } |
dcoban | 0:1a61c61d0845 | 79 | else |
dcoban | 0:1a61c61d0845 | 80 | { |
dcoban | 0:1a61c61d0845 | 81 | // For DHCP, all strings must be NULL. |
dcoban | 0:1a61c61d0845 | 82 | assert ( !pSubnetMask && !pGatewayAddress ); |
dcoban | 0:1a61c61d0845 | 83 | |
dcoban | 0:1a61c61d0845 | 84 | // Clear the IP addresses and use DHCP instead. |
dcoban | 0:1a61c61d0845 | 85 | ip_addr_set_zero(&IpAddress); |
dcoban | 0:1a61c61d0845 | 86 | ip_addr_set_zero(&NetMask); |
dcoban | 0:1a61c61d0845 | 87 | ip_addr_set_zero(&GatewayAddress); |
dcoban | 0:1a61c61d0845 | 88 | } |
dcoban | 0:1a61c61d0845 | 89 | |
dcoban | 0:1a61c61d0845 | 90 | // Obtain the MAC address for the Ethernet device. |
dcoban | 0:1a61c61d0845 | 91 | // NOTE: This should really be done in eth_init() |
dcoban | 0:1a61c61d0845 | 92 | pNetwork->EthernetInterface.hwaddr_len = ETHARP_HWADDR_LEN; |
dcoban | 0:1a61c61d0845 | 93 | eth_address((char *)pNetwork->EthernetInterface.hwaddr); |
dcoban | 0:1a61c61d0845 | 94 | |
dcoban | 0:1a61c61d0845 | 95 | // Connect the LPC17xx ethernet driver into the lwIP stack. |
dcoban | 0:1a61c61d0845 | 96 | pAddResult = netif_add(&pNetwork->EthernetInterface, |
dcoban | 0:1a61c61d0845 | 97 | &IpAddress, |
dcoban | 0:1a61c61d0845 | 98 | &NetMask, |
dcoban | 0:1a61c61d0845 | 99 | &GatewayAddress, |
dcoban | 0:1a61c61d0845 | 100 | NULL, |
dcoban | 0:1a61c61d0845 | 101 | eth_init, |
dcoban | 0:1a61c61d0845 | 102 | ethernet_input); |
dcoban | 0:1a61c61d0845 | 103 | if (!pAddResult) |
dcoban | 0:1a61c61d0845 | 104 | { |
dcoban | 0:1a61c61d0845 | 105 | printf("error: Failed to add ethernet interface to lwIP.\r\n"); |
dcoban | 0:1a61c61d0845 | 106 | goto Error; |
dcoban | 0:1a61c61d0845 | 107 | } |
dcoban | 0:1a61c61d0845 | 108 | netif_set_default(&pNetwork->EthernetInterface); |
dcoban | 0:1a61c61d0845 | 109 | |
dcoban | 0:1a61c61d0845 | 110 | // Start the required timers. |
dcoban | 0:1a61c61d0845 | 111 | pNetwork->ARP.start(); |
dcoban | 0:1a61c61d0845 | 112 | pNetwork->DHCPCoarse.start(); |
dcoban | 0:1a61c61d0845 | 113 | pNetwork->DHCPFine.start(); |
dcoban | 0:1a61c61d0845 | 114 | pNetwork->TCP.start(); |
dcoban | 0:1a61c61d0845 | 115 | pNetwork->DNS.start(); |
dcoban | 0:1a61c61d0845 | 116 | |
dcoban | 0:1a61c61d0845 | 117 | if (pIPAddress) |
dcoban | 0:1a61c61d0845 | 118 | { |
dcoban | 0:1a61c61d0845 | 119 | // Start the ethernet interface up with the static IP address. |
dcoban | 0:1a61c61d0845 | 120 | netif_set_up(&pNetwork->EthernetInterface); |
dcoban | 0:1a61c61d0845 | 121 | } |
dcoban | 0:1a61c61d0845 | 122 | else |
dcoban | 0:1a61c61d0845 | 123 | { |
dcoban | 0:1a61c61d0845 | 124 | err_t StartResult; |
dcoban | 0:1a61c61d0845 | 125 | |
dcoban | 0:1a61c61d0845 | 126 | // Start the DHCP request. |
dcoban | 0:1a61c61d0845 | 127 | pNetwork->EthernetInterface.hostname = (char*)pHostName; |
dcoban | 0:1a61c61d0845 | 128 | dhcp_set_struct(&pNetwork->EthernetInterface, &pNetwork->DHCP); |
dcoban | 0:1a61c61d0845 | 129 | StartResult = dhcp_start(&pNetwork->EthernetInterface); |
dcoban | 0:1a61c61d0845 | 130 | if (ERR_OK != StartResult) |
dcoban | 0:1a61c61d0845 | 131 | { |
dcoban | 0:1a61c61d0845 | 132 | printf("error: Failed to start DHCP service.\r\n"); |
dcoban | 0:1a61c61d0845 | 133 | goto Error; |
dcoban | 0:1a61c61d0845 | 134 | } |
dcoban | 0:1a61c61d0845 | 135 | } |
dcoban | 0:1a61c61d0845 | 136 | |
dcoban | 0:1a61c61d0845 | 137 | // Wait for network to startup. |
dcoban | 0:1a61c61d0845 | 138 | Timeout.start(); |
dcoban | 0:1a61c61d0845 | 139 | printf("Waiting for network...\r\n"); |
dcoban | 0:1a61c61d0845 | 140 | |
dcoban | 0:1a61c61d0845 | 141 | // Wait until interface is up |
dcoban | 0:1a61c61d0845 | 142 | while (!netif_is_up(&pNetwork->EthernetInterface)) |
dcoban | 0:1a61c61d0845 | 143 | { |
dcoban | 0:1a61c61d0845 | 144 | SNetwork_Poll(pNetwork); |
dcoban | 0:1a61c61d0845 | 145 | |
dcoban | 0:1a61c61d0845 | 146 | // Stop program if we get a timeout on DHCP attempt. |
dcoban | 0:1a61c61d0845 | 147 | if (Timeout.read_ms() > 10000) |
dcoban | 0:1a61c61d0845 | 148 | { |
dcoban | 0:1a61c61d0845 | 149 | printf("error: Timeout while waiting for network to initialize.\r\n"); |
dcoban | 0:1a61c61d0845 | 150 | goto Error; |
dcoban | 0:1a61c61d0845 | 151 | } |
dcoban | 0:1a61c61d0845 | 152 | } |
dcoban | 0:1a61c61d0845 | 153 | |
dcoban | 0:1a61c61d0845 | 154 | // Print out the DHCP provided IP addresses. |
dcoban | 0:1a61c61d0845 | 155 | printf("IP : "); |
dcoban | 0:1a61c61d0845 | 156 | SNetwork_PrintAddress(&pNetwork->EthernetInterface.ip_addr); |
dcoban | 0:1a61c61d0845 | 157 | printf("\r\n"); |
dcoban | 0:1a61c61d0845 | 158 | |
dcoban | 0:1a61c61d0845 | 159 | printf("Gateway: "); |
dcoban | 0:1a61c61d0845 | 160 | SNetwork_PrintAddress(&pNetwork->EthernetInterface.gw); |
dcoban | 0:1a61c61d0845 | 161 | printf("\r\n"); |
dcoban | 0:1a61c61d0845 | 162 | |
dcoban | 0:1a61c61d0845 | 163 | printf("Mask : "); |
dcoban | 0:1a61c61d0845 | 164 | SNetwork_PrintAddress(&pNetwork->EthernetInterface.netmask); |
dcoban | 0:1a61c61d0845 | 165 | printf("\r\n"); |
dcoban | 0:1a61c61d0845 | 166 | |
dcoban | 0:1a61c61d0845 | 167 | Return = 0; |
dcoban | 0:1a61c61d0845 | 168 | Error: |
dcoban | 0:1a61c61d0845 | 169 | return Return; |
dcoban | 0:1a61c61d0845 | 170 | } |
dcoban | 0:1a61c61d0845 | 171 | |
dcoban | 0:1a61c61d0845 | 172 | |
dcoban | 0:1a61c61d0845 | 173 | /* Called from within the main application loop to perform network maintenance |
dcoban | 0:1a61c61d0845 | 174 | tasks at appropriate time intervals and execute the ethernet driver which |
dcoban | 0:1a61c61d0845 | 175 | will push new network packets into the lwIP stack. lwIP will then call into |
dcoban | 0:1a61c61d0845 | 176 | the callbacks which have been configured by this application. |
dcoban | 0:1a61c61d0845 | 177 | |
dcoban | 0:1a61c61d0845 | 178 | Parameters: |
dcoban | 0:1a61c61d0845 | 179 | pNetwork is a pointer to the intitialized network object. |
dcoban | 0:1a61c61d0845 | 180 | |
dcoban | 0:1a61c61d0845 | 181 | Returns: |
dcoban | 0:1a61c61d0845 | 182 | Number of network tasks run during this polling process. If 0 then no |
dcoban | 0:1a61c61d0845 | 183 | network related tasks were completed during this polling iteration. |
dcoban | 0:1a61c61d0845 | 184 | */ |
dcoban | 0:1a61c61d0845 | 185 | int SNetwork_Poll(SNetwork* pNetwork) |
dcoban | 0:1a61c61d0845 | 186 | { |
dcoban | 0:1a61c61d0845 | 187 | int TasksRun = 0; |
dcoban | 0:1a61c61d0845 | 188 | |
dcoban | 0:1a61c61d0845 | 189 | // Validate parameters. |
dcoban | 0:1a61c61d0845 | 190 | assert ( pNetwork ); |
dcoban | 0:1a61c61d0845 | 191 | |
dcoban | 0:1a61c61d0845 | 192 | // Execute timed maintenance tasks. |
dcoban | 0:1a61c61d0845 | 193 | if (pNetwork->DHCPFine.read_ms() >= DHCP_FINE_TIMER_MSECS) |
dcoban | 0:1a61c61d0845 | 194 | { |
dcoban | 0:1a61c61d0845 | 195 | pNetwork->DHCPFine.reset(); |
dcoban | 0:1a61c61d0845 | 196 | dhcp_fine_tmr(); |
dcoban | 0:1a61c61d0845 | 197 | TasksRun++; |
dcoban | 0:1a61c61d0845 | 198 | } |
dcoban | 0:1a61c61d0845 | 199 | if (pNetwork->DHCPCoarse.read() >= DHCP_COARSE_TIMER_SECS) |
dcoban | 0:1a61c61d0845 | 200 | { |
dcoban | 0:1a61c61d0845 | 201 | pNetwork->DHCPCoarse.reset(); |
dcoban | 0:1a61c61d0845 | 202 | dhcp_coarse_tmr(); |
dcoban | 0:1a61c61d0845 | 203 | TasksRun++; |
dcoban | 0:1a61c61d0845 | 204 | } |
dcoban | 0:1a61c61d0845 | 205 | if (pNetwork->ARP.read_ms() >= ARP_TMR_INTERVAL) |
dcoban | 0:1a61c61d0845 | 206 | { |
dcoban | 0:1a61c61d0845 | 207 | pNetwork->ARP.reset(); |
dcoban | 0:1a61c61d0845 | 208 | etharp_tmr(); |
dcoban | 0:1a61c61d0845 | 209 | TasksRun++; |
dcoban | 0:1a61c61d0845 | 210 | } |
dcoban | 0:1a61c61d0845 | 211 | if (pNetwork->TCP.read_ms() >= TCP_TMR_INTERVAL) |
dcoban | 0:1a61c61d0845 | 212 | { |
dcoban | 0:1a61c61d0845 | 213 | pNetwork->TCP.reset(); |
dcoban | 0:1a61c61d0845 | 214 | tcp_tmr(); |
dcoban | 0:1a61c61d0845 | 215 | TasksRun++; |
dcoban | 0:1a61c61d0845 | 216 | } |
dcoban | 0:1a61c61d0845 | 217 | if (pNetwork->DNS.read_ms() >= DNS_TMR_INTERVAL) |
dcoban | 0:1a61c61d0845 | 218 | { |
dcoban | 0:1a61c61d0845 | 219 | pNetwork->DNS.reset(); |
dcoban | 0:1a61c61d0845 | 220 | dns_tmr(); |
dcoban | 0:1a61c61d0845 | 221 | TasksRun++; |
dcoban | 0:1a61c61d0845 | 222 | } |
dcoban | 0:1a61c61d0845 | 223 | |
dcoban | 0:1a61c61d0845 | 224 | // Poll the ethernet driver to let it pull packets in and push new packets |
dcoban | 0:1a61c61d0845 | 225 | // into the lwIP network stack. |
dcoban | 0:1a61c61d0845 | 226 | TasksRun += eth_poll(); |
dcoban | 0:1a61c61d0845 | 227 | |
dcoban | 0:1a61c61d0845 | 228 | return TasksRun; |
dcoban | 0:1a61c61d0845 | 229 | } |
dcoban | 0:1a61c61d0845 | 230 | |
dcoban | 0:1a61c61d0845 | 231 | |
dcoban | 0:1a61c61d0845 | 232 | /* Prints out the caller supplied IP address. |
dcoban | 0:1a61c61d0845 | 233 | |
dcoban | 0:1a61c61d0845 | 234 | Parameters: |
dcoban | 0:1a61c61d0845 | 235 | pAddress is a pointer to the ip4 address to be displayed. |
dcoban | 0:1a61c61d0845 | 236 | |
dcoban | 0:1a61c61d0845 | 237 | Returns: |
dcoban | 0:1a61c61d0845 | 238 | Nothing. |
dcoban | 0:1a61c61d0845 | 239 | */ |
dcoban | 0:1a61c61d0845 | 240 | void SNetwork_PrintAddress(ip_addr_t* pAddress) |
dcoban | 0:1a61c61d0845 | 241 | { |
dcoban | 0:1a61c61d0845 | 242 | // Validate parameters. |
dcoban | 0:1a61c61d0845 | 243 | assert ( pAddress ); |
dcoban | 0:1a61c61d0845 | 244 | |
dcoban | 0:1a61c61d0845 | 245 | printf("%d.%d.%d.%d", |
dcoban | 0:1a61c61d0845 | 246 | ip4_addr1(pAddress), |
dcoban | 0:1a61c61d0845 | 247 | ip4_addr2(pAddress), |
dcoban | 0:1a61c61d0845 | 248 | ip4_addr3(pAddress), |
dcoban | 0:1a61c61d0845 | 249 | ip4_addr4(pAddress)); |
dcoban | 0:1a61c61d0845 | 250 | } |