From 62e650f2c2a8751ccdaa44be2c903f506297d9b5 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 21 Jun 2023 17:08:58 +0200 Subject: [PATCH] renesas-ra: Add networking support using lwIP. Signed-off-by: iabdalkader --- ports/renesas-ra/Makefile | 3 +- ports/renesas-ra/lwip_inc/arch/cc.h | 10 +++ ports/renesas-ra/lwip_inc/arch/sys_arch.h | 1 + ports/renesas-ra/lwip_inc/lwipopts.h | 54 +++++++++++++++++ ports/renesas-ra/main.c | 26 ++++++++ ports/renesas-ra/mpconfigport.h | 39 ++++++++++++ ports/renesas-ra/mpnetworkport.c | 74 +++++++++++++++++++++++ 7 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 ports/renesas-ra/lwip_inc/arch/cc.h create mode 100644 ports/renesas-ra/lwip_inc/arch/sys_arch.h create mode 100644 ports/renesas-ra/lwip_inc/lwipopts.h create mode 100644 ports/renesas-ra/mpnetworkport.c diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile index 50a710053..54d69691e 100644 --- a/ports/renesas-ra/Makefile +++ b/ports/renesas-ra/Makefile @@ -72,7 +72,7 @@ INC += -I$(TOP)/$(HAL_DIR)/ra/fsp/src/bsp/cmsis/Device/RENESAS/Include INC += -I$(TOP)/lib/tinyusb/hw INC += -I$(TOP)/lib/tinyusb/src INC += -I$(TOP)/shared/tinyusb -#INC += -Ilwip_inc +INC += -Ilwip_inc ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),RA4M1 RA4W1 RA6M1 RA6M2 RA6M5)) INC += -Ira endif @@ -305,6 +305,7 @@ SRC_C += \ ra_it.c \ rng.c \ mphalport.c \ + mpnetworkport.c \ mpthreadport.c \ irq.c \ pendsv.c \ diff --git a/ports/renesas-ra/lwip_inc/arch/cc.h b/ports/renesas-ra/lwip_inc/arch/cc.h new file mode 100644 index 000000000..c31e54e9d --- /dev/null +++ b/ports/renesas-ra/lwip_inc/arch/cc.h @@ -0,0 +1,10 @@ +#ifndef MICROPY_INCLUDED_RP2_LWIP_ARCH_CC_H +#define MICROPY_INCLUDED_RP2_LWIP_ARCH_CC_H + +#include +#define LWIP_PLATFORM_DIAG(x) +#define LWIP_PLATFORM_ASSERT(x) { assert(1); } + +#define LWIP_NO_CTYPE_H 1 + +#endif // MICROPY_INCLUDED_RP2_LWIP_ARCH_CC_H diff --git a/ports/renesas-ra/lwip_inc/arch/sys_arch.h b/ports/renesas-ra/lwip_inc/arch/sys_arch.h new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/ports/renesas-ra/lwip_inc/arch/sys_arch.h @@ -0,0 +1 @@ +// empty diff --git a/ports/renesas-ra/lwip_inc/lwipopts.h b/ports/renesas-ra/lwip_inc/lwipopts.h new file mode 100644 index 000000000..036da9bce --- /dev/null +++ b/ports/renesas-ra/lwip_inc/lwipopts.h @@ -0,0 +1,54 @@ +#ifndef MICROPY_INCLUDED_RA_LWIP_LWIPOPTS_H +#define MICROPY_INCLUDED_RA_LWIP_LWIPOPTS_H + +#include + +// This protection is not needed, instead protect lwIP code with flags +#define SYS_ARCH_DECL_PROTECT(lev) do { } while (0) +#define SYS_ARCH_PROTECT(lev) do { } while (0) +#define SYS_ARCH_UNPROTECT(lev) do { } while (0) + +#define NO_SYS 1 +#define SYS_LIGHTWEIGHT_PROT 1 +#define MEM_ALIGNMENT 4 + +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_CHECKSUM_CTRL_PER_NETIF 1 + +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_RAW 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 DHCP_DOES_ARP_CHECK 0 // to speed DHCP up +#define LWIP_DNS 1 +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define LWIP_MDNS_RESPONDER 1 +#define LWIP_IGMP 1 + +#define LWIP_NUM_NETIF_CLIENT_DATA LWIP_MDNS_RESPONDER +#define MEMP_NUM_UDP_PCB (4 + LWIP_MDNS_RESPONDER) +#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + LWIP_MDNS_RESPONDER) + +#define SO_REUSE 1 +#define TCP_LISTEN_BACKLOG 1 + +extern uint32_t rng_read(void); +#define LWIP_RAND() rng_read() + +// lwip takes 26700 bytes +#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) + +typedef uint32_t sys_prot_t; + +#endif // MICROPY_INCLUDED_RA_LWIP_LWIPOPTS_H diff --git a/ports/renesas-ra/main.c b/ports/renesas-ra/main.c index 65ff76bb7..c4cb7cc9d 100644 --- a/ports/renesas-ra/main.c +++ b/ports/renesas-ra/main.c @@ -63,10 +63,15 @@ #include "rtc.h" #include "storage.h" #include "tusb.h" +#if MICROPY_PY_LWIP +#include "lwip/init.h" +#include "lwip/apps/mdns.h" +#endif #if MICROPY_PY_BLUETOOTH #include "mpbthciport.h" #include "extmod/modbluetooth.h" #endif +#include "extmod/modnetwork.h" #define RA_EARLY_PRINT 1 /* for enabling mp_print in boardctrl. */ @@ -274,6 +279,16 @@ int main(void) { MICROPY_BOARD_BEFORE_SOFT_RESET_LOOP(&state); + #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(); + #if LWIP_MDNS_RESPONDER + mdns_resp_init(); + #endif + #endif + soft_reset: MICROPY_BOARD_TOP_SOFT_RESET_LOOP(&state); @@ -320,6 +335,14 @@ soft_reset: machine_i2s_init0(); #endif + #if MICROPY_PY_NETWORK + mod_network_init(); + #endif + + #if MICROPY_PY_LWIP + mod_network_lwip_init(); + #endif + // Initialise the local flash filesystem. // Create it if needed, mount in on /flash, and set it as current dir. bool mounted_flash = false; @@ -393,6 +416,9 @@ soft_reset_exit: #if MICROPY_PY_BLUETOOTH mp_bluetooth_deinit(); #endif + #if MICROPY_PY_NETWORK + mod_network_deinit(); + #endif soft_timer_deinit(); timer_deinit(); uart_deinit_all(); diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index 27a0f21e5..46320a838 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -126,6 +126,7 @@ #define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1) #define MICROPY_PY_TIME_TIME_TIME_NS (1) #define MICROPY_PY_TIME_INCLUDEFILE "ports/renesas-ra/modtime.c" +#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) #ifndef MICROPY_PY_MACHINE #define MICROPY_PY_MACHINE (1) #ifndef MICROPY_PY_MACHINE_BITSTREAM @@ -168,6 +169,25 @@ #define MICROPY_FATFS_MAX_SS (FLASH_SECTOR_SIZE) #endif +// By default networking should include sockets, ssl, websockets, webrepl, dupterm. +#if MICROPY_PY_NETWORK +#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT +#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-ra" +#endif +#ifndef MICROPY_PY_USOCKET +#define MICROPY_PY_USOCKET (1) +#endif +#ifndef MICROPY_PY_USSL +#define MICROPY_PY_USSL (1) +#endif +#ifndef MICROPY_PY_UWEBSOCKET +#define MICROPY_PY_UWEBSOCKET (1) +#endif +#ifndef MICROPY_PY_WEBREPL +#define MICROPY_PY_WEBREPL (1) +#endif +#endif + #if MICROPY_PY_MACHINE #define MACHINE_BUILTIN_MODULE_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, @@ -181,6 +201,21 @@ #define MP_STATE_PORT MP_STATE_VM +#if MICROPY_PY_NETWORK_ESP_HOSTED +extern const struct _mp_obj_type_t mod_network_esp_hosted_type; +#define MICROPY_HW_NIC_ESP_HOSTED { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_esp_hosted_type) }, +#else +#define MICROPY_HW_NIC_ESP_HOSTED +#endif + +#ifndef MICROPY_BOARD_NETWORK_INTERFACES +#define MICROPY_BOARD_NETWORK_INTERFACES +#endif + +#define MICROPY_PORT_NETWORK_INTERFACES \ + MICROPY_HW_NIC_ESP_HOSTED \ + MICROPY_BOARD_NETWORK_INTERFACES \ + // Miscellaneous settings #ifndef MICROPY_HW_USB_VID @@ -269,6 +304,10 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_THREAD_YIELD() #endif +#define MICROPY_PY_LWIP_ENTER +#define MICROPY_PY_LWIP_REENTER +#define MICROPY_PY_LWIP_EXIT + #ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1) #endif diff --git a/ports/renesas-ra/mpnetworkport.c b/ports/renesas-ra/mpnetworkport.c new file mode 100644 index 000000000..2bc6bf439 --- /dev/null +++ b/ports/renesas-ra/mpnetworkport.c @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Arduino SA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "shared/runtime/softtimer.h" + +#if MICROPY_PY_LWIP + +#include "lwip/timeouts.h" + +static mp_sched_node_t network_poll_node; +static soft_timer_entry_t network_timer; + +u32_t sys_now(void) { + return mp_hal_ticks_ms(); +} + +static void network_poll(mp_sched_node_t *node) { + // Run the lwIP internal updates + sys_check_timeouts(); + + #if MICROPY_PY_NETWORK_ESP_HOSTED + extern int esp_hosted_wifi_poll(void); + // Poll the NIC for incoming data + if (esp_hosted_wifi_poll() == -1) { + soft_timer_remove(&network_timer); + } + #endif +} + +void mod_network_poll_events(void) { + mp_sched_schedule_node(&network_poll_node, network_poll); +} + +static void network_timer_callback(soft_timer_entry_t *self) { + mod_network_poll_events(); +} + +void mod_network_lwip_init(void) { + static bool timer_started = false; + if (timer_started) { + soft_timer_remove(&network_timer); + timer_started = false; + } + // Start poll timer. + soft_timer_static_init(&network_timer, SOFT_TIMER_MODE_PERIODIC, 128, network_timer_callback); + soft_timer_reinsert(&network_timer, 128); + timer_started = true; +} +#endif // MICROPY_PY_LWIP