diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 99e2995ffb..cbfd8baa1a 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -184,6 +184,7 @@ SRC_LIBM = $(addprefix lib/libm/,\ endif EXTMOD_SRC_C = $(addprefix extmod/,\ + modlwip.c \ modonewire.c \ ) @@ -337,6 +338,47 @@ SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\ ) endif +LWIP_DIR = lib/lwip/src +INC += -I$(TOP)/$(LWIP_DIR)/include -Ilwip_inc +$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address +SRC_MOD += $(addprefix $(LWIP_DIR)/,\ + core/def.c \ + core/dns.c \ + core/inet_chksum.c \ + core/init.c \ + core/ip.c \ + core/mem.c \ + core/memp.c \ + core/netif.c \ + core/pbuf.c \ + core/raw.c \ + core/stats.c \ + core/sys.c \ + core/tcp.c \ + core/tcp_in.c \ + core/tcp_out.c \ + core/timeouts.c \ + core/udp.c \ + core/ipv4/autoip.c \ + core/ipv4/dhcp.c \ + core/ipv4/etharp.c \ + core/ipv4/icmp.c \ + core/ipv4/igmp.c \ + core/ipv4/ip4_addr.c \ + core/ipv4/ip4.c \ + core/ipv4/ip4_frag.c \ + core/ipv6/dhcp6.c \ + core/ipv6/ethip6.c \ + core/ipv6/icmp6.c \ + core/ipv6/inet6.c \ + core/ipv6/ip6_addr.c \ + core/ipv6/ip6.c \ + core/ipv6/ip6_frag.c \ + core/ipv6/mld6.c \ + core/ipv6/nd6.c \ + netif/ethernet.c \ + ) + OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) diff --git a/ports/stm32/lwip_inc/arch/cc.h b/ports/stm32/lwip_inc/arch/cc.h new file mode 100644 index 0000000000..635b1c8056 --- /dev/null +++ b/ports/stm32/lwip_inc/arch/cc.h @@ -0,0 +1,8 @@ +#ifndef MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H +#define MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H + +#include +#define LWIP_PLATFORM_DIAG(x) +#define LWIP_PLATFORM_ASSERT(x) { assert(1); } + +#endif // MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H diff --git a/ports/stm32/lwip_inc/arch/sys_arch.h b/ports/stm32/lwip_inc/arch/sys_arch.h new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/ports/stm32/lwip_inc/arch/sys_arch.h @@ -0,0 +1 @@ +// empty diff --git a/ports/stm32/lwip_inc/lwipopts.h b/ports/stm32/lwip_inc/lwipopts.h new file mode 100644 index 0000000000..b8ab8a2ab0 --- /dev/null +++ b/ports/stm32/lwip_inc/lwipopts.h @@ -0,0 +1,61 @@ +#ifndef MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H +#define MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H + +#include + +#define NO_SYS 1 +#define SYS_LIGHTWEIGHT_PROT 1 +#define MEM_ALIGNMENT 4 + +#define LWIP_CHKSUM_ALGORITHM 3 + +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_STATS 0 +#define LWIP_NETIF_HOSTNAME 1 + +#define LWIP_IPV6 0 +#define LWIP_DHCP 1 +#define LWIP_DHCP_CHECK_LINK_UP 1 +#define LWIP_DNS 1 +#define LWIP_IGMP 1 + +#define SO_REUSE 1 + +extern uint32_t rng_get(void); +#define LWIP_RAND() rng_get() + +// default +// lwip takes 15800 bytes; TCP d/l: 380k/s local, 7.2k/s remote +// TCP u/l is very slow + +#if 0 +// lwip takes 19159 bytes; TCP d/l and u/l are around 320k/s on local network +#define MEM_SIZE (5000) +#define TCP_WND (4 * TCP_MSS) +#define TCP_SND_BUF (4 * TCP_MSS) +#endif + +#if 1 +// lwip takes 26700 bytes; TCP dl/ul are around 750/600 k/s on local network +#define MEM_SIZE (8000) +#define TCP_MSS (800) +#define TCP_WND (8 * TCP_MSS) +#define TCP_SND_BUF (8 * TCP_MSS) +#define MEMP_NUM_TCP_SEG (32) +#endif + +#if 0 +// lwip takes 45600 bytes; TCP dl/ul are around 1200/1000 k/s on local network +#define MEM_SIZE (16000) +#define TCP_MSS (1460) +#define TCP_WND (8 * TCP_MSS) +#define TCP_SND_BUF (8 * TCP_MSS) +#define MEMP_NUM_TCP_SEG (32) +#endif + +typedef uint32_t sys_prot_t; + +#endif // MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 460a19ccb1..44f5b05c45 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -34,6 +34,7 @@ #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" +#include "lwip/init.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" @@ -512,6 +513,12 @@ void stm32_main(uint32_t reset_mode) { sdcard_init(); #endif storage_init(); + #if MICROPY_PY_LWIP + // lwIP doesn't allow to reinitialise itself by subsequent calls to this function + // because the system timeout list (next_timeout) is only ever reset by BSS clearing. + // So for now we only init the lwIP stack once on power-up. + lwip_init(); + #endif soft_reset: @@ -726,6 +733,9 @@ soft_reset_exit: storage_flush(); printf("PYB: soft reboot\n"); + #if MICROPY_PY_NETWORK + mod_network_deinit(); + #endif timer_deinit(); uart_deinit(); #if MICROPY_HW_ENABLE_CAN diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 6421745325..156c73572e 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -30,10 +30,34 @@ #include "py/objlist.h" #include "py/runtime.h" +#include "py/mphal.h" #include "modnetwork.h" #if MICROPY_PY_NETWORK +#if MICROPY_PY_LWIP + +#include "lwip/netif.h" +#include "lwip/timeouts.h" + +u32_t sys_now(void) { + return mp_hal_ticks_ms(); +} + +void pyb_lwip_poll(void) { + // Poll all the NICs for incoming data + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + if (netif->flags & NETIF_FLAG_LINK_UP) { + mod_network_nic_type_t *nic = netif->state; + nic->poll_callback(nic, netif); + } + } + // Run the lwIP internal updates + sys_check_timeouts(); +} + +#endif + /// \module network - network configuration /// /// This module provides network drivers and routing configuration. @@ -42,6 +66,15 @@ void mod_network_init(void) { mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); } +void mod_network_deinit(void) { + #if MICROPY_PY_LWIP + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + netif_remove(netif); + } + // TODO there may be some timeouts that are still pending... + #endif +} + void mod_network_register_nic(mp_obj_t nic) { for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { diff --git a/ports/stm32/modnetwork.h b/ports/stm32/modnetwork.h index 6796b087a4..af46a54a65 100644 --- a/ports/stm32/modnetwork.h +++ b/ports/stm32/modnetwork.h @@ -35,6 +35,17 @@ #define MOD_NETWORK_SOCK_DGRAM (2) #define MOD_NETWORK_SOCK_RAW (3) +#if MICROPY_PY_LWIP + +struct netif; + +typedef struct _mod_network_nic_type_t { + mp_obj_type_t base; + void (*poll_callback)(void *data, struct netif *netif); +} mod_network_nic_type_t; + +#else + struct _mod_network_socket_obj_t; typedef struct _mod_network_nic_type_t { @@ -73,10 +84,13 @@ typedef struct _mod_network_socket_obj_t { }; } mod_network_socket_obj_t; +#endif + extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; extern const mod_network_nic_type_t mod_network_nic_type_cc3k; void mod_network_init(void); +void mod_network_deinit(void); void mod_network_register_nic(mp_obj_t nic); mp_obj_t mod_network_find_nic(const uint8_t *ip); diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c index 0c663437e3..715faa3c4b 100644 --- a/ports/stm32/modusocket.c +++ b/ports/stm32/modusocket.c @@ -35,7 +35,7 @@ #include "lib/netutils/netutils.h" #include "modnetwork.h" -#if MICROPY_PY_USOCKET +#if MICROPY_PY_USOCKET && !MICROPY_PY_LWIP /******************************************************************************/ // socket class @@ -465,4 +465,4 @@ const mp_obj_module_t mp_module_usocket = { .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, }; -#endif // MICROPY_PY_USOCKET +#endif // MICROPY_PY_USOCKET && !MICROPY_PY_LWIP diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 72744f04b1..115006367c 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -192,12 +192,21 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define STM_BUILTIN_MODULE #endif -#if MICROPY_PY_USOCKET +#if MICROPY_PY_USOCKET && MICROPY_PY_LWIP +// usocket implementation provided by lwIP +#define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_lwip) }, +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_lwip) }, +#define SOCKET_POLL extern void pyb_lwip_poll(void); pyb_lwip_poll(); +#elif MICROPY_PY_USOCKET +// usocket implementation provided by skeleton wrapper #define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, #define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, +#define SOCKET_POLL #else +// no usocket module #define SOCKET_BUILTIN_MODULE #define SOCKET_BUILTIN_MODULE_WEAK_LINKS +#define SOCKET_POLL #endif #if MICROPY_PY_NETWORK @@ -313,6 +322,7 @@ static inline mp_uint_t disable_irq(void) { do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ + SOCKET_POLL \ if (pyb_thread_enabled) { \ MP_THREAD_GIL_EXIT(); \ pyb_thread_yield(); \ @@ -328,6 +338,7 @@ static inline mp_uint_t disable_irq(void) { do { \ extern void mp_handle_pending(void); \ mp_handle_pending(); \ + SOCKET_POLL \ __WFI(); \ } while (0);