From abd2ddbf632fe63c205329be625f71d40b682101 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Apr 2023 21:20:56 +0200 Subject: [PATCH 1/5] NINAW10: Add a network.NinaW10 class supporting external NINA modules. It is possible to attach the network module shall be attached as separate board. Therefore, the WLAN class is to be extended allowing to define the connections. See separate PR. - Add the NINA W10 drivers and networking wlan = network.NinaW10(, *, spi=SPI, cs=CS_pin, busy=Busy_pin, reset=RST_pin) The keywords are optional, unless only wiring is to be set. But then all pins and spi must be provided. All parameters must be objects of the respective types. The signal names are those used by Adafruit airlift modules. The constructor wlan = network.WLAN() can still be used, if the default wiring for a board/WLAN module is used. Signed-off-by: robert-hh --- drivers/ninaw10/nina_wifi_bsp.c | 136 +++++++++++++++++++++++++------- drivers/ninaw10/nina_wifi_drv.h | 9 +++ extmod/network_ninaw10.c | 41 +++++++++- 3 files changed, 154 insertions(+), 32 deletions(-) diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index c65fb111fb101..966e96f53bd04 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -37,6 +37,7 @@ #include "py/runtime.h" #include "modmachine.h" #include "extmod/machine_spi.h" +#include "extmod/virtpin.h" #include "mpconfigboard.h" #include "nina_bsp.h" @@ -48,45 +49,122 @@ #define debug_printf(...) #endif +#define PIN_NOT_SET ((mp_hal_pin_obj_t)0xffffffff) + +nina_wiring_t nina_wiring = { + NULL, + PIN_NOT_SET, + PIN_NOT_SET, + PIN_NOT_SET, + PIN_NOT_SET, +}; + +void nina_bsp_wiring(mp_obj_type_t *spi, mp_obj_type_t *cs, mp_obj_type_t *ack, mp_obj_type_t *reset) { + // Set the default values + nina_wiring.spi = NULL; + + #if defined MICROPY_HW_NINA_GPIO1 + nina_wiring.cs = MICROPY_HW_NINA_GPIO1; + #elif defined MICROPY_HW_NINA_CS + nina_wiring.cs = MICROPY_HW_NINA_CS; + #else + nina_wiring.cs = PIN_NOT_SET; + #endif + + #ifdef MICROPY_HW_NINA_ACK + nina_wiring.ack = MICROPY_HW_NINA_ACK; + #else + nina_wiring.ack = PIN_NOT_SET; + #endif + + #ifdef MICROPY_HW_NINA_RESET + nina_wiring.reset = MICROPY_HW_NINA_RESET; + #else + nina_wiring.reset = PIN_NOT_SET; + #endif + + // Check for dedicated settings. + if (spi != mp_const_none) { + if (mp_obj_is_type(spi, &machine_spi_type)) { + nina_wiring.spi = spi; + } else { + mp_raise_TypeError(MP_ERROR_TEXT("not an SPI object")); + } + } + if (cs != mp_const_none) { + nina_wiring.cs = mp_hal_get_pin_obj(cs); + } + if (ack != mp_const_none) { + nina_wiring.ack = mp_hal_get_pin_obj(ack); + } + if (reset != mp_const_none) { + nina_wiring.reset = mp_hal_get_pin_obj(reset); + } + + if (nina_wiring.cs == PIN_NOT_SET || nina_wiring.ack == PIN_NOT_SET || nina_wiring.reset == PIN_NOT_SET) { + mp_raise_ValueError(MP_ERROR_TEXT("cs, busy or reset not set")); + } +} + int nina_bsp_init(void) { - mp_hal_pin_output(MICROPY_HW_NINA_GPIO1); - mp_hal_pin_input(MICROPY_HW_NINA_ACK); - mp_hal_pin_output(MICROPY_HW_NINA_RESET); - mp_hal_pin_output(MICROPY_HW_NINA_GPIO0); + mp_hal_pin_output(nina_wiring.cs); + mp_hal_pin_input(nina_wiring.ack); + mp_hal_pin_output(nina_wiring.reset); + if (nina_wiring.gpio0 != PIN_NOT_SET) { + mp_hal_pin_input(nina_wiring.gpio0); + } // Reset module in WiFi mode - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1); + mp_hal_pin_write(nina_wiring.cs, 1); - mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); + mp_hal_pin_write(nina_wiring.reset, 0); mp_hal_delay_ms(100); - mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1); + mp_hal_pin_write(nina_wiring.reset, 1); mp_hal_delay_ms(750); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 0); - mp_hal_pin_input(MICROPY_HW_NINA_GPIO0); - // Initialize SPI. - mp_obj_t args[] = { - MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_ID), - MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE), - }; - - MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 0, args); + if (nina_wiring.spi == NULL) { + // use the hard-coded setting + #ifdef MICROPY_HW_WIFI_SPI_ID + #ifdef MICROPY_HW_WIFI_SPI_SCK + mp_obj_t sck_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_SCK); + mp_obj_t miso_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_MISO); + mp_obj_t mosi_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_MOSI); + mp_obj_t args[] = { + MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_ID), + MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE), + MP_ROM_QSTR(MP_QSTR_sck), mp_pin_make_new(NULL, 1, 0, &sck_obj), + MP_ROM_QSTR(MP_QSTR_miso), mp_pin_make_new(NULL, 1, 0, &miso_obj), + MP_ROM_QSTR(MP_QSTR_mosi), mp_pin_make_new(NULL, 1, 0, &mosi_obj), + }; + MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)( + (mp_obj_t)&machine_spi_type, 2, 3, args); + #else // MICROPY_HW_WIFI_SPI_SCK + mp_obj_t args[] = { + MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_ID), + MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE), + }; + MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)( + (mp_obj_t)&machine_spi_type, 2, 0, args); + #endif // MICROPY_HW_WIFI_SPI_SCK + #else // MICROPY_HW_WIFI_SPI_ID + mp_raise_ValueError(MP_ERROR_TEXT("no NINA wiring defined")); + #endif // MICROPY_HW_WIFI_SPI_ID + } else { + MP_STATE_PORT(mp_wifi_spi) = (struct _machine_spi_obj_t *)nina_wiring.spi; + } return 0; } int nina_bsp_deinit(void) { - mp_hal_pin_output(MICROPY_HW_NINA_GPIO1); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); + mp_hal_pin_output(nina_wiring.cs); + mp_hal_pin_write(nina_wiring.cs, 1); - mp_hal_pin_output(MICROPY_HW_NINA_RESET); - mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); + mp_hal_pin_output(nina_wiring.reset); + mp_hal_pin_write(nina_wiring.reset, 0); mp_hal_delay_ms(100); - mp_hal_pin_output(MICROPY_HW_NINA_GPIO0); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1); return 0; } @@ -105,24 +183,24 @@ int nina_bsp_atomic_exit(void) { } int nina_bsp_read_irq(void) { - return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0); + return nina_wiring.gpio0 != PIN_NOT_SET ? mp_hal_pin_read(nina_wiring.gpio0) : 1; } int nina_bsp_spi_slave_select(uint32_t timeout) { // Wait for ACK to go low. - for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(MICROPY_HW_NINA_ACK) == 1; mp_hal_delay_ms(1)) { + for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(nina_wiring.ack) == 1; mp_hal_delay_ms(1)) { if (timeout && ((mp_hal_ticks_ms() - start) >= timeout)) { return -1; } } // Chip select. - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 0); + mp_hal_pin_write(nina_wiring.cs, 0); // Wait for ACK to go high. - for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(MICROPY_HW_NINA_ACK) == 0; mp_hal_delay_ms(1)) { + for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(nina_wiring.ack) == 0; mp_hal_delay_ms(1)) { if ((mp_hal_ticks_ms() - start) >= 100) { - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); + mp_hal_pin_write(nina_wiring.cs, 1); return -1; } } @@ -131,7 +209,7 @@ int nina_bsp_spi_slave_select(uint32_t timeout) { } int nina_bsp_spi_slave_deselect(void) { - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); + mp_hal_pin_write(nina_wiring.cs, 1); return 0; } diff --git a/drivers/ninaw10/nina_wifi_drv.h b/drivers/ninaw10/nina_wifi_drv.h index 4b09ac8bd24ab..197212dedeeeb 100644 --- a/drivers/ninaw10/nina_wifi_drv.h +++ b/drivers/ninaw10/nina_wifi_drv.h @@ -105,6 +105,14 @@ typedef struct { uint8_t bssid[NINA_MAC_ADDR_LEN]; } nina_netinfo_t; +typedef struct { + mp_obj_type_t *spi; + mp_hal_pin_obj_t cs; + mp_hal_pin_obj_t ack; + mp_hal_pin_obj_t reset; + mp_hal_pin_obj_t gpio0; +} nina_wiring_t; + typedef int (*nina_scan_callback_t)(nina_scan_result_t *, void *); int nina_init(void); @@ -140,4 +148,5 @@ int nina_socket_poll(int fd, uint8_t *flags); int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint16_t optlen); int nina_socket_getsockopt(int fd, uint32_t level, uint32_t opt, void *optval, uint16_t optlen); int nina_socket_getpeername(int fd, uint8_t *ip, uint16_t *port); +void nina_bsp_wiring(mp_obj_type_t *spi, mp_obj_type_t *cs, mp_obj_type_t *ack, mp_obj_type_t *reset); #endif // MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 00f53eff137a8..0a7d0be317906 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -145,19 +145,45 @@ STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_timer_callback_obj, network_ninaw10_timer_callback); -STATIC mp_obj_t network_ninaw10_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); +STATIC mp_obj_t network_ninaw10_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_interface, ARG_spi, ARG_cs, ARG_busy, ARG_reset }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_interface, MP_ARG_INT, {.u_int = MOD_NETWORK_STA_IF} }, + { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_busy, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_obj_t nina_obj; - if (n_args == 0 || mp_obj_get_int(args[0]) == MOD_NETWORK_STA_IF) { + if (args[ARG_interface].u_int == MOD_NETWORK_STA_IF) { nina_obj = MP_OBJ_FROM_PTR(&network_nina_wl_sta); } else { nina_obj = MP_OBJ_FROM_PTR(&network_nina_wl_ap); } + nina_bsp_wiring(args[ARG_spi].u_obj, args[ARG_cs].u_obj, args[ARG_busy].u_obj, args[ARG_reset].u_obj); + // Register with network module mod_network_register_nic(nina_obj); return nina_obj; } +STATIC mp_obj_t network_wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_interface }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_interface, MP_ARG_INT, {.u_int = MOD_NETWORK_STA_IF} }, + }; + // Just use the shim to check the argument and reject forbidden ones. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // Everything else is done in network_ninaw10_make_new() + return network_ninaw10_make_new(type, n_args, n_kw, all_args); +} + + STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) { nina_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (n_args == 2) { @@ -851,6 +877,15 @@ MP_DEFINE_CONST_OBJ_TYPE( protocol, &mod_network_nic_protocol_nina ); +MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_wlan, + MP_QSTR_wlan, + MP_TYPE_FLAG_NONE, + make_new, network_wlan_make_new, + locals_dict, &nina_locals_dict, + protocol, &mod_network_nic_protocol_nina + ); + MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi); MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer); MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list); From 5b009f117e67c9089b47e968d7b1d9a8db8e80e7 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Apr 2023 21:26:28 +0200 Subject: [PATCH 2/5] samd/WLAN: Adapt the SAMD port files to support NINA base WLAN. Including changes to the make and configuration files, and changes to main.c and adding mbedtls config files. The code area for samd51x20 devices is increased to 512k. Signed-off-by: robert-hh --- ports/samd/Makefile | 5 +- .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json | 3 ++ ports/samd/main.c | 17 +++++++ ports/samd/mbedtls/mbedtls_config.h | 35 ++++++++++++++ ports/samd/mbedtls/mbedtls_port.c | 41 +++++++++++++++++ ports/samd/mcu/samd51/manifest_net.py | 8 ++++ ports/samd/mcu/samd51/mpconfigmcu.h | 3 ++ ports/samd/mcu/samd51/mpconfigmcu.mk | 40 ++++++++++++++++ ports/samd/mpconfigport.h | 46 +++++++++++++++++++ 9 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 ports/samd/mbedtls/mbedtls_config.h create mode 100644 ports/samd/mbedtls/mbedtls_port.c create mode 100644 ports/samd/mcu/samd51/manifest_net.py diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 6dd71bd93f4c5..03807880b67c2 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -65,7 +65,7 @@ CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU) -fsingle CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ CFLAGS += $(CFLAGS_EXTRA) -CFLAGS += -DMICROPY_HW_CODESIZE=$(MICROPY_HW_CODESIZE) +CFLAGS += -DMICROPY_HW_CODESIZE=$(strip $(subst K,' ', $(MICROPY_HW_CODESIZE))) LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref LDFLAGS += --defsym=_codesize=$(MICROPY_HW_CODESIZE) @@ -194,6 +194,9 @@ OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o)) +query-variants: + $(ECHO) "VARIANTS:" $(BOARD_VARIANTS) + all: $(BUILD)/firmware.uf2 $(BUILD)/firmware.elf: $(OBJ) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json index a998529ccde2e..315068eeab0d4 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json @@ -12,6 +12,9 @@ "itsybitsy_m4_express.jpg" ], "mcu": "samd51", + "variants": { + "wlan": "WiFi support using a ESP32 module with NINA firmware" + }, "product": "ItsyBitsy M4 Express", "thumbnail": "", "url": "https://www.adafruit.com/product/3800", diff --git a/ports/samd/main.c b/ports/samd/main.c index 74eb5e328526b..9b701e2efcc9f 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -29,6 +29,8 @@ #include "py/gc.h" #include "py/mperrno.h" #include "py/stackctrl.h" +// #include "extmod/modbluetooth.h" +#include "extmod/modnetwork.h" #include "shared/readline/readline.h" #include "shared/runtime/gchelper.h" #include "shared/runtime/pyexec.h" @@ -50,6 +52,15 @@ void samd_main(void) { // Initialise sub-systems. readline_init0(); + #if MICROPY_PY_BLUETOOTH + // mp_bluetooth_hci_init(); + #endif + #if MICROPY_PY_NETWORK + mod_network_init(); + #endif + #if MICROPY_PY_LWIP + mod_network_lwip_init(); + #endif // Execute _boot.py to set up the filesystem. pyexec_frozen_module("_boot.py", false); @@ -81,6 +92,12 @@ void samd_main(void) { soft_reset_exit: mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + #if MICROPY_PY_NETWORK + mod_network_deinit(); + #endif + #if MICROPY_PY_BLUETOOTH + // mp_bluetooth_deinit(); + #endif #if MICROPY_PY_MACHINE_ADC adc_deinit_all(); #endif diff --git a/ports/samd/mbedtls/mbedtls_config.h b/ports/samd/mbedtls/mbedtls_config.h new file mode 100644 index 0000000000000..4140bb5145555 --- /dev/null +++ b/ports/samd/mbedtls/mbedtls_config.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * 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. + */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H + +// Set MicroPython-specific options. +#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) + +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" + +#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/samd/mbedtls/mbedtls_port.c b/ports/samd/mbedtls/mbedtls_port.c new file mode 100644 index 0000000000000..6259613dbaaca --- /dev/null +++ b/ports/samd/mbedtls/mbedtls_port.c @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * 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. + */ + +#ifdef MICROPY_SSL_MBEDTLS + +#include "mbedtls_config.h" +uint32_t trng_random_u32(); + +int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { + + *olen = len; + for (size_t i = 0; i < len; i++) { + output[i] = (unsigned char)trng_random_u32(); + } + return 0; +} + +#endif diff --git a/ports/samd/mcu/samd51/manifest_net.py b/ports/samd/mcu/samd51/manifest_net.py new file mode 100644 index 0000000000000..6353bdb47eb6a --- /dev/null +++ b/ports/samd/mcu/samd51/manifest_net.py @@ -0,0 +1,8 @@ +include("$(PORT_DIR)/boards/manifest.py") +include("$(MPY_DIR)/extmod/asyncio") +# Drivers +require("onewire") +require("ds18x20") +require("dht") +# Networking +require("bundle-networking") diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h index 399b48c040d69..1fe323f0939d9 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -24,6 +24,9 @@ #ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (0) #endif +// Enable MD5 hash. +#define MICROPY_PY_UHASHLIB_MD5 (MICROPY_SSL_MBEDTLS) +#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS) #define MICROPY_PY_OS_SYNC (1) #define MICROPY_PY_OS_URANDOM (1) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index c706331aca459..ac85a734be929 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -6,9 +6,49 @@ MICROPY_HW_CODESIZE ?= 368K MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 + +ifeq ($(BOARD_VARIANT),wlan) +MICROPY_PY_NETWORK ?= 1 +MICROPY_PY_NETWORK_NINAW10 ?= 1 +ifeq ($(MICROPY_HW_CODESIZE),496K) +MICROPY_PY_SSL ?= 1 +MICROPY_SSL_MBEDTLS ?= 1 +endif +ifeq ($(MICROPY_HW_CODESIZE),1008K) +MICROPY_PY_SSL ?= 1 +MICROPY_SSL_MBEDTLS ?= 1 +endif +endif + +ifeq ($(MICROPY_PY_NETWORK),1) +FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest_net.py +else FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py +endif SRC_S += shared/runtime/gchelper_thumb2.s SRC_C += \ fatfs_port.c \ + mbedtls/mbedtls_port.c + + +ifeq ($(MICROPY_PY_NETWORK),1) +CFLAGS += -DMICROPY_PY_NETWORK=1 + +SHARED_SRC_C += \ + shared/netutils/dhcpserver.c \ + shared/netutils/netutils.c \ + shared/netutils/trace.c +endif + +ifeq ($(MICROPY_PY_NETWORK_NINAW10),1) +CFLAGS += -DMICROPY_PY_NETWORK_NINAW10=1 +INC += -I$(TOP)/drivers/ninaw10 + +DRIVERS_SRC_C += \ + drivers/ninaw10/nina_bt_hci.c \ + drivers/ninaw10/nina_wifi_drv.c \ + drivers/ninaw10/nina_wifi_bsp.c \ + drivers/ninaw10/machine_pin_nina.c +endif \ No newline at end of file diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index c983d7e6d669c..bbdb4334ddaed 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -134,6 +134,52 @@ #define MP_STATE_PORT MP_STATE_VM +// 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-samd" +#endif + +#ifndef MICROPY_PY_SOCKET +#define MICROPY_PY_SOCKET (1) +#endif +#ifndef MICROPY_PY_SSL +#define MICROPY_PY_SSL (1) +#endif +#ifndef MICROPY_PY_WEBSOCKET +#define MICROPY_PY_WEBSOCKET (1) +#endif +#ifndef MICROPY_PY_WEBREPL +#define MICROPY_PY_WEBREPL (1) +#endif + +#if MICROPY_PY_NETWORK_NINAW10 +// This Network interface requires the extended socket state. +#ifndef MICROPY_PY_SOCKET_EXTENDED_STATE +#define MICROPY_PY_SOCKET_EXTENDED_STATE (1) +#endif +extern const struct _mp_obj_type_t mod_network_nic_type_nina; +extern const struct _mp_obj_type_t mod_network_nic_type_wlan; +#define MICROPY_HW_NIC_WLAN { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_wlan) }, +#define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_NinaW10), MP_ROM_PTR(&mod_network_nic_type_nina) }, + +#else + +#define MICROPY_HW_NIC_NINAW10 + +#endif // MICROPY_PY_NETWORK_NINAW10 + +#ifndef MICROPY_BOARD_NETWORK_INTERFACES +#define MICROPY_BOARD_NETWORK_INTERFACES +#endif + +#define MICROPY_PORT_NETWORK_INTERFACES \ + MICROPY_HW_NIC_WLAN \ + MICROPY_HW_NIC_NINAW10 \ + MICROPY_BOARD_NETWORK_INTERFACES + +#endif // MICROPY_PY_NETWORK + // Additional entries for use with pendsv_schedule_dispatch. #ifndef MICROPY_BOARD_PENDSV_ENTRIES #define MICROPY_BOARD_PENDSV_ENTRIES From fc0bafce112bf5c069bca5416c958d3fbbfbab15 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Apr 2023 21:32:15 +0200 Subject: [PATCH 3/5] samd/WLAN: Change the board definition files for WLAN support. Including: ADAFRUIT_FEATHER_M4_EXPRESS ADAFRUIT_ITSYBITSY_M4_EXPRESS SPARKFUN_SAMD51_THING_PLUS Pin definitions are added as well for: ADAFRUIT_FEATHER_M0_EXPRESS ADAFRUIT_ITSYBITSY_M0_EXPRESS which can support basic WLAN once the use of the on-board flash for the file system is available. Signed-off-by: robert-hh --- .../ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h | 11 +++++++++++ .../boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json | 3 +++ .../ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h | 11 +++++++++++ .../ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk | 2 ++ .../ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h | 11 +++++++++++ .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h | 12 ++++++++++++ .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk | 2 ++ .../samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json | 2 +- .../boards/SPARKFUN_SAMD51_THING_PLUS/board.json | 3 +++ .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h | 11 +++++++++++ .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk | 1 + 11 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h index 880df8d200390..66d0e1853519a 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h @@ -5,3 +5,14 @@ #define MICROPY_HW_SPIFLASH (1) #define MICROPY_HW_SPIFLASH_ID (2) + +#define MICROPY_HW_WIFI_SPI_ID (4) +#define MICROPY_HW_WIFI_SPI_BAUDRATE (8000000) + +#define MICROPY_HW_WIFI_SPI_MOSI (42) +#define MICROPY_HW_WIFI_SPI_MISO (12) +#define MICROPY_HW_WIFI_SPI_SCK (43) + +#define MICROPY_HW_NINA_CS (17) +#define MICROPY_HW_NINA_ACK (16) +#define MICROPY_HW_NINA_RESET (19) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json index 06cd9a4fe4d9b..1e7631cd735be 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json @@ -14,6 +14,9 @@ "feather_m4_express.jpg" ], "mcu": "samd51", + "variants": { + "wlan": "WiFi support using a ESP32 module with NINA firmware" + }, "product": "Feather M4 Express", "thumbnail": "", "url": "https://www.adafruit.com/product/3857", diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h index a9f7d518e2364..570355441fc94 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h @@ -5,3 +5,14 @@ #define MICROPY_HW_MCU_OSC32KULP (1) #define MICROPY_HW_QSPIFLASH GD25Q16C + +#define MICROPY_HW_WIFI_SPI_ID (1) +#define MICROPY_HW_WIFI_SPI_BAUDRATE (8000000) + +#define MICROPY_HW_WIFI_SPI_MOSI (55) +#define MICROPY_HW_WIFI_SPI_MISO (54) +#define MICROPY_HW_WIFI_SPI_SCK (17) + +#define MICROPY_HW_NINA_ACK (21) +#define MICROPY_HW_NINA_CS (23) +#define MICROPY_HW_NINA_RESET (22) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk index 6ec2d43dedbd8..2f09f13b7b5f1 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk @@ -6,3 +6,5 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 496K + +BOARD_VARIANTS += "wlan" diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h index 16018fdc56356..c7b08b7e0ea5e 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h @@ -5,3 +5,14 @@ #define MICROPY_HW_SPIFLASH (1) #define MICROPY_HW_SPIFLASH_ID (5) + +#define MICROPY_HW_WIFI_SPI_ID (4) +#define MICROPY_HW_WIFI_SPI_BAUDRATE (8000000) + +#define MICROPY_HW_WIFI_SPI_MOSI (42) +#define MICROPY_HW_WIFI_SPI_MISO (12) +#define MICROPY_HW_WIFI_SPI_SCK (43) + +#define MICROPY_HW_NINA_CS (17) +#define MICROPY_HW_NINA_ACK (16) +#define MICROPY_HW_NINA_RESET (19) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h index 2f246c60b188c..e217a6e3aa1bc 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -4,3 +4,15 @@ #define MICROPY_HW_DFLL_USB_SYNC (1) #define MICROPY_HW_QSPIFLASH GD25Q16C +#define MICROPY_HW_DFLL_USB_SYNC (1) + +#define MICROPY_HW_WIFI_SPI_ID (1) +#define MICROPY_HW_WIFI_SPI_BAUDRATE (8000000) + +#define MICROPY_HW_WIFI_SPI_MOSI (0) +#define MICROPY_HW_WIFI_SPI_MISO (55) +#define MICROPY_HW_WIFI_SPI_SCK (1) + +#define MICROPY_HW_NINA_CS (22) +#define MICROPY_HW_NINA_ACK (21) +#define MICROPY_HW_NINA_RESET (23) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk index 740154a6d6825..ba7e0789fc860 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk @@ -6,3 +6,5 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 496K + +BOARD_VARIANTS += "wlan" diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json index f830ff223f909..e2b7c9798b952 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json @@ -16,7 +16,7 @@ ], "mcu": "samd51", "variants": { - "wlan": "WLAN without SSL support" + "wlan": "WLAN using the on-board Airlift module" }, "product": "Metro M4 Express Airlift", "thumbnail": "", diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json index ee9ca9d3689b0..37787f1e4fae8 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json @@ -13,6 +13,9 @@ "sparkfun_samd51_thing_plus.jpg" ], "mcu": "samd51", + "variants": { + "wlan": "WiFi support using a ESP32 module with NINA firmware" + }, "product": "Sparkfun SAMD51 Thing Plus", "thumbnail": "", "url": "https://www.sparkfun.com/products/14713", diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h index 706fc3c64c37b..bb70781e667aa 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h @@ -13,3 +13,14 @@ // the board's external flash. #define MICROPY_HW_SPIFLASH (1) #define MICROPY_HW_SPIFLASH_ID (0) + +#define MICROPY_HW_WIFI_SPI_ID (4) +#define MICROPY_HW_WIFI_SPI_BAUDRATE (8000000) + +#define MICROPY_HW_WIFI_SPI_MOSI (44) +#define MICROPY_HW_WIFI_SPI_MISO (43) +#define MICROPY_HW_WIFI_SPI_SCK (45) + +#define MICROPY_HW_NINA_ACK (16) +#define MICROPY_HW_NINA_CS (17) +#define MICROPY_HW_NINA_RESET (19) diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk index 263e582694495..239816e177296 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk @@ -6,3 +6,4 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 1008K +BOARD_VARIANTS += "wlan" From da14bc0a144e25eff35e519831ccb45e1247ca60 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Apr 2023 21:37:00 +0200 Subject: [PATCH 4/5] NINAW10: Add the network.NinaW10 class to the documentation. Signed-off-by: robert-hh --- docs/library/network.NinaW10.rst | 102 +++++++++++++++++++ docs/library/network.WLAN.rst | 3 +- docs/library/network.rst | 1 + docs/samd/quickref.rst | 41 ++++++++ ports/samd/boards/deploy.md | 167 ++++++++++++++++++++++++++++++- 5 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 docs/library/network.NinaW10.rst diff --git a/docs/library/network.NinaW10.rst b/docs/library/network.NinaW10.rst new file mode 100644 index 0000000000000..24831ef29aa72 --- /dev/null +++ b/docs/library/network.NinaW10.rst @@ -0,0 +1,102 @@ +.. currentmodule:: network +.. _network.NinaW10: + +class NinaW10 -- control WiFi modules with NINA firmware +======================================================== + +This class allows you to control WLAN modules based on the NINA firmware, +like the u.Blox W102, Adafruit Airlift modules or genuine ESP32 boards.. + +Example usage:: + + import network + from machine import SPI, Pin + spi=SPI(1, 8000000, sck="SCK", mosi="MOSI", miso="MISO") + wlan = network.NinaW10(network.STA_IF, spi=spi, cs=Pin("D13"), busy=Pin("D11"), reset=Pin("D12")) + + # now use socket as usual + ... + +For this example to work the NINA module must have the following connections: + + - the SPI interface with MOSI, MISO and SCK + - cs connected to pin D13 + - busy connected to D11 + - reset connected to D12 + +It is possible to use other SPI buses and other pins for cs, busy and reset. + +Constructors +------------ + +.. class:: NinaW10(interface, *, spi=spi, cs=pin_cs, busy=pin_busy, reset=pin_rst) + + Create a NinaW10 driver object, initialise the NINA module using the given + SPI bus and pins, and return the Wlan object. + + Arguments are: + + - *interface* is the interface mode, either network.STA_IF or network.AP_IF. If + it is omitted, network.STA_IF is assumed. + - *spi* is an :ref:`SPI object ` which is the SPI bus that the NINA module is + connected to (the MOSI, MISO and SCLK pins). + - *pin_cs* is a :ref:`Pin object ` which is connected to the NINA CS pin. + - *pin_busy* is a :ref:`Pin object ` which is connected to the NINA busy pin. + - *pin_rst* is a :ref:`Pin object ` which is connected to the NINA reset pin. + + The SPI object must be initialized beforehand. The mode of the Pin objects will be + set by the driver. + +The default pins for some boards and extensions are: + +======== ========= ======= ======= ========= ========= +Airlift ItsyBitsy Feather Airlift METRO M4 Sparkfun +Breakout Add-on Add-on shield Airlift SAMD51_TP +======== ========= ======= ======= ========= ========= +MOSI MOSI MOSI D11 MOSI MOSI +MISO MISO MISO D12 MISO MISO +SCK SCK SCK D13 SCK SCK +CS D13 D13 D10 ESP_CS D13 +Busy D11 D11 D7 ESP_BUSY D11 +Reset D12 D12 D5 ESP_RESET D12 +GP0 D10 D10 D6 ESP_GP0 D10 +======== ========= ======= ======= ========= ========= + + +A useful function for connecting to your local WiFi network is:: + + def do_connect(): + from machine import SPI, Pin + import time + + spi=SPI(1, 8000000, sck="SCK", mosi="MOSI", miso="MISO") + wlan = network.WLAN(network.STA_IF, spi=spi, cs=Pin("D13"), busy=Pin("D11"), reset=Pin("D12")) + wlan.active(True) + if not wlan.isconnected(): + wlan.connect(WIFI_SSID, WIFI_PASSWD) # connect to an AP + + for _ in range(20): + if wlan.isconnected(): + print('\nnetwork config:', wlan.ifconfig()) + break + print(".", end="") + time.sleep(0.5) + else: + print(" Connect attempt timed out\n") + +Once the network is established the :mod:`socket ` module can be used +to create and use TCP/UDP sockets as usual. WLAN support is at the moment +only supported for SAM51 boards with a matching add-on board. + +Note: + + - If feasible, pull the RESET line low with an external resistor. The + required value depends on the NINA module. A good value is 2.2 kOhm. + This forces the GPIO lines of the module to high impedance when + not being used. + +Methods +------- + +The methods of the WLAN class are supported. For further details, +see :ref:`WLAN class ` diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst index 68cd49769afff..47ce139d0a984 100644 --- a/docs/library/network.WLAN.rst +++ b/docs/library/network.WLAN.rst @@ -15,7 +15,7 @@ This class provides a driver for WiFi network processors. Example usage:: Constructors ------------ -.. class:: WLAN(interface_id) +.. class:: WLAN(interface, *, spi, cs, busy, reset) Create a WLAN network interface object. Supported interfaces are ``network.STA_IF`` (station aka client, connects to upstream WiFi access @@ -23,6 +23,7 @@ points) and ``network.AP_IF`` (access point, allows other WiFi clients to connect). Availability of the methods below depends on interface type. For example, only STA interface may `WLAN.connect()` to an access point. + Methods ------- diff --git a/docs/library/network.rst b/docs/library/network.rst index b13c84123ce7f..1e54fbdc6cd1e 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -151,6 +151,7 @@ provide a way to control networking interfaces of various kinds. network.WLAN.rst network.WLANWiPy.rst network.WIZNET5K.rst + network.NinaW10.rst network.LAN.rst Network functions diff --git a/docs/samd/quickref.rst b/docs/samd/quickref.rst index 60c57b3a47a31..3b6ede07607f1 100644 --- a/docs/samd/quickref.rst +++ b/docs/samd/quickref.rst @@ -414,6 +414,47 @@ has the same methods as software SPI above:: i2c = I2C(2, scl=Pin("SCL"), sda=Pin("SDA"), freq=400_000) i2c.writeto(0x76, b"Hello World") + +WLAN +---- + +SAMD51 MCUs support networking using a ESP32 based extension module with NINA firmware. +Some SAMD51 are already equipped with such a module. For some boards +add-on modules are available which can be stacked to that board. But +any generic ESP32 or a ESP32 WROOM module can be used for that purpose. +Since the WLAN module's wiring may vary, it must be specified when +setting up the connection. The example below shows the set-up +for a Adafruit ItsyBitsy M4 module with the matching add-on board, +for which the wiring is defined in the firmware:: + + wlan = network.WLAN(network.STA_IF) + wlan.active(True) # activate the interface + wlan.scan() # scan for access points + wlan.isconnected() # check if the station is connected to an AP + wlan.connect('ssid', 'key') # connect to an AP + wlan.config('mac') # get the interface's MAC address + wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses + +If no default wiring exist or the wiring differs from the default, it +can be specified with the alternative NinaW10 WLAN class e.g.:: + + import network + from machine import SPI, Pin + spi=SPI(1, 8000000, sck="SCK", mosi="MOSI", miso="MISO") + wlan = network.NinaW10(network.STA_IF, spi=spi, cs=Pin("D13"), busy=Pin("D11"), reset=Pin("D12")) + +In that case, all wiring parameters must be specified, even if some of them +match the default connection. For further details, see :ref:`NinaW10 class `. + +Notes: + + - All supported SAMD51 boards provide basic WLAN support. SSL is at the moment only + included for boards with a SAMD51x20 MCU. SSL requires a lot of code space. + - If feasible, pull the RESET line low with an external resistor. A good value + is 2.2 kOhm. This forces the GPIO lines of the module to high impedance when + not being used. + + OneWire driver -------------- diff --git a/ports/samd/boards/deploy.md b/ports/samd/boards/deploy.md index fac5c994ab702..f6f90c1d0cfd9 100644 --- a/ports/samd/boards/deploy.md +++ b/ports/samd/boards/deploy.md @@ -1,10 +1,167 @@ +# Deploy firmware to the SAMD boards and a NINA/ESP32 WiFi module. + +## Deploy the MicroPython firmware + For deploying the MicroPython firmware to the SAMD module, follow -the procedure: +the usual procedure: + +1. Push reset twice or call machine.bootloader(), if there was already + MicroPyhton installed at the board. A drive icon should appear + representing a virtual drive. +2. Copy the .uf2 file with the required firmware to that drive. As + soon as the drive disappears, the firmware is loaded and started. + +If a MicroPython firmware is already installed at the board, it is also +possible to enable the bootloader by shortly switching the USB Serial +to 1200 baud and back, like it is done in the short script below. That +allows for scripted update. + +```Py +import serial +import time +import sys +com=serial.Serial(sys.argv[1], 1200, dsrdtr=True) +com.dtr=False +com.rts=False +time.sleep(0.2) +com.close() +time.sleep(4) +# then copy the firmware file to the drive +``` + +## Deploy the Wifi firmware. + +The WiFi module uses the NINA firmware, which works on any ESP32 module, +like the u.Blox NINA W102, the Adafruit Airlink modules or a generic +ESP32 device with at least 2 MB flash. Before the first use the appropriate +firmware has to be loaded to the device. A pre-existing firmware might +not work. The procedure differs between device types. + +### Firmware source and types. + +There exist two firmware versions, which only differ in the connection +for the MOSI connection between host MCU and WiFi module. The connections +for Wifi use are: +``` + Driver NINA Airlift Airlift + Name W102 pin Name pin + ---------------------------------- + MOSI 12 MOSI 14 + MISO 23 MISO 23 + SCK 18 SCK 18 + GPIO1 5 CS 5 + ACK 33 Busy 33 + RESET EN Reset EN +``` +The firmware binaries are available at https://github.com/micropython/micropython-lib/tree/master/micropython/espflash or https://github.com/robert-hh/Shared-Stuff. +For a generic ESP32 device you can use either version, given that the +MOSI signal is wired properly. If possible, add a **pull-down** resistor to +the RESET pin, value 1.5 to 10k, such that RESET is kept low as long as +WiFi is not used. That keeps the ESP32 in inactive state and it's GPIO pins +at high impedance. + +### Firmware upload to a Generic ESP32 device. + +That is the easiest task, if the USB port of the device is available. Just +follow the standard ESP procedure for uploading firmware using esptool.py with +the command: + +``` +esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0 NINA_FW_v1.5.0_W102.bin +``` + +Note that the load address is 0. The port name will be different depending on +the PC set-up and it's operating system. If the USB port is not available, follow +the procedure for built-in modules. + +### Firmware upload for built-in or breakout modules + +For firmware upload, the following connections to the WiFi module are required: + +- Pin Reset (as above) +- Pin GPIO0 +- UART RX +- UART TX + +The GPIO pins and UART device id varies between boards. If the WiFi module is hardwired +to a MCU or Add-on board, the Pin and UART properties can be found in the documentation, +otherwise any suitable pins can be used. On some add-on boards like the Adafruit ItsyBitsy, +Feather or Arduino Shield modules solder bridges may have to be closed to RX, TX and GPIO0. +RX and TX are needed for bluetooth as well. +Once the wiring is done, the firmware can be uploaded, using the espflash.py module, a short script +using espflash.py and mpremote. espflash.py is usually embedded into the MicroPython firmware +of the SAMD device as frozen bytecode. Otherwise, it is available at https://github.com/micropython/micropython-lib/tree/master/micropython/espflash. This place also holds the example script. + +``` +import espflash +from machine import Pin +from machine import UART +import sys +sys.path.append("/") + +if True: + reset = Pin("ESP_RESET", Pin.OUT) + gpio0 = Pin("ESP_GPIO0", Pin.OUT) + uart = UART(0, 115200, tx=Pin("ESP_TX"), rx=Pin("ESP_RX"), timeout=350) -- Push the reset button twice or call machine.bootloader(). A drive - icon should appear representing a virtual drive. + md5sum = b"b0b9ab23da820a469e597c41364acb3a" + path = "/remote/NINA_FW_v1.5.0_Airlift.bin" -- Copy the .uf2 file with the required firmware to that drive. + esp = espflash.ESPFlash(reset, gpio0, uart) + # Enter bootloader download mode, at 115200 + esp.bootloader() + # Can now change to higher/lower baud rate + esp.set_baudrate(921600) + # Must call this first before any flash functions. + esp.flash_attach() + # Read flash size + size = esp.flash_read_size() + # Configure flash parameters. + esp.flash_config(size) + # Write firmware image from internal storage. + esp.flash_write_file(path) + # Compares file and flash MD5 checksum. + esp.flash_verify_file(path, md5sum) + # Resets the ESP32 chip. + esp.reboot() +``` -As soon as the drive disappears, the firmware is loaded and started. +The script shows the set-up for the Metro M4 Express Airlift board. +The md5sum is the one of the WiFi firmware. It may change and +can be recalculated using e.g. the Linux `md5sum` command. It is used to +verify the firmware upload. To upload the firmware, place the firmware +and the above script (let's call it ninaflash.py) into the same directory +on your PC, and run the command: +``` +mprememote connect mount . run ninaflash.py +``` +After a while the upload will start. A typical start sequence looks like: +``` +Local directory . is mounted at /remote +Failed to read response to command 8. +Failed to read response to command 8. +Changing baudrate => 921600 +Flash attached +Flash size 2.0 MBytes +Flash write size: 1310720 total_blocks: 320 block size: 4096 +Writing sequence number 0/320... +Writing sequence number 1/320... +Writing sequence number 2/320... +Writing sequence number 3/320... +Writing sequence number 4/320... +.... +.... +Writing sequence number 317/320... +Writing sequence number 318/320... +Writing sequence number 319/320... +Flash write finished +Flash verify: File MD5 b'b0b9ab23da820a469e597c41364acb3a' +Flash verify: Flash MD5 b'b0b9ab23da820a469e597c41364acb3a' +Firmware verified. +``` +The initial messages `Failed to read response to command 8.` +can be ignored. +Once the firmware upload is finished, the connection to RX, TX and GPIO0 +can be removed, unless the modules is used to Bluetooth communication, +which needs RX and TX. From 0f18337e362070ba23860b09282dd68d4ee1dea5 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Tue, 15 Aug 2023 10:27:34 +0200 Subject: [PATCH 5/5] samd: Update the variant scheme. - Remove the query_variant tag from Makefile. - Remove the definition of BOARD_VARIANTS. - Use uppercase for board variants. - Append the variant name to the build directory name. Signed-off-by: robert-hh --- ports/samd/Makefile | 7 ++++--- ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json | 2 +- .../boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk | 2 -- ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json | 2 +- .../boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk | 2 -- ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json | 2 +- ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json | 2 +- .../boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk | 1 - ports/samd/mcu/samd51/mpconfigmcu.mk | 2 +- 9 files changed, 9 insertions(+), 13 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 03807880b67c2..e6585ce791487 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -13,7 +13,11 @@ ifeq ($(wildcard $(BOARD_DIR)/.),) $(error Invalid BOARD specified: $(BOARD_DIR)) endif +ifneq ($(BOARD_VARIANT),) +BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) +else BUILD ?= build-$(BOARD) +endif CROSS_COMPILE ?= arm-none-eabi- UF2CONV ?= $(TOP)/tools/uf2conv.py @@ -194,9 +198,6 @@ OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o)) -query-variants: - $(ECHO) "VARIANTS:" $(BOARD_VARIANTS) - all: $(BUILD)/firmware.uf2 $(BUILD)/firmware.elf: $(OBJ) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json index 1e7631cd735be..faeb0c780e979 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json @@ -15,7 +15,7 @@ ], "mcu": "samd51", "variants": { - "wlan": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware" }, "product": "Feather M4 Express", "thumbnail": "", diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk index 2f09f13b7b5f1..6ec2d43dedbd8 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk @@ -6,5 +6,3 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 496K - -BOARD_VARIANTS += "wlan" diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json index 315068eeab0d4..c596b7a7ae359 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json @@ -13,7 +13,7 @@ ], "mcu": "samd51", "variants": { - "wlan": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware" }, "product": "ItsyBitsy M4 Express", "thumbnail": "", diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk index ba7e0789fc860..740154a6d6825 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk @@ -6,5 +6,3 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 496K - -BOARD_VARIANTS += "wlan" diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json index e2b7c9798b952..c4d8aa68dae2f 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json @@ -16,7 +16,7 @@ ], "mcu": "samd51", "variants": { - "wlan": "WLAN using the on-board Airlift module" + "WLAN": "WLAN using the on-board Airlift module" }, "product": "Metro M4 Express Airlift", "thumbnail": "", diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json index 37787f1e4fae8..7dcb836512fe2 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json @@ -14,7 +14,7 @@ ], "mcu": "samd51", "variants": { - "wlan": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware" }, "product": "Sparkfun SAMD51 Thing Plus", "thumbnail": "", diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk index 239816e177296..263e582694495 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk @@ -6,4 +6,3 @@ TEXT0 = 0x4000 # The ?='s allow overriding in mpconfigboard.mk. # MicroPython settings MICROPY_HW_CODESIZE ?= 1008K -BOARD_VARIANTS += "wlan" diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index ac85a734be929..a8e9402c531b1 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -7,7 +7,7 @@ MICROPY_HW_CODESIZE ?= 368K MICROPY_VFS_LFS2 ?= 1 MICROPY_VFS_FAT ?= 1 -ifeq ($(BOARD_VARIANT),wlan) +ifeq ($(BOARD_VARIANT),WLAN) MICROPY_PY_NETWORK ?= 1 MICROPY_PY_NETWORK_NINAW10 ?= 1 ifeq ($(MICROPY_HW_CODESIZE),496K)