stm32: Integrate lwIP as implementation of usocket module.
This patch allows to use lwIP as the implementation of the usocket module, instead of the existing socket-multiplexer that delegates the entire TCP/IP layer to the NIC itself. This is disabled by default, and enabled by defining MICROPY_PY_LWIP to 1. When enabled, the lwIP TCP/IP stack will be included in the build with default settings for memory usage and performance (see lwip_inc/lwipopts.h). It is then up to a particular NIC to register itself with lwIP using the standard lwIP netif API.
This commit is contained in:
parent
41766ba7e6
commit
cda964198a
|
@ -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))
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H
|
||||
#define MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H
|
||||
|
||||
#include <assert.h>
|
||||
#define LWIP_PLATFORM_DIAG(x)
|
||||
#define LWIP_PLATFORM_ASSERT(x) { assert(1); }
|
||||
|
||||
#endif // MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H
|
|
@ -0,0 +1 @@
|
|||
// empty
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H
|
||||
#define MICROPY_INCLUDED_STM32_LWIP_LWIPOPTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue