From 2bdd39bf3f07c2fdb5112d137e1a392d35a51d0c Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Tue, 15 Aug 2017 15:55:30 +0300 Subject: [PATCH 01/13] Porting ethernet to EMAC Updating EMAC to enable multiple interfaces Untangling networking classes, making the abstractions a bit clearer to follow, etc General refactoring Removal of DEVICE_EMAC flag and introducing DEVICE_ETH and DEVICE_WIFI --- doxyfile_options | 2 +- .../TESTS/mbedmicro-net/connectivity/main.cpp | 4 +- .../mbedmicro-net/gethostbyname/main.cpp | 4 +- .../TESTS/mbedmicro-net/tcp_echo/main.cpp | 4 +- .../mbedmicro-net/tcp_echo_parallel/main.cpp | 4 +- .../mbedmicro-net/tcp_hello_world/main.cpp | 4 +- .../tcp_packet_pressure/main.cpp | 4 +- .../tcp_packet_pressure_parallel/main.cpp | 4 +- .../mbedmicro-net/udp_dtls_handshake/main.cpp | 4 +- .../TESTS/mbedmicro-net/udp_echo/main.cpp | 4 +- .../mbedmicro-net/udp_echo_parallel/main.cpp | 4 +- .../udp_packet_pressure/main.cpp | 4 +- .../udp_packet_pressure_parallel/main.cpp | 4 +- .../FEATURE_LWIP/lwip-interface/emac_lwip.c | 129 +- .../{eth_arch.h => emac_lwip.h} | 18 +- ...c_stack_lwip.cpp => emac_stack_mem_lwip.c} | 28 +- .../lwip-interface/ipstack_lwip.c | 356 ++++++ .../arch/TARGET_CM3DS_MPS2/mps2_emac.c | 2 +- .../arch/TARGET_Freescale/k64f_emac.c | 473 +++----- .../arch/TARGET_Freescale/k64f_emac_config.h | 5 + .../TARGET_NUC472/nuc472_netif.c | 2 +- .../lwip-eth/arch/TARGET_NXP/lpc17_emac.c | 2 +- .../FEATURE_LWIP/lwip-interface/lwip_stack.c | 1059 ----------------- .../FEATURE_LWIP/lwip-interface/lwip_stack.h | 47 - .../FEATURE_LWIP/lwip-interface/lwip_tools.c | 112 ++ .../FEATURE_LWIP/lwip-interface/lwip_tools.h | 43 + .../lwip-interface/nsapi_stack_lwip.c | 504 ++++++++ .../FEATURE_LWIP/lwip-interface/ppp_lwip.cpp | 2 +- .../EthernetInterface.cpp | 38 +- .../EthernetInterface.h | 10 +- features/netsocket/emac_stack_mem.h | 41 +- features/netsocket/mbed_ipstack.h | 123 ++ features/netsocket/nsapi.h | 1 - features/netsocket/nsapi_types.h | 4 + hal/emac_api.h | 37 +- .../TARGET_AMEBA/RTWInterface.cpp | 14 +- .../sdk/wifi_emac/wifi_emac_api.cpp | 2 +- targets/targets.json | 2 +- 38 files changed, 1560 insertions(+), 1544 deletions(-) rename features/FEATURE_LWIP/lwip-interface/{eth_arch.h => emac_lwip.h} (77%) rename features/FEATURE_LWIP/lwip-interface/{emac_stack_lwip.cpp => emac_stack_mem_lwip.c} (68%) create mode 100644 features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c delete mode 100644 features/FEATURE_LWIP/lwip-interface/lwip_stack.c delete mode 100644 features/FEATURE_LWIP/lwip-interface/lwip_stack.h create mode 100644 features/FEATURE_LWIP/lwip-interface/lwip_tools.c create mode 100644 features/FEATURE_LWIP/lwip-interface/lwip_tools.h create mode 100644 features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c rename features/{FEATURE_LWIP/lwip-interface => netsocket}/EthernetInterface.cpp (67%) rename features/{FEATURE_LWIP/lwip-interface => netsocket}/EthernetInterface.h (95%) create mode 100644 features/netsocket/mbed_ipstack.h diff --git a/doxyfile_options b/doxyfile_options index cab5340a046..d433f01df30 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -2061,7 +2061,7 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_ANALOGOUT \ DEVICE_CAN \ DEVICE_ETHERNET \ - DEVICE_EMAC \ + DEVICE_ETH \ DEVICE_FLASH \ DEVICE_I2C \ DEVICE_I2CSLAVE \ diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp index 67119ea20fb..938b7f04e0e 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp index b0a5d4eb7b7..21515701713 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp index 6324e6d1043..1014d93301c 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo_parallel/main.cpp index 377a4229b66..1942815182e 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo_parallel/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo_parallel/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp index f5a0b0b9a98..61d7b02cb30 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp index ec0731c9c78..b56ff51537f 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #ifndef MBED_EXTENDED_TESTS #error [NOT_SUPPORTED] Pressure tests are not supported by default diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp index 847e40ae15d..455878ae60f 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #ifndef MBED_EXTENDED_TESTS #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp index 2563bc2dfae..9c52f3698da 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp index ab07f52f038..6e7e03ce894 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp index 8e8c19ccf11..73aa437e12a 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #include "mbed.h" diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp index 3faa23b4669..4c477898a0c 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #ifndef MBED_EXTENDED_TESTS #error [NOT_SUPPORTED] Pressure tests are not supported by default diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp index acb543b4bb3..f3ef1ca7101 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp @@ -16,8 +16,8 @@ #if !FEATURE_LWIP #error [NOT_SUPPORTED] LWIP not supported for this target #endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets +#if !DEVICE_ETH + #error [NOT_SUPPORTED] Ethernet not supported for this targets #endif #ifndef MBED_EXTENDED_TESTS #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default diff --git a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c index f189bb2a988..d1ba12325d9 100644 --- a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c @@ -14,8 +14,6 @@ * limitations under the License. */ -#if DEVICE_EMAC - #include "emac_api.h" #include "emac_stack_mem.h" #include "lwip/tcpip.h" @@ -26,12 +24,11 @@ static err_t emac_lwip_low_level_output(struct netif *netif, struct pbuf *p) { emac_interface_t *mac = (emac_interface_t *)netif->state; - bool ret = mac->ops.link_out(mac, (emac_stack_mem_t *)p); - + bool ret = mac->ops->link_out(mac, (emac_stack_mem_chain_t *)p); return ret ? ERR_OK : ERR_IF; } -static void emac_lwip_input(void *data, emac_stack_t *buf) +static void emac_lwip_input(void *data, emac_stack_mem_t *buf) { struct pbuf *p = (struct pbuf *)buf; struct netif *netif = (struct netif *)data; @@ -55,34 +52,128 @@ static void emac_lwip_state_change(void *data, bool up) } } -err_t emac_lwip_if_init(struct netif *netif) +#if LWIP_IGMP + +#include "lwip/igmp.h" +/** + * IPv4 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv4 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t action) { - int err = ERR_OK; - emac_interface_t *mac = (emac_interface_t *)netif->state; + emac_interface_t *emac = netif->state; + if (emac->ops->add_multicast_group == NULL) { + return ERR_OK; /* This function is not mandatory */ + } - mac->ops.set_link_input_cb(mac, emac_lwip_input, netif); - mac->ops.set_link_state_cb(mac, emac_lwip_state_change, netif); + switch (action) { + case NETIF_ADD_MAC_FILTER: + { + uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; + uint8_t addr[6]; + addr[0] = LL_IP4_MULTICAST_ADDR_0; + addr[1] = LL_IP4_MULTICAST_ADDR_1; + addr[2] = LL_IP4_MULTICAST_ADDR_2; + addr[3] = group23 >> 16; + addr[4] = group23 >> 8; + addr[5] = group23; + emac->ops->add_multicast_group(emac, addr); + return ERR_OK; + } + case NETIF_DEL_MAC_FILTER: + /* As we don't reference count, silently ignore delete requests */ + return ERR_OK; + default: + return ERR_ARG; + } +} +#endif - if (!mac->ops.power_up(mac)) { - err = ERR_IF; +#if LWIP_IPV6_MLD + +#include "lwip/mld6.h" +/** + * IPv6 address filtering setup. + * + * \param[in] netif the lwip network interface structure + * \param[in] group IPv6 group to modify + * \param[in] action + * \return ERR_OK or error code + */ +static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t action) +{ + emac_interface_t *emac = netif->state; + if (emac->ops->add_multicast_group == NULL) { + return ERR_OK; /* This function is not mandatory */ + } + + switch (action) { + case NETIF_ADD_MAC_FILTER: + { + uint32_t group32 = ntohl(group->addr[3]); + uint8_t addr[6]; + addr[0] = LL_IP6_MULTICAST_ADDR_0; + addr[1] = LL_IP6_MULTICAST_ADDR_1; + addr[2] = group32 >> 24; + addr[3] = group32 >> 16; + addr[4] = group32 >> 8; + addr[5] = group32; + emac->ops->add_multicast_group(emac, addr); + return ERR_OK; + } + case NETIF_DEL_MAC_FILTER: + /* As we don't reference count, silently ignore delete requests */ + return ERR_OK; + default: + return ERR_ARG; } +} +#endif + +err_t emac_lwip_if_init(struct netif *netif) +{ + int err = ERR_OK; + emac_interface_t *emac = netif->state; - netif->mtu = mac->ops.get_mtu_size(mac); - netif->hwaddr_len = mac->ops.get_hwaddr_size(mac); - mac->ops.get_hwaddr(mac, netif->hwaddr); + emac->ops->set_link_input_cb(emac, emac_lwip_input, netif); + emac->ops->set_link_state_cb(emac, emac_lwip_state_change, netif); + + netif->hwaddr_len = emac->ops->get_hwaddr_size(emac); + emac->ops->get_hwaddr(emac, netif->hwaddr); + netif->mtu = emac->ops->get_mtu_size(emac); /* Interface capabilities */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; - mac->ops.get_ifname(mac, netif->name, 2); + emac->ops->get_ifname(emac, netif->name, 2); #if LWIP_IPV4 netif->output = etharp_output; +#if LWIP_IGMP + netif->igmp_mac_filter = igmp_mac_filter; + netif->flags |= NETIF_FLAG_IGMP; +#endif /* LWIP_IGMP */ #endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#if LWIP_IPV6_MLD + netif->mld_mac_filter = mld_mac_filter; + netif->flags |= NETIF_FLAG_MLD6; +#else +// Would need to enable all multicasts here - no API in fsl_enet to do that +#error "IPv6 multicasts won't be received if LWIP_IPV6_MLD is disabled, breaking the system" +#endif +#endif netif->linkoutput = emac_lwip_low_level_output; + if (!emac->ops->power_up(emac)) { + err = ERR_IF; + } + return err; } - -#endif /* DEVICE_EMAC */ diff --git a/features/FEATURE_LWIP/lwip-interface/eth_arch.h b/features/FEATURE_LWIP/lwip-interface/emac_lwip.h similarity index 77% rename from features/FEATURE_LWIP/lwip-interface/eth_arch.h rename to features/FEATURE_LWIP/lwip-interface/emac_lwip.h index 25bdde38dda..6ec310e3c86 100644 --- a/features/FEATURE_LWIP/lwip-interface/eth_arch.h +++ b/features/FEATURE_LWIP/lwip-interface/emac_lwip.h @@ -1,4 +1,4 @@ -/* EthernetInterface.h */ +/* emac_lwip.h */ /* Copyright (C) 2012 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software @@ -17,11 +17,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// Architecture specific Ethernet interface -// Must be implemented by each target - -#ifndef ETHARCH_H_ -#define ETHARCH_H_ +#ifndef EMAC_LWIP_H_ +#define EMAC_LWIP_H_ #include "lwip/netif.h" @@ -29,17 +26,10 @@ extern "C" { #endif -#if DEVICE_EMAC err_t emac_lwip_if_init(struct netif *netif); -#else /* DEVICE_EMAC */ -void eth_arch_enable_interrupts(void); -void eth_arch_disable_interrupts(void); -err_t eth_arch_enetif_init(struct netif *netif); -#endif - #ifdef __cplusplus } #endif -#endif // #ifndef ETHARCHINTERFACE_H_ +#endif // #ifndef EMAC_LWIP_H_ diff --git a/features/FEATURE_LWIP/lwip-interface/emac_stack_lwip.cpp b/features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c similarity index 68% rename from features/FEATURE_LWIP/lwip-interface/emac_stack_lwip.cpp rename to features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c index 42ec7ff82a8..d84427802cc 100644 --- a/features/FEATURE_LWIP/lwip-interface/emac_stack_lwip.cpp +++ b/features/FEATURE_LWIP/lwip-interface/emac_stack_mem_lwip.c @@ -14,12 +14,10 @@ * limitations under the License. */ -#if DEVICE_EMAC - #include "emac_stack_mem.h" #include "pbuf.h" -emac_stack_mem_t *emac_stack_mem_alloc(emac_stack_t* stack, uint32_t size, uint32_t align) +emac_stack_mem_t *emac_stack_mem_alloc(uint32_t size, uint32_t align) { struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, size + align, PBUF_RAM); @@ -42,34 +40,34 @@ emac_stack_mem_t *emac_stack_mem_alloc(emac_stack_t* stack, uint32_t size, uint3 return (emac_stack_mem_t*)pbuf; } -void emac_stack_mem_free(emac_stack_t* stack, emac_stack_mem_t *mem) +void emac_stack_mem_free(emac_stack_mem_t *mem) { pbuf_free((struct pbuf*)mem); } -void emac_stack_mem_copy(emac_stack_t* stack, emac_stack_mem_t *to, emac_stack_mem_t *from) +void emac_stack_mem_copy(emac_stack_mem_t *to, emac_stack_mem_t *from) { pbuf_copy((struct pbuf*)to, (struct pbuf*)from); } -void *emac_stack_mem_ptr(emac_stack_t* stack, emac_stack_mem_t *mem) +void *emac_stack_mem_ptr(emac_stack_mem_t *mem) { return ((struct pbuf*)mem)->payload; } -uint32_t emac_stack_mem_len(emac_stack_t* stack, emac_stack_mem_t *mem) +uint32_t emac_stack_mem_len(emac_stack_mem_t *mem) { return ((struct pbuf*)mem)->len; } -void emac_stack_mem_set_len(emac_stack_t* stack, emac_stack_mem_t *mem, uint32_t len) +void emac_stack_mem_set_len(emac_stack_mem_t *mem, uint32_t len) { struct pbuf *pbuf = (struct pbuf*)mem; pbuf->len = len; } -emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_t* stack, emac_stack_mem_chain_t **chain) +emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_mem_chain_t **chain) { struct pbuf **list = (struct pbuf**)chain; struct pbuf *head = *list; @@ -78,14 +76,18 @@ emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_t* stack, emac_stack_m return (emac_stack_mem_t *)head; } -uint32_t emac_stack_mem_chain_len(emac_stack_t* stack, emac_stack_mem_chain_t *chain) +uint32_t emac_stack_mem_chain_len(emac_stack_mem_chain_t *chain) { return ((struct pbuf*)chain)->tot_len; } -void emac_stack_mem_ref(emac_stack_t* stack, emac_stack_mem_t *mem) +void emac_stack_mem_set_chain_len(emac_stack_mem_chain_t *chain, uint32_t len) + { + struct pbuf *pbuf = (struct pbuf*)chain; + pbuf->tot_len = len; +} + +void emac_stack_mem_ref(emac_stack_mem_t *mem) { pbuf_ref((struct pbuf*)mem); } - -#endif /* DEVICE_EMAC */ diff --git a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c new file mode 100644 index 00000000000..2a903d818d5 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c @@ -0,0 +1,356 @@ +/* LWIP implementation of NetworkInterfaceAPI + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nsapi.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include +#include +#include + +#include "lwip/opt.h" +#include "lwip/api.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" +#include "lwip/tcp.h" +#include "lwip/ip.h" +#include "lwip/mld6.h" +#include "lwip/dns.h" +#include "lwip/udp.h" + +#include "emac_api.h" +#include "emac_lwip.h" +#include "mbed_ipstack.h" +#include "lwip_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static bool mbed_lwip_inited = false; +static sys_sem_t lwip_tcpip_inited; + +static void add_dns_addr(struct netif *lwip_netif) +{ + // Do nothing if not brought up + const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); + if (!ip_addr) { + return; + } + + // Check for existing dns server + for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { + const ip_addr_t *dns_ip_addr = dns_getserver(numdns); + if (!ip_addr_isany(dns_ip_addr)) { + return; + } + } + +#if LWIP_IPV6 + if (IP_IS_V6(ip_addr)) { + /* 2001:4860:4860::8888 google */ + ip_addr_t ipv6_dns_addr = IPADDR6_INIT( + PP_HTONL(0x20014860UL), + PP_HTONL(0x48600000UL), + PP_HTONL(0x00000000UL), + PP_HTONL(0x00008888UL)); + dns_setserver(0, &ipv6_dns_addr); + } +#endif + +#if LWIP_IPV4 + if (IP_IS_V4(ip_addr)) { + /* 8.8.8.8 google */ + ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808); + dns_setserver(0, &ipv4_dns_addr); + } +#endif +} + +static void mbed_lwip_tcpip_init_irq(void *eh) +{ + sys_sem_signal(&lwip_tcpip_inited); +} + +static void mbed_lwip_netif_link_irq(struct netif *netif) +{ + if (netif_is_link_up(netif)) { + emac_interface_t *emac = netif->state; + sys_sem_signal(&emac->linked); + } +} + +static void mbed_lwip_netif_status_irq(struct netif *netif) +{ + static bool any_addr = true; + emac_interface_t *emac = netif->state; + + if (netif_is_up(netif)) { + // Indicates that has address + if (any_addr == true && mbed_lwip_get_ip_addr(true, netif)) { + sys_sem_signal(&emac->has_addr); + any_addr = false; + return; + } + + // Indicates that has preferred address + if (mbed_lwip_get_ip_addr(false, netif)) { + sys_sem_signal(&emac->has_addr); + } + } else { + any_addr = true; + } +} + +#if LWIP_IPV6 +static void mbed_lwip_clear_ipv6_addresses(struct netif *netif) +{ + for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); + } +} +#endif + +char *mbed_ipstack_get_mac_address(emac_interface_t *emac) +{ + return emac->hwaddr; +} + +char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +{ + const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &emac->netif); + if (!addr) { + return NULL; + } +#if LWIP_IPV6 + if (IP_IS_V6(addr)) { + return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); + } +#endif +#if LWIP_IPV4 + if (IP_IS_V4(addr)) { + return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); + } +#endif + return NULL; +} + +char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +{ +#if LWIP_IPV4 + const ip4_addr_t *addr = netif_ip4_netmask(&emac->netif); + if (!ip4_addr_isany(addr)) { + return ip4addr_ntoa_r(addr, buf, buflen); + } else { + return NULL; + } +#else + return NULL; +#endif +} + +char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +{ +#if LWIP_IPV4 + const ip4_addr_t *addr = netif_ip4_gw(&emac->netif); + if (!ip4_addr_isany(addr)) { + return ip4addr_ntoa_r(addr, buf, buflen); + } else { + return NULL; + } +#else + return NULL; +#endif +} + +void mbed_ipstack_init(void) +{ + if(mbed_lwip_inited) + return; + + sys_sem_new(&lwip_tcpip_inited, 0); + tcpip_init(mbed_lwip_tcpip_init_irq, NULL); + sys_arch_sem_wait(&lwip_tcpip_inited, 0); + + // Zero out socket set + mbed_lwip_arena_init(); + + mbed_lwip_inited = true; +} + +nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if) +{ + emac->connected = false; + emac->dhcp = true; + sys_sem_new(&emac->linked, 0); + sys_sem_new(&emac->has_addr, 0); + memset(&emac->netif, 0, sizeof(emac->netif)); + emac->netif.state = emac; + + mbed_mac_address(emac->hwaddr); + + if (!netif_add(&emac->netif, +#if LWIP_IPV4 + 0, 0, 0, +#endif + emac, emac_lwip_if_init, tcpip_input)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + if (default_if) + netif_set_default(&emac->netif); + + netif_set_link_callback(&emac->netif, mbed_lwip_netif_link_irq); + netif_set_status_callback(&emac->netif, mbed_lwip_netif_status_irq); + + return NSAPI_ERROR_OK; +} + +nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, const char *netmask, const char *gw) +{ + // Check if we've already connected + if (emac->connected) { + return NSAPI_ERROR_PARAMETER; + } + + mbed_ipstack_init(); + +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&emac->netif, 1/*from MAC*/); +#if LWIP_IPV6_MLD + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (emac->netif.mld_mac_filter != NULL) { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + emac->netif.mld_mac_filter(&emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6_MLD */ + +#if LWIP_IPV6_AUTOCONFIG + /* IPv6 address autoconfiguration not enabled by default */ + emac->netif.ip6_autoconfig_enabled = 1; +#endif /* LWIP_IPV6_AUTOCONFIG */ + +#endif /* LWIP_IPV6 */ + + u32_t ret; + + if (!netif_is_link_up(&emac->netif)) { + ret = sys_arch_sem_wait(&emac->linked, 15000); + + if (ret == SYS_ARCH_TIMEOUT) { + return NSAPI_ERROR_NO_CONNECTION; + } + } + +#if LWIP_IPV4 + if (!dhcp) { + ip4_addr_t ip_addr; + ip4_addr_t netmask_addr; + ip4_addr_t gw_addr; + + if (!inet_aton(ip, &ip_addr) || + !inet_aton(netmask, &netmask_addr) || + !inet_aton(gw, &gw_addr)) { + return NSAPI_ERROR_PARAMETER; + } + + netif_set_addr(&emac->netif, &ip_addr, &netmask_addr, &gw_addr); + } +#endif + + netif_set_up(&emac->netif); + +#if LWIP_IPV4 + // Connect to the network + emac->dhcp = dhcp; + + if (dhcp) { + err_t err = dhcp_start(&emac->netif); + if (err) { + return NSAPI_ERROR_DHCP_FAILURE; + } + } +#endif + + // If doesn't have address + if (!mbed_lwip_get_ip_addr(true, &emac->netif)) { + ret = sys_arch_sem_wait(&emac->has_addr, 15000); + if (ret == SYS_ARCH_TIMEOUT) { + return NSAPI_ERROR_DHCP_FAILURE; + } + + emac->connected = true; + } + +#if ADDR_TIMEOUT + // If address is not for preferred stack waits a while to see + // if preferred stack address is acquired + if (!mbed_lwip_get_ip_addr(false, &emac->netif)) { + ret = sys_arch_sem_wait(&emac->has_addr, ADDR_TIMEOUT * 1000); + } +#endif + + add_dns_addr(&emac->netif); + + return 0; +} + +nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) +{ + // Check if we've connected + if (!emac->connected) { + return NSAPI_ERROR_PARAMETER; + } + +#if LWIP_IPV4 + // Disconnect from the network + if (emac->dhcp) { + dhcp_release(&emac->netif); + dhcp_stop(&emac->netif); + emac->dhcp = false; + } +#endif + + netif_set_down(&emac->netif); + +#if LWIP_IPV6 + mbed_lwip_clear_ipv6_addresses(&emac->netif); +#endif + + sys_sem_free(&emac->has_addr); + sys_sem_new(&emac->has_addr, 0); + emac->connected = false; + return 0; +} + +extern const nsapi_stack_api_t lwip_stack_api; /* Defined in nsapi_stack_lwip.c */ + +void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack) +{ + stack->emac = emac; + stack->stack_api = &lwip_stack_api; +} + +#ifdef __cplusplus +} +#endif diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_CM3DS_MPS2/mps2_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_CM3DS_MPS2/mps2_emac.c index 13a47fc6710..3aedc6f7220 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_CM3DS_MPS2/mps2_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_CM3DS_MPS2/mps2_emac.c @@ -19,7 +19,7 @@ #include #include "ethernet_api.h" -#include "eth_arch.h" +#include "emac_lwip.h" #include "lwip/def.h" #include "lwip/ethip6.h" diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index b4c9d1e8221..64c609e1d29 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -1,21 +1,7 @@ -#include "lwip/opt.h" -#include "lwip/sys.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/tcpip.h" -#include "lwip/ethip6.h" -#include "lwip/igmp.h" -#include "lwip/mld6.h" -#include "netif/etharp.h" -#include "netif/ppp/pppoe.h" - -#include "eth_arch.h" +#include "cmsis_os.h" #include "sys_arch.h" - #include "fsl_phy.h" + #include "k64f_emac_config.h" #include #include @@ -23,6 +9,13 @@ #include #include "mbed_interface.h" +#include "emac_api.h" +#include "emac_stack_mem.h" +#include "mbed_assert.h" + +/* LWIP dependencies - TODO: Should be removed */ +#include "lwip/sys.h" +#include "lwip_ethernet.h" enet_handle_t g_handle; // TX Buffer descriptors @@ -30,12 +23,15 @@ uint8_t *tx_desc_start_addr; // RX Buffer descriptors uint8_t *rx_desc_start_addr; // RX packet buffer pointers -struct pbuf *rx_buff[ENET_RX_RING_LEN]; +emac_stack_mem_t *rx_buff[ENET_RX_RING_LEN]; // TX packet buffer pointers -struct pbuf *tx_buff[ENET_RX_RING_LEN]; +emac_stack_mem_t *tx_buff[ENET_RX_RING_LEN]; // RX packet payload pointers uint32_t *rx_ptr[ENET_RX_RING_LEN]; +#define K64_ETH_MTU_SIZE 1500 +#define K64_ETH_IF_NAME "en" + /******************************************************************************** * Internal data ********************************************************************************/ @@ -51,12 +47,15 @@ extern void k66f_init_eth_hardware(void); /* K64F EMAC driver data structure */ struct k64f_enetdata { - struct netif *netif; /**< Reference back to LWIP parent netif */ sys_sem_t RxReadySem; /**< RX packet ready semaphore */ sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ sys_mutex_t TXLockMutex; /**< TX critical section mutex */ sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */ uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ + emac_link_input_fn emac_link_input_cb; /**< Callback for incoming data */ + void *emac_link_input_cb_data; /**< Data to be passed to input cb */ + emac_link_state_change_fn emac_link_state_cb; /**< Link state change callback */ + void *emac_link_state_cb_data; /**< Data to be passed to link state cb */ }; static struct k64f_enetdata k64f_enetdata; @@ -102,66 +101,68 @@ static void update_read_buffer(uint8_t *buf) /** \brief Free TX buffers that are complete * - * \param[in] k64f_enet Pointer to driver data structure + * \param[in] k64f Pointer to driver data structure */ -static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet) +static void k64f_tx_reclaim(struct k64f_enetdata *enet) { /* Get exclusive access */ - sys_mutex_lock(&k64f_enet->TXLockMutex); + sys_mutex_lock(&enet->TXLockMutex); // Traverse all descriptors, looking for the ones modified by the uDMA - while((k64f_enet->tx_consume_index != k64f_enet->tx_produce_index) && + while((enet->tx_consume_index != enet->tx_produce_index) && (!(g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { - pbuf_free(tx_buff[k64f_enet->tx_consume_index % ENET_TX_RING_LEN]); + emac_stack_mem_free(tx_buff[enet->tx_consume_index % ENET_TX_RING_LEN]); if (g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) g_handle.txBdDirty = g_handle.txBdBase; else g_handle.txBdDirty++; - k64f_enet->tx_consume_index += 1; - osSemaphoreRelease(k64f_enet->xTXDCountSem.id); + enet->tx_consume_index += 1; + osSemaphoreRelease(enet->xTXDCountSem.id); } /* Restore access */ - sys_mutex_unlock(&k64f_enet->TXLockMutex); + sys_mutex_unlock(&enet->TXLockMutex); } /** \brief Ethernet receive interrupt handler * * This function handles the receive interrupt of K64F. */ -void enet_mac_rx_isr() +void enet_mac_rx_isr(struct k64f_enetdata *enet) { - sys_sem_signal(&k64f_enetdata.RxReadySem); + sys_sem_signal(&enet->RxReadySem); } -void enet_mac_tx_isr() +void enet_mac_tx_isr(struct k64f_enetdata *enet) { - sys_sem_signal(&k64f_enetdata.TxCleanSem); + sys_sem_signal(&enet->TxCleanSem); } void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) { - switch (event) + struct k64f_enetdata *enet = param; + switch (event) { case kENET_RxEvent: - enet_mac_rx_isr(); + enet_mac_rx_isr(enet); break; case kENET_TxEvent: - enet_mac_tx_isr(); + enet_mac_tx_isr(enet); break; default: break; } } + /** \brief Low level init of the MAC and PHY. * - * \param[in] netif Pointer to LWIP netif structure + * \param[in] enet Pointer to K64F enet structure + * \param[in] hwaddr MAC address */ -static err_t low_level_init(struct netif *netif) +static err_t low_level_init(struct k64f_enetdata *enet, char *hwaddr) { - struct k64f_enetdata *k64f_enet = netif->state; uint8_t i; uint32_t sysClock; phy_speed_t phy_speed; @@ -169,6 +170,7 @@ static err_t low_level_init(struct netif *netif) uint32_t phyAddr = 0; bool link = false; enet_config_t config; + void *payload; // Allocate RX descriptors rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); @@ -185,7 +187,7 @@ static err_t low_level_init(struct netif *netif) /* Create buffers for each receive BD */ for (i = 0; i < ENET_RX_RING_LEN; i++) { - rx_buff[i] = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM); + rx_buff[i] = emac_stack_mem_alloc(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); if (NULL == rx_buff[i]) return ERR_MEM; @@ -193,11 +195,12 @@ static err_t low_level_init(struct netif *netif) RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing a data structure which is internal to lwIP. This might not prove to be a good idea in the long run, but a better fix would probably involve modifying lwIP itself */ - rx_buff[i]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[i]->payload, ENET_BUFF_ALIGNMENT); - rx_ptr[i] = rx_buff[i]->payload; + payload = emac_stack_mem_ptr(rx_buff[i]); + payload = (void*)ENET_ALIGN((uint32_t)payload, ENET_BUFF_ALIGNMENT); + rx_ptr[i] = payload; } - k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0; + enet->tx_consume_index = enet->tx_produce_index = 0; /* prepare the buffer configuration. */ enet_buffer_config_t buffCfg = { @@ -237,144 +240,35 @@ static err_t low_level_init(struct netif *netif) config.macSpecialConfig = kENET_ControlFlowControlEnable; config.txAccelerConfig = kENET_TxAccelIsShift16Enabled; config.rxAccelerConfig = kENET_RxAccelisShift16Enabled | kENET_RxAccelMacCheckEnabled; - ENET_Init(ENET, &g_handle, &config, &buffCfg, netif->hwaddr, sysClock); - ENET_SetCallback(&g_handle, ethernet_callback, netif); + ENET_Init(ENET, &g_handle, &config, &buffCfg, (uint8_t*)hwaddr, sysClock); + ENET_SetCallback(&g_handle, ethernet_callback, enet); ENET_ActiveRead(ENET); return ERR_OK; } -/** - * This function is the ipv4 ethernet packet send function. It calls - * etharp_output after checking link status. - * - * \param[in] netif the lwip network interface structure for this enetif - * \param[in] q Pointer to pbug to send - * \param[in] ipaddr IP address - * \return ERR_OK or error code - */ -#if LWIP_IPV4 -err_t k64f_etharp_output_ipv4(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) -{ - /* Only send packet is link is up */ - if (netif->flags & NETIF_FLAG_LINK_UP) { - return etharp_output(netif, q, ipaddr); - } - - return ERR_CONN; -} -#endif - -/** - * This function is the ipv6 ethernet packet send function. It calls - * ethip6_output after checking link status. - * - * \param[in] netif the lwip network interface structure for this enetif - * \param[in] q Pointer to pbug to send - * \param[in] ipaddr IP address - * \return ERR_OK or error code - */ -#if LWIP_IPV6 -err_t k64f_etharp_output_ipv6(struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr) -{ - /* Only send packet is link is up */ - if (netif->flags & NETIF_FLAG_LINK_UP) { - return ethip6_output(netif, q, ipaddr); - } - - return ERR_CONN; -} -#endif - -#if LWIP_IGMP -/** - * IPv4 address filtering setup. +/** \brief Allocates a emac_stack_mem_t and returns the data from the incoming packet. * - * \param[in] netif the lwip network interface structure for this enetif - * \param[in] group IPv4 group to modify - * \param[in] action - * \return ERR_OK or error code - */ -err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, enum netif_mac_filter_action action) -{ - switch (action) { - case NETIF_ADD_MAC_FILTER: - { - uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; - uint8_t addr[6]; - addr[0] = LL_IP4_MULTICAST_ADDR_0; - addr[1] = LL_IP4_MULTICAST_ADDR_1; - addr[2] = LL_IP4_MULTICAST_ADDR_2; - addr[3] = group23 >> 16; - addr[4] = group23 >> 8; - addr[5] = group23; - ENET_AddMulticastGroup(ENET, addr); - return ERR_OK; - } - case NETIF_DEL_MAC_FILTER: - /* As we don't reference count, silently ignore delete requests */ - return ERR_OK; - default: - return ERR_ARG; - } -} -#endif - -#if LWIP_IPV6_MLD -/** - * IPv6 address filtering setup. - * - * \param[in] netif the lwip network interface structure for this enetif - * \param[in] group IPv6 group to modify - * \param[in] action - * \return ERR_OK or error code - */ -err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action) -{ - switch (action) { - case NETIF_ADD_MAC_FILTER: - { - uint32_t group32 = ntohl(group->addr[3]); - uint8_t addr[6]; - addr[0] = LL_IP6_MULTICAST_ADDR_0; - addr[1] = LL_IP6_MULTICAST_ADDR_1; - addr[2] = group32 >> 24; - addr[3] = group32 >> 16; - addr[4] = group32 >> 8; - addr[5] = group32; - ENET_AddMulticastGroup(ENET, addr); - return ERR_OK; - } - case NETIF_DEL_MAC_FILTER: - /* As we don't reference count, silently ignore delete requests */ - return ERR_OK; - default: - return ERR_ARG; - } -} -#endif - -/** \brief Allocates a pbuf and returns the data from the incoming packet. - * - * \param[in] netif the lwip network interface structure * \param[in] idx index of packet to be read - * \return a pbuf filled with the received packet (including MAC header) + * \return a emac_stack_mem_t filled with the received packet (including MAC header) */ -static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) +static emac_stack_mem_t *k64f_low_level_input(int idx) { volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent; - struct pbuf *p = NULL; - struct pbuf *temp_rxbuf = NULL; + emac_stack_mem_t *p = NULL; + emac_stack_mem_t *temp_rxbuf = NULL; u32_t length = 0; const u16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; -#ifdef LOCK_RX_THREAD - /* Get exclusive access */ - sys_mutex_lock(&k64f_enet->TXLockMutex); -#endif + void *payload; + + #ifdef LOCK_RX_THREAD + /* Get exclusive access */ + sys_mutex_lock(&enet->TXLockMutex); + #endif /* Determine if a frame has been received */ if ((bdPtr->control & err_mask) != 0) { @@ -393,10 +287,10 @@ static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) /* Zero-copy */ p = rx_buff[idx]; - p->len = length; + emac_stack_mem_set_len(p, length); /* Attempt to queue new buffer */ - temp_rxbuf = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM); + temp_rxbuf = emac_stack_mem_alloc(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); if (NULL == temp_rxbuf) { /* Drop frame (out of memory) */ LINK_STATS_INC(link.drop); @@ -408,7 +302,7 @@ static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) ("k64f_low_level_input: Packet index %d dropped for OOM\n", idx)); #ifdef LOCK_RX_THREAD - sys_mutex_unlock(&k64f_enet->TXLockMutex); + sys_mutex_unlock(&enet->TXLockMutex); #endif return NULL; @@ -419,21 +313,22 @@ static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing a data structure which is internal to lwIP. This might not prove to be a good idea in the long run, but a better fix would probably involve modifying lwIP itself */ - rx_buff[idx]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[idx]->payload, ENET_BUFF_ALIGNMENT); - rx_ptr[idx] = rx_buff[idx]->payload; + payload = emac_stack_mem_ptr(rx_buff[idx]); + payload = (void*)ENET_ALIGN((uint32_t)payload, ENET_BUFF_ALIGNMENT); + rx_ptr[idx] = payload; - update_read_buffer(rx_buff[idx]->payload); + update_read_buffer(payload); LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, ("k64f_low_level_input: Packet received: %p, size %"PRIu32" (index=%d)\n", p, length, idx)); /* Save size */ - p->tot_len = (u16_t) length; + emac_stack_mem_set_chain_len(p, length); LINK_STATS_INC(link.recv); } #ifdef LOCK_RX_THREAD - sys_mutex_unlock(&k64f_enet->TXLockMutex); + sys_mutex_unlock(&enet->TXLockMutex); #endif return p; @@ -444,21 +339,17 @@ static struct pbuf *k64f_low_level_input(struct netif *netif, int idx) * \param[in] netif the lwip network interface structure * \param[in] idx index of packet to be read */ -void k64f_enetif_input(struct netif *netif, int idx) +void k64f_enetif_input(struct k64f_enetdata *enet, int idx) { - struct pbuf *p; + emac_stack_mem_t *p; - /* move received packet into a new pbuf */ - p = k64f_low_level_input(netif, idx); + /* move received packet into a new buf */ + p = k64f_low_level_input(idx); if (p == NULL) return; - /* pass all packets to ethernet_input, which decides what packets it supports */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: input error\n")); - /* Free buffer */ - pbuf_free(p); - } + enet->emac_link_input_cb(enet->emac_link_input_cb_data, p); + } /** \brief Packet reception task @@ -469,15 +360,15 @@ void k64f_enetif_input(struct netif *netif, int idx) * \param[in] pvParameters pointer to the interface data */ static void packet_rx(void* pvParameters) { - struct k64f_enetdata *k64f_enet = pvParameters; + struct k64f_enetdata *enet = pvParameters; int idx = 0; while (1) { /* Wait for receive task to wakeup */ - sys_arch_sem_wait(&k64f_enet->RxReadySem, 0); + sys_arch_sem_wait(&enet->RxReadySem, 0); while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { - k64f_enetif_input(k64f_enet->netif, idx); + k64f_enetif_input(enet, idx); idx = (idx + 1) % ENET_RX_RING_LEN; } } @@ -486,18 +377,18 @@ static void packet_rx(void* pvParameters) { /** \brief Transmit cleanup task * * This task is called when a transmit interrupt occurs and - * reclaims the pbuf and descriptor used for the packet once + * reclaims the buffer and descriptor used for the packet once * the packet has been transferred. * * \param[in] pvParameters pointer to the interface data */ static void packet_tx(void* pvParameters) { - struct k64f_enetdata *k64f_enet = pvParameters; + struct k64f_enetdata *enet = pvParameters; while (1) { /* Wait for transmit cleanup task to wakeup */ - sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0); - k64f_tx_reclaim(k64f_enet); + sys_arch_sem_wait(&enet->TxCleanSem, 0); + k64f_tx_reclaim(enet); } } @@ -505,47 +396,47 @@ static void packet_tx(void* pvParameters) { * interrupt context, as it may block until TX descriptors * become available. * - * \param[in] netif the lwip network interface structure for this netif - * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \param[in] emac Emac driver for the network interface + * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent */ -static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p) +static bool k64f_eth_link_out(emac_interface_t *emac, emac_stack_mem_chain_t *chain) { - struct k64f_enetdata *k64f_enet = netif->state; - struct pbuf *q; - struct pbuf *temp_pbuf; + struct k64f_enetdata *enet = emac->hw; + emac_stack_mem_t *q; + emac_stack_mem_t *temp_pbuf; uint8_t *psend = NULL, *dst; - temp_pbuf = pbuf_alloc(PBUF_RAW, p->tot_len + ENET_BUFF_ALIGNMENT, PBUF_RAM); + temp_pbuf = emac_stack_mem_alloc(emac_stack_mem_chain_len(chain), ENET_BUFF_ALIGNMENT); if (NULL == temp_pbuf) - return ERR_MEM; + return false; /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing a data structure which is internal to lwIP. This might not prove to be a good idea in the long run, but a better fix would probably involve modifying lwIP itself */ - psend = (uint8_t *)ENET_ALIGN((uint32_t)temp_pbuf->payload, ENET_BUFF_ALIGNMENT); + psend = (uint8_t *)ENET_ALIGN((uint32_t)emac_stack_mem_ptr(temp_pbuf), ENET_BUFF_ALIGNMENT); - for (q = p, dst = psend; q != NULL; q = q->next) { - MEMCPY(dst, q->payload, q->len); - dst += q->len; + for (q = emac_stack_mem_chain_dequeue(&chain), dst = psend; q != NULL; q = emac_stack_mem_chain_dequeue(&chain)) { + memcpy(dst, emac_stack_mem_ptr(q), emac_stack_mem_len(q)); + dst += emac_stack_mem_len(q); } /* Check if a descriptor is available for the transfer. */ - osStatus_t stat = osSemaphoreAcquire(k64f_enet->xTXDCountSem.id, 0); + osStatus_t stat = osSemaphoreAcquire(enet->xTXDCountSem.id, 0); if (stat != osOK) - return ERR_BUF; + return false; /* Get exclusive access */ - sys_mutex_lock(&k64f_enet->TXLockMutex); + sys_mutex_lock(&enet->TXLockMutex); /* Save the buffer so that it can be freed when transmit is done */ - tx_buff[k64f_enet->tx_produce_index % ENET_TX_RING_LEN] = temp_pbuf; - k64f_enet->tx_produce_index += 1; + tx_buff[enet->tx_produce_index % ENET_TX_RING_LEN] = temp_pbuf; + enet->tx_produce_index += 1; /* Setup transfers */ g_handle.txBdCurrent->buffer = psend; - g_handle.txBdCurrent->length = p->tot_len; + g_handle.txBdCurrent->length = emac_stack_mem_len(temp_pbuf); g_handle.txBdCurrent->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); /* Increase the buffer descriptor address. */ @@ -560,9 +451,9 @@ static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p) LINK_STATS_INC(link.xmit); /* Restore access */ - sys_mutex_unlock(&k64f_enet->TXLockMutex); + sys_mutex_unlock(&enet->TXLockMutex); - return ERR_OK; + return true; } /******************************************************************************* @@ -587,7 +478,7 @@ int phy_link_status() { } static void k64f_phy_task(void *data) { - struct netif *netif = (struct netif*)data; + struct k64f_enetdata *enet = data; bool connection_status; PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN}; PHY_STATE prev_state; @@ -604,10 +495,7 @@ static void k64f_phy_task(void *data) { // Compare with previous state if (crt_state.connected != prev_state.connected) { - if (crt_state.connected) - tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1); - else - tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1); + enet->emac_link_state_cb(enet->emac_link_state_cb_data, crt_state.connected); } if (crt_state.speed != prev_state.speed) { @@ -622,79 +510,16 @@ static void k64f_phy_task(void *data) { } } -/** - * Should be called at the beginning of the program to set up the - * network interface. - * - * This function should be passed as a parameter to netif_add(). - * - * @param[in] netif the lwip network interface structure for this netif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t eth_arch_enetif_init(struct netif *netif) +static bool k64f_eth_power_up(emac_interface_t *emac) { err_t err; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - - k64f_enetdata.netif = netif; - - /* set MAC hardware address */ -#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) - netif->hwaddr[0] = MBED_MAC_ADDR_0; - netif->hwaddr[1] = MBED_MAC_ADDR_1; - netif->hwaddr[2] = MBED_MAC_ADDR_2; - netif->hwaddr[3] = MBED_MAC_ADDR_3; - netif->hwaddr[4] = MBED_MAC_ADDR_4; - netif->hwaddr[5] = MBED_MAC_ADDR_5; -#else - mbed_mac_address((char *)netif->hwaddr); -#endif - - /* Ethernet address length */ - netif->hwaddr_len = ETH_HWADDR_LEN; - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - // TODOETH: check if the flags are correct below - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; + char hwaddr[ETH_HWADDR_LEN]; /* Initialize the hardware */ - netif->state = &k64f_enetdata; - err = low_level_init(netif); + mbed_mac_address(hwaddr); + err = low_level_init(&k64f_enetdata, hwaddr); if (err != ERR_OK) - return err; - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwipk64f"; -#endif /* LWIP_NETIF_HOSTNAME */ - - netif->name[0] = 'e'; - netif->name[1] = 'n'; - -#if LWIP_IPV4 - netif->output = k64f_etharp_output_ipv4; -#if LWIP_IGMP - netif->igmp_mac_filter = igmp_mac_filter; - netif->flags |= NETIF_FLAG_IGMP; -#endif -#endif -#if LWIP_IPV6 - netif->output_ip6 = k64f_etharp_output_ipv6; -#if LWIP_IPV6_MLD - netif->mld_mac_filter = mld_mac_filter; - netif->flags |= NETIF_FLAG_MLD6; -#else - // Would need to enable all multicasts here - no API in fsl_enet to do that - #error "IPv6 multicasts won't be received if LWIP_IPV6_MLD is disabled, breaking the system" -#endif -#endif - netif->linkoutput = k64f_low_level_output; + return false; /* CMSIS-RTOS, start tasks */ memset(&k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data)); @@ -702,44 +527,104 @@ err_t eth_arch_enetif_init(struct netif *netif) k64f_enetdata.xTXDCountSem.attr.cb_size = sizeof(k64f_enetdata.xTXDCountSem.data); k64f_enetdata.xTXDCountSem.id = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &k64f_enetdata.xTXDCountSem.attr); - LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL)); + MBED_ASSERT(k64f_enetdata.xTXDCountSem.id != NULL); err = sys_mutex_new(&k64f_enetdata.TXLockMutex); - LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK)); + MBED_ASSERT(err == ERR_OK); /* Packet receive task */ err = sys_sem_new(&k64f_enetdata.RxReadySem, 0); - LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK)); + MBED_ASSERT(err == ERR_OK); #ifdef LWIP_DEBUG - sys_thread_new("k64f_emac_rx_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY); + sys_thread_new("k64f_emac_rx_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY); #else - sys_thread_new("k64f_emac_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); + sys_thread_new("k64f_emac_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); #endif /* Transmit cleanup task */ err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0); - LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK)); - sys_thread_new("k64f_emac_txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY); + MBED_ASSERT(err == ERR_OK); + sys_thread_new("k64f_emac_txclean_thread", packet_tx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY); /* PHY monitoring task */ - sys_thread_new("k64f_emac_phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY); + sys_thread_new("k64f_emac_phy_thread", k64f_phy_task, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY); /* Allow the PHY task to detect the initial link state and set up the proper flags */ osDelay(10); - return ERR_OK; + return true; +} + + +static uint32_t k64f_eth_get_mtu_size(emac_interface_t *emac) +{ + return K64_ETH_MTU_SIZE; } -void eth_arch_enable_interrupts(void) { - //NVIC_SetPriority(ENET_Receive_IRQn, 6U); - //NVIC_SetPriority(ENET_Transmit_IRQn, 6U); +static void k64f_eth_get_ifname(emac_interface_t *emac, char *name, uint8_t size) +{ + memcpy(name, K64_ETH_IF_NAME, (size < sizeof(K64_ETH_IF_NAME)) ? size : sizeof(K64_ETH_IF_NAME)); } -void eth_arch_disable_interrupts(void) { +static uint8_t k64f_eth_get_hwaddr_size(emac_interface_t *emac) +{ + return ETH_HWADDR_LEN; +} +static void k64f_eth_get_hwaddr(emac_interface_t *emac, uint8_t *addr) +{ + mbed_mac_address((char*)addr); +} + +static void k64f_eth_set_hwaddr(emac_interface_t *emac, uint8_t *addr) +{ + /* No-op at this stage */ } +static void k64f_eth_set_link_input_cb(emac_interface_t *emac, emac_link_input_fn input_cb, void *data) +{ + struct k64f_enetdata *enet = emac->hw; + + enet->emac_link_input_cb = input_cb; + enet->emac_link_input_cb_data = data; +} + +static void k64f_eth_set_link_state_cb(emac_interface_t *emac, emac_link_state_change_fn state_cb, void *data) +{ + struct k64f_enetdata *enet = emac->hw; + + enet->emac_link_state_cb = state_cb; + enet->emac_link_state_cb_data = data; +} + +static void k64f_eth_add_multicast_group(emac_interface_t *emac, uint8_t *addr) +{ + ENET_AddMulticastGroup(ENET, addr); +} + +static void k64f_eth_power_down(emac_interface_t *emac) +{ + /* No-op at this stage */ +} + + +const emac_interface_ops_t k64f_eth_emac_ops = { + .get_mtu_size = k64f_eth_get_mtu_size, + .get_ifname = k64f_eth_get_ifname, + .get_hwaddr_size = k64f_eth_get_hwaddr_size, + .get_hwaddr = k64f_eth_get_hwaddr, + .set_hwaddr = k64f_eth_set_hwaddr, + .link_out = k64f_eth_link_out, + .power_up = k64f_eth_power_up, + .power_down = k64f_eth_power_down, + .set_link_input_cb = k64f_eth_set_link_input_cb, + .set_link_state_cb = k64f_eth_set_link_state_cb, + .add_multicast_group = k64f_eth_add_multicast_group +}; + +emac_interface_t mbed_emac_eth_default = {&k64f_eth_emac_ops, &k64f_enetdata}; + /** * @} */ diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h index 8ec5f2ddaf3..7676d3890c5 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h @@ -34,9 +34,14 @@ #define ENET_RX_RING_LEN (16) #define ENET_TX_RING_LEN (8) +#define ETH_HWADDR_LEN (6) #define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame +#define K64_ETH_MTU_SIZE 1500 +#define K64_ETH_IF_NAME "en" + + #if defined(__cplusplus) extern "C" { #endif diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NUVOTON/TARGET_NUC472/nuc472_netif.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NUVOTON/TARGET_NUC472/nuc472_netif.c index cd954a6a436..28fd5c639f4 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NUVOTON/TARGET_NUC472/nuc472_netif.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NUVOTON/TARGET_NUC472/nuc472_netif.c @@ -57,7 +57,7 @@ #include "nuc472_eth.h" #include "string.h" -#include "eth_arch.h" +#include "emac_lwip.h" #include "sys_arch.h" #include #include diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NXP/lpc17_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NXP/lpc17_emac.c index a9aef9a524c..c6a7be57724 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NXP/lpc17_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_NXP/lpc17_emac.c @@ -35,7 +35,7 @@ #include "netif/ppp/pppoe.h" #include "lpc17xx_emac.h" -#include "eth_arch.h" +#include "emac_lwip.h" #include "lpc_emac_config.h" #include "lpc_phy.h" #include "sys_arch.h" diff --git a/features/FEATURE_LWIP/lwip-interface/lwip_stack.c b/features/FEATURE_LWIP/lwip-interface/lwip_stack.c deleted file mode 100644 index 115ad3539fe..00000000000 --- a/features/FEATURE_LWIP/lwip-interface/lwip_stack.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* LWIP implementation of NetworkInterfaceAPI - * Copyright (c) 2015 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nsapi.h" -#include "mbed_interface.h" -#include "mbed_assert.h" -#include -#include -#include -#include "lwip_stack.h" - -#include "eth_arch.h" -#include "lwip/opt.h" -#include "lwip/api.h" -#include "lwip/inet.h" -#include "lwip/netif.h" -#include "lwip/dhcp.h" -#include "lwip/tcpip.h" -#include "lwip/tcp.h" -#include "lwip/ip.h" -#include "lwip/mld6.h" -#include "lwip/dns.h" -#include "lwip/udp.h" -#include "netif/lwip_ethernet.h" -#include "emac_api.h" -#include "ppp_lwip.h" -#include "lwip_tcp_isn.h" - -static nsapi_error_t mbed_lwip_err_remap(err_t err); - -#if DEVICE_EMAC - #define MBED_NETIF_INIT_FN emac_lwip_if_init -#else - #define MBED_NETIF_INIT_FN eth_arch_enetif_init -#endif - -/* Static arena of sockets */ -static struct lwip_socket { - bool in_use; - - struct netconn *conn; - struct netbuf *buf; - u16_t offset; - - void (*cb)(void *); - void *data; -} lwip_arena[MEMP_NUM_NETCONN]; - -static bool lwip_inited = false; -static bool lwip_connected = false; -static bool netif_inited = false; -static bool netif_is_ppp = false; - -static struct lwip_socket *mbed_lwip_arena_alloc(void) -{ - sys_prot_t prot = sys_arch_protect(); - - for (int i = 0; i < MEMP_NUM_NETCONN; i++) { - if (!lwip_arena[i].in_use) { - struct lwip_socket *s = &lwip_arena[i]; - memset(s, 0, sizeof *s); - s->in_use = true; - sys_arch_unprotect(prot); - return s; - } - } - - sys_arch_unprotect(prot); - return 0; -} - -static void mbed_lwip_arena_dealloc(struct lwip_socket *s) -{ - s->in_use = false; -} - -static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) -{ - // Filter send minus events - if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) { - return; - } - - sys_prot_t prot = sys_arch_protect(); - - for (int i = 0; i < MEMP_NUM_NETCONN; i++) { - if (lwip_arena[i].in_use - && lwip_arena[i].conn == nc - && lwip_arena[i].cb) { - lwip_arena[i].cb(lwip_arena[i].data); - } - } - - sys_arch_unprotect(prot); -} - - -/* TCP/IP and Network Interface Initialisation */ -static struct netif lwip_netif; -#if LWIP_DHCP -static bool lwip_dhcp = false; -#endif -static char lwip_mac_address[NSAPI_MAC_SIZE]; - -#if !LWIP_IPV4 || !LWIP_IPV6 -static bool all_zeros(const uint8_t *p, int len) -{ - for (int i = 0; i < len; i++) { - if (p[i]) { - return false; - } - } - - return true; -} -#endif - -static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) -{ -#if LWIP_IPV6 - if (in->version == NSAPI_IPv6) { - IP_SET_TYPE(out, IPADDR_TYPE_V6); - MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); - return true; - } -#if !LWIP_IPV4 - /* For bind() and other purposes, need to accept "null" of other type */ - /* (People use IPv4 0.0.0.0 as a general null) */ - if (in->version == NSAPI_UNSPEC || - (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { - ip_addr_set_zero_ip6(out); - return true; - } -#endif -#endif - -#if LWIP_IPV4 - if (in->version == NSAPI_IPv4) { - IP_SET_TYPE(out, IPADDR_TYPE_V4); - MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); - return true; - } -#if !LWIP_IPV6 - /* For symmetry with above, accept IPv6 :: as a general null */ - if (in->version == NSAPI_UNSPEC || - (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { - ip_addr_set_zero_ip4(out); - return true; - } -#endif -#endif - -#if LWIP_IPV4 && LWIP_IPV6 - if (in->version == NSAPI_UNSPEC) { -#if IP_VERSION_PREF == PREF_IPV4 - ip_addr_set_zero_ip4(out); -#else - ip_addr_set_zero_ip6(out); -#endif - return true; - } -#endif - - return false; -} - -static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in) -{ -#if LWIP_IPV6 - if (IP_IS_V6(in)) { - out->version = NSAPI_IPv6; - MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t)); - return true; - } -#endif -#if LWIP_IPV4 - if (IP_IS_V4(in)) { - out->version = NSAPI_IPv4; - MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t)); - return true; - } -#endif -#if LWIP_IPV6 && LWIP_IPV4 - return false; -#endif -} - -static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif) -{ -#if LWIP_IPV4 - if (!netif_is_up(netif)) { - return NULL; - } - - if (!ip4_addr_isany(netif_ip4_addr(netif))) { - return netif_ip_addr4(netif); - } -#endif - - return NULL; -} - -static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif) -{ -#if LWIP_IPV6 - if (!netif_is_up(netif)) { - return NULL; - } - - for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } -#endif - - return NULL; - -} - -const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif) -{ - const ip_addr_t *pref_ip_addr = 0; - const ip_addr_t *npref_ip_addr = 0; - -#if IP_VERSION_PREF == PREF_IPV4 - pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); - npref_ip_addr = mbed_lwip_get_ipv6_addr(netif); -#else - pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); - npref_ip_addr = mbed_lwip_get_ipv4_addr(netif); -#endif - - if (pref_ip_addr) { - return pref_ip_addr; - } else if (npref_ip_addr && any_addr) { - return npref_ip_addr; - } - - return NULL; -} - -void add_dns_addr(struct netif *lwip_netif) -{ - // Do nothing if not brought up - const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); - if (!ip_addr) { - return; - } - - // Check for existing dns server - for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { - const ip_addr_t *dns_ip_addr = dns_getserver(numdns); - if (!ip_addr_isany(dns_ip_addr)) { - return; - } - } - -#if LWIP_IPV6 - if (IP_IS_V6(ip_addr)) { - /* 2001:4860:4860::8888 google */ - ip_addr_t ipv6_dns_addr = IPADDR6_INIT( - PP_HTONL(0x20014860UL), - PP_HTONL(0x48600000UL), - PP_HTONL(0x00000000UL), - PP_HTONL(0x00008888UL)); - dns_setserver(0, &ipv6_dns_addr); - } -#endif - -#if LWIP_IPV4 - if (IP_IS_V4(ip_addr)) { - /* 8.8.8.8 google */ - ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808); - dns_setserver(0, &ipv4_dns_addr); - } -#endif -} - -static sys_sem_t lwip_tcpip_inited; -static void mbed_lwip_tcpip_init_irq(void *eh) -{ - sys_sem_signal(&lwip_tcpip_inited); -} - -static sys_sem_t lwip_netif_linked; -static sys_sem_t lwip_netif_unlinked; -static void mbed_lwip_netif_link_irq(struct netif *lwip_netif) -{ - if (netif_is_link_up(lwip_netif)) { - sys_sem_signal(&lwip_netif_linked); - } else { - sys_sem_signal(&lwip_netif_unlinked); - } -} - -static sys_sem_t lwip_netif_has_addr; -static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) -{ - static bool any_addr = true; - - if (netif_is_up(lwip_netif)) { - // Indicates that has address - if (any_addr == true && mbed_lwip_get_ip_addr(true, lwip_netif)) { - sys_sem_signal(&lwip_netif_has_addr); - any_addr = false; - return; - } - - // Indicates that has preferred address - if (mbed_lwip_get_ip_addr(false, lwip_netif)) { - sys_sem_signal(&lwip_netif_has_addr); - } - } else { - any_addr = true; - } -} - -#if LWIP_ETHERNET -static void mbed_lwip_set_mac_address(struct netif *netif) -{ -#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) - netif->hwaddr[0] = MBED_MAC_ADDR_0; - netif->hwaddr[1] = MBED_MAC_ADDR_1; - netif->hwaddr[2] = MBED_MAC_ADDR_2; - netif->hwaddr[3] = MBED_MAC_ADDR_3; - netif->hwaddr[4] = MBED_MAC_ADDR_4; - netif->hwaddr[5] = MBED_MAC_ADDR_5; -#else - mbed_mac_address((char *)netif->hwaddr); -#endif - - netif->hwaddr_len = ETH_HWADDR_LEN; - - /* Use mac address as additional seed to random number generator */ - uint64_t seed = netif->hwaddr[0]; - for (uint8_t i = 1; i < 8; i++) { - seed <<= 8; - seed |= netif->hwaddr[i % 6]; - } - lwip_add_random_seed(seed); -} - -static void mbed_lwip_record_mac_address(const struct netif *netif) -{ - const u8_t *mac = netif->hwaddr; - snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); -} -#endif // LWIP_ETHERNET - -/* LWIP interface implementation */ -const char *mbed_lwip_get_mac_address(void) -{ - return lwip_mac_address[0] ? lwip_mac_address : NULL; -} - -char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen) -{ - const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif); - if (!addr) { - return NULL; - } -#if LWIP_IPV6 - if (IP_IS_V6(addr)) { - return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); - } -#endif -#if LWIP_IPV4 - if (IP_IS_V4(addr)) { - return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); - } -#endif -#if LWIP_IPV6 && LWIP_IPV4 - return NULL; -#endif -} - -char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen) -{ -#if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif); - if (!ip4_addr_isany(addr)) { - return ip4addr_ntoa_r(addr, buf, buflen); - } else { - return NULL; - } -#else - return NULL; -#endif -} - -char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen) -{ -#if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif); - if (!ip4_addr_isany(addr)) { - return ip4addr_ntoa_r(addr, buf, buflen); - } else { - return NULL; - } -#else - return NULL; -#endif -} - -static void mbed_lwip_core_init(void) -{ - - // Check if we've already brought up lwip - if (!lwip_inited) { - // Seed lwip random - lwip_seed_random(); - - // Initialise TCP sequence number - uint32_t tcp_isn_secret[4]; - for (int i = 0; i < 4; i++) { - tcp_isn_secret[i] = LWIP_RAND(); - } - lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret); - - sys_sem_new(&lwip_tcpip_inited, 0); - sys_sem_new(&lwip_netif_linked, 0); - sys_sem_new(&lwip_netif_unlinked, 0); - sys_sem_new(&lwip_netif_has_addr, 0); - - tcpip_init(mbed_lwip_tcpip_init_irq, NULL); - sys_arch_sem_wait(&lwip_tcpip_inited, 0); - - lwip_inited = true; - } -} - -nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac) -{ -#if LWIP_ETHERNET - // Choose a MAC address - driver can override - mbed_lwip_set_mac_address(&lwip_netif); - - // Set up network - if (!netif_add(&lwip_netif, -#if LWIP_IPV4 - 0, 0, 0, -#endif - emac, MBED_NETIF_INIT_FN, tcpip_input)) { - return NSAPI_ERROR_DEVICE_ERROR; - } - - // Note the MAC address actually in use - mbed_lwip_record_mac_address(&lwip_netif); - -#if !DEVICE_EMAC - eth_arch_enable_interrupts(); -#endif - - return NSAPI_ERROR_OK; -#else - return NSAPI_ERROR_UNSUPPORTED; -#endif //LWIP_ETHERNET -} - -// Backwards compatibility with people using DEVICE_EMAC -nsapi_error_t mbed_lwip_init(emac_interface_t *emac) -{ - nsapi_error_t ret; - mbed_lwip_core_init(); - ret = mbed_lwip_emac_init(emac); - if (ret == NSAPI_ERROR_OK) { - netif_inited = true; - } - return ret; -} - -// Backwards compatibility with people using DEVICE_EMAC -nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw) -{ - return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw); -} - -nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw) -{ - // Check if we've already connected - if (lwip_connected) { - return NSAPI_ERROR_PARAMETER; - } - - mbed_lwip_core_init(); - - nsapi_error_t ret; - if (netif_inited) { - /* Can't cope with changing mode */ - if (netif_is_ppp == ppp) { - ret = NSAPI_ERROR_OK; - } else { - ret = NSAPI_ERROR_PARAMETER; - } - } else { - if (ppp) { - ret = ppp_lwip_if_init(&lwip_netif); - } else { - ret = mbed_lwip_emac_init(NULL); - } - } - - if (ret != NSAPI_ERROR_OK) { - return ret; - } - - netif_inited = true; - if (ppp) { - netif_is_ppp = ppp; - } - - netif_set_default(&lwip_netif); - netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); - netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); - -#if LWIP_IPV6 - if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) { - netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); - } - -#if LWIP_IPV6_MLD - /* - * For hardware/netifs that implement MAC filtering. - * All-nodes link-local is handled by default, so we must let the hardware know - * to allow multicast packets in. - * Should set mld_mac_filter previously. */ - if (lwip_netif.mld_mac_filter != NULL) { - ip6_addr_t ip6_allnodes_ll; - ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); - } -#endif /* LWIP_IPV6_MLD */ - -#if LWIP_IPV6_AUTOCONFIG - /* IPv6 address autoconfiguration not enabled by default */ - lwip_netif.ip6_autoconfig_enabled = 1; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#endif // LWIP_IPV6 - - -#if LWIP_IPV4 - if (!dhcp && !ppp) { - ip4_addr_t ip_addr; - ip4_addr_t netmask_addr; - ip4_addr_t gw_addr; - - if (!inet_aton(ip, &ip_addr) || - !inet_aton(netmask, &netmask_addr) || - !inet_aton(gw, &gw_addr)) { - return NSAPI_ERROR_PARAMETER; - } - - netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); - } -#endif - - if (ppp) { - err_t err = ppp_lwip_connect(); - if (err) { - return mbed_lwip_err_remap(err); - } - } - - if (!netif_is_link_up(&lwip_netif)) { - if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) { - if (ppp) { - ppp_lwip_disconnect(); - } - return NSAPI_ERROR_NO_CONNECTION; - } - } - - if (!ppp) { - netif_set_up(&lwip_netif); - } - -#if LWIP_DHCP - // Connect to the network - lwip_dhcp = dhcp; - - if (lwip_dhcp) { - err_t err = dhcp_start(&lwip_netif); - if (err) { - return NSAPI_ERROR_DHCP_FAILURE; - } - } -#endif - - // If doesn't have address - if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { - if (sys_arch_sem_wait(&lwip_netif_has_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) { - if (ppp) { - ppp_lwip_disconnect(); - } - - return NSAPI_ERROR_DHCP_FAILURE; - } - } - -#if ADDR_TIMEOUT - // If address is not for preferred stack waits a while to see - // if preferred stack address is acquired - if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { - sys_arch_sem_wait(&lwip_netif_has_addr, ADDR_TIMEOUT * 1000); - } -#endif - - add_dns_addr(&lwip_netif); - - lwip_connected = true; - return 0; -} - -#if LWIP_IPV6 -void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif) -{ - for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID); - } -} -#endif - -// Backwards compatibility with people using DEVICE_EMAC -nsapi_error_t mbed_lwip_bringdown(void) -{ - return mbed_lwip_bringdown_2(false); -} - -nsapi_error_t mbed_lwip_bringdown_2(bool ppp) -{ - // Check if we've connected - if (!lwip_connected) { - return NSAPI_ERROR_PARAMETER; - } - -#if LWIP_DHCP - // Disconnect from the network - if (lwip_dhcp) { - dhcp_release(&lwip_netif); - dhcp_stop(&lwip_netif); - lwip_dhcp = false; - } -#endif - - if (ppp) { - /* this is a blocking call, returns when PPP is properly closed */ - err_t err = ppp_lwip_disconnect(); - if (err) { - return mbed_lwip_err_remap(err); - } - MBED_ASSERT(!netif_is_link_up(&lwip_netif)); - /*if (netif_is_link_up(&lwip_netif)) { - if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) { - return NSAPI_ERROR_DEVICE_ERROR; - } - }*/ - } else { - netif_set_down(&lwip_netif); - } - -#if LWIP_IPV6 - mbed_lwip_clear_ipv6_addresses(&lwip_netif); -#endif - - - sys_sem_free(&lwip_netif_has_addr); - sys_sem_new(&lwip_netif_has_addr, 0); - - lwip_connected = false; - return 0; -} - -/* LWIP error remapping */ -static nsapi_error_t mbed_lwip_err_remap(err_t err) { - switch (err) { - case ERR_OK: - case ERR_CLSD: - return 0; - case ERR_MEM: - return NSAPI_ERROR_NO_MEMORY; - case ERR_CONN: - case ERR_RST: - case ERR_ABRT: - return NSAPI_ERROR_NO_CONNECTION; - case ERR_TIMEOUT: - case ERR_RTE: - case ERR_WOULDBLOCK: - return NSAPI_ERROR_WOULD_BLOCK; - case ERR_VAL: - case ERR_USE: - case ERR_ARG: - return NSAPI_ERROR_PARAMETER; - case ERR_INPROGRESS: - return NSAPI_ERROR_IN_PROGRESS; - case ERR_ALREADY: - return NSAPI_ERROR_ALREADY; - case ERR_ISCONN: - return NSAPI_ERROR_IS_CONNECTED; - default: - return NSAPI_ERROR_DEVICE_ERROR; - } -} - -/* LWIP network stack implementation */ -static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) -{ - ip_addr_t lwip_addr; - -#if LWIP_IPV4 && LWIP_IPV6 - u8_t addr_type; - if (version == NSAPI_UNSPEC) { - const ip_addr_t *ip_addr; - ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); - if (IP_IS_V6(ip_addr)) { - addr_type = NETCONN_DNS_IPV6; - } else { - addr_type = NETCONN_DNS_IPV4; - } - } else if (version == NSAPI_IPv4) { - addr_type = NETCONN_DNS_IPV4; - } else if (version == NSAPI_IPv6) { - addr_type = NETCONN_DNS_IPV6; - } - err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); -#elif LWIP_IPV4 - if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { - return NSAPI_ERROR_DNS_FAILURE; - } - err_t err = netconn_gethostbyname(host, &lwip_addr); -#elif LWIP_IPV6 - if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) { - return NSAPI_ERROR_DNS_FAILURE; - } - err_t err = netconn_gethostbyname(host, &lwip_addr); -#endif - - if (err != ERR_OK) { - return NSAPI_ERROR_DNS_FAILURE; - } - - convert_lwip_addr_to_mbed(addr, &lwip_addr); - - return 0; -} - -static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr) -{ - // Shift all dns servers down to give precedence to new server - for (int i = DNS_MAX_SERVERS-1; i > 0; i--) { - dns_setserver(i, dns_getserver(i-1)); - } - - ip_addr_t ip_addr; - if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { - return NSAPI_ERROR_PARAMETER; - } - - dns_setserver(0, &ip_addr); - return 0; -} - -static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) -{ - // check if network is connected - if (!lwip_connected) { - return NSAPI_ERROR_NO_CONNECTION; - } - - // allocate a socket - struct lwip_socket *s = mbed_lwip_arena_alloc(); - if (!s) { - return NSAPI_ERROR_NO_SOCKET; - } - - enum netconn_type lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; - -#if LWIP_IPV6 && LWIP_IPV4 - const ip_addr_t *ip_addr; - ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); - - if (IP_IS_V6(ip_addr)) { - // Enable IPv6 (or dual-stack). LWIP dual-stack support is - // currently incomplete as of 2.0.0rc2 - eg we will only be able - // to do a UDP sendto to an address matching the type selected - // here. Matching "get_ip_addr" and DNS logic, use v4 if - // available. - lwip_proto |= NETCONN_TYPE_IPV6; - } -#elif LWIP_IPV6 - lwip_proto |= NETCONN_TYPE_IPV6; -#endif - - s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); - - if (!s->conn) { - mbed_lwip_arena_dealloc(s); - return NSAPI_ERROR_NO_SOCKET; - } - - netconn_set_recvtimeout(s->conn, 1); - *(struct lwip_socket **)handle = s; - return 0; -} - -static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - - netbuf_delete(s->buf); - err_t err = netconn_delete(s->conn); - mbed_lwip_arena_dealloc(s); - return mbed_lwip_err_remap(err); -} - -static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - ip_addr_t ip_addr; - - if ( -#if LWIP_TCP - (s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || -#endif - (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { - return NSAPI_ERROR_PARAMETER; - } - - if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { - return NSAPI_ERROR_PARAMETER; - } - - err_t err = netconn_bind(s->conn, &ip_addr, port); - return mbed_lwip_err_remap(err); -} - -static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - - err_t err = netconn_listen_with_backlog(s->conn, backlog); - return mbed_lwip_err_remap(err); -} - -static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - ip_addr_t ip_addr; - - if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { - return NSAPI_ERROR_PARAMETER; - } - - netconn_set_nonblocking(s->conn, false); - err_t err = netconn_connect(s->conn, &ip_addr, port); - netconn_set_nonblocking(s->conn, true); - - return mbed_lwip_err_remap(err); -} - -static nsapi_error_t mbed_lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port) -{ - struct lwip_socket *s = (struct lwip_socket *)server; - struct lwip_socket *ns = mbed_lwip_arena_alloc(); - if (!ns) { - return NSAPI_ERROR_NO_SOCKET; - } - - err_t err = netconn_accept(s->conn, &ns->conn); - if (err != ERR_OK) { - mbed_lwip_arena_dealloc(ns); - return mbed_lwip_err_remap(err); - } - - netconn_set_recvtimeout(ns->conn, 1); - *(struct lwip_socket **)handle = ns; - - ip_addr_t peer_addr; - (void) netconn_peer(ns->conn, &peer_addr, port); - convert_lwip_addr_to_mbed(addr, &peer_addr); - - netconn_set_nonblocking(ns->conn, true); - - return 0; -} - -static nsapi_size_or_error_t mbed_lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, nsapi_size_t size) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - size_t bytes_written = 0; - - err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); - if (err != ERR_OK) { - return mbed_lwip_err_remap(err); - } - - return (nsapi_size_or_error_t)bytes_written; -} - -static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - - if (!s->buf) { - err_t err = netconn_recv(s->conn, &s->buf); - s->offset = 0; - - if (err != ERR_OK) { - return mbed_lwip_err_remap(err); - } - } - - u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); - s->offset += recv; - - if (s->offset >= netbuf_len(s->buf)) { - netbuf_delete(s->buf); - s->buf = 0; - } - - return recv; -} - -static nsapi_size_or_error_t mbed_lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - ip_addr_t ip_addr; - - if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { - return NSAPI_ERROR_PARAMETER; - } - - struct netbuf *buf = netbuf_new(); - err_t err = netbuf_ref(buf, data, (u16_t)size); - if (err != ERR_OK) { - netbuf_free(buf); - return mbed_lwip_err_remap(err); - } - - err = netconn_sendto(s->conn, buf, &ip_addr, port); - netbuf_delete(buf); - if (err != ERR_OK) { - return mbed_lwip_err_remap(err); - } - - return size; -} - -static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, nsapi_size_t size) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - struct netbuf *buf; - - err_t err = netconn_recv(s->conn, &buf); - if (err != ERR_OK) { - return mbed_lwip_err_remap(err); - } - - convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); - *port = netbuf_fromport(buf); - - u16_t recv = netbuf_copy(buf, data, (u16_t)size); - netbuf_delete(buf); - - return recv; -} - -static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - - switch (optname) { -#if LWIP_TCP - case NSAPI_KEEPALIVE: - if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { - return NSAPI_ERROR_UNSUPPORTED; - } - - s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; - return 0; - - case NSAPI_KEEPIDLE: - if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { - return NSAPI_ERROR_UNSUPPORTED; - } - - s->conn->pcb.tcp->keep_idle = *(int*)optval; - return 0; - - case NSAPI_KEEPINTVL: - if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { - return NSAPI_ERROR_UNSUPPORTED; - } - - s->conn->pcb.tcp->keep_intvl = *(int*)optval; - return 0; -#endif - - case NSAPI_REUSEADDR: - if (optlen != sizeof(int)) { - return NSAPI_ERROR_UNSUPPORTED; - } - - if (*(int *)optval) { - ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR); - } else { - ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR); - } - return 0; - - default: - return NSAPI_ERROR_UNSUPPORTED; - } -} - -static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) -{ - struct lwip_socket *s = (struct lwip_socket *)handle; - - s->cb = callback; - s->data = data; -} - -/* LWIP network stack */ -const nsapi_stack_api_t lwip_stack_api = { - .gethostbyname = mbed_lwip_gethostbyname, - .add_dns_server = mbed_lwip_add_dns_server, - .socket_open = mbed_lwip_socket_open, - .socket_close = mbed_lwip_socket_close, - .socket_bind = mbed_lwip_socket_bind, - .socket_listen = mbed_lwip_socket_listen, - .socket_connect = mbed_lwip_socket_connect, - .socket_accept = mbed_lwip_socket_accept, - .socket_send = mbed_lwip_socket_send, - .socket_recv = mbed_lwip_socket_recv, - .socket_sendto = mbed_lwip_socket_sendto, - .socket_recvfrom = mbed_lwip_socket_recvfrom, - .setsockopt = mbed_lwip_setsockopt, - .socket_attach = mbed_lwip_socket_attach, -}; - -nsapi_stack_t lwip_stack = { - .stack_api = &lwip_stack_api, -}; diff --git a/features/FEATURE_LWIP/lwip-interface/lwip_stack.h b/features/FEATURE_LWIP/lwip-interface/lwip_stack.h deleted file mode 100644 index f40dbf7e7d2..00000000000 --- a/features/FEATURE_LWIP/lwip-interface/lwip_stack.h +++ /dev/null @@ -1,47 +0,0 @@ -/* LWIP implementation of NetworkInterfaceAPI - * Copyright (c) 2015 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LWIP_STACK_H -#define LWIP_STACK_H - -#include "nsapi.h" -#include "emac_api.h" -#include "lwip/opt.h" -#ifdef __cplusplus -extern "C" { -#endif - -// Access to lwip through the nsapi - be wary of API changes as external 1st-generation EMAC -// drivers attach through these. -nsapi_error_t mbed_lwip_init(emac_interface_t *emac); -nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac); -nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw); -nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw); -nsapi_error_t mbed_lwip_bringdown(void); -nsapi_error_t mbed_lwip_bringdown_2(bool ppp); - -const char *mbed_lwip_get_mac_address(void); -char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen); -char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen); -char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen); - -extern nsapi_stack_t lwip_stack; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/features/FEATURE_LWIP/lwip-interface/lwip_tools.c b/features/FEATURE_LWIP/lwip-interface/lwip_tools.c new file mode 100644 index 00000000000..825a7b20ce6 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/lwip_tools.c @@ -0,0 +1,112 @@ +/* LWIP common helpers + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "lwip/opt.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/api.h" + +#include "lwip_tools.h" + +/* Static arena of sockets */ +struct mbed_lwip_socket mbed_lwip_arena[MEMP_NUM_NETCONN]; + +static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif) +{ +#if LWIP_IPV4 + if (!netif_is_up(netif)) { + return NULL; + } + + if (!ip4_addr_isany(netif_ip4_addr(netif))) { + return netif_ip_addr4(netif); + } +#endif + + return NULL; +} + +static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif) +{ +#if LWIP_IPV6 + if (!netif_is_up(netif)) { + return NULL; + } + + for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } +#endif + + return NULL; + +} + +const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif) +{ + const ip_addr_t *pref_ip_addr = 0; + const ip_addr_t *npref_ip_addr = 0; + +#if IP_VERSION_PREF == PREF_IPV4 + pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); + npref_ip_addr = mbed_lwip_get_ipv6_addr(netif); +#else + pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); + npref_ip_addr = mbed_lwip_get_ipv4_addr(netif); +#endif + + if (pref_ip_addr) { + return pref_ip_addr; + } else if (npref_ip_addr && any_addr) { + return npref_ip_addr; + } + + return NULL; +} + +void mbed_lwip_arena_init(void) +{ + memset(mbed_lwip_arena, 0, sizeof(mbed_lwip_arena)); +} + +struct mbed_lwip_socket *mbed_lwip_arena_alloc(void) +{ + sys_prot_t prot = sys_arch_protect(); + + for (int i = 0; i < MEMP_NUM_NETCONN; i++) { + if (!mbed_lwip_arena[i].in_use) { + struct mbed_lwip_socket *s = &mbed_lwip_arena[i]; + memset(s, 0, sizeof(*s)); + s->in_use = true; + sys_arch_unprotect(prot); + return s; + } + } + + sys_arch_unprotect(prot); + return 0; +} + +void mbed_lwip_arena_dealloc(struct mbed_lwip_socket *s) +{ + s->in_use = false; +} diff --git a/features/FEATURE_LWIP/lwip-interface/lwip_tools.h b/features/FEATURE_LWIP/lwip-interface/lwip_tools.h new file mode 100644 index 00000000000..35c60edb60c --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/lwip_tools.h @@ -0,0 +1,43 @@ +/* LWIP common helpers + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LWIP_TOOLS_H +#define LWIP_TOOLS_H + +#include + +#include "lwip/netif.h" +#include "lwip/ip.h" + +struct mbed_lwip_socket { + bool in_use; + + struct netconn *conn; + struct netbuf *buf; + u16_t offset; + + void (*cb)(void *); + void *data; +}; + +extern struct mbed_lwip_socket mbed_lwip_arena[MEMP_NUM_NETCONN]; + +const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif); +void mbed_lwip_arena_init(void); +struct mbed_lwip_socket *mbed_lwip_arena_alloc(void); +void mbed_lwip_arena_dealloc(struct mbed_lwip_socket *s); + +#endif /* LWIP_TOOLS_H */ diff --git a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c new file mode 100644 index 00000000000..a8b396c7576 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c @@ -0,0 +1,504 @@ +/* LWIP implementation of NSAPI NetworkStack + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "nsapi.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include +#include +#include + +#include "lwip/opt.h" +#include "lwip/api.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" +#include "lwip/tcp.h" +#include "lwip/ip.h" +#include "lwip/mld6.h" +#include "lwip/dns.h" +#include "lwip/udp.h" + +#include "emac_api.h" +#include "lwip_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) +{ + // Filter send minus events + if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) { + return; + } + + sys_prot_t prot = sys_arch_protect(); + + for (int i = 0; i < MEMP_NUM_NETCONN; i++) { + if (mbed_lwip_arena[i].in_use + && mbed_lwip_arena[i].conn == nc + && mbed_lwip_arena[i].cb) { + mbed_lwip_arena[i].cb(mbed_lwip_arena[i].data); + } + } + + sys_arch_unprotect(prot); +} + +/* LWIP error remapping */ +static nsapi_error_t mbed_lwip_err_remap(err_t err) { + switch (err) { + case ERR_OK: + case ERR_CLSD: + return 0; + case ERR_MEM: + return NSAPI_ERROR_NO_MEMORY; + case ERR_CONN: + case ERR_RST: + case ERR_ABRT: + return NSAPI_ERROR_NO_CONNECTION; + case ERR_TIMEOUT: + case ERR_RTE: + case ERR_INPROGRESS: + case ERR_WOULDBLOCK: + return NSAPI_ERROR_WOULD_BLOCK; + case ERR_VAL: + case ERR_USE: + case ERR_ISCONN: + case ERR_ARG: + return NSAPI_ERROR_PARAMETER; + default: + return NSAPI_ERROR_DEVICE_ERROR; + } +} + +#if !LWIP_IPV4 || !LWIP_IPV6 +static bool all_zeros(const uint8_t *p, int len) +{ + for (int i = 0; i < len; i++) { + if (p[i]) { + return false; + } + } + + return true; +} +#endif + +static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in) +{ +#if LWIP_IPV6 + if (IP_IS_V6(in)) { + out->version = NSAPI_IPv6; + MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t)); + return true; + } +#endif +#if LWIP_IPV4 + if (IP_IS_V4(in)) { + out->version = NSAPI_IPv4; + MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t)); + return true; + } +#endif + return false; +} + +static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) +{ +#if LWIP_IPV6 + if (in->version == NSAPI_IPv6) { + IP_SET_TYPE(out, IPADDR_TYPE_V6); + MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); + return true; + } +#if !LWIP_IPV4 + /* For bind() and other purposes, need to accept "null" of other type */ + /* (People use IPv4 0.0.0.0 as a general null) */ + if (in->version == NSAPI_UNSPEC || + (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { + ip_addr_set_zero_ip6(out); + return true; + } +#endif +#endif + +#if LWIP_IPV4 + if (in->version == NSAPI_IPv4) { + IP_SET_TYPE(out, IPADDR_TYPE_V4); + MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); + return true; + } +#if !LWIP_IPV6 + /* For symmetry with above, accept IPv6 :: as a general null */ + if (in->version == NSAPI_UNSPEC || + (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { + ip_addr_set_zero_ip4(out); + return true; + } +#endif +#endif + +#if LWIP_IPV4 && LWIP_IPV6 + if (in->version == NSAPI_UNSPEC) { +#if IP_VERSION_PREF == PREF_IPV4 + ip_addr_set_zero_ip4(out); +#else + ip_addr_set_zero_ip6(out); +#endif + return true; + } +#endif + + return false; +} + +/* LWIP network stack implementation */ +static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) +{ + ip_addr_t lwip_addr; + +#if LWIP_IPV4 && LWIP_IPV6 + u8_t addr_type; + if (version == NSAPI_UNSPEC) { + const ip_addr_t *ip_addr; + ip_addr = mbed_lwip_get_ip_addr(true, &stack->emac->netif); + if (IP_IS_V6(ip_addr)) { + addr_type = NETCONN_DNS_IPV6; + } else { + addr_type = NETCONN_DNS_IPV4; + } + } else if (version == NSAPI_IPv4) { + addr_type = NETCONN_DNS_IPV4; + } else if (version == NSAPI_IPv6) { + addr_type = NETCONN_DNS_IPV6; + } + err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); +#elif LWIP_IPV4 + if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { + return NSAPI_ERROR_DNS_FAILURE; + } + err_t err = netconn_gethostbyname(host, &lwip_addr); +#elif LWIP_IPV6 + if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) { + return NSAPI_ERROR_DNS_FAILURE; + } + err_t err = netconn_gethostbyname(host, &lwip_addr); +#endif + + if (err != ERR_OK) { + return NSAPI_ERROR_DNS_FAILURE; + } + + convert_lwip_addr_to_mbed(addr, &lwip_addr); + + return 0; +} + +static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr) +{ + // Shift all dns servers down to give precedence to new server + for (int i = DNS_MAX_SERVERS-1; i > 0; i--) { + dns_setserver(i, dns_getserver(i-1)); + } + + ip_addr_t ip_addr; + if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { + return NSAPI_ERROR_PARAMETER; + } + + dns_setserver(0, &ip_addr); + return 0; +} + +static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) +{ + // check if network is connected + if (!stack->emac->connected) { + return NSAPI_ERROR_NO_CONNECTION; + } + + // allocate a socket + struct mbed_lwip_socket *s = mbed_lwip_arena_alloc(); + if (!s) { + return NSAPI_ERROR_NO_SOCKET; + } + + u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; + +#if LWIP_IPV6 && LWIP_IPV4 + const ip_addr_t *ip_addr; + ip_addr = mbed_lwip_get_ip_addr(true, &stack->emac->netif); + + if (IP_IS_V6(ip_addr)) { + // Enable IPv6 (or dual-stack). LWIP dual-stack support is + // currently incomplete as of 2.0.0rc2 - eg we will only be able + // to do a UDP sendto to an address matching the type selected + // here. Matching "get_ip_addr" and DNS logic, use v4 if + // available. + lwip_proto |= NETCONN_TYPE_IPV6; + } +#elif LWIP_IPV6 + lwip_proto |= NETCONN_TYPE_IPV6; +#endif + + s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); + + if (!s->conn) { + mbed_lwip_arena_dealloc(s); + return NSAPI_ERROR_NO_SOCKET; + } + + netconn_set_recvtimeout(s->conn, 1); + *(struct mbed_lwip_socket **)handle = s; + return 0; +} + +static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + + netbuf_delete(s->buf); + err_t err = netconn_delete(s->conn); + mbed_lwip_arena_dealloc(s); + return mbed_lwip_err_remap(err); +} + +static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + ip_addr_t ip_addr; + + if ((s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || + (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { + return NSAPI_ERROR_PARAMETER; + } + + if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { + return NSAPI_ERROR_PARAMETER; + } + + err_t err = netconn_bind(s->conn, &ip_addr, port); + return mbed_lwip_err_remap(err); +} + +static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + + err_t err = netconn_listen_with_backlog(s->conn, backlog); + return mbed_lwip_err_remap(err); +} + +static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + ip_addr_t ip_addr; + + if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { + return NSAPI_ERROR_PARAMETER; + } + + netconn_set_nonblocking(s->conn, false); + err_t err = netconn_connect(s->conn, &ip_addr, port); + netconn_set_nonblocking(s->conn, true); + + return mbed_lwip_err_remap(err); +} + +static nsapi_error_t mbed_lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)server; + struct mbed_lwip_socket *ns = mbed_lwip_arena_alloc(); + if (!ns) { + return NSAPI_ERROR_NO_SOCKET; + } + + err_t err = netconn_accept(s->conn, &ns->conn); + if (err != ERR_OK) { + mbed_lwip_arena_dealloc(ns); + return mbed_lwip_err_remap(err); + } + + netconn_set_recvtimeout(ns->conn, 1); + *(struct mbed_lwip_socket **)handle = ns; + + ip_addr_t peer_addr; + (void) netconn_peer(ns->conn, &peer_addr, port); + convert_lwip_addr_to_mbed(addr, &peer_addr); + + netconn_set_nonblocking(ns->conn, true); + + return 0; +} + +static nsapi_size_or_error_t mbed_lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, nsapi_size_t size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + size_t bytes_written = 0; + + err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); + if (err != ERR_OK) { + return mbed_lwip_err_remap(err); + } + + return (nsapi_size_or_error_t)bytes_written; +} + +static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + + if (!s->buf) { + err_t err = netconn_recv(s->conn, &s->buf); + s->offset = 0; + + if (err != ERR_OK) { + return mbed_lwip_err_remap(err); + } + } + + u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); + s->offset += recv; + + if (s->offset >= netbuf_len(s->buf)) { + netbuf_delete(s->buf); + s->buf = 0; + } + + return recv; +} + +static nsapi_size_or_error_t mbed_lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + ip_addr_t ip_addr; + + if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { + return NSAPI_ERROR_PARAMETER; + } + + struct netbuf *buf = netbuf_new(); + err_t err = netbuf_ref(buf, data, (u16_t)size); + if (err != ERR_OK) { + netbuf_free(buf); + return mbed_lwip_err_remap(err); + } + + err = netconn_sendto(s->conn, buf, &ip_addr, port); + netbuf_delete(buf); + if (err != ERR_OK) { + return mbed_lwip_err_remap(err); + } + + return size; +} + +static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, nsapi_size_t size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + struct netbuf *buf; + + err_t err = netconn_recv(s->conn, &buf); + if (err != ERR_OK) { + return mbed_lwip_err_remap(err); + } + + convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); + *port = netbuf_fromport(buf); + + u16_t recv = netbuf_copy(buf, data, (u16_t)size); + netbuf_delete(buf); + + return recv; +} + +static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + + switch (optname) { + case NSAPI_KEEPALIVE: + if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { + return NSAPI_ERROR_UNSUPPORTED; + } + + s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; + return 0; + + case NSAPI_KEEPIDLE: + if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { + return NSAPI_ERROR_UNSUPPORTED; + } + + s->conn->pcb.tcp->keep_idle = *(int*)optval; + return 0; + + case NSAPI_KEEPINTVL: + if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { + return NSAPI_ERROR_UNSUPPORTED; + } + + s->conn->pcb.tcp->keep_intvl = *(int*)optval; + return 0; + + case NSAPI_REUSEADDR: + if (optlen != sizeof(int)) { + return NSAPI_ERROR_UNSUPPORTED; + } + + if (*(int *)optval) { + s->conn->pcb.tcp->so_options |= SOF_REUSEADDR; + } else { + s->conn->pcb.tcp->so_options &= ~SOF_REUSEADDR; + } + return 0; + + default: + return NSAPI_ERROR_UNSUPPORTED; + } +} + +static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + + s->cb = callback; + s->data = data; +} + +/* LWIP network stack */ +const nsapi_stack_api_t lwip_stack_api = { + .gethostbyname = mbed_lwip_gethostbyname, + .add_dns_server = mbed_lwip_add_dns_server, + .socket_open = mbed_lwip_socket_open, + .socket_close = mbed_lwip_socket_close, + .socket_bind = mbed_lwip_socket_bind, + .socket_listen = mbed_lwip_socket_listen, + .socket_connect = mbed_lwip_socket_connect, + .socket_accept = mbed_lwip_socket_accept, + .socket_send = mbed_lwip_socket_send, + .socket_recv = mbed_lwip_socket_recv, + .socket_sendto = mbed_lwip_socket_sendto, + .socket_recvfrom = mbed_lwip_socket_recvfrom, + .setsockopt = mbed_lwip_setsockopt, + .socket_attach = mbed_lwip_socket_attach, +}; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp b/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp index 6801ac710e0..ba506646fb2 100644 --- a/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp +++ b/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp @@ -38,7 +38,7 @@ extern "C" { // "pppos.h" is missing extern C #include "nsapi_ppp.h" #include "ppp_lwip.h" -#include "lwip_stack.h" +//#include "mbed_ipstack.h" namespace mbed { diff --git a/features/FEATURE_LWIP/lwip-interface/EthernetInterface.cpp b/features/netsocket/EthernetInterface.cpp similarity index 67% rename from features/FEATURE_LWIP/lwip-interface/EthernetInterface.cpp rename to features/netsocket/EthernetInterface.cpp index d0418798aa7..679f1fbfcfc 100644 --- a/features/FEATURE_LWIP/lwip-interface/EthernetInterface.cpp +++ b/features/netsocket/EthernetInterface.cpp @@ -15,26 +15,21 @@ */ #include "EthernetInterface.h" -#include "lwip_stack.h" - +#include "mbed_ipstack.h" /* Interface implementation */ -EthernetInterface::EthernetInterface() - : _dhcp(true), _ip_address(), _netmask(), _gateway() +EthernetInterface::EthernetInterface(emac_interface_t *emac) + : _dhcp(true), _ip_address(), _netmask(), _gateway(), _stack() { + mbed_ipstack_set_stack(emac, &_stack); } nsapi_error_t EthernetInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) { _dhcp = false; - strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address)); - _ip_address[sizeof(_ip_address) - 1] = '\0'; strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask)); - _netmask[sizeof(_netmask) - 1] = '\0'; strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway)); - _gateway[sizeof(_gateway) - 1] = '\0'; - return NSAPI_ERROR_OK; } @@ -46,7 +41,16 @@ nsapi_error_t EthernetInterface::set_dhcp(bool dhcp) nsapi_error_t EthernetInterface::connect() { - return mbed_lwip_bringup_2(_dhcp, false, + nsapi_error_t err; + if (_stack.emac == NULL) + return NSAPI_ERROR_UNSUPPORTED; + + mbed_ipstack_init(); + err = mbed_ipstack_add_netif(_stack.emac, true); + if (err != NSAPI_ERROR_OK) + return err; + + return mbed_ipstack_bringup(_stack.emac, _dhcp, _ip_address[0] ? _ip_address : 0, _netmask[0] ? _netmask : 0, _gateway[0] ? _gateway : 0); @@ -54,17 +58,17 @@ nsapi_error_t EthernetInterface::connect() nsapi_error_t EthernetInterface::disconnect() { - return mbed_lwip_bringdown_2(false); + return mbed_ipstack_bringdown(_stack.emac); } const char *EthernetInterface::get_mac_address() { - return mbed_lwip_get_mac_address(); + return mbed_ipstack_get_mac_address(_stack.emac); } const char *EthernetInterface::get_ip_address() { - if (mbed_lwip_get_ip_address(_ip_address, sizeof _ip_address)) { + if (mbed_ipstack_get_ip_address(_stack.emac, _ip_address, sizeof(_ip_address))) { return _ip_address; } @@ -73,7 +77,7 @@ const char *EthernetInterface::get_ip_address() const char *EthernetInterface::get_netmask() { - if (mbed_lwip_get_netmask(_netmask, sizeof _netmask)) { + if (mbed_ipstack_get_netmask(_stack.emac, _netmask, sizeof(_netmask))) { return _netmask; } @@ -82,7 +86,7 @@ const char *EthernetInterface::get_netmask() const char *EthernetInterface::get_gateway() { - if (mbed_lwip_get_gateway(_gateway, sizeof _gateway)) { + if (mbed_ipstack_get_gateway(_stack.emac, _gateway, sizeof(_gateway))) { return _gateway; } @@ -91,5 +95,5 @@ const char *EthernetInterface::get_gateway() NetworkStack *EthernetInterface::get_stack() { - return nsapi_create_stack(&lwip_stack); -} + return nsapi_create_stack(&_stack); +} \ No newline at end of file diff --git a/features/FEATURE_LWIP/lwip-interface/EthernetInterface.h b/features/netsocket/EthernetInterface.h similarity index 95% rename from features/FEATURE_LWIP/lwip-interface/EthernetInterface.h rename to features/netsocket/EthernetInterface.h index f92f70e4ebf..3bbe15b8fff 100644 --- a/features/FEATURE_LWIP/lwip-interface/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -19,7 +19,7 @@ #include "nsapi.h" #include "rtos.h" -#include "lwip/netif.h" +#include "hal/emac_api.h" // Forward declaration class NetworkStack; @@ -28,12 +28,12 @@ class NetworkStack; /** EthernetInterface class * Implementation of the NetworkStack for LWIP */ -class EthernetInterface : public EthInterface +class EthernetInterface : public NetworkInterface { public: /** EthernetInterface lifetime */ - EthernetInterface(); + EthernetInterface(emac_interface_t *emac = &mbed_emac_eth_default); /** Set a static IP address * @@ -111,7 +111,7 @@ class EthernetInterface : public EthInterface char _ip_address[IPADDR_STRLEN_MAX]; char _netmask[NSAPI_IPv4_SIZE]; char _gateway[NSAPI_IPv4_SIZE]; + nsapi_stack_t _stack; }; - -#endif +#endif \ No newline at end of file diff --git a/features/netsocket/emac_stack_mem.h b/features/netsocket/emac_stack_mem.h index d3e0e4dd14f..c4f5fc942e1 100644 --- a/features/netsocket/emac_stack_mem.h +++ b/features/netsocket/emac_stack_mem.h @@ -16,8 +16,6 @@ #ifndef MBED_EMAC_STACK_MEM_H #define MBED_EMAC_STACK_MEM_H -#if DEVICE_EMAC - #include /** @@ -29,88 +27,77 @@ */ typedef void emac_stack_mem_t; typedef void emac_stack_mem_chain_t; -typedef void emac_stack_t; /** * Allocates stack memory * - * @param stack Emac stack context * @param size Size of memory to allocate * @param align Memory alignment requirements * @return Allocated memory struct, or NULL in case of error */ -emac_stack_mem_t *emac_stack_mem_alloc(emac_stack_t* stack, uint32_t size, uint32_t align); +emac_stack_mem_t *emac_stack_mem_alloc(uint32_t size, uint32_t align); /** * Free memory allocated using @a stack_mem_alloc * - * @param stack Emac stack context * @param mem Memory to be freed */ -void emac_stack_mem_free(emac_stack_t* stack, emac_stack_mem_t *mem); +void emac_stack_mem_free(emac_stack_mem_t *mem); /** * Copy memory * - * @param stack Emac stack context * @param to Memory to copy to * @param from Memory to copy from */ -void emac_stack_mem_copy(emac_stack_t* stack, emac_stack_mem_t *to, emac_stack_mem_t *from); +void emac_stack_mem_copy(emac_stack_mem_t *to, emac_stack_mem_t *from); /** * Return pointer to the payload * - * @param stack Emac stack context * @param mem Memory structure * @return Pointer to the payload */ -void *emac_stack_mem_ptr(emac_stack_t* stack, emac_stack_mem_t *mem); +void *emac_stack_mem_ptr(emac_stack_mem_t *mem); /** * Return actual payload size * - * @param stack Emac stack context * @param mem Memory structure * @return Size in bytes */ -uint32_t emac_stack_mem_len(emac_stack_t* stack, emac_stack_mem_t *mem); +uint32_t emac_stack_mem_len(emac_stack_mem_t *mem); /** * Sets the actual payload size (the allocated payload size will not change) * - * @param stack Emac stack context * @param mem Memory structure * @param len Actual payload size */ -void emac_stack_mem_set_len(emac_stack_t* stack, emac_stack_mem_t *mem, uint32_t len); +void emac_stack_mem_set_len(emac_stack_mem_t *mem, uint32_t len); /** * Returns first memory structure from the list and move the head to point to the next node * - * @param stack Emac stack context * @param chain Pointer to the list * @return First memory structure from the list */ -emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_t* stack, emac_stack_mem_chain_t **chain); +emac_stack_mem_t *emac_stack_mem_chain_dequeue(emac_stack_mem_chain_t **chain); /** * Return total length of the memory chain * - * @param stack Emac stack context * @param chain Memory chain * @return Chain length */ -uint32_t emac_stack_mem_chain_len(emac_stack_t* stack, emac_stack_mem_chain_t *chain); +uint32_t emac_stack_mem_chain_len(emac_stack_mem_chain_t *chain); /** - * Increases the reference counter for the memory - * - * @param stack Emac stack context - * @param mem Memory structure - */ -void emac_stack_mem_ref(emac_stack_t* stack, emac_stack_mem_t *mem); - -#endif /* DEVICE_EMAC */ +* Set total length of the memory chain +* +* @param chain Memory chain +* @param len Total chain length + */ +void emac_stack_mem_set_chain_len(emac_stack_mem_chain_t *chain, uint32_t len); #endif /* EMAC_MBED_STACK_MEM_h */ diff --git a/features/netsocket/mbed_ipstack.h b/features/netsocket/mbed_ipstack.h new file mode 100644 index 00000000000..9055e2b29d3 --- /dev/null +++ b/features/netsocket/mbed_ipstack.h @@ -0,0 +1,123 @@ +/* mbed OS IP stack API + * Copyright (c) 2015-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_IPSTACK_H +#define MBED_IPSTACK_H + +#include "nsapi.h" +#include "emac_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * mbed OS API for IP stack abstraction + * + * This interface should be used by targets to initialize IP stack, create, bring up and bring down network interfaces. + */ + +/** Initialize IP stack + * + * This function should be called before any of the network interfaces is added. It's up to target's setup code, to make + * sure that the stack is initialized and all the existing interfaces are registered with the stack. + * This function can be safely called multiple times, it will do nothing and return NSAPI_ERROR_OK if stack is already + * initialized. + * + * @return NSAPI_ERROR_OK on success, or error code + */ +void mbed_ipstack_init(void); + +/** Register a network interface with the IP stack + * + * Connects EMAC layer with the IP stack and initializes all the required infrastructure. + * This function should be called only once for each available interface. + * + * @param emac EMAC HAL implementation for this network interface + * @param default_if true if the interface should be treated as the default one + * @return NSAPI_ERROR_OK on success, or error code + */ +nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if); + +/** Connect network stack with the IP stack + * + * @param emac EMAC HAL implementation + * @param stack Pointer to nsapi_stack_t to be set for this interface + */ +void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack); + +/** Connect the interface to the network + * + * Sets up a connection on specified network interface, using DHCP or provided network details. If the @a dhcp is set to + * true all the remaining parameters are ignored. + * + * @param emac EMAC HAL implementation for this network interface + * @param dhcp true if the network details should be acquired using DHCP + * @param ip IP address to be used for the interface as "W:X:Y:Z" or NULL + * @param netmask Net mask to be used for the interface as "W:X:Y:Z" or NULL + * @param gw Gateway address to be used for the interface as "W:X:Y:Z" or NULL + * @return NSAPI_ERROR_OK on success, or error code + */ +nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, + const char *netmask, const char *gw); + +/** Disconnect interface from the network + * + * After this call the network interface is inactive, to use it again user needs to call @mbed_lwip_bringup again. + * + * @return NSAPI_ERROR_OK on success, or error code + */ +nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac); + +/** Return MAC address of the network interface + * + * @param emac EMAC HAL implementation for this network interface + * @return MAC address as "V:W:X:Y:Z" + */ +char *mbed_ipstack_get_mac_address(emac_interface_t *emac); + +/** Copies IP address of the network interface to user supplied buffer + * + * @param emac EMAC HAL implementation for this network interface + * @param buf buffer to which IP address will be copied as "W:X:Y:Z" + * @param buflen size of supplied buffer + * @return Pointer to a buffer, or NULL if the buffer is too small + */ +char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + +/** Copies netmask of the network interface to user supplied buffer + * + * @param emac EMAC HAL implementation for this network interface + * @param buf buffer to which netmask will be copied as "W:X:Y:Z" + * @param buflen size of supplied buffer + * @return Pointer to a buffer, or NULL if the buffer is too small + */ +char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + +/** Copies gateway address of the network interface to user supplied buffer + * + * @param emac EMAC HAL implementation for this network interface + * @param buf buffer to which gateway address will be copied as "W:X:Y:Z" + * @param buflen size of supplied buffer + * @return Pointer to a buffer, or NULL if the buffer is too small + */ +char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* MBED_IPSTACK_H */ \ No newline at end of file diff --git a/features/netsocket/nsapi.h b/features/netsocket/nsapi.h index c9ed8bd6e47..0202323ff89 100644 --- a/features/netsocket/nsapi.h +++ b/features/netsocket/nsapi.h @@ -31,7 +31,6 @@ #include "netsocket/NetworkStack.h" #include "netsocket/NetworkInterface.h" -#include "netsocket/EthInterface.h" #include "netsocket/WiFiInterface.h" #include "netsocket/CellularInterface.h" #include "netsocket/MeshInterface.h" diff --git a/features/netsocket/nsapi_types.h b/features/netsocket/nsapi_types.h index 120873d5d91..083fa7ca0b0 100644 --- a/features/netsocket/nsapi_types.h +++ b/features/netsocket/nsapi_types.h @@ -21,6 +21,7 @@ #define NSAPI_TYPES_H #include +#include "hal/emac_api.h" #ifdef __cplusplus extern "C" { @@ -252,6 +253,9 @@ typedef struct nsapi_stack { // Internal nsapi buffer unsigned _stack_buffer[16]; + /** EMAC HAL implementation for the network interface + */ + emac_interface_t *emac; } nsapi_stack_t; /** nsapi_stack_api structure diff --git a/hal/emac_api.h b/hal/emac_api.h index e5fbd1a9419..b1045022d1e 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -17,10 +17,10 @@ #ifndef MBED_EMAC_API_H #define MBED_EMAC_API_H -#if DEVICE_EMAC - #include #include "emac_stack_mem.h" +#include "arch/sys_arch.h" +#include "lwip/netif.h" typedef struct emac_interface emac_interface_t; @@ -30,6 +30,11 @@ typedef struct emac_interface emac_interface_t; * This interface should be used to abstract low level access to networking hardware */ +/** This structure needs to be defined by targets wishing to provide ethernet driver using EMAC interface. It will + * be used by the EthernetInterface class to initialize the networking subsystem. + */ +extern emac_interface_t mbed_emac_eth_default; + /** * Callback to be register with Emac interface and to be called fore received packets * @@ -100,7 +105,7 @@ typedef void (*emac_set_hwaddr_fn)(emac_interface_t *emac, uint8_t *addr); * @param buf Packet to be send * @return True if the packet was send successfully, False otherwise */ -typedef bool (*emac_link_out_fn)(emac_interface_t *emac, emac_stack_mem_t *buf); +typedef bool (*emac_link_out_fn)(emac_interface_t *emac, emac_stack_mem_chain_t *buf); /** * Initializes the HW @@ -134,6 +139,13 @@ typedef void (*emac_set_link_input_cb_fn)(emac_interface_t *emac, emac_link_inpu */ typedef void (*emac_set_link_state_cb_fn)(emac_interface_t *emac, emac_link_state_change_fn state_cb, void *data); +/** Add device to a multicast group + * + * @param emac Emac interface + * @param address An multicast group IPv4 address + */ +typedef void (*emac_add_multicast_group)(emac_interface_t *emac, uint8_t *address); + typedef struct emac_interface_ops { emac_get_mtu_size_fn get_mtu_size; emac_get_ifname_fn get_ifname; @@ -145,16 +157,21 @@ typedef struct emac_interface_ops { emac_power_down_fn power_down; emac_set_link_input_cb_fn set_link_input_cb; emac_set_link_state_cb_fn set_link_state_cb; + emac_add_multicast_group add_multicast_group; } emac_interface_ops_t; typedef struct emac_interface { - const emac_interface_ops_t ops; - void *hw; + /* Members implemented by vendor */ + const emac_interface_ops_t *ops; /**< HW specific emac implementation */ + void *hw; /**< EMAC implementation specific user data */ + + /* Private members used by the stack */ + sys_sem_t linked; + sys_sem_t has_addr; + bool connected; + bool dhcp; + char hwaddr[6]; + struct netif netif; } emac_interface_t; -#else - -typedef void *emac_interface_t; - -#endif /* DEVICE_EMAC */ #endif /* MBED_EMAC_API_H */ diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/RTWInterface.cpp b/targets/TARGET_Realtek/TARGET_AMEBA/RTWInterface.cpp index 273e3d1a695..5de912c7fc6 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/RTWInterface.cpp +++ b/targets/TARGET_Realtek/TARGET_AMEBA/RTWInterface.cpp @@ -97,7 +97,7 @@ RTWInterface::RTWInterface(bool debug) return; } emac->ops.power_up(emac); - ret = mbed_lwip_init(emac); + ret = mbed_ipstack_init(emac); if (ret != 0) { printf("Error init RTWInterface!(%d)\r\n", ret); return; @@ -107,7 +107,7 @@ RTWInterface::RTWInterface(bool debug) RTWInterface::~RTWInterface() { wlan_emac_link_change(false); - mbed_lwip_bringdown(); + mbed_ipstack_bringdown(); } nsapi_error_t RTWInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) @@ -175,7 +175,7 @@ nsapi_error_t RTWInterface::connect() } wlan_emac_link_change(true); - return mbed_lwip_bringup(_dhcp, + return mbed_ipstack_bringup(_dhcp, _ip_address[0] ? _ip_address : 0, _netmask[0] ? _netmask : 0, _gateway[0] ? _gateway : 0); @@ -251,12 +251,12 @@ int RTWInterface::is_connected() const char *RTWInterface::get_mac_address() { - return mbed_lwip_get_mac_address(); + return mbed_ipstack_get_mac_address(); } const char *RTWInterface::get_ip_address() { - if (mbed_lwip_get_ip_address(_ip_address, sizeof _ip_address)) { + if (mbed_ipstack_get_ip_address(_ip_address, sizeof _ip_address)) { return _ip_address; } return 0; @@ -264,7 +264,7 @@ const char *RTWInterface::get_ip_address() const char *RTWInterface::get_netmask() { - if (mbed_lwip_get_netmask(_netmask, sizeof _netmask)) { + if (mbed_ipstack_get_netmask(_netmask, sizeof _netmask)) { return _netmask; } return 0; @@ -272,7 +272,7 @@ const char *RTWInterface::get_netmask() const char *RTWInterface::get_gateway() { - if (mbed_lwip_get_gateway(_gateway, sizeof _gateway)) { + if (mbed_ipstack_get_gateway(_gateway, sizeof _gateway)) { return _gateway; } return 0; diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_UBLOX_EVK_ODIN_W2/sdk/wifi_emac/wifi_emac_api.cpp b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_UBLOX_EVK_ODIN_W2/sdk/wifi_emac/wifi_emac_api.cpp index 0839fcd7439..2106243467a 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_UBLOX_EVK_ODIN_W2/sdk/wifi_emac/wifi_emac_api.cpp +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_UBLOX_EVK_ODIN_W2/sdk/wifi_emac/wifi_emac_api.cpp @@ -1,4 +1,4 @@ -#if DEVICE_EMAC +#if DEVICE_WIFI #include #include "cb_main.h" diff --git a/targets/targets.json b/targets/targets.json index fd9550f01cc..6f4d9449c30 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -606,7 +606,7 @@ "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0240"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "ETH", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], "features": ["LWIP", "STORAGE"], "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12", From 2016e494633e1e6c8ff108d91b0af2356ffb956d Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Wed, 16 Aug 2017 11:04:21 +0300 Subject: [PATCH 02/13] Refactor k64f_emac Remove lwip depencies --- .../arch/TARGET_Freescale/k64f_emac.c | 152 +++++++++++++----- 1 file changed, 109 insertions(+), 43 deletions(-) diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index 64c609e1d29..2c3978e645b 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -1,3 +1,35 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * Copyright (c) 2017 ARM Limited + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "cmsis_os.h" #include "sys_arch.h" #include "fsl_phy.h" @@ -13,10 +45,6 @@ #include "emac_stack_mem.h" #include "mbed_assert.h" -/* LWIP dependencies - TODO: Should be removed */ -#include "lwip/sys.h" -#include "lwip_ethernet.h" - enet_handle_t g_handle; // TX Buffer descriptors uint8_t *tx_desc_start_addr; @@ -29,9 +57,6 @@ emac_stack_mem_t *tx_buff[ENET_RX_RING_LEN]; // RX packet payload pointers uint32_t *rx_ptr[ENET_RX_RING_LEN]; -#define K64_ETH_MTU_SIZE 1500 -#define K64_ETH_IF_NAME "en" - /******************************************************************************** * Internal data ********************************************************************************/ @@ -45,12 +70,44 @@ extern void k64f_init_eth_hardware(void); extern void k66f_init_eth_hardware(void); #endif +static os_mutex_t txlock_mutex = {0}; +static const osMutexAttr_t txlock_mutex_attr = { + .name = "tx_mutex_mutex", + .attr_bits = 0, + .cb_mem = &txlock_mutex, + .cb_size = sizeof txlock_mutex, +}; + +static os_semaphore_t rxreadysem = {0}; +static const osSemaphoreAttr_t rxreadysem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &rxreadysem, + .cb_size = sizeof(rxreadysem), +}; + +static os_semaphore_t txcleansem = {0}; +static const osSemaphoreAttr_t txcleansem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &txcleansem, + .cb_size = sizeof(txcleansem), +}; + +static os_semaphore_t xtxdcountsem = {0}; +static const osSemaphoreAttr_t xtxdcountsem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &xtxdcountsem, + .cb_size = sizeof(xtxdcountsem), +}; + /* K64F EMAC driver data structure */ struct k64f_enetdata { - sys_sem_t RxReadySem; /**< RX packet ready semaphore */ - sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ - sys_mutex_t TXLockMutex; /**< TX critical section mutex */ - sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */ + osSemaphoreId_t RxReadySem; /**< RX packet ready semaphore */ + osSemaphoreId_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ + osMutexId_t TXLockMutex;/**< TX critical section mutex */ + osSemaphoreId_t xTXDCountSem; /**< TX free buffer counting semaphore */ uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ emac_link_input_fn emac_link_input_cb; /**< Callback for incoming data */ void *emac_link_input_cb_data; /**< Data to be passed to input cb */ @@ -60,6 +117,11 @@ struct k64f_enetdata { static struct k64f_enetdata k64f_enetdata; +static osThreadAttr_t default_thread_attr = {0}; +static os_thread_t packet_tx_cb = {0}; +static os_thread_t packet_rx_cb = {0}; +static os_thread_t phy_task_cb = {0}; + /** \brief Driver transmit and receive thread priorities * * Thread priorities for receive thread and TX cleanup thread. Alter @@ -70,6 +132,16 @@ static struct k64f_enetdata k64f_enetdata; #define TX_PRIORITY (osPriorityNormal) #define PHY_PRIORITY (osPriorityNormal) +static void create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, int priority, os_thread_t *thread_cb) +{ + default_thread_attr.name = threadName; + default_thread_attr.stack_mem = malloc(stacksize); + default_thread_attr.cb_mem = thread_cb; + default_thread_attr.stack_size = stacksize; + default_thread_attr.cb_size = sizeof(os_thread_t); + default_thread_attr.priority = priority; + osThreadNew((osThreadFunc_t)thread, &k64f_enetdata, &default_thread_attr); +} /******************************************************************************** * Buffer management ********************************************************************************/ @@ -106,7 +178,7 @@ static void update_read_buffer(uint8_t *buf) static void k64f_tx_reclaim(struct k64f_enetdata *enet) { /* Get exclusive access */ - sys_mutex_lock(&enet->TXLockMutex); + osMutexAcquire(enet->TXLockMutex, osWaitForever); // Traverse all descriptors, looking for the ones modified by the uDMA while((enet->tx_consume_index != enet->tx_produce_index) && @@ -118,11 +190,11 @@ static void k64f_tx_reclaim(struct k64f_enetdata *enet) g_handle.txBdDirty++; enet->tx_consume_index += 1; - osSemaphoreRelease(enet->xTXDCountSem.id); + osSemaphoreRelease(enet->xTXDCountSem); } /* Restore access */ - sys_mutex_unlock(&enet->TXLockMutex); + osMutexRelease(enet->TXLockMutex); } /** \brief Ethernet receive interrupt handler @@ -131,12 +203,12 @@ static void k64f_tx_reclaim(struct k64f_enetdata *enet) */ void enet_mac_rx_isr(struct k64f_enetdata *enet) { - sys_sem_signal(&enet->RxReadySem); + osSemaphoreRelease(enet->RxReadySem); } void enet_mac_tx_isr(struct k64f_enetdata *enet) { - sys_sem_signal(&enet->TxCleanSem); + osSemaphoreRelease(enet->TxCleanSem); } void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) @@ -267,7 +339,7 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) #ifdef LOCK_RX_THREAD /* Get exclusive access */ - sys_mutex_lock(&enet->TXLockMutex); + osMutexAcquire(enet->TXLockMutex, osWaitForever); #endif /* Determine if a frame has been received */ @@ -302,7 +374,7 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) ("k64f_low_level_input: Packet index %d dropped for OOM\n", idx)); #ifdef LOCK_RX_THREAD - sys_mutex_unlock(&enet->TXLockMutex); + osMutexRelease(enet->TXLockMutex); #endif return NULL; @@ -328,7 +400,7 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) } #ifdef LOCK_RX_THREAD - sys_mutex_unlock(&enet->TXLockMutex); + osMutexRelease(enet->TXLockMutex); #endif return p; @@ -365,7 +437,7 @@ static void packet_rx(void* pvParameters) { while (1) { /* Wait for receive task to wakeup */ - sys_arch_sem_wait(&enet->RxReadySem, 0); + osSemaphoreAcquire(enet->RxReadySem, osWaitForever); while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { k64f_enetif_input(enet, idx); @@ -387,7 +459,7 @@ static void packet_tx(void* pvParameters) { while (1) { /* Wait for transmit cleanup task to wakeup */ - sys_arch_sem_wait(&enet->TxCleanSem, 0); + osSemaphoreAcquire(enet->TxCleanSem, osWaitForever); k64f_tx_reclaim(enet); } } @@ -423,12 +495,12 @@ static bool k64f_eth_link_out(emac_interface_t *emac, emac_stack_mem_chain_t *ch } /* Check if a descriptor is available for the transfer. */ - osStatus_t stat = osSemaphoreAcquire(enet->xTXDCountSem.id, 0); + osStatus_t stat = osSemaphoreAcquire(enet->xTXDCountSem, 0); if (stat != osOK) return false; /* Get exclusive access */ - sys_mutex_lock(&enet->TXLockMutex); + osMutexAcquire(enet->TXLockMutex, osWaitForever); /* Save the buffer so that it can be freed when transmit is done */ tx_buff[enet->tx_produce_index % ENET_TX_RING_LEN] = temp_pbuf; @@ -451,7 +523,7 @@ static bool k64f_eth_link_out(emac_interface_t *emac, emac_stack_mem_chain_t *ch LINK_STATS_INC(link.xmit); /* Restore access */ - sys_mutex_unlock(&enet->TXLockMutex); + osMutexRelease(enet->TXLockMutex); return true; } @@ -521,34 +593,28 @@ static bool k64f_eth_power_up(emac_interface_t *emac) if (err != ERR_OK) return false; - /* CMSIS-RTOS, start tasks */ - memset(&k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data)); - k64f_enetdata.xTXDCountSem.attr.cb_mem = &k64f_enetdata.xTXDCountSem.data; - k64f_enetdata.xTXDCountSem.attr.cb_size = sizeof(k64f_enetdata.xTXDCountSem.data); - k64f_enetdata.xTXDCountSem.id = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &k64f_enetdata.xTXDCountSem.attr); - - MBED_ASSERT(k64f_enetdata.xTXDCountSem.id != NULL); + k64f_enetdata.xTXDCountSem = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &xtxdcountsem_attr); + MBED_ASSERT(k64f_enetdata.xTXDCountSem); - err = sys_mutex_new(&k64f_enetdata.TXLockMutex); - MBED_ASSERT(err == ERR_OK); + k64f_enetdata.TXLockMutex = osMutexNew(&txlock_mutex_attr); + MBED_ASSERT(k64f_enetdata.TXLockMutex); - /* Packet receive task */ - err = sys_sem_new(&k64f_enetdata.RxReadySem, 0); - MBED_ASSERT(err == ERR_OK); + k64f_enetdata.RxReadySem = osSemaphoreNew(UINT16_MAX, 0, &rxreadysem_attr); + MBED_ASSERT(k64f_enetdata.RxReadySem); #ifdef LWIP_DEBUG - sys_thread_new("k64f_emac_rx_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY); + create_new_thread("k64f_emac_rx_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY, &packet_rx_cb); #else - sys_thread_new("k64f_emac_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); + create_new_thread("k64f_emac_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &packet_rx_cb); #endif - /* Transmit cleanup task */ - err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0); - MBED_ASSERT(err == ERR_OK); - sys_thread_new("k64f_emac_txclean_thread", packet_tx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY); + k64f_enetdata.TxCleanSem = osSemaphoreNew(UINT16_MAX, 0, &txcleansem_attr); + MBED_ASSERT(k64f_enetdata.TxCleanSem); + + create_new_thread("k64f_emac_txclean_thread", packet_tx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &packet_tx_cb); /* PHY monitoring task */ - sys_thread_new("k64f_emac_phy_thread", k64f_phy_task, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY); + create_new_thread("k64f_emac_phy_thread", k64f_phy_task, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY, &phy_task_cb); /* Allow the PHY task to detect the initial link state and set up the proper flags */ osDelay(10); From 605e32b3b046d0e6fa6d288a2f50cd06783a5334 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Fri, 18 Aug 2017 11:59:12 +0300 Subject: [PATCH 03/13] Remove netif.h from emac_api.h ipstack_lwip.c renamed as mbed_ipstack.c --- .../arch/TARGET_Freescale/k64f_emac.c | 33 ++-------- .../lwip-interface/nsapi_stack_lwip.c | 10 +-- .../mbed_ipstack.c} | 61 ++++++++++--------- hal/emac_api.h | 3 +- 4 files changed, 44 insertions(+), 63 deletions(-) rename features/{FEATURE_LWIP/lwip-interface/ipstack_lwip.c => netsocket/mbed_ipstack.c} (79%) diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index 2c3978e645b..7226aa339b1 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -233,7 +233,7 @@ void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t even * \param[in] enet Pointer to K64F enet structure * \param[in] hwaddr MAC address */ -static err_t low_level_init(struct k64f_enetdata *enet, char *hwaddr) +static bool low_level_init_successful(struct k64f_enetdata *enet, char *hwaddr) { uint8_t i; uint32_t sysClock; @@ -247,12 +247,12 @@ static err_t low_level_init(struct k64f_enetdata *enet, char *hwaddr) // Allocate RX descriptors rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); if(!rx_desc_start_addr) - return ERR_MEM; + return false; // Allocate TX descriptors tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT); if(!tx_desc_start_addr) - return ERR_MEM; + return false; rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT); tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT); @@ -261,7 +261,7 @@ static err_t low_level_init(struct k64f_enetdata *enet, char *hwaddr) for (i = 0; i < ENET_RX_RING_LEN; i++) { rx_buff[i] = emac_stack_mem_alloc(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); if (NULL == rx_buff[i]) - return ERR_MEM; + return false; /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing @@ -316,7 +316,7 @@ static err_t low_level_init(struct k64f_enetdata *enet, char *hwaddr) ENET_SetCallback(&g_handle, ethernet_callback, enet); ENET_ActiveRead(ENET); - return ERR_OK; + return true; } @@ -344,13 +344,6 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) /* Determine if a frame has been received */ if ((bdPtr->control & err_mask) != 0) { -#if LINK_STATS - if ((bdPtr->control & ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK) != 0) - LINK_STATS_INC(link.lenerr); - else - LINK_STATS_INC(link.chkerr); -#endif - LINK_STATS_INC(link.drop); /* Re-use the same buffer in case of error */ update_read_buffer(NULL); } else { @@ -364,15 +357,9 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) /* Attempt to queue new buffer */ temp_rxbuf = emac_stack_mem_alloc(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); if (NULL == temp_rxbuf) { - /* Drop frame (out of memory) */ - LINK_STATS_INC(link.drop); - /* Re-queue the same buffer */ update_read_buffer(NULL); - LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, - ("k64f_low_level_input: Packet index %d dropped for OOM\n", - idx)); #ifdef LOCK_RX_THREAD osMutexRelease(enet->TXLockMutex); #endif @@ -390,13 +377,9 @@ static emac_stack_mem_t *k64f_low_level_input(int idx) rx_ptr[idx] = payload; update_read_buffer(payload); - LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, - ("k64f_low_level_input: Packet received: %p, size %"PRIu32" (index=%d)\n", - p, length, idx)); /* Save size */ emac_stack_mem_set_chain_len(p, length); - LINK_STATS_INC(link.recv); } #ifdef LOCK_RX_THREAD @@ -520,8 +503,6 @@ static bool k64f_eth_link_out(emac_interface_t *emac, emac_stack_mem_chain_t *ch /* Active the transmit buffer descriptor. */ ENET->TDAR = ENET_TDAR_TDAR_MASK; - LINK_STATS_INC(link.xmit); - /* Restore access */ osMutexRelease(enet->TXLockMutex); @@ -584,13 +565,11 @@ static void k64f_phy_task(void *data) { static bool k64f_eth_power_up(emac_interface_t *emac) { - err_t err; char hwaddr[ETH_HWADDR_LEN]; /* Initialize the hardware */ mbed_mac_address(hwaddr); - err = low_level_init(&k64f_enetdata, hwaddr); - if (err != ERR_OK) + if (!low_level_init_successful(&k64f_enetdata, hwaddr)) return false; k64f_enetdata.xTXDCountSem = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &xtxdcountsem_attr); diff --git a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c index a8b396c7576..86bf987bae0 100644 --- a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c @@ -172,11 +172,11 @@ static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *h { ip_addr_t lwip_addr; -#if LWIP_IPV4 && LWIP_IPV6 + #if LWIP_IPV4 && LWIP_IPV6 u8_t addr_type; if (version == NSAPI_UNSPEC) { const ip_addr_t *ip_addr; - ip_addr = mbed_lwip_get_ip_addr(true, &stack->emac->netif); + ip_addr = mbed_lwip_get_ip_addr(true, (struct netif *)&stack->emac->netif); if (IP_IS_V6(ip_addr)) { addr_type = NETCONN_DNS_IPV6; } else { @@ -189,7 +189,7 @@ static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *h } err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); #elif LWIP_IPV4 - if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { + if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname(host, &lwip_addr); @@ -242,7 +242,7 @@ static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t #if LWIP_IPV6 && LWIP_IPV4 const ip_addr_t *ip_addr; - ip_addr = mbed_lwip_get_ip_addr(true, &stack->emac->netif); + ip_addr = mbed_lwip_get_ip_addr(true, (struct netif *)&stack->emac->netif); if (IP_IS_V6(ip_addr)) { // Enable IPv6 (or dual-stack). LWIP dual-stack support is @@ -501,4 +501,4 @@ const nsapi_stack_api_t lwip_stack_api = { #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c b/features/netsocket/mbed_ipstack.c similarity index 79% rename from features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c rename to features/netsocket/mbed_ipstack.c index 2a903d818d5..04cee9ba1ed 100644 --- a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c +++ b/features/netsocket/mbed_ipstack.c @@ -1,5 +1,4 @@ -/* LWIP implementation of NetworkInterfaceAPI - * Copyright (c) 2015 ARM Limited +/* Copyright (c) 2017 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,12 +81,12 @@ static void add_dns_addr(struct netif *lwip_netif) #endif } -static void mbed_lwip_tcpip_init_irq(void *eh) +static void mbed_ipstack_tcpip_init_irq(void *eh) { sys_sem_signal(&lwip_tcpip_inited); } -static void mbed_lwip_netif_link_irq(struct netif *netif) +static void mbed_ipstack_netif_link_irq(struct netif *netif) { if (netif_is_link_up(netif)) { emac_interface_t *emac = netif->state; @@ -95,7 +94,7 @@ static void mbed_lwip_netif_link_irq(struct netif *netif) } } -static void mbed_lwip_netif_status_irq(struct netif *netif) +static void mbed_ipstack_netif_status_irq(struct netif *netif) { static bool any_addr = true; emac_interface_t *emac = netif->state; @@ -133,7 +132,7 @@ char *mbed_ipstack_get_mac_address(emac_interface_t *emac) char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { - const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &emac->netif); + const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, (struct netif *)emac->netif); if (!addr) { return NULL; } @@ -153,7 +152,7 @@ char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_ char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { #if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_netmask(&emac->netif); + const ip4_addr_t *addr = netif_ip4_netmask((struct netif *)emac->netif); if (!ip4_addr_isany(addr)) { return ip4addr_ntoa_r(addr, buf, buflen); } else { @@ -167,7 +166,7 @@ char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t b char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { #if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_gw(&emac->netif); + const ip4_addr_t *addr = netif_ip4_gw((struct netif *)emac->netif); if (!ip4_addr_isany(addr)) { return ip4addr_ntoa_r(addr, buf, buflen); } else { @@ -184,7 +183,7 @@ void mbed_ipstack_init(void) return; sys_sem_new(&lwip_tcpip_inited, 0); - tcpip_init(mbed_lwip_tcpip_init_irq, NULL); + tcpip_init(mbed_ipstack_tcpip_init_irq, NULL); sys_arch_sem_wait(&lwip_tcpip_inited, 0); // Zero out socket set @@ -199,24 +198,28 @@ nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if) emac->dhcp = true; sys_sem_new(&emac->linked, 0); sys_sem_new(&emac->has_addr, 0); - memset(&emac->netif, 0, sizeof(emac->netif)); - emac->netif.state = emac; mbed_mac_address(emac->hwaddr); - if (!netif_add(&emac->netif, + struct netif *lwip_netif = (struct netif *)malloc(sizeof(struct netif)); + memset(lwip_netif, 0, sizeof(lwip_netif)); + lwip_netif->state = emac; + + emac->netif = (void *)netif_add(lwip_netif, #if LWIP_IPV4 0, 0, 0, #endif - emac, emac_lwip_if_init, tcpip_input)) { + emac, emac_lwip_if_init, tcpip_input); + if (!emac->netif) + { return NSAPI_ERROR_DEVICE_ERROR; } if (default_if) - netif_set_default(&emac->netif); + netif_set_default((struct netif *)emac->netif); - netif_set_link_callback(&emac->netif, mbed_lwip_netif_link_irq); - netif_set_status_callback(&emac->netif, mbed_lwip_netif_status_irq); + netif_set_link_callback((struct netif *)emac->netif, mbed_ipstack_netif_link_irq); + netif_set_status_callback((struct netif *)emac->netif, mbed_ipstack_netif_status_irq); return NSAPI_ERROR_OK; } @@ -231,7 +234,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char mbed_ipstack_init(); #if LWIP_IPV6 - netif_create_ip6_linklocal_address(&emac->netif, 1/*from MAC*/); + netif_create_ip6_linklocal_address((struct netif *)emac->netif, 1/*from MAC*/); #if LWIP_IPV6_MLD /* * For hardware/netifs that implement MAC filtering. @@ -241,7 +244,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char if (emac->netif.mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - emac->netif.mld_mac_filter(&emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + emac->netif.mld_mac_filter((struct netif *)emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6_MLD */ @@ -254,7 +257,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char u32_t ret; - if (!netif_is_link_up(&emac->netif)) { + if (!netif_is_link_up((struct netif *)emac->netif)) { ret = sys_arch_sem_wait(&emac->linked, 15000); if (ret == SYS_ARCH_TIMEOUT) { @@ -274,18 +277,18 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char return NSAPI_ERROR_PARAMETER; } - netif_set_addr(&emac->netif, &ip_addr, &netmask_addr, &gw_addr); + netif_set_addr((struct netif *)emac->netif, &ip_addr, &netmask_addr, &gw_addr); } #endif - netif_set_up(&emac->netif); + netif_set_up((struct netif *)emac->netif); #if LWIP_IPV4 // Connect to the network emac->dhcp = dhcp; if (dhcp) { - err_t err = dhcp_start(&emac->netif); + err_t err = dhcp_start((struct netif *)emac->netif); if (err) { return NSAPI_ERROR_DHCP_FAILURE; } @@ -293,7 +296,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char #endif // If doesn't have address - if (!mbed_lwip_get_ip_addr(true, &emac->netif)) { + if (!mbed_lwip_get_ip_addr(true, (struct netif *)emac->netif)) { ret = sys_arch_sem_wait(&emac->has_addr, 15000); if (ret == SYS_ARCH_TIMEOUT) { return NSAPI_ERROR_DHCP_FAILURE; @@ -305,12 +308,12 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char #if ADDR_TIMEOUT // If address is not for preferred stack waits a while to see // if preferred stack address is acquired - if (!mbed_lwip_get_ip_addr(false, &emac->netif)) { + if (!mbed_lwip_get_ip_addr(false, (struct netif *)emac->netif)) { ret = sys_arch_sem_wait(&emac->has_addr, ADDR_TIMEOUT * 1000); } #endif - add_dns_addr(&emac->netif); + add_dns_addr((struct netif *)emac->netif); return 0; } @@ -325,16 +328,16 @@ nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) #if LWIP_IPV4 // Disconnect from the network if (emac->dhcp) { - dhcp_release(&emac->netif); - dhcp_stop(&emac->netif); + dhcp_release((struct netif *)emac->netif); + dhcp_stop((struct netif *)emac->netif); emac->dhcp = false; } #endif - netif_set_down(&emac->netif); + netif_set_down((struct netif *)emac->netif); #if LWIP_IPV6 - mbed_lwip_clear_ipv6_addresses(&emac->netif); + mbed_lwip_clear_ipv6_addresses((struct netif *)emac->netif); #endif sys_sem_free(&emac->has_addr); diff --git a/hal/emac_api.h b/hal/emac_api.h index b1045022d1e..c874e75cd73 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -20,7 +20,6 @@ #include #include "emac_stack_mem.h" #include "arch/sys_arch.h" -#include "lwip/netif.h" typedef struct emac_interface emac_interface_t; @@ -171,7 +170,7 @@ typedef struct emac_interface { bool connected; bool dhcp; char hwaddr[6]; - struct netif netif; + void *netif; } emac_interface_t; #endif /* MBED_EMAC_API_H */ From 3aae01cffe2a0c2e89c9cc909df684af71d45f34 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Mon, 21 Aug 2017 11:07:52 +0300 Subject: [PATCH 04/13] Revert ipstack_lwip.c renaming. mbed_ipstac.c renamed back to ipstack_lwip.c and moved to back \FEATURE_LWIP\lwip-interface --- .../lwip-interface/ipstack_lwip.c} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename features/{netsocket/mbed_ipstack.c => FEATURE_LWIP/lwip-interface/ipstack_lwip.c} (96%) diff --git a/features/netsocket/mbed_ipstack.c b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c similarity index 96% rename from features/netsocket/mbed_ipstack.c rename to features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c index 04cee9ba1ed..e91128217df 100644 --- a/features/netsocket/mbed_ipstack.c +++ b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c @@ -81,12 +81,12 @@ static void add_dns_addr(struct netif *lwip_netif) #endif } -static void mbed_ipstack_tcpip_init_irq(void *eh) +static void mbed_lwip_tcpip_init_irq(void *eh) { sys_sem_signal(&lwip_tcpip_inited); } -static void mbed_ipstack_netif_link_irq(struct netif *netif) +static void mbed_lwip_netif_link_irq(struct netif *netif) { if (netif_is_link_up(netif)) { emac_interface_t *emac = netif->state; @@ -94,7 +94,7 @@ static void mbed_ipstack_netif_link_irq(struct netif *netif) } } -static void mbed_ipstack_netif_status_irq(struct netif *netif) +static void mbed_lwip_netif_status_irq(struct netif *netif) { static bool any_addr = true; emac_interface_t *emac = netif->state; @@ -183,7 +183,7 @@ void mbed_ipstack_init(void) return; sys_sem_new(&lwip_tcpip_inited, 0); - tcpip_init(mbed_ipstack_tcpip_init_irq, NULL); + tcpip_init(mbed_lwip_tcpip_init_irq, NULL); sys_arch_sem_wait(&lwip_tcpip_inited, 0); // Zero out socket set @@ -218,8 +218,8 @@ nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if) if (default_if) netif_set_default((struct netif *)emac->netif); - netif_set_link_callback((struct netif *)emac->netif, mbed_ipstack_netif_link_irq); - netif_set_status_callback((struct netif *)emac->netif, mbed_ipstack_netif_status_irq); + netif_set_link_callback((struct netif *)emac->netif, mbed_lwip_netif_link_irq); + netif_set_status_callback((struct netif *)emac->netif, mbed_lwip_netif_status_irq); return NSAPI_ERROR_OK; } From db59feda4b8c81dbd7554d1422588955ba03633e Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Tue, 22 Aug 2017 13:36:40 +0300 Subject: [PATCH 05/13] Review changes and IPV6 compiler corrections --- doxyfile_options | 1 + .../FEATURE_LWIP/lwip-interface/emac_lwip.c | 36 ++++++++++--------- .../lwip-interface/ipstack_lwip.c | 8 ++--- .../arch/TARGET_Freescale/k64f_emac.c | 10 ++++-- features/netsocket/EthernetInterface.cpp | 15 +++++--- features/netsocket/mbed_ipstack.h | 6 ++-- hal/emac_api.h | 5 +-- 7 files changed, 49 insertions(+), 32 deletions(-) diff --git a/doxyfile_options b/doxyfile_options index d433f01df30..76ae414fb99 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -2061,6 +2061,7 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_ANALOGOUT \ DEVICE_CAN \ DEVICE_ETHERNET \ + DEVICE_EMAC \ DEVICE_ETH \ DEVICE_FLASH \ DEVICE_I2C \ diff --git a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c index d1ba12325d9..121a05551af 100644 --- a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c @@ -20,6 +20,8 @@ #include "lwip/tcp.h" #include "lwip/ip.h" #include "netif/etharp.h" +#include "lwip/ethip6.h" +#include "netsocket/nsapi_types.h" static err_t emac_lwip_low_level_output(struct netif *netif, struct pbuf *p) { @@ -73,15 +75,16 @@ static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t switch (action) { case NETIF_ADD_MAC_FILTER: { + nsapi_addr_t *addrs; uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; - uint8_t addr[6]; - addr[0] = LL_IP4_MULTICAST_ADDR_0; - addr[1] = LL_IP4_MULTICAST_ADDR_1; - addr[2] = LL_IP4_MULTICAST_ADDR_2; - addr[3] = group23 >> 16; - addr[4] = group23 >> 8; - addr[5] = group23; - emac->ops->add_multicast_group(emac, addr); + addrs->version = NSAPI_IPv4; + addrs->bytes[0] = LL_IP4_MULTICAST_ADDR_0; + addrs->bytes[1] = LL_IP4_MULTICAST_ADDR_1; + addrs->bytes[2] = LL_IP4_MULTICAST_ADDR_2; + addrs->bytes[3] = group23 >> 16; + addrs->bytes[4] = group23 >> 8; + addrs->bytes[5] = group23; + emac->ops->add_multicast_group(emac, addrs); return ERR_OK; } case NETIF_DEL_MAC_FILTER: @@ -114,15 +117,16 @@ static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t a switch (action) { case NETIF_ADD_MAC_FILTER: { + nsapi_addr_t *addrs; uint32_t group32 = ntohl(group->addr[3]); - uint8_t addr[6]; - addr[0] = LL_IP6_MULTICAST_ADDR_0; - addr[1] = LL_IP6_MULTICAST_ADDR_1; - addr[2] = group32 >> 24; - addr[3] = group32 >> 16; - addr[4] = group32 >> 8; - addr[5] = group32; - emac->ops->add_multicast_group(emac, addr); + addrs->version = NSAPI_IPv6; + addrs->bytes[0] = LL_IP6_MULTICAST_ADDR_0; + addrs->bytes[1] = LL_IP6_MULTICAST_ADDR_1; + addrs->bytes[2] = group32 >> 24; + addrs->bytes[3] = group32 >> 16; + addrs->bytes[4] = group32 >> 8; + addrs->bytes[5] = group32; + emac->ops->add_multicast_group(emac, addrs); return ERR_OK; } case NETIF_DEL_MAC_FILTER: diff --git a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c index e91128217df..b3918b41d2f 100644 --- a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c @@ -192,7 +192,7 @@ void mbed_ipstack_init(void) mbed_lwip_inited = true; } -nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if) +nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if) { emac->connected = false; emac->dhcp = true; @@ -241,16 +241,16 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char * All-nodes link-local is handled by default, so we must let the hardware know * to allow multicast packets in. * Should set mld_mac_filter previously. */ - if (emac->netif.mld_mac_filter != NULL) { + if (((struct netif *)emac->netif)->mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - emac->netif.mld_mac_filter((struct netif *)emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + ((struct netif *)emac->netif)->mld_mac_filter((struct netif *)emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_AUTOCONFIG /* IPv6 address autoconfiguration not enabled by default */ - emac->netif.ip6_autoconfig_enabled = 1; + ((struct netif *)emac->netif)->ip6_autoconfig_enabled = 1; #endif /* LWIP_IPV6_AUTOCONFIG */ #endif /* LWIP_IPV6 */ diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index 7226aa339b1..e87761fc910 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -44,6 +44,7 @@ #include "emac_api.h" #include "emac_stack_mem.h" #include "mbed_assert.h" +#include "netsocket/nsapi_types.h" enet_handle_t g_handle; // TX Buffer descriptors @@ -643,9 +644,14 @@ static void k64f_eth_set_link_state_cb(emac_interface_t *emac, emac_link_state_c enet->emac_link_state_cb_data = data; } -static void k64f_eth_add_multicast_group(emac_interface_t *emac, uint8_t *addr) +static void k64f_eth_add_multicast_group(emac_interface_t *emac, const nsapi_addr_t *addr) { - ENET_AddMulticastGroup(ENET, addr); + + uint8_t _addr[NSAPI_IP_BYTES]; + for (int i = 0; i < NSAPI_IP_BYTES; i++) { + _addr[i] = addr->bytes[i]; + } + ENET_AddMulticastGroup(ENET, _addr); } static void k64f_eth_power_down(emac_interface_t *emac) diff --git a/features/netsocket/EthernetInterface.cpp b/features/netsocket/EthernetInterface.cpp index 679f1fbfcfc..12d749e7b07 100644 --- a/features/netsocket/EthernetInterface.cpp +++ b/features/netsocket/EthernetInterface.cpp @@ -27,9 +27,14 @@ EthernetInterface::EthernetInterface(emac_interface_t *emac) nsapi_error_t EthernetInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) { _dhcp = false; + strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address)); + _ip_address[sizeof(_ip_address) - 1] = '\0'; strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask)); + _netmask[sizeof(_netmask) - 1] = '\0'; strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway)); + _gateway[sizeof(_gateway) - 1] = '\0'; + return NSAPI_ERROR_OK; } @@ -42,13 +47,15 @@ nsapi_error_t EthernetInterface::set_dhcp(bool dhcp) nsapi_error_t EthernetInterface::connect() { nsapi_error_t err; - if (_stack.emac == NULL) + if (_stack.emac == NULL) { return NSAPI_ERROR_UNSUPPORTED; + } mbed_ipstack_init(); - err = mbed_ipstack_add_netif(_stack.emac, true); - if (err != NSAPI_ERROR_OK) + err = mbed_ipstack_add_interface(_stack.emac, true); + if (err != NSAPI_ERROR_OK) { return err; + } return mbed_ipstack_bringup(_stack.emac, _dhcp, _ip_address[0] ? _ip_address : 0, @@ -96,4 +103,4 @@ const char *EthernetInterface::get_gateway() NetworkStack *EthernetInterface::get_stack() { return nsapi_create_stack(&_stack); -} \ No newline at end of file +} diff --git a/features/netsocket/mbed_ipstack.h b/features/netsocket/mbed_ipstack.h index 9055e2b29d3..23ba41c655a 100644 --- a/features/netsocket/mbed_ipstack.h +++ b/features/netsocket/mbed_ipstack.h @@ -36,8 +36,6 @@ extern "C" { * sure that the stack is initialized and all the existing interfaces are registered with the stack. * This function can be safely called multiple times, it will do nothing and return NSAPI_ERROR_OK if stack is already * initialized. - * - * @return NSAPI_ERROR_OK on success, or error code */ void mbed_ipstack_init(void); @@ -50,7 +48,7 @@ void mbed_ipstack_init(void); * @param default_if true if the interface should be treated as the default one * @return NSAPI_ERROR_OK on success, or error code */ -nsapi_error_t mbed_ipstack_add_netif(emac_interface_t *emac, bool default_if); +nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if); /** Connect network stack with the IP stack * @@ -120,4 +118,4 @@ char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t b } #endif -#endif /* MBED_IPSTACK_H */ \ No newline at end of file +#endif /* MBED_IPSTACK_H */ diff --git a/hal/emac_api.h b/hal/emac_api.h index c874e75cd73..34137a09c98 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -22,6 +22,7 @@ #include "arch/sys_arch.h" typedef struct emac_interface emac_interface_t; +typedef struct nsapi_addr nsapi_addr_t; /** * EmacInterface @@ -141,9 +142,9 @@ typedef void (*emac_set_link_state_cb_fn)(emac_interface_t *emac, emac_link_stat /** Add device to a multicast group * * @param emac Emac interface - * @param address An multicast group IPv4 address + * @param address An multicast group address */ -typedef void (*emac_add_multicast_group)(emac_interface_t *emac, uint8_t *address); +typedef void (*emac_add_multicast_group)(emac_interface_t *emac, const nsapi_addr_t *address); typedef struct emac_interface_ops { emac_get_mtu_size_fn get_mtu_size; From 062ce13be1204114c07a5f000608f33d039aea74 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Thu, 24 Aug 2017 16:03:23 +0300 Subject: [PATCH 06/13] Define emac_interface_t as const at the emac_api.h and take it to use at K64F Change "uint8_t *addr" to "uint8_t addr[ETH_HWADDR_LEN]" at the emac_api.h Correct reset at emac_lwip.c --- .../FEATURE_LWIP/lwip-interface/emac_lwip.c | 38 ++++++++++--------- .../arch/TARGET_Freescale/k64f_emac.c | 22 +++++------ .../arch/TARGET_Freescale/k64f_emac_config.h | 1 - hal/emac_api.h | 23 +++++------ 4 files changed, 43 insertions(+), 41 deletions(-) diff --git a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c index 121a05551af..60706b6877d 100644 --- a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c @@ -75,16 +75,17 @@ static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t switch (action) { case NETIF_ADD_MAC_FILTER: { - nsapi_addr_t *addrs; + nsapi_addr_t addrs; + memset(&addrs, 0x00, sizeof(nsapi_addr_t)); uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; - addrs->version = NSAPI_IPv4; - addrs->bytes[0] = LL_IP4_MULTICAST_ADDR_0; - addrs->bytes[1] = LL_IP4_MULTICAST_ADDR_1; - addrs->bytes[2] = LL_IP4_MULTICAST_ADDR_2; - addrs->bytes[3] = group23 >> 16; - addrs->bytes[4] = group23 >> 8; - addrs->bytes[5] = group23; - emac->ops->add_multicast_group(emac, addrs); + addrs.version = NSAPI_IPv4; + addrs.bytes[0] = LL_IP4_MULTICAST_ADDR_0; + addrs.bytes[1] = LL_IP4_MULTICAST_ADDR_1; + addrs.bytes[2] = LL_IP4_MULTICAST_ADDR_2; + addrs.bytes[3] = group23 >> 16; + addrs.bytes[4] = group23 >> 8; + addrs.bytes[5] = group23; + emac->ops->add_multicast_group(emac, &addrs); return ERR_OK; } case NETIF_DEL_MAC_FILTER: @@ -117,16 +118,17 @@ static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t a switch (action) { case NETIF_ADD_MAC_FILTER: { - nsapi_addr_t *addrs; + nsapi_addr_t addrs; + memset((void*)&addrs, 0x00, sizeof(nsapi_addr_t)); uint32_t group32 = ntohl(group->addr[3]); - addrs->version = NSAPI_IPv6; - addrs->bytes[0] = LL_IP6_MULTICAST_ADDR_0; - addrs->bytes[1] = LL_IP6_MULTICAST_ADDR_1; - addrs->bytes[2] = group32 >> 24; - addrs->bytes[3] = group32 >> 16; - addrs->bytes[4] = group32 >> 8; - addrs->bytes[5] = group32; - emac->ops->add_multicast_group(emac, addrs); + addrs.version = NSAPI_IPv6; + addrs.bytes[0] = LL_IP6_MULTICAST_ADDR_0; + addrs.bytes[1] = LL_IP6_MULTICAST_ADDR_1; + addrs.bytes[2] = group32 >> 24; + addrs.bytes[3] = group32 >> 16; + addrs.bytes[4] = group32 >> 8; + addrs.bytes[5] = group32; + emac->ops->add_multicast_group(emac, &addrs); return ERR_OK; } case NETIF_DEL_MAC_FILTER: diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index e87761fc910..b2f98c32252 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -456,7 +456,7 @@ static void packet_tx(void* pvParameters) { * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent */ -static bool k64f_eth_link_out(emac_interface_t *emac, emac_stack_mem_chain_t *chain) +static bool k64f_eth_link_out(const emac_interface_t *emac, emac_stack_mem_chain_t *chain) { struct k64f_enetdata *enet = emac->hw; emac_stack_mem_t *q; @@ -564,7 +564,7 @@ static void k64f_phy_task(void *data) { } } -static bool k64f_eth_power_up(emac_interface_t *emac) +static bool k64f_eth_power_up(const emac_interface_t *emac) { char hwaddr[ETH_HWADDR_LEN]; @@ -603,32 +603,32 @@ static bool k64f_eth_power_up(emac_interface_t *emac) } -static uint32_t k64f_eth_get_mtu_size(emac_interface_t *emac) +static uint32_t k64f_eth_get_mtu_size(const emac_interface_t *emac) { return K64_ETH_MTU_SIZE; } -static void k64f_eth_get_ifname(emac_interface_t *emac, char *name, uint8_t size) +static void k64f_eth_get_ifname(const emac_interface_t *emac, char *name, uint8_t size) { memcpy(name, K64_ETH_IF_NAME, (size < sizeof(K64_ETH_IF_NAME)) ? size : sizeof(K64_ETH_IF_NAME)); } -static uint8_t k64f_eth_get_hwaddr_size(emac_interface_t *emac) +static uint8_t k64f_eth_get_hwaddr_size(const emac_interface_t *emac) { return ETH_HWADDR_LEN; } -static void k64f_eth_get_hwaddr(emac_interface_t *emac, uint8_t *addr) +static void k64f_eth_get_hwaddr(const emac_interface_t *emac, uint8_t addr[ETH_HWADDR_LEN]) { mbed_mac_address((char*)addr); } -static void k64f_eth_set_hwaddr(emac_interface_t *emac, uint8_t *addr) +static void k64f_eth_set_hwaddr(const emac_interface_t *emac, const uint8_t addr[ETH_HWADDR_LEN]) { /* No-op at this stage */ } -static void k64f_eth_set_link_input_cb(emac_interface_t *emac, emac_link_input_fn input_cb, void *data) +static void k64f_eth_set_link_input_cb(emac_interface_t *emac, const emac_link_input_fn input_cb, void *data) { struct k64f_enetdata *enet = emac->hw; @@ -636,7 +636,7 @@ static void k64f_eth_set_link_input_cb(emac_interface_t *emac, emac_link_input_f enet->emac_link_input_cb_data = data; } -static void k64f_eth_set_link_state_cb(emac_interface_t *emac, emac_link_state_change_fn state_cb, void *data) +static void k64f_eth_set_link_state_cb(emac_interface_t *emac, const emac_link_state_change_fn state_cb, void *data) { struct k64f_enetdata *enet = emac->hw; @@ -644,7 +644,7 @@ static void k64f_eth_set_link_state_cb(emac_interface_t *emac, emac_link_state_c enet->emac_link_state_cb_data = data; } -static void k64f_eth_add_multicast_group(emac_interface_t *emac, const nsapi_addr_t *addr) +static void k64f_eth_add_multicast_group(const emac_interface_t *emac, const nsapi_addr_t *addr) { uint8_t _addr[NSAPI_IP_BYTES]; @@ -654,7 +654,7 @@ static void k64f_eth_add_multicast_group(emac_interface_t *emac, const nsapi_add ENET_AddMulticastGroup(ENET, _addr); } -static void k64f_eth_power_down(emac_interface_t *emac) +static void k64f_eth_power_down(const emac_interface_t *emac) { /* No-op at this stage */ } diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h index 7676d3890c5..a82d80560dd 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h @@ -34,7 +34,6 @@ #define ENET_RX_RING_LEN (16) #define ENET_TX_RING_LEN (8) -#define ETH_HWADDR_LEN (6) #define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame diff --git a/hal/emac_api.h b/hal/emac_api.h index 34137a09c98..ce00af8cde0 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -23,6 +23,7 @@ typedef struct emac_interface emac_interface_t; typedef struct nsapi_addr nsapi_addr_t; +#define ETH_HWADDR_LEN 6 /** * EmacInterface @@ -57,7 +58,7 @@ typedef void (*emac_link_state_change_fn)(void *data, bool up); * @param emac Emac interface * @return MTU in bytes */ -typedef uint32_t (*emac_get_mtu_size_fn)(emac_interface_t *emac); +typedef uint32_t (*emac_get_mtu_size_fn)(const emac_interface_t *emac); /** * Return interface name @@ -66,7 +67,7 @@ typedef uint32_t (*emac_get_mtu_size_fn)(emac_interface_t *emac); * @param name Pointer to where the name should be written * @param size Maximum number of character to copy */ -typedef void (*emac_get_ifname_fn)(emac_interface_t *emac, char *name, uint8_t size); +typedef void (*emac_get_ifname_fn)(const emac_interface_t *emac, char *name, uint8_t size); /** * Returns size of the underlying interface HW address size @@ -74,7 +75,7 @@ typedef void (*emac_get_ifname_fn)(emac_interface_t *emac, char *name, uint8_t s * @param emac Emac interface * @return HW address size in bytes */ -typedef uint8_t (*emac_get_hwaddr_size_fn)(emac_interface_t *emac); +typedef uint8_t (*emac_get_hwaddr_size_fn)(const emac_interface_t *emac); /** * Return interface hw address @@ -84,7 +85,7 @@ typedef uint8_t (*emac_get_hwaddr_size_fn)(emac_interface_t *emac); * @param emac Emac interface * @param addr HW address for underlying interface */ -typedef void (*emac_get_hwaddr_fn)(emac_interface_t *emac, uint8_t *addr); +typedef void (*emac_get_hwaddr_fn)(const emac_interface_t *emac, uint8_t addr[ETH_HWADDR_LEN]); /** * Set HW address for interface @@ -94,7 +95,7 @@ typedef void (*emac_get_hwaddr_fn)(emac_interface_t *emac, uint8_t *addr); * @param emac Emac interface * @param addr Address to be set */ -typedef void (*emac_set_hwaddr_fn)(emac_interface_t *emac, uint8_t *addr); +typedef void (*emac_set_hwaddr_fn)(const emac_interface_t *emac, const uint8_t addr[ETH_HWADDR_LEN]); /** * Sends the packet over the link @@ -105,21 +106,21 @@ typedef void (*emac_set_hwaddr_fn)(emac_interface_t *emac, uint8_t *addr); * @param buf Packet to be send * @return True if the packet was send successfully, False otherwise */ -typedef bool (*emac_link_out_fn)(emac_interface_t *emac, emac_stack_mem_chain_t *buf); +typedef bool (*emac_link_out_fn)(const emac_interface_t *emac, emac_stack_mem_chain_t *buf); /** * Initializes the HW * * @return True on success, False in case of an error. */ -typedef bool (*emac_power_up_fn)(emac_interface_t *emac); +typedef bool (*emac_power_up_fn)(const emac_interface_t *emac); /** * Deinitializes the HW * * @param emac Emac interface */ -typedef void (*emac_power_down_fn)(emac_interface_t *emac); +typedef void (*emac_power_down_fn)(const emac_interface_t *emac); /** * Sets a callback that needs to be called for packets received for that interface @@ -128,7 +129,7 @@ typedef void (*emac_power_down_fn)(emac_interface_t *emac); * @param input_cb Function to be register as a callback * @param data Arbitrary user data to be passed to the callback */ -typedef void (*emac_set_link_input_cb_fn)(emac_interface_t *emac, emac_link_input_fn input_cb, void *data); +typedef void (*emac_set_link_input_cb_fn)(emac_interface_t *emac, const emac_link_input_fn input_cb, void *data); /** * Sets a callback that needs to be called on link status changes for given interface @@ -137,14 +138,14 @@ typedef void (*emac_set_link_input_cb_fn)(emac_interface_t *emac, emac_link_inpu * @param state_cb Function to be register as a callback * @param data Arbitrary user data to be passed to the callback */ -typedef void (*emac_set_link_state_cb_fn)(emac_interface_t *emac, emac_link_state_change_fn state_cb, void *data); +typedef void (*emac_set_link_state_cb_fn)(emac_interface_t *emac, const emac_link_state_change_fn state_cb, void *data); /** Add device to a multicast group * * @param emac Emac interface * @param address An multicast group address */ -typedef void (*emac_add_multicast_group)(emac_interface_t *emac, const nsapi_addr_t *address); +typedef void (*emac_add_multicast_group)(const emac_interface_t *emac, const nsapi_addr_t *address); typedef struct emac_interface_ops { emac_get_mtu_size_fn get_mtu_size; From 638888df5d388805ce139a5a5c5c031be1ae049b Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Fri, 25 Aug 2017 15:53:32 +0300 Subject: [PATCH 07/13] Remove sys_arch.h from emac_api.h sys_sem_* replaced with osSemaphore* so that \arch\sys_arch.h can be removed from emac_api.h --- .../lwip-interface/ipstack_lwip.c | 56 +++++++++++++------ features/netsocket/EthernetInterface.h | 3 +- hal/emac_api.h | 6 +- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c index b3918b41d2f..2f1dbec2074 100644 --- a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c @@ -42,7 +42,31 @@ extern "C" { #endif static bool mbed_lwip_inited = false; -static sys_sem_t lwip_tcpip_inited; + +static os_semaphore_t tcpip_inited_sem = {0}; +static const osSemaphoreAttr_t tcpip_inited_sem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &tcpip_inited_sem, + .cb_size = sizeof(tcpip_inited_sem), +}; + +static os_semaphore_t linked_sem = {0}; +static const osSemaphoreAttr_t linked_sem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &linked_sem, + .cb_size = sizeof(linked_sem), +}; + +static os_semaphore_t has_addr_sem = {0}; +static const osSemaphoreAttr_t has_addr_sem_attr = { + .name = "", + .attr_bits = 0, + .cb_mem = &has_addr_sem, + .cb_size = sizeof(has_addr_sem), +}; +osSemaphoreId_t tcpip_inited; static void add_dns_addr(struct netif *lwip_netif) { @@ -83,14 +107,14 @@ static void add_dns_addr(struct netif *lwip_netif) static void mbed_lwip_tcpip_init_irq(void *eh) { - sys_sem_signal(&lwip_tcpip_inited); + osSemaphoreRelease(tcpip_inited); } static void mbed_lwip_netif_link_irq(struct netif *netif) { if (netif_is_link_up(netif)) { emac_interface_t *emac = netif->state; - sys_sem_signal(&emac->linked); + osSemaphoreRelease(emac->linked); } } @@ -102,14 +126,14 @@ static void mbed_lwip_netif_status_irq(struct netif *netif) if (netif_is_up(netif)) { // Indicates that has address if (any_addr == true && mbed_lwip_get_ip_addr(true, netif)) { - sys_sem_signal(&emac->has_addr); + osSemaphoreRelease(emac->has_addr); any_addr = false; return; } // Indicates that has preferred address if (mbed_lwip_get_ip_addr(false, netif)) { - sys_sem_signal(&emac->has_addr); + osSemaphoreRelease(emac->has_addr); } } else { any_addr = true; @@ -182,9 +206,9 @@ void mbed_ipstack_init(void) if(mbed_lwip_inited) return; - sys_sem_new(&lwip_tcpip_inited, 0); + tcpip_inited = osSemaphoreNew(UINT16_MAX, 0, &tcpip_inited_sem_attr); tcpip_init(mbed_lwip_tcpip_init_irq, NULL); - sys_arch_sem_wait(&lwip_tcpip_inited, 0); + osSemaphoreAcquire(tcpip_inited, 0); // Zero out socket set mbed_lwip_arena_init(); @@ -196,9 +220,8 @@ nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if { emac->connected = false; emac->dhcp = true; - sys_sem_new(&emac->linked, 0); - sys_sem_new(&emac->has_addr, 0); - + emac->linked = osSemaphoreNew(UINT16_MAX, 0, &linked_sem_attr); + emac->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); mbed_mac_address(emac->hwaddr); struct netif *lwip_netif = (struct netif *)malloc(sizeof(struct netif)); @@ -258,9 +281,8 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char u32_t ret; if (!netif_is_link_up((struct netif *)emac->netif)) { - ret = sys_arch_sem_wait(&emac->linked, 15000); - - if (ret == SYS_ARCH_TIMEOUT) { + ret = osSemaphoreAcquire(emac->linked, 15000); + if (ret != osOK) { return NSAPI_ERROR_NO_CONNECTION; } } @@ -297,11 +319,10 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char // If doesn't have address if (!mbed_lwip_get_ip_addr(true, (struct netif *)emac->netif)) { - ret = sys_arch_sem_wait(&emac->has_addr, 15000); - if (ret == SYS_ARCH_TIMEOUT) { + ret = osSemaphoreAcquire(emac->has_addr, 15000); + if (ret != osOK) { return NSAPI_ERROR_DHCP_FAILURE; } - emac->connected = true; } @@ -340,8 +361,7 @@ nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) mbed_lwip_clear_ipv6_addresses((struct netif *)emac->netif); #endif - sys_sem_free(&emac->has_addr); - sys_sem_new(&emac->has_addr, 0); + emac->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); emac->connected = false; return 0; } diff --git a/features/netsocket/EthernetInterface.h b/features/netsocket/EthernetInterface.h index 3bbe15b8fff..c682188ad4f 100644 --- a/features/netsocket/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -20,6 +20,7 @@ #include "nsapi.h" #include "rtos.h" #include "hal/emac_api.h" +#include "lwip/api.h" // Forward declaration class NetworkStack; @@ -114,4 +115,4 @@ class EthernetInterface : public NetworkInterface nsapi_stack_t _stack; }; -#endif \ No newline at end of file +#endif diff --git a/hal/emac_api.h b/hal/emac_api.h index ce00af8cde0..6bd5130a11d 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -19,7 +19,7 @@ #include #include "emac_stack_mem.h" -#include "arch/sys_arch.h" +#include "cmsis_os.h" typedef struct emac_interface emac_interface_t; typedef struct nsapi_addr nsapi_addr_t; @@ -167,8 +167,8 @@ typedef struct emac_interface { void *hw; /**< EMAC implementation specific user data */ /* Private members used by the stack */ - sys_sem_t linked; - sys_sem_t has_addr; + osSemaphoreId_t linked; + osSemaphoreId_t has_addr; bool connected; bool dhcp; char hwaddr[6]; From 1d7a5f388bfdecfab0ea09b3d44153e5b19c1dd9 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Mon, 28 Aug 2017 13:04:38 +0300 Subject: [PATCH 08/13] Correct doxygen warnings --- features/netsocket/EthernetInterface.h | 8 ++++---- features/netsocket/mbed_ipstack.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/netsocket/EthernetInterface.h b/features/netsocket/EthernetInterface.h index c682188ad4f..684902917fd 100644 --- a/features/netsocket/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -42,10 +42,10 @@ class EthernetInterface : public NetworkInterface * Implicitly disables DHCP, which can be enabled in set_dhcp. * Requires that the network is disconnected. * - * @param address Null-terminated representation of the local IP address - * @param netmask Null-terminated representation of the local network mask - * @param gateway Null-terminated representation of the local gateway - * @return 0 on success, negative error code on failure + * @param ip_address Null-terminated representation of the local IP address + * @param netmask Null-terminated representation of the local network mask + * @param gateway Null-terminated representation of the local gateway + * @return 0 on success, negative error code on failure */ virtual nsapi_error_t set_network( const char *ip_address, const char *netmask, const char *gateway); diff --git a/features/netsocket/mbed_ipstack.h b/features/netsocket/mbed_ipstack.h index 23ba41c655a..d4692da95c6 100644 --- a/features/netsocket/mbed_ipstack.h +++ b/features/netsocket/mbed_ipstack.h @@ -74,7 +74,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char /** Disconnect interface from the network * - * After this call the network interface is inactive, to use it again user needs to call @mbed_lwip_bringup again. + * After this call the network interface is inactive, to use it again user needs to call @mbed_ipstack_bringup again. * * @return NSAPI_ERROR_OK on success, or error code */ From fdf190eaba86e0203dc566f64e6d0b33c312f205 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Tue, 29 Aug 2017 10:28:32 +0300 Subject: [PATCH 09/13] Remove lwip depency from EthernetInterface.h --- features/netsocket/EthernetInterface.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/features/netsocket/EthernetInterface.h b/features/netsocket/EthernetInterface.h index 684902917fd..1ecd6ca3301 100644 --- a/features/netsocket/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -20,7 +20,6 @@ #include "nsapi.h" #include "rtos.h" #include "hal/emac_api.h" -#include "lwip/api.h" // Forward declaration class NetworkStack; @@ -109,7 +108,7 @@ class EthernetInterface : public NetworkInterface virtual NetworkStack *get_stack(); bool _dhcp; - char _ip_address[IPADDR_STRLEN_MAX]; + char _ip_address[NSAPI_IPv6_SIZE]; char _netmask[NSAPI_IPv4_SIZE]; char _gateway[NSAPI_IPv4_SIZE]; nsapi_stack_t _stack; From 185435e7294b7d8a4584d7c996eed2266043259b Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Wed, 30 Aug 2017 10:55:59 +0300 Subject: [PATCH 10/13] Temporary file mbed_iptack.c created, so that mbed-os can be compiled without lwip Doxygen warning corrected --- features/netsocket/mbed_ipstack.c | 27 +++++++++++++++++++++++++++ features/netsocket/mbed_ipstack.h | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 features/netsocket/mbed_ipstack.c diff --git a/features/netsocket/mbed_ipstack.c b/features/netsocket/mbed_ipstack.c new file mode 100644 index 00000000000..a3dcfba6552 --- /dev/null +++ b/features/netsocket/mbed_ipstack.c @@ -0,0 +1,27 @@ +/* + * TEMPORARY FILE + * this file will be removed once the EMAC refactoring is completed + */ + +#include "platform/mbed_toolchain.h" +#include "mbed_ipstack.h" + + +MBED_WEAK void mbed_ipstack_init(void); + +MBED_WEAK nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if); + +MBED_WEAK void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack); + +MBED_WEAK nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, + const char *netmask, const char *gw); + +MBED_WEAK nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac); + +MBED_WEAK char *mbed_ipstack_get_mac_address(emac_interface_t *emac); + +MBED_WEAK char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + +MBED_WEAK char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + +MBED_WEAK char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen); diff --git a/features/netsocket/mbed_ipstack.h b/features/netsocket/mbed_ipstack.h index d4692da95c6..54109fc572a 100644 --- a/features/netsocket/mbed_ipstack.h +++ b/features/netsocket/mbed_ipstack.h @@ -74,7 +74,7 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char /** Disconnect interface from the network * - * After this call the network interface is inactive, to use it again user needs to call @mbed_ipstack_bringup again. + * After this call the network interface is inactive, to use it again user needs to call @a mbed_ipstack_bringup again. * * @return NSAPI_ERROR_OK on success, or error code */ From 743700c3678bfcbea55c8285b879249e634d1ce8 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Wed, 30 Aug 2017 16:05:29 +0300 Subject: [PATCH 11/13] Add error traces to mbed_ipstack.c --- features/netsocket/mbed_ipstack.c | 55 +++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/features/netsocket/mbed_ipstack.c b/features/netsocket/mbed_ipstack.c index a3dcfba6552..9ef12d4c4b6 100644 --- a/features/netsocket/mbed_ipstack.c +++ b/features/netsocket/mbed_ipstack.c @@ -5,23 +5,50 @@ #include "platform/mbed_toolchain.h" #include "mbed_ipstack.h" +#include "ns_trace.h" +#define TRACE_GROUP "mbed_ipstack" -MBED_WEAK void mbed_ipstack_init(void); +MBED_WEAK void mbed_ipstack_init(void) { + tr_error("Error, this function shouln't be called!"); +} -MBED_WEAK nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if); +MBED_WEAK nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if) { + tr_error("Error, this function shouln't be called!"); + return NSAPI_ERROR_UNSUPPORTED; +} -MBED_WEAK void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack); +MBED_WEAK void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack) { + tr_error("Error, this function shouln't be called!"); +} MBED_WEAK nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, - const char *netmask, const char *gw); - -MBED_WEAK nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac); - -MBED_WEAK char *mbed_ipstack_get_mac_address(emac_interface_t *emac); - -MBED_WEAK char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen); - -MBED_WEAK char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen); - -MBED_WEAK char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen); + const char *netmask, const char *gw) { + tr_error("Error, this function shouln't be called!"); + return NSAPI_ERROR_UNSUPPORTED; +} + +MBED_WEAK nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) { + tr_error("Error, this function shouln't be called!"); + return NSAPI_ERROR_UNSUPPORTED; +} + +MBED_WEAK char *mbed_ipstack_get_mac_address(emac_interface_t *emac) { + tr_error("Error, this function shouln't be called!"); + return NULL; +} + +MBED_WEAK char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { + tr_error("Error, this function shouln't be called!"); + return NULL; +} + +MBED_WEAK char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { + tr_error("Error, this function shouln't be called!"); + return NULL; +} + +MBED_WEAK char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { + tr_error("Error, this function shouln't be called!"); + return NULL; +} From a562087cdc0daa82e7ccc1902b258a986d7508c1 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Fri, 1 Sep 2017 09:32:34 +0300 Subject: [PATCH 12/13] Include ns_trace.h changed mbed_trace.h --- features/netsocket/mbed_ipstack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/netsocket/mbed_ipstack.c b/features/netsocket/mbed_ipstack.c index 9ef12d4c4b6..febeecefac3 100644 --- a/features/netsocket/mbed_ipstack.c +++ b/features/netsocket/mbed_ipstack.c @@ -5,7 +5,7 @@ #include "platform/mbed_toolchain.h" #include "mbed_ipstack.h" -#include "ns_trace.h" +#include "mbed_trace.h" #define TRACE_GROUP "mbed_ipstack" From 86d13be688ed9806c8300b1795523265aae5e337 Mon Sep 17 00:00:00 2001 From: Kari Haapalehto Date: Tue, 12 Sep 2017 15:04:06 +0300 Subject: [PATCH 13/13] Replace emac_interface_t* with void* at emac_api.h Move emac_interface_t from emac_api.h to mbed_ipstack_lwip.h and rename it to mbed_ipstack_interface emac_interface_ops_t, mbed_ipstack_interface_t and _hw added to EthernetInterface.h and _stack removed. ipstack_lwip.c renamed as mbed_ipstack_lwip.c --- .../FEATURE_LWIP/lwip-interface/emac_lwip.c | 71 ++++----- .../arch/TARGET_Freescale/k64f_emac.c | 75 +++++---- .../arch/TARGET_Freescale/k64f_emac_config.h | 2 + .../FEATURE_LWIP/lwip-interface/lwip_tools.c | 4 + .../{ipstack_lwip.c => mbed_ipstack_lwip.cpp} | 147 +++++++++--------- .../lwip-interface/mbed_ipstack_lwip.h | 46 ++++++ .../lwip-interface/nsapi_stack_lwip.c | 23 +-- .../lwip-interface/nsapi_stack_lwip.h | 31 ++++ .../FEATURE_LWIP/lwip-interface/ppp_lwip.cpp | 1 - features/netsocket/EthernetInterface.cpp | 25 +-- features/netsocket/EthernetInterface.h | 8 +- features/netsocket/mbed_ipstack.c | 25 +-- features/netsocket/mbed_ipstack.h | 31 ++-- features/netsocket/nsapi_types.h | 3 - hal/emac_api.h | 77 ++++----- 15 files changed, 324 insertions(+), 245 deletions(-) rename features/FEATURE_LWIP/lwip-interface/{ipstack_lwip.c => mbed_ipstack_lwip.cpp} (62%) create mode 100644 features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.h create mode 100644 features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.h diff --git a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c index 60706b6877d..0aec34bdae0 100644 --- a/features/FEATURE_LWIP/lwip-interface/emac_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/emac_lwip.c @@ -14,7 +14,8 @@ * limitations under the License. */ -#include "emac_api.h" +#if !NSAPI_PPP_AVAILABLE +#include "mbed_ipstack.h" #include "emac_stack_mem.h" #include "lwip/tcpip.h" #include "lwip/tcp.h" @@ -23,17 +24,19 @@ #include "lwip/ethip6.h" #include "netsocket/nsapi_types.h" +#include "mbed_ipstack_lwip.h" + static err_t emac_lwip_low_level_output(struct netif *netif, struct pbuf *p) { - emac_interface_t *mac = (emac_interface_t *)netif->state; - bool ret = mac->ops->link_out(mac, (emac_stack_mem_chain_t *)p); + mbed_ipstack_interface_t *mac = netif->state; + bool ret = mac->ops->link_out(mac->hw, p); return ret ? ERR_OK : ERR_IF; } static void emac_lwip_input(void *data, emac_stack_mem_t *buf) { - struct pbuf *p = (struct pbuf *)buf; - struct netif *netif = (struct netif *)data; + struct pbuf *p = buf; + struct netif *netif = data; /* pass all packets to ethernet_input, which decides what packets it supports */ if (netif->input(p, netif) != ERR_OK) { @@ -45,7 +48,7 @@ static void emac_lwip_input(void *data, emac_stack_mem_t *buf) static void emac_lwip_state_change(void *data, bool up) { - struct netif *netif = (struct netif *)data; + struct netif *netif = data; if (up) { tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, netif, 1); @@ -67,7 +70,7 @@ static void emac_lwip_state_change(void *data, bool up) */ static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t action) { - emac_interface_t *emac = netif->state; + mbed_ipstack_interface_t *emac = netif->state; if (emac->ops->add_multicast_group == NULL) { return ERR_OK; /* This function is not mandatory */ } @@ -75,17 +78,15 @@ static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t switch (action) { case NETIF_ADD_MAC_FILTER: { - nsapi_addr_t addrs; - memset(&addrs, 0x00, sizeof(nsapi_addr_t)); uint32_t group23 = ntohl(group->addr) & 0x007FFFFF; - addrs.version = NSAPI_IPv4; - addrs.bytes[0] = LL_IP4_MULTICAST_ADDR_0; - addrs.bytes[1] = LL_IP4_MULTICAST_ADDR_1; - addrs.bytes[2] = LL_IP4_MULTICAST_ADDR_2; - addrs.bytes[3] = group23 >> 16; - addrs.bytes[4] = group23 >> 8; - addrs.bytes[5] = group23; - emac->ops->add_multicast_group(emac, &addrs); + uint8_t addr[6]; + addr[0] = LL_IP4_MULTICAST_ADDR_0; + addr[1] = LL_IP4_MULTICAST_ADDR_1; + addr[2] = LL_IP4_MULTICAST_ADDR_2; + addr[3] = group23 >> 16; + addr[4] = group23 >> 8; + addr[5] = group23; + emac->ops->add_multicast_group(emac, addr); return ERR_OK; } case NETIF_DEL_MAC_FILTER: @@ -110,7 +111,7 @@ static err_t igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t */ static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t action) { - emac_interface_t *emac = netif->state; + mbed_ipstack_interface_t *emac = netif->state; if (emac->ops->add_multicast_group == NULL) { return ERR_OK; /* This function is not mandatory */ } @@ -118,17 +119,15 @@ static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t a switch (action) { case NETIF_ADD_MAC_FILTER: { - nsapi_addr_t addrs; - memset((void*)&addrs, 0x00, sizeof(nsapi_addr_t)); uint32_t group32 = ntohl(group->addr[3]); - addrs.version = NSAPI_IPv6; - addrs.bytes[0] = LL_IP6_MULTICAST_ADDR_0; - addrs.bytes[1] = LL_IP6_MULTICAST_ADDR_1; - addrs.bytes[2] = group32 >> 24; - addrs.bytes[3] = group32 >> 16; - addrs.bytes[4] = group32 >> 8; - addrs.bytes[5] = group32; - emac->ops->add_multicast_group(emac, &addrs); + uint8_t addr[6]; + addr[0] = LL_IP6_MULTICAST_ADDR_0; + addr[1] = LL_IP6_MULTICAST_ADDR_1; + addr[2] = group32 >> 24; + addr[3] = group32 >> 16; + addr[4] = group32 >> 8; + addr[5] = group32; + emac->ops->add_multicast_group(emac, addr); return ERR_OK; } case NETIF_DEL_MAC_FILTER: @@ -143,19 +142,19 @@ static err_t mld_mac_filter(struct netif *netif, const ip6_addr_t *group, u8_t a err_t emac_lwip_if_init(struct netif *netif) { int err = ERR_OK; - emac_interface_t *emac = netif->state; + mbed_ipstack_interface_t *emac = netif->state; - emac->ops->set_link_input_cb(emac, emac_lwip_input, netif); - emac->ops->set_link_state_cb(emac, emac_lwip_state_change, netif); + emac->ops->set_link_input_cb(emac->hw, emac_lwip_input, netif); + emac->ops->set_link_state_cb(emac->hw, emac_lwip_state_change, netif); netif->hwaddr_len = emac->ops->get_hwaddr_size(emac); - emac->ops->get_hwaddr(emac, netif->hwaddr); - netif->mtu = emac->ops->get_mtu_size(emac); + emac->ops->get_hwaddr(emac->hw, netif->hwaddr); + netif->mtu = emac->ops->get_mtu_size(emac->hw); /* Interface capabilities */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; - emac->ops->get_ifname(emac, netif->name, 2); + emac->ops->get_ifname(emac->hw, netif->name, 2); #if LWIP_IPV4 netif->output = etharp_output; @@ -177,9 +176,11 @@ err_t emac_lwip_if_init(struct netif *netif) netif->linkoutput = emac_lwip_low_level_output; - if (!emac->ops->power_up(emac)) { + if (!emac->ops->power_up(emac->hw)) { err = ERR_IF; } return err; } + +#endif //!NSAPI_PPP_AVAILABLE diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c index b2f98c32252..415a1087f94 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c @@ -456,9 +456,9 @@ static void packet_tx(void* pvParameters) { * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent */ -static bool k64f_eth_link_out(const emac_interface_t *emac, emac_stack_mem_chain_t *chain) +static bool k64f_eth_link_out(void *hw, emac_stack_mem_chain_t *chain) { - struct k64f_enetdata *enet = emac->hw; + struct k64f_enetdata *enet = hw; emac_stack_mem_t *q; emac_stack_mem_t *temp_pbuf; uint8_t *psend = NULL, *dst; @@ -564,37 +564,38 @@ static void k64f_phy_task(void *data) { } } -static bool k64f_eth_power_up(const emac_interface_t *emac) +static bool k64f_eth_power_up(void *hw) { - char hwaddr[ETH_HWADDR_LEN]; + char hwaddr[K64F_HWADDR_SIZE]; + struct k64f_enetdata *enet = hw; /* Initialize the hardware */ mbed_mac_address(hwaddr); - if (!low_level_init_successful(&k64f_enetdata, hwaddr)) + if (!low_level_init_successful(enet, hwaddr)) return false; - k64f_enetdata.xTXDCountSem = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &xtxdcountsem_attr); - MBED_ASSERT(k64f_enetdata.xTXDCountSem); + enet->xTXDCountSem = osSemaphoreNew(ENET_TX_RING_LEN, ENET_TX_RING_LEN, &xtxdcountsem_attr); + MBED_ASSERT(enet->xTXDCountSem); - k64f_enetdata.TXLockMutex = osMutexNew(&txlock_mutex_attr); - MBED_ASSERT(k64f_enetdata.TXLockMutex); + enet->TXLockMutex = osMutexNew(&txlock_mutex_attr); + MBED_ASSERT(enet->TXLockMutex); - k64f_enetdata.RxReadySem = osSemaphoreNew(UINT16_MAX, 0, &rxreadysem_attr); - MBED_ASSERT(k64f_enetdata.RxReadySem); + enet->RxReadySem = osSemaphoreNew(UINT16_MAX, 0, &rxreadysem_attr); + MBED_ASSERT(enet->RxReadySem); #ifdef LWIP_DEBUG - create_new_thread("k64f_emac_rx_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY, &packet_rx_cb); + create_new_thread("k64f_emac_rx_thread", packet_rx, enet, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY, &packet_rx_cb); #else - create_new_thread("k64f_emac_thread", packet_rx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &packet_rx_cb); + create_new_thread("k64f_emac_thread", packet_rx, enet, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &packet_rx_cb); #endif - k64f_enetdata.TxCleanSem = osSemaphoreNew(UINT16_MAX, 0, &txcleansem_attr); - MBED_ASSERT(k64f_enetdata.TxCleanSem); + enet->TxCleanSem = osSemaphoreNew(UINT16_MAX, 0, &txcleansem_attr); + MBED_ASSERT(enet->TxCleanSem); - create_new_thread("k64f_emac_txclean_thread", packet_tx, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &packet_tx_cb); + create_new_thread("k64f_emac_txclean_thread", packet_tx, enet, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &packet_tx_cb); /* PHY monitoring task */ - create_new_thread("k64f_emac_phy_thread", k64f_phy_task, &k64f_enetdata, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY, &phy_task_cb); + create_new_thread("k64f_emac_phy_thread", k64f_phy_task, enet, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY, &phy_task_cb); /* Allow the PHY task to detect the initial link state and set up the proper flags */ osDelay(10); @@ -603,64 +604,59 @@ static bool k64f_eth_power_up(const emac_interface_t *emac) } -static uint32_t k64f_eth_get_mtu_size(const emac_interface_t *emac) +static uint32_t k64f_eth_get_mtu_size(void *hw) { return K64_ETH_MTU_SIZE; } -static void k64f_eth_get_ifname(const emac_interface_t *emac, char *name, uint8_t size) +static void k64f_eth_get_ifname(void *hw, char *name, uint8_t size) { memcpy(name, K64_ETH_IF_NAME, (size < sizeof(K64_ETH_IF_NAME)) ? size : sizeof(K64_ETH_IF_NAME)); } -static uint8_t k64f_eth_get_hwaddr_size(const emac_interface_t *emac) +static uint8_t k64f_eth_get_hwaddr_size(void *hw) { - return ETH_HWADDR_LEN; + return K64F_HWADDR_SIZE; } -static void k64f_eth_get_hwaddr(const emac_interface_t *emac, uint8_t addr[ETH_HWADDR_LEN]) +static void k64f_eth_get_hwaddr(void *hw, uint8_t *addr) { - mbed_mac_address((char*)addr); + mbed_mac_address((char *)addr); } -static void k64f_eth_set_hwaddr(const emac_interface_t *emac, const uint8_t addr[ETH_HWADDR_LEN]) +static void k64f_eth_set_hwaddr(void *hw, const uint8_t *addr) { /* No-op at this stage */ } -static void k64f_eth_set_link_input_cb(emac_interface_t *emac, const emac_link_input_fn input_cb, void *data) +static void k64f_eth_set_link_input_cb(void *hw, const emac_link_input_fn input_cb, void *data) { - struct k64f_enetdata *enet = emac->hw; + struct k64f_enetdata *enet = hw; enet->emac_link_input_cb = input_cb; enet->emac_link_input_cb_data = data; } -static void k64f_eth_set_link_state_cb(emac_interface_t *emac, const emac_link_state_change_fn state_cb, void *data) +static void k64f_eth_set_link_state_cb(void *hw, const emac_link_state_change_fn state_cb, void *data) { - struct k64f_enetdata *enet = emac->hw; + struct k64f_enetdata *enet = hw; enet->emac_link_state_cb = state_cb; enet->emac_link_state_cb_data = data; } -static void k64f_eth_add_multicast_group(const emac_interface_t *emac, const nsapi_addr_t *addr) +static void k64f_eth_add_multicast_group(void *hw, uint8_t *addr) { - - uint8_t _addr[NSAPI_IP_BYTES]; - for (int i = 0; i < NSAPI_IP_BYTES; i++) { - _addr[i] = addr->bytes[i]; - } - ENET_AddMulticastGroup(ENET, _addr); + ENET_AddMulticastGroup(ENET, addr); } -static void k64f_eth_power_down(const emac_interface_t *emac) +static void k64f_eth_power_down(void *hw) { /* No-op at this stage */ } -const emac_interface_ops_t k64f_eth_emac_ops = { +const emac_interface_ops_t mbed_emac_eth_ops_default = { .get_mtu_size = k64f_eth_get_mtu_size, .get_ifname = k64f_eth_get_ifname, .get_hwaddr_size = k64f_eth_get_hwaddr_size, @@ -674,8 +670,9 @@ const emac_interface_ops_t k64f_eth_emac_ops = { .add_multicast_group = k64f_eth_add_multicast_group }; -emac_interface_t mbed_emac_eth_default = {&k64f_eth_emac_ops, &k64f_enetdata}; - +//emac_interface_t mbed_emac_eth_default = {&k64f_eth_emac_ops, &k64f_enetdata}; +//emac_interface_ops_t mbed_emac_eth_ops_default = {&k64f_eth_emac_ops}; +void *mbed_emac_eth_hw_default = &k64f_enetdata; /** * @} */ diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h index a82d80560dd..796389ce421 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac_config.h @@ -37,6 +37,8 @@ #define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame +#define K64F_HWADDR_SIZE (6) + #define K64_ETH_MTU_SIZE 1500 #define K64_ETH_IF_NAME "en" diff --git a/features/FEATURE_LWIP/lwip-interface/lwip_tools.c b/features/FEATURE_LWIP/lwip-interface/lwip_tools.c index 825a7b20ce6..c1996b7d944 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip_tools.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip_tools.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#if !NSAPI_PPP_AVAILABLE + #include #include @@ -110,3 +112,5 @@ void mbed_lwip_arena_dealloc(struct mbed_lwip_socket *s) { s->in_use = false; } + +#endif //!NSAPI_PPP_AVAILABLE diff --git a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c b/features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.cpp similarity index 62% rename from features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c rename to features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.cpp index 2f1dbec2074..b8649c2b2b6 100644 --- a/features/FEATURE_LWIP/lwip-interface/ipstack_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.cpp @@ -35,11 +35,12 @@ #include "emac_api.h" #include "emac_lwip.h" #include "mbed_ipstack.h" -#include "lwip_tools.h" -#ifdef __cplusplus +#include "mbed_ipstack_lwip.h" +#include "nsapi_stack_lwip.h" + extern "C" { -#endif +#include "lwip_tools.h" static bool mbed_lwip_inited = false; @@ -66,7 +67,8 @@ static const osSemaphoreAttr_t has_addr_sem_attr = { .cb_mem = &has_addr_sem, .cb_size = sizeof(has_addr_sem), }; -osSemaphoreId_t tcpip_inited; + +static osSemaphoreId_t tcpip_inited; static void add_dns_addr(struct netif *lwip_netif) { @@ -112,28 +114,28 @@ static void mbed_lwip_tcpip_init_irq(void *eh) static void mbed_lwip_netif_link_irq(struct netif *netif) { + mbed_ipstack_interface_t *interface = (mbed_ipstack_interface_t *)netif->state; if (netif_is_link_up(netif)) { - emac_interface_t *emac = netif->state; - osSemaphoreRelease(emac->linked); + osSemaphoreRelease(interface->linked); } } static void mbed_lwip_netif_status_irq(struct netif *netif) { static bool any_addr = true; - emac_interface_t *emac = netif->state; + mbed_ipstack_interface_t *interface = (mbed_ipstack_interface_t *)netif->state; if (netif_is_up(netif)) { // Indicates that has address if (any_addr == true && mbed_lwip_get_ip_addr(true, netif)) { - osSemaphoreRelease(emac->has_addr); + osSemaphoreRelease(interface->has_addr); any_addr = false; return; } // Indicates that has preferred address if (mbed_lwip_get_ip_addr(false, netif)) { - osSemaphoreRelease(emac->has_addr); + osSemaphoreRelease(interface->has_addr); } } else { any_addr = true; @@ -149,14 +151,14 @@ static void mbed_lwip_clear_ipv6_addresses(struct netif *netif) } #endif -char *mbed_ipstack_get_mac_address(emac_interface_t *emac) +char *mbed_ipstack_get_mac_address(mbed_ipstack_interface_t *interface) { - return emac->hwaddr; + return interface->hwaddr; } -char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +char *mbed_ipstack_get_ip_address(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { - const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, (struct netif *)emac->netif); + const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &interface->netif); if (!addr) { return NULL; } @@ -173,10 +175,10 @@ char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_ return NULL; } -char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +char *mbed_ipstack_get_netmask(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { #if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_netmask((struct netif *)emac->netif); + const ip4_addr_t *addr = netif_ip4_netmask(&interface->netif); if (!ip4_addr_isany(addr)) { return ip4addr_ntoa_r(addr, buf, buflen); } else { @@ -187,10 +189,10 @@ char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t b #endif } -char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen) +char *mbed_ipstack_get_gateway(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { #if LWIP_IPV4 - const ip4_addr_t *addr = netif_ip4_gw((struct netif *)emac->netif); + const ip4_addr_t *addr = netif_ip4_gw(&interface->netif); if (!ip4_addr_isany(addr)) { return ip4addr_ntoa_r(addr, buf, buflen); } else { @@ -216,72 +218,79 @@ void mbed_ipstack_init(void) mbed_lwip_inited = true; } -nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if) +nsapi_error_t mbed_ipstack_add_ethernet_interface(const emac_interface_ops_t *emac_ops, void *hw, bool default_if, mbed_ipstack_interface_t **interface_out) { - emac->connected = false; - emac->dhcp = true; - emac->linked = osSemaphoreNew(UINT16_MAX, 0, &linked_sem_attr); - emac->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); - mbed_mac_address(emac->hwaddr); - - struct netif *lwip_netif = (struct netif *)malloc(sizeof(struct netif)); - memset(lwip_netif, 0, sizeof(lwip_netif)); - lwip_netif->state = emac; - - emac->netif = (void *)netif_add(lwip_netif, + mbed_ipstack_interface_t *interface = (mbed_ipstack_interface_t *)malloc(sizeof(mbed_ipstack_interface_t)); + if (!interface) { + return NSAPI_ERROR_NO_MEMORY; + } + memset(interface, 0, sizeof(mbed_ipstack_interface_t)); + interface->ops = emac_ops; + interface->hw = hw; + interface->connected = false; + interface->dhcp = true; + interface->linked = osSemaphoreNew(UINT16_MAX, 0, &linked_sem_attr); + interface->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); + mbed_mac_address(interface->hwaddr); + + interface->netif.state = interface; + + if (!netif_add(&interface->netif, #if LWIP_IPV4 0, 0, 0, #endif - emac, emac_lwip_if_init, tcpip_input); - if (!emac->netif) - { + interface, emac_lwip_if_init, tcpip_input)) { return NSAPI_ERROR_DEVICE_ERROR; } if (default_if) - netif_set_default((struct netif *)emac->netif); + netif_set_default(&interface->netif); + + netif_set_link_callback(&interface->netif, mbed_lwip_netif_link_irq); + netif_set_status_callback(&interface->netif, mbed_lwip_netif_status_irq); - netif_set_link_callback((struct netif *)emac->netif, mbed_lwip_netif_link_irq); - netif_set_status_callback((struct netif *)emac->netif, mbed_lwip_netif_status_irq); + *interface_out = interface; return NSAPI_ERROR_OK; } -nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, const char *netmask, const char *gw) +// TODO - PPP equivalent of above + +nsapi_error_t mbed_ipstack_bringup(mbed_ipstack_interface_t *interface, bool dhcp, const char *ip, const char *netmask, const char *gw) { // Check if we've already connected - if (emac->connected) { + if (interface->connected) { return NSAPI_ERROR_PARAMETER; } mbed_ipstack_init(); #if LWIP_IPV6 - netif_create_ip6_linklocal_address((struct netif *)emac->netif, 1/*from MAC*/); + netif_create_ip6_linklocal_address(interface->netif, 1/*from MAC*/); #if LWIP_IPV6_MLD /* * For hardware/netifs that implement MAC filtering. * All-nodes link-local is handled by default, so we must let the hardware know * to allow multicast packets in. * Should set mld_mac_filter previously. */ - if (((struct netif *)emac->netif)->mld_mac_filter != NULL) { + if ((interface->netif)->mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - ((struct netif *)emac->netif)->mld_mac_filter((struct netif *)emac->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + (interface->netif)->mld_mac_filter(interface->netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_AUTOCONFIG /* IPv6 address autoconfiguration not enabled by default */ - ((struct netif *)emac->netif)->ip6_autoconfig_enabled = 1; + interface->netif->ip6_autoconfig_enabled = 1; #endif /* LWIP_IPV6_AUTOCONFIG */ #endif /* LWIP_IPV6 */ u32_t ret; - if (!netif_is_link_up((struct netif *)emac->netif)) { - ret = osSemaphoreAcquire(emac->linked, 15000); + if (!netif_is_link_up(&interface->netif)) { + ret = osSemaphoreAcquire(interface->linked, 15000); if (ret != osOK) { return NSAPI_ERROR_NO_CONNECTION; } @@ -299,18 +308,18 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char return NSAPI_ERROR_PARAMETER; } - netif_set_addr((struct netif *)emac->netif, &ip_addr, &netmask_addr, &gw_addr); + netif_set_addr(&interface->netif, &ip_addr, &netmask_addr, &gw_addr); } #endif - netif_set_up((struct netif *)emac->netif); + netif_set_up(&interface->netif); #if LWIP_IPV4 // Connect to the network - emac->dhcp = dhcp; + interface->dhcp = dhcp; if (dhcp) { - err_t err = dhcp_start((struct netif *)emac->netif); + err_t err = dhcp_start(&interface->netif); if (err) { return NSAPI_ERROR_DHCP_FAILURE; } @@ -318,62 +327,56 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char #endif // If doesn't have address - if (!mbed_lwip_get_ip_addr(true, (struct netif *)emac->netif)) { - ret = osSemaphoreAcquire(emac->has_addr, 15000); + if (!mbed_lwip_get_ip_addr(true, &interface->netif)) { + ret = osSemaphoreAcquire(interface->has_addr, 15000); if (ret != osOK) { return NSAPI_ERROR_DHCP_FAILURE; } - emac->connected = true; + interface->connected = true; } #if ADDR_TIMEOUT // If address is not for preferred stack waits a while to see // if preferred stack address is acquired - if (!mbed_lwip_get_ip_addr(false, (struct netif *)emac->netif)) { - ret = sys_arch_sem_wait(&emac->has_addr, ADDR_TIMEOUT * 1000); + if (!mbed_lwip_get_ip_addr(false, interface->netif)) { + ret = sys_arch_sem_wait(&interface->has_addr, ADDR_TIMEOUT * 1000); } #endif - add_dns_addr((struct netif *)emac->netif); + add_dns_addr(&interface->netif); return 0; } -nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) +nsapi_error_t mbed_ipstack_bringdown(mbed_ipstack_interface_t *interface) { // Check if we've connected - if (!emac->connected) { + if (!interface->connected) { return NSAPI_ERROR_PARAMETER; } #if LWIP_IPV4 // Disconnect from the network - if (emac->dhcp) { - dhcp_release((struct netif *)emac->netif); - dhcp_stop((struct netif *)emac->netif); - emac->dhcp = false; + if (interface->dhcp) { + dhcp_release(&interface->netif); + dhcp_stop(&interface->netif); + interface->dhcp = false; } #endif - netif_set_down((struct netif *)emac->netif); + netif_set_down(&interface->netif); #if LWIP_IPV6 - mbed_lwip_clear_ipv6_addresses((struct netif *)emac->netif); + mbed_lwip_clear_ipv6_addresses(interface->netif); #endif - emac->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); - emac->connected = false; + interface->has_addr = osSemaphoreNew(UINT16_MAX, 0, &has_addr_sem_attr); + interface->connected = false; return 0; } -extern const nsapi_stack_api_t lwip_stack_api; /* Defined in nsapi_stack_lwip.c */ +} // extern "C" -void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack) -{ - stack->emac = emac; - stack->stack_api = &lwip_stack_api; +NetworkStack *mbed_ipstack_get_stack() { + return nsapi_create_stack(&lwip_stack); } - -#ifdef __cplusplus -} -#endif diff --git a/features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.h b/features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.h new file mode 100644 index 00000000000..e2cc195aae2 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/mbed_ipstack_lwip.h @@ -0,0 +1,46 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_IPSTACK_LWIP_H_ +#define MBED_IPSTACK_LWIP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +struct mbed_ipstack_interface { + + /* Members implemented by vendor */ + const emac_interface_ops_t *ops; /**< HW specific emac implementation */ + void *hw; /**< EMAC implementation specific user data */ + + /* Private members used by the stack */ + osSemaphoreId_t linked; + osSemaphoreId_t has_addr; + bool connected; + bool dhcp; + bool ppp; + char hwaddr[6]; + struct netif netif; +}; + +#ifdef __cplusplus +} +#endif + + +#endif /* MBED_IPSTACK_LWIP_H_ */ diff --git a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c index 86bf987bae0..09729d6b801 100644 --- a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c +++ b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.c @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if !NSAPI_PPP_AVAILABLE + #include "nsapi.h" #include "mbed_interface.h" #include "mbed_assert.h" @@ -34,10 +36,7 @@ #include "emac_api.h" #include "lwip_tools.h" - -#ifdef __cplusplus -extern "C" { -#endif +#include "nsapi_stack_lwip.h" static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) { @@ -228,9 +227,9 @@ static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) { // check if network is connected - if (!stack->emac->connected) { - return NSAPI_ERROR_NO_CONNECTION; - } +// if (!stack-> ->emac->connected) { +// return NSAPI_ERROR_NO_CONNECTION; +// } // allocate a socket struct mbed_lwip_socket *s = mbed_lwip_arena_alloc(); @@ -482,7 +481,7 @@ static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, } /* LWIP network stack */ -const nsapi_stack_api_t lwip_stack_api = { +static const nsapi_stack_api_t lwip_stack_api = { .gethostbyname = mbed_lwip_gethostbyname, .add_dns_server = mbed_lwip_add_dns_server, .socket_open = mbed_lwip_socket_open, @@ -499,6 +498,8 @@ const nsapi_stack_api_t lwip_stack_api = { .socket_attach = mbed_lwip_socket_attach, }; -#ifdef __cplusplus -} -#endif +nsapi_stack_t lwip_stack = { + .stack_api = &lwip_stack_api, +}; + +#endif //#if !NSAPI_PPP_AVAILABLE diff --git a/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.h b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.h new file mode 100644 index 00000000000..8a1c292b742 --- /dev/null +++ b/features/FEATURE_LWIP/lwip-interface/nsapi_stack_lwip.h @@ -0,0 +1,31 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NSAPI_STACK_LWIP_H_ +#define NSAPI_STACK_LWIP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern nsapi_stack_t lwip_stack; + +#ifdef __cplusplus +} +#endif + + +#endif /* NSAPI_LWIP_H_ */ diff --git a/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp b/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp index ba506646fb2..0a0140d7e93 100644 --- a/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp +++ b/features/FEATURE_LWIP/lwip-interface/ppp_lwip.cpp @@ -38,7 +38,6 @@ extern "C" { // "pppos.h" is missing extern C #include "nsapi_ppp.h" #include "ppp_lwip.h" -//#include "mbed_ipstack.h" namespace mbed { diff --git a/features/netsocket/EthernetInterface.cpp b/features/netsocket/EthernetInterface.cpp index 12d749e7b07..f0b1a7ff75c 100644 --- a/features/netsocket/EthernetInterface.cpp +++ b/features/netsocket/EthernetInterface.cpp @@ -18,10 +18,9 @@ #include "mbed_ipstack.h" /* Interface implementation */ -EthernetInterface::EthernetInterface(emac_interface_t *emac) - : _dhcp(true), _ip_address(), _netmask(), _gateway(), _stack() +EthernetInterface::EthernetInterface(void) + : _emac_ops(&mbed_emac_eth_ops_default), _hw(mbed_emac_eth_hw_default), _dhcp(true), _ip_address(), _netmask(), _gateway() { - mbed_ipstack_set_stack(emac, &_stack); } nsapi_error_t EthernetInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) @@ -47,17 +46,19 @@ nsapi_error_t EthernetInterface::set_dhcp(bool dhcp) nsapi_error_t EthernetInterface::connect() { nsapi_error_t err; - if (_stack.emac == NULL) { + if (_emac_ops == NULL) { return NSAPI_ERROR_UNSUPPORTED; } + // This checks for double init, so okay mbed_ipstack_init(); - err = mbed_ipstack_add_interface(_stack.emac, true); + // XXX But this will add a second time + err = mbed_ipstack_add_ethernet_interface(_emac_ops, _hw, true, &_interface); if (err != NSAPI_ERROR_OK) { return err; } - return mbed_ipstack_bringup(_stack.emac, _dhcp, + return mbed_ipstack_bringup(_interface, _dhcp, _ip_address[0] ? _ip_address : 0, _netmask[0] ? _netmask : 0, _gateway[0] ? _gateway : 0); @@ -65,17 +66,17 @@ nsapi_error_t EthernetInterface::connect() nsapi_error_t EthernetInterface::disconnect() { - return mbed_ipstack_bringdown(_stack.emac); + return mbed_ipstack_bringdown(_interface); } const char *EthernetInterface::get_mac_address() { - return mbed_ipstack_get_mac_address(_stack.emac); + return mbed_ipstack_get_mac_address(_interface); } const char *EthernetInterface::get_ip_address() { - if (mbed_ipstack_get_ip_address(_stack.emac, _ip_address, sizeof(_ip_address))) { + if (mbed_ipstack_get_ip_address(_interface, _ip_address, sizeof(_ip_address))) { return _ip_address; } @@ -84,7 +85,7 @@ const char *EthernetInterface::get_ip_address() const char *EthernetInterface::get_netmask() { - if (mbed_ipstack_get_netmask(_stack.emac, _netmask, sizeof(_netmask))) { + if (mbed_ipstack_get_netmask(_interface, _netmask, sizeof(_netmask))) { return _netmask; } @@ -93,7 +94,7 @@ const char *EthernetInterface::get_netmask() const char *EthernetInterface::get_gateway() { - if (mbed_ipstack_get_gateway(_stack.emac, _gateway, sizeof(_gateway))) { + if (mbed_ipstack_get_gateway(_interface, _gateway, sizeof(_gateway))) { return _gateway; } @@ -102,5 +103,5 @@ const char *EthernetInterface::get_gateway() NetworkStack *EthernetInterface::get_stack() { - return nsapi_create_stack(&_stack); + return mbed_ipstack_get_stack(); } diff --git a/features/netsocket/EthernetInterface.h b/features/netsocket/EthernetInterface.h index 1ecd6ca3301..d7ceeb5e496 100644 --- a/features/netsocket/EthernetInterface.h +++ b/features/netsocket/EthernetInterface.h @@ -19,7 +19,7 @@ #include "nsapi.h" #include "rtos.h" -#include "hal/emac_api.h" +#include "mbed_ipstack.h" // Forward declaration class NetworkStack; @@ -33,7 +33,7 @@ class EthernetInterface : public NetworkInterface public: /** EthernetInterface lifetime */ - EthernetInterface(emac_interface_t *emac = &mbed_emac_eth_default); + EthernetInterface(void); /** Set a static IP address * @@ -107,11 +107,13 @@ class EthernetInterface : public NetworkInterface */ virtual NetworkStack *get_stack(); + const emac_interface_ops_t *_emac_ops; + void *_hw; + mbed_ipstack_interface_t *_interface; bool _dhcp; char _ip_address[NSAPI_IPv6_SIZE]; char _netmask[NSAPI_IPv4_SIZE]; char _gateway[NSAPI_IPv4_SIZE]; - nsapi_stack_t _stack; }; #endif diff --git a/features/netsocket/mbed_ipstack.c b/features/netsocket/mbed_ipstack.c index febeecefac3..502a78ceba0 100644 --- a/features/netsocket/mbed_ipstack.c +++ b/features/netsocket/mbed_ipstack.c @@ -5,50 +5,51 @@ #include "platform/mbed_toolchain.h" #include "mbed_ipstack.h" -#include "mbed_trace.h" +#if defined(FEATURE_COMMON_PAL) +#include "mbed_trace.h" #define TRACE_GROUP "mbed_ipstack" +#else +#define tr_debug(...) (void(0)) //dummies if feature common pal is not added +#endif //defined(FEATURE_COMMON_PAL) + MBED_WEAK void mbed_ipstack_init(void) { tr_error("Error, this function shouln't be called!"); } -MBED_WEAK nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if) { +MBED_WEAK nsapi_error_t mbed_ipstack_add_ethernet_interface(const emac_interface_ops_t *emac_ops, void *hw, bool default_if, mbed_ipstack_interface_t **interface_out) { tr_error("Error, this function shouln't be called!"); return NSAPI_ERROR_UNSUPPORTED; } -MBED_WEAK void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack) { - tr_error("Error, this function shouln't be called!"); -} - -MBED_WEAK nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, +MBED_WEAK nsapi_error_t mbed_ipstack_bringup(mbed_ipstack_interface_t *interface, bool dhcp, const char *ip, const char *netmask, const char *gw) { tr_error("Error, this function shouln't be called!"); return NSAPI_ERROR_UNSUPPORTED; } -MBED_WEAK nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac) { +MBED_WEAK nsapi_error_t mbed_ipstack_bringdown(mbed_ipstack_interface_t *interface) { tr_error("Error, this function shouln't be called!"); return NSAPI_ERROR_UNSUPPORTED; } -MBED_WEAK char *mbed_ipstack_get_mac_address(emac_interface_t *emac) { +MBED_WEAK char *mbed_ipstack_get_mac_address(mbed_ipstack_interface_t *interface) { tr_error("Error, this function shouln't be called!"); return NULL; } -MBED_WEAK char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { +MBED_WEAK char *mbed_ipstack_get_ip_address(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { tr_error("Error, this function shouln't be called!"); return NULL; } -MBED_WEAK char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { +MBED_WEAK char *mbed_ipstack_get_netmask(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { tr_error("Error, this function shouln't be called!"); return NULL; } -MBED_WEAK char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen) { +MBED_WEAK char *mbed_ipstack_get_gateway(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen) { tr_error("Error, this function shouln't be called!"); return NULL; } diff --git a/features/netsocket/mbed_ipstack.h b/features/netsocket/mbed_ipstack.h index 54109fc572a..ae0a47e9761 100644 --- a/features/netsocket/mbed_ipstack.h +++ b/features/netsocket/mbed_ipstack.h @@ -18,12 +18,15 @@ #define MBED_IPSTACK_H #include "nsapi.h" -#include "emac_api.h" +#include "hal/emac_api.h" #ifdef __cplusplus +#include "NetworkStack.h" extern "C" { #endif +typedef struct mbed_ipstack_interface mbed_ipstack_interface_t; + /** * mbed OS API for IP stack abstraction * @@ -44,18 +47,20 @@ void mbed_ipstack_init(void); * Connects EMAC layer with the IP stack and initializes all the required infrastructure. * This function should be called only once for each available interface. * - * @param emac EMAC HAL implementation for this network interface - * @param default_if true if the interface should be treated as the default one - * @return NSAPI_ERROR_OK on success, or error code + * @param emac_ops EMAC HAL implementation for this network interface + * @param hw EMAC implementation specific user data; will be passed to EMAC ops + * @param default_if true if the interface should be treated as the default one + * @param[out] interface_out set to interface handle that must be passed to subsequent mbed_stack calls + * @return NSAPI_ERROR_OK on success, or error code */ -nsapi_error_t mbed_ipstack_add_interface(emac_interface_t *emac, bool default_if); +nsapi_error_t mbed_ipstack_add_ethernet_interface(const emac_interface_ops_t *emac_ops, void *hw, bool default_if, mbed_ipstack_interface_t **interface_out); /** Connect network stack with the IP stack * * @param emac EMAC HAL implementation * @param stack Pointer to nsapi_stack_t to be set for this interface */ -void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack); +void mbed_ipstack_set_stack(mbed_ipstack_interface_t *interface, nsapi_stack_t *stack); /** Connect the interface to the network * @@ -69,7 +74,7 @@ void mbed_ipstack_set_stack(emac_interface_t *emac, nsapi_stack_t *stack); * @param gw Gateway address to be used for the interface as "W:X:Y:Z" or NULL * @return NSAPI_ERROR_OK on success, or error code */ -nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char *ip, +nsapi_error_t mbed_ipstack_bringup(mbed_ipstack_interface_t *interface, bool dhcp, const char *ip, const char *netmask, const char *gw); /** Disconnect interface from the network @@ -78,14 +83,14 @@ nsapi_error_t mbed_ipstack_bringup(emac_interface_t *emac, bool dhcp, const char * * @return NSAPI_ERROR_OK on success, or error code */ -nsapi_error_t mbed_ipstack_bringdown(emac_interface_t *emac); +nsapi_error_t mbed_ipstack_bringdown(mbed_ipstack_interface_t *interface); /** Return MAC address of the network interface * * @param emac EMAC HAL implementation for this network interface * @return MAC address as "V:W:X:Y:Z" */ -char *mbed_ipstack_get_mac_address(emac_interface_t *emac); +char *mbed_ipstack_get_mac_address(mbed_ipstack_interface_t *interface); /** Copies IP address of the network interface to user supplied buffer * @@ -94,7 +99,7 @@ char *mbed_ipstack_get_mac_address(emac_interface_t *emac); * @param buflen size of supplied buffer * @return Pointer to a buffer, or NULL if the buffer is too small */ -char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_t buflen); +char *mbed_ipstack_get_ip_address(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen); /** Copies netmask of the network interface to user supplied buffer * @@ -103,7 +108,7 @@ char *mbed_ipstack_get_ip_address(emac_interface_t *emac, char *buf, nsapi_size_ * @param buflen size of supplied buffer * @return Pointer to a buffer, or NULL if the buffer is too small */ -char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t buflen); +char *mbed_ipstack_get_netmask(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen); /** Copies gateway address of the network interface to user supplied buffer * @@ -112,10 +117,12 @@ char *mbed_ipstack_get_netmask(emac_interface_t *emac, char *buf, nsapi_size_t b * @param buflen size of supplied buffer * @return Pointer to a buffer, or NULL if the buffer is too small */ -char *mbed_ipstack_get_gateway(emac_interface_t *emac, char *buf, nsapi_size_t buflen); +char *mbed_ipstack_get_gateway(mbed_ipstack_interface_t *interface, char *buf, nsapi_size_t buflen); #ifdef __cplusplus } + +NetworkStack *mbed_ipstack_get_stack(); #endif #endif /* MBED_IPSTACK_H */ diff --git a/features/netsocket/nsapi_types.h b/features/netsocket/nsapi_types.h index 083fa7ca0b0..b1ba404a70d 100644 --- a/features/netsocket/nsapi_types.h +++ b/features/netsocket/nsapi_types.h @@ -253,9 +253,6 @@ typedef struct nsapi_stack { // Internal nsapi buffer unsigned _stack_buffer[16]; - /** EMAC HAL implementation for the network interface - */ - emac_interface_t *emac; } nsapi_stack_t; /** nsapi_stack_api structure diff --git a/hal/emac_api.h b/hal/emac_api.h index 6bd5130a11d..1bd137964f8 100644 --- a/hal/emac_api.h +++ b/hal/emac_api.h @@ -21,20 +21,14 @@ #include "emac_stack_mem.h" #include "cmsis_os.h" -typedef struct emac_interface emac_interface_t; -typedef struct nsapi_addr nsapi_addr_t; -#define ETH_HWADDR_LEN 6 - /** - * EmacInterface + * emac_interface_ops_t * * This interface should be used to abstract low level access to networking hardware + * All operations receive a `void *` hw pointer which an emac device provides when + * it is registered with a stack. */ -/** This structure needs to be defined by targets wishing to provide ethernet driver using EMAC interface. It will - * be used by the EthernetInterface class to initialize the networking subsystem. - */ -extern emac_interface_t mbed_emac_eth_default; /** * Callback to be register with Emac interface and to be called fore received packets @@ -55,97 +49,98 @@ typedef void (*emac_link_state_change_fn)(void *data, bool up); /** * Return maximum transmission unit * - * @param emac Emac interface + * @param hw Emac interface's handle * @return MTU in bytes */ -typedef uint32_t (*emac_get_mtu_size_fn)(const emac_interface_t *emac); +typedef uint32_t (*emac_get_mtu_size_fn)(void *hw); /** * Return interface name * - * @param emac Emac interface + * @param hw Emac interface's handle * @param name Pointer to where the name should be written * @param size Maximum number of character to copy */ -typedef void (*emac_get_ifname_fn)(const emac_interface_t *emac, char *name, uint8_t size); +typedef void (*emac_get_ifname_fn)(void *hw, char *name, uint8_t size); /** * Returns size of the underlying interface HW address size * - * @param emac Emac interface + * @param hw Emac interface's handle * @return HW address size in bytes */ -typedef uint8_t (*emac_get_hwaddr_size_fn)(const emac_interface_t *emac); +typedef uint8_t (*emac_get_hwaddr_size_fn)(void *hw); /** * Return interface hw address * * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size * - * @param emac Emac interface + * @param hw Emac interface's handle * @param addr HW address for underlying interface */ -typedef void (*emac_get_hwaddr_fn)(const emac_interface_t *emac, uint8_t addr[ETH_HWADDR_LEN]); +typedef void (*emac_get_hwaddr_fn)(void *hw, uint8_t *addr); /** * Set HW address for interface * * Provided address has to be of correct size, see @a get_hwaddr_size * - * @param emac Emac interface + * @param hw Emac interface's handle * @param addr Address to be set */ -typedef void (*emac_set_hwaddr_fn)(const emac_interface_t *emac, const uint8_t addr[ETH_HWADDR_LEN]); +typedef void (*emac_set_hwaddr_fn)(void *hw, const uint8_t *addr); /** * Sends the packet over the link * * That can not be called from an interrupt context. * - * @param emac Emac interface + * @param hw Emac interface's handle * @param buf Packet to be send * @return True if the packet was send successfully, False otherwise */ -typedef bool (*emac_link_out_fn)(const emac_interface_t *emac, emac_stack_mem_chain_t *buf); +typedef bool (*emac_link_out_fn)(void *hw, emac_stack_mem_chain_t *buf); /** * Initializes the HW * + * @param hw Emac interface's handle * @return True on success, False in case of an error. */ -typedef bool (*emac_power_up_fn)(const emac_interface_t *emac); +typedef bool (*emac_power_up_fn)(void *hw); /** * Deinitializes the HW * - * @param emac Emac interface + * @param hw Emac interface's handle */ -typedef void (*emac_power_down_fn)(const emac_interface_t *emac); +typedef void (*emac_power_down_fn)(void *hw); /** * Sets a callback that needs to be called for packets received for that interface * - * @param emac Emac interface + * @param hw Emac interface's handle * @param input_cb Function to be register as a callback * @param data Arbitrary user data to be passed to the callback */ -typedef void (*emac_set_link_input_cb_fn)(emac_interface_t *emac, const emac_link_input_fn input_cb, void *data); +typedef void (*emac_set_link_input_cb_fn)(void *hw, emac_link_input_fn input_cb, void *data); /** * Sets a callback that needs to be called on link status changes for given interface * - * @param emac Emac interface + * @param hw Emac interface's handle * @param state_cb Function to be register as a callback - * @param data Arbitrary user data to be passed to the callback + * @param data Arbitrary user data to be passed to the callback */ -typedef void (*emac_set_link_state_cb_fn)(emac_interface_t *emac, const emac_link_state_change_fn state_cb, void *data); +typedef void (*emac_set_link_state_cb_fn)(void *hw, emac_link_state_change_fn state_cb, void *data); /** Add device to a multicast group * - * @param emac Emac interface - * @param address An multicast group address + * @param hw Emac interface's handle + * @param address A multicast group hardware address */ -typedef void (*emac_add_multicast_group)(const emac_interface_t *emac, const nsapi_addr_t *address); +typedef void (*emac_add_multicast_group)(void *hw, uint8_t *address); typedef struct emac_interface_ops { emac_get_mtu_size_fn get_mtu_size; @@ -161,18 +156,10 @@ typedef struct emac_interface_ops { emac_add_multicast_group add_multicast_group; } emac_interface_ops_t; -typedef struct emac_interface { - /* Members implemented by vendor */ - const emac_interface_ops_t *ops; /**< HW specific emac implementation */ - void *hw; /**< EMAC implementation specific user data */ - - /* Private members used by the stack */ - osSemaphoreId_t linked; - osSemaphoreId_t has_addr; - bool connected; - bool dhcp; - char hwaddr[6]; - void *netif; -} emac_interface_t; +/** These need to be defined by targets wishing to provide an Ethernet driver using EMAC interface. It will + * be used by the EthernetInterface class's default constructor to initialise the networking subsystem. + */ +extern const emac_interface_ops_t mbed_emac_eth_ops_default; +extern void *mbed_emac_eth_hw_default; #endif /* MBED_EMAC_API_H */