From 0b3c90613eec2aa21657ea5c2f929919c1be5c5c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 23 Sep 2023 10:24:16 +0200 Subject: [PATCH 01/10] samd/WLAN: Support external NINA10 modules for WLAN. Using the network.WLAN module with Pin settings defined in mpconfigboard.h. To allow for port specific WiFi configurations, the functions in drivers/ninaw10/nina_wifi_bsp.c are declared as MP_WEAK. Signed-off-by: robert-hh --- drivers/ninaw10/nina_wifi_bsp.c | 53 +++++--- ports/samd/Makefile | 4 + .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json | 3 + ports/samd/main.c | 14 +++ ports/samd/mbedtls/mbedtls_config.h | 35 ++++++ ports/samd/mbedtls/mbedtls_port.c | 42 +++++++ ports/samd/mcu/samd51/manifest_net.py | 8 ++ ports/samd/mcu/samd51/mpconfigmcu.h | 12 +- ports/samd/mcu/samd51/mpconfigmcu.mk | 43 +++++++ ports/samd/mpconfigport.h | 47 +++++++- ports/samd/nina_wifi_bsp.c | 113 ++++++++++++++++++ 11 files changed, 350 insertions(+), 24 deletions(-) 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 create mode 100644 ports/samd/nina_wifi_bsp.c diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c index dc71c8260c61f..04a20b2efb281 100644 --- a/drivers/ninaw10/nina_wifi_bsp.c +++ b/drivers/ninaw10/nina_wifi_bsp.c @@ -46,15 +46,22 @@ #define debug_printf(...) #endif -int nina_bsp_init(void) { - mp_hal_pin_output(MICROPY_HW_NINA_GPIO1); +// Use the name CS instead of GPIO1 +#ifndef MICROPY_HW_NINA_CS +#define MICROPY_HW_NINA_CS MICROPY_HW_NINA_GPIO1 +#endif + +MP_WEAK int nina_bsp_init(void) { + mp_hal_pin_output(MICROPY_HW_NINA_CS); mp_hal_pin_input(MICROPY_HW_NINA_ACK); mp_hal_pin_output(MICROPY_HW_NINA_RESET); + #ifdef MICROPY_HW_NINA_GPIO0 mp_hal_pin_output(MICROPY_HW_NINA_GPIO0); + mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1); + #endif // 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(MICROPY_HW_NINA_CS, 1); mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); mp_hal_delay_ms(100); @@ -62,51 +69,59 @@ int nina_bsp_init(void) { mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1); mp_hal_delay_ms(750); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 0); + #ifdef MICROPY_HW_NINA_GPIO0 mp_hal_pin_input(MICROPY_HW_NINA_GPIO0); + #endif // 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); + 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); 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_WEAK int nina_bsp_deinit(void) { + mp_hal_pin_output(MICROPY_HW_NINA_CS); + mp_hal_pin_write(MICROPY_HW_NINA_CS, 1); mp_hal_pin_output(MICROPY_HW_NINA_RESET); mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); mp_hal_delay_ms(100); + #ifdef MICROPY_HW_NINA_GPIO0 mp_hal_pin_output(MICROPY_HW_NINA_GPIO0); mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1); + #endif + return 0; } -int nina_bsp_atomic_enter(void) { +MP_WEAK int nina_bsp_atomic_enter(void) { #if MICROPY_ENABLE_SCHEDULER mp_sched_lock(); #endif return 0; } -int nina_bsp_atomic_exit(void) { +MP_WEAK int nina_bsp_atomic_exit(void) { #if MICROPY_ENABLE_SCHEDULER mp_sched_unlock(); #endif return 0; } -int nina_bsp_read_irq(void) { +MP_WEAK int nina_bsp_read_irq(void) { + #ifdef MICROPY_HW_NINA_GPIO0 return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0); + #else + return 1; + #endif } -int nina_bsp_spi_slave_select(uint32_t timeout) { +MP_WEAK 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)) { if (timeout && ((mp_hal_ticks_ms() - start) >= timeout)) { @@ -115,12 +130,12 @@ int nina_bsp_spi_slave_select(uint32_t timeout) { } // Chip select. - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 0); + mp_hal_pin_write(MICROPY_HW_NINA_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)) { if ((mp_hal_ticks_ms() - start) >= 100) { - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); + mp_hal_pin_write(MICROPY_HW_NINA_CS, 1); return -1; } } @@ -128,12 +143,12 @@ int nina_bsp_spi_slave_select(uint32_t timeout) { return 0; } -int nina_bsp_spi_slave_deselect(void) { - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 1); +MP_WEAK int nina_bsp_spi_slave_deselect(void) { + mp_hal_pin_write(MICROPY_HW_NINA_CS, 1); return 0; } -int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) { +MP_WEAK int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) { mp_obj_t mp_wifi_spi = MP_STATE_PORT(mp_wifi_spi); ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, protocol))->transfer(mp_wifi_spi, size, tx_buf, rx_buf); #if NINA_DEBUG diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 75a4d9b1de355..3d35be02df514 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 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 2bbaf63e6e4c5..8a393f88a8d00 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" @@ -52,6 +54,12 @@ 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 // Execute _boot.py to set up the filesystem. pyexec_frozen_module("_boot.py", false); @@ -87,6 +95,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..d2509488bfa7a --- /dev/null +++ b/ports/samd/mbedtls/mbedtls_port.c @@ -0,0 +1,42 @@ +/* + * 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" +#include +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 9a7b8528f3573..5e8221d1ff08f 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.h +++ b/ports/samd/mcu/samd51/mpconfigmcu.h @@ -17,11 +17,15 @@ unsigned long trng_random_u32(void); #define MICROPY_PY_MACHINE_UART_IRQ (1) +// Enable MD5 hash. +#define MICROPY_PY_UHASHLIB_MD5 (MICROPY_SSL_MBEDTLS) +#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS) + // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define VFS_BLOCK_SIZE_BYTES (1536) // diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 9bef5eca166ab..1439b6ee61cc0 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -8,11 +8,54 @@ 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 UF2CONV_FLAGS += -f 0x55114460 + +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 + +SRC_C += \ + nina_wifi_bsp.c + +endif diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 0b47500bf7e7c..3a5c05447be7a 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -48,7 +48,6 @@ #endif #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_PY_BUILTINS_HELP_TEXT samd_help_text -#define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_HW_ENABLE_USBDEV (1) @@ -139,6 +138,52 @@ #define MICROPY_HW_USB_PID (0x9802) #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-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; +#define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) }, + +#define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL) + +#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_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 diff --git a/ports/samd/nina_wifi_bsp.c b/ports/samd/nina_wifi_bsp.c new file mode 100644 index 0000000000000..abe6e585bc737 --- /dev/null +++ b/ports/samd/nina_wifi_bsp.c @@ -0,0 +1,113 @@ +/* + * This file is part of the OpenMV project, https://openmv.io. + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2021 Ibrahim Abdelkader + * Copyright (c) 2013-2021 Kwabena W. Agyeman + * + * 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. + * + * NINA-W10 driver BSP implementation. + */ + +#include "py/mphal.h" + +#if MICROPY_PY_NETWORK_NINAW10 + +#include +#include + +#include "py/runtime.h" +#include "extmod/modmachine.h" +#include "extmod/virtpin.h" +#include "mpconfigboard.h" + +#include "nina_bsp.h" +#include "nina_wifi_drv.h" + +#if NINA_DEBUG +#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__) +#else +#define debug_printf(...) +#endif + +// Use the name CS instead of GPIO1 +#ifndef MICROPY_HW_NINA_CS +#define MICROPY_HW_NINA_CS MICROPY_HW_NINA_GPIO1 +#endif + +int nina_bsp_init(void) { + mp_hal_pin_output(MICROPY_HW_NINA_CS); + mp_hal_pin_input(MICROPY_HW_NINA_ACK); + mp_hal_pin_output(MICROPY_HW_NINA_RESET); + #ifdef MICROPY_HW_NINA_GPIO0 + mp_hal_pin_output(MICROPY_HW_NINA_GPIO0); + mp_hal_pin_write(MICROPY_HW_NINA_GPIO0, 1); + #endif + + // Reset module in WiFi mode + mp_hal_pin_write(MICROPY_HW_NINA_CS, 1); + + mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); + mp_hal_delay_ms(100); + + mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1); + mp_hal_delay_ms(750); + + #ifdef MICROPY_HW_NINA_GPIO0 + mp_hal_pin_input(MICROPY_HW_NINA_GPIO0); + #endif + + // 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_ROM_QSTR(MP_QSTR_sck), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_SCK), + MP_ROM_QSTR(MP_QSTR_miso), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_MISO), + MP_ROM_QSTR(MP_QSTR_mosi), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_MOSI), + }; + 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); + return 0; +} + +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_us(100)) { + if (timeout && ((mp_hal_ticks_ms() - start) >= timeout)) { + return -1; + } + } + + // Chip select. + mp_hal_pin_write(MICROPY_HW_NINA_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_us(100)) { + if ((mp_hal_ticks_ms() - start) >= 100) { + mp_hal_pin_write(MICROPY_HW_NINA_CS, 1); + return -1; + } + } + + return 0; +} + +#endif // MICROPY_PY_NETWORK_NINAW10 From 12a81e4ca247aaac063c67ad6f1aafae2d1c7779 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 22 Apr 2023 21:32:15 +0200 Subject: [PATCH 02/10] samd/WLAN: Add/update WLAN definitions for more boards. Including: ADAFRUIT_FEATHER_M4_EXPRESS ADAFRUIT_ITSYBITSY_M4_EXPRESS SPARKFUN_SAMD51_THING_PLUS ADAFRUIT_METRO_M4_EXPRESS Always build the Metro M4 board with WLAN, drop the variant for this board. Pin definitions are added as well for: ADAFRUIT_FEATHER_M0_EXPRESS ADAFRUIT_ITSYBITSY_M0_EXPRESS which can support basic WLAN. 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_ITSYBITSY_M0_EXPRESS/mpconfigboard.h | 11 +++++++++++ .../boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json | 2 +- .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h | 12 ++++++++++++ .../ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk | 8 +++++--- .../boards/SPARKFUN_SAMD51_THING_PLUS/board.json | 3 +++ .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h | 11 +++++++++++ 9 files changed, 68 insertions(+), 4 deletions(-) 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..faeb0c780e979 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_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/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.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_METRO_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk index 43ca5a59cc636..4ab61a4b9da5e 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk @@ -4,7 +4,9 @@ LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 # MicroPython settings -MICROPY_PY_NETWORK ?= 1 -MICROPY_PY_NETWORK_NINAW10 ?= 1 +MICROPY_PY_NETWORK = 1 +MICROPY_PY_NETWORK_NINAW10 = 1 +MICROPY_PY_SSL = 1 +MICROPY_SSL_MBEDTLS = 1 -MICROPY_HW_CODESIZE ?= 496K +MICROPY_HW_CODESIZE = 496K diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json index ee9ca9d3689b0..7dcb836512fe2 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) From e0f22835adfc7325533926cd3034f7371895c597 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 22 Sep 2023 08:34:27 +0200 Subject: [PATCH 03/10] pyproject.toml: Add a rule for manifest_*.py files at ports/**/mcu. These were not covered yet and the mcu scheme can be useful for other ports as well. Alternatively, the second rule could just be refer to "**/manifest_*.py" instead of "ports/**/boards/**/manifest_*.py". Signed-off-by: robert-hh --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index e44afe37e0ebb..6470c4626a490 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ max-complexity = 40 # manifest.py files are evaluated with some global names pre-defined "**/manifest.py" = ["F821"] "ports/**/boards/**/manifest_*.py" = ["F821"] +"ports/**/mcu/**/manifest_*.py" = ["F821"] [tool.ruff.format] # Exclude third-party code, and exclude the following tests: From c944fd94e9882c4cecffe8744c0f690826bc44a6 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 21 Apr 2023 09:33:31 +0200 Subject: [PATCH 04/10] samd/BLE: Add mpbthciport.c and mpnimbleport.c, change nina_bt_hci.c. Use MICROPY_HW_NINA_CS instead of MICROPY_HW_NINA_GPIO1 in nina_bt_hci.c and set RTS and CTS, if defined. Signed-off-by: robert-hh --- drivers/ninaw10/nina_bt_hci.c | 24 +++- ports/samd/main.c | 2 +- ports/samd/modmachine.h | 1 + ports/samd/mpbthciport.c | 204 ++++++++++++++++++++++++++++++++++ ports/samd/mpbthciport.h | 46 ++++++++ ports/samd/mpnimbleport.c | 80 +++++++++++++ ports/samd/mpnimbleport.h | 29 +++++ 7 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 ports/samd/mpbthciport.c create mode 100644 ports/samd/mpbthciport.h create mode 100644 ports/samd/mpnimbleport.c create mode 100644 ports/samd/mpnimbleport.h diff --git a/drivers/ninaw10/nina_bt_hci.c b/drivers/ninaw10/nina_bt_hci.c index f0d1b9bc8986b..b93a605f9047a 100644 --- a/drivers/ninaw10/nina_bt_hci.c +++ b/drivers/ninaw10/nina_bt_hci.c @@ -50,6 +50,11 @@ #define OCF_SET_EVENT_MASK (0x0001) #define OCF_RESET (0x0003) +// Use the name CS instead of GPIO1 +#ifndef MICROPY_HW_NINA_CS +#define MICROPY_HW_NINA_CS MICROPY_HW_NINA_GPIO1 +#endif + #define error_printf(...) // mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__) #define debug_printf(...) // mp_printf(&mp_plat_print, "nina_bt_hci.c: " __VA_ARGS__) @@ -59,6 +64,12 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; static int nina_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) { uint8_t *buf = mp_bluetooth_hci_cmd_buf; + // Clear the UART input buffer before sending the reset command. + // The ESP32 reset message may stick in it. + while (mp_bluetooth_hci_uart_any()) { + mp_bluetooth_hci_uart_readchar(); + } + buf[0] = HCI_COMMAND_PACKET; buf[1] = ocf; buf[2] = ogf << 2 | ocf >> 8; @@ -125,8 +136,17 @@ int mp_bluetooth_hci_controller_init(void) { mp_hal_pin_output(MICROPY_HW_NINA_RESET); mp_hal_pin_write(MICROPY_HW_NINA_RESET, 0); - mp_hal_pin_output(MICROPY_HW_NINA_GPIO1); - mp_hal_pin_write(MICROPY_HW_NINA_GPIO1, 0); + // care for dedicated setting of RTS/CTS + #ifdef MICROPY_HW_NINA_RTS + mp_hal_pin_output(MICROPY_HW_NINA_RTS); + mp_hal_pin_write(MICROPY_HW_NINA_RTS, 0); + #endif + #ifdef MICROPY_HW_NINA_CTS + mp_hal_pin_input(MICROPY_HW_NINA_CTS); + #endif + + mp_hal_pin_output(MICROPY_HW_NINA_CS); + mp_hal_pin_write(MICROPY_HW_NINA_CS, 0); mp_hal_delay_ms(150); mp_hal_pin_write(MICROPY_HW_NINA_RESET, 1); diff --git a/ports/samd/main.c b/ports/samd/main.c index 8a393f88a8d00..09a15e30c6b08 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -99,7 +99,7 @@ void samd_main(void) { mod_network_deinit(); #endif #if MICROPY_PY_BLUETOOTH - // mp_bluetooth_deinit(); + mp_bluetooth_deinit(); #endif #if MICROPY_PY_MACHINE_ADC adc_deinit_all(); diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h index e1279a2886d0c..1a2a7627f305b 100644 --- a/ports/samd/modmachine.h +++ b/ports/samd/modmachine.h @@ -34,5 +34,6 @@ extern const mp_obj_type_t machine_dac_type; #endif void rtc_gettime(timeutils_struct_time_t *tm); +void machine_uart_set_baudrate(mp_obj_t self, uint32_t baudrate); #endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H diff --git a/ports/samd/mpbthciport.c b/ports/samd/mpbthciport.c new file mode 100644 index 0000000000000..4df6404f44fc4 --- /dev/null +++ b/ports/samd/mpbthciport.c @@ -0,0 +1,204 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Ibrahim Abdelkader + * + * 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/stream.h" +#include "py/mphal.h" +#include "extmod/modbluetooth.h" +#include "extmod/mpbthci.h" +#include "shared/runtime/softtimer.h" +#include "modmachine.h" +#include "extmod/modmachine.h" +#include "mpbthciport.h" + +#if MICROPY_PY_BLUETOOTH + +#define debug_printf(...) // mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__) +#define error_printf(...) mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__) + +uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; + +MP_REGISTER_ROOT_POINTER(mp_obj_t mp_bthci_uart); + +// Soft timer for scheduling a HCI poll. +static soft_timer_entry_t mp_bluetooth_hci_soft_timer; + +// This is called by soft_timer and executes at IRQ_PRI_PENDSV. +static void mp_bluetooth_hci_soft_timer_callback(soft_timer_entry_t *self) { + mp_bluetooth_hci_poll_now(); +} + +void mp_bluetooth_hci_init(void) { + soft_timer_static_init( + &mp_bluetooth_hci_soft_timer, + SOFT_TIMER_MODE_ONE_SHOT, + 0, + mp_bluetooth_hci_soft_timer_callback + ); +} + +static void mp_bluetooth_hci_start_polling(void) { + mp_bluetooth_hci_poll_now(); +} + +void mp_bluetooth_hci_poll_in_ms(uint32_t ms) { + soft_timer_reinsert(&mp_bluetooth_hci_soft_timer, ms); +} + +static mp_sched_node_t mp_bluetooth_hci_sched_node; + +// For synchronous mode, we run all BLE stack code inside a scheduled task. +// This task is scheduled periodically via a timer, or immediately after UART RX IRQ. +static void run_events_scheduled_task(mp_sched_node_t *node) { + (void)node; + // This will process all buffered HCI UART data, and run any callouts or events. + mp_bluetooth_hci_poll(); +} + +// Called periodically (systick) or directly (e.g. UART RX IRQ) in order to +// request that processing happens ASAP in the scheduler. +void mp_bluetooth_hci_poll_now(void) { + mp_sched_schedule_node(&mp_bluetooth_hci_sched_node, run_events_scheduled_task); +} + +int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { + debug_printf("mp_bluetooth_hci_uart_init\n"); + + mp_obj_t args[] = { + MP_OBJ_NEW_SMALL_INT(port), + MP_OBJ_NEW_SMALL_INT(baudrate), + MP_OBJ_NEW_QSTR(MP_QSTR_tx), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_BLE_UART_TX), + MP_OBJ_NEW_QSTR(MP_QSTR_rx), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_BLE_UART_RX), + MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_OBJ_NEW_SMALL_INT(1000), + MP_OBJ_NEW_QSTR(MP_QSTR_timeout_char), MP_OBJ_NEW_SMALL_INT(1000), + MP_OBJ_NEW_QSTR(MP_QSTR_rxbuf), MP_OBJ_NEW_SMALL_INT(768), + MP_OBJ_NEW_QSTR(MP_QSTR_txbuf), MP_OBJ_NEW_SMALL_INT(768), + }; + + // This is not a statically-allocated UART (see machine_uart.c), + // so it has to be tracked as a root pointer. + MP_STATE_PORT(mp_bthci_uart) = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, 2, 6, args); + // Start the HCI polling to process any initial events/packets. + mp_bluetooth_hci_start_polling(); + return 0; +} + +int mp_bluetooth_hci_uart_deinit(void) { + debug_printf("mp_bluetooth_hci_uart_deinit\n"); + mp_obj_t uart = MP_OBJ_TO_PTR(MP_STATE_PORT(mp_bthci_uart)); + mp_obj_t uart_deinit_args[] = { + NULL, // Method pointer + uart, // uart object + }; + mp_load_method_maybe((mp_obj_t)uart, MP_QSTR_deinit, uart_deinit_args); + if (uart_deinit_args[0] != MP_OBJ_NULL && uart_deinit_args[1] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, uart_deinit_args); + } + soft_timer_remove(&mp_bluetooth_hci_soft_timer); + return 0; +} + +int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) { + debug_printf("mp_bluetooth_hci_uart_set_baudrate(%lu)\n", baudrate); + mp_obj_t uart = MP_OBJ_TO_PTR(MP_STATE_PORT(mp_bthci_uart)); + machine_uart_set_baudrate(uart, baudrate); + return 0; +} + +int mp_bluetooth_hci_uart_any(void) { + int errcode = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + + mp_uint_t ret = proto->ioctl(MP_STATE_PORT(mp_bthci_uart), MP_STREAM_POLL, MP_STREAM_POLL_RD, &errcode); + if (errcode != 0) { + error_printf("Uart ioctl failed to poll UART %d\n", errcode); + return -1; + } + return ret & MP_STREAM_POLL_RD; +} + +int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) { + debug_printf("mp_bluetooth_hci_uart_write\n"); + + int errcode = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + + mp_bluetooth_hci_controller_wakeup(); + + if (proto->write(MP_STATE_PORT(mp_bthci_uart), (void *)buf, len, &errcode) < 0) { + error_printf("mp_bluetooth_hci_uart_write: failed to write to UART %d\n", errcode); + } + return 0; +} + +// This function expects the controller to be in the wake state via a previous call +// to mp_bluetooth_hci_controller_woken. +int mp_bluetooth_hci_uart_readchar(void) { + debug_printf("mp_bluetooth_hci_uart_readchar\n"); + if (mp_bluetooth_hci_uart_any()) { + int errcode = 0; + uint8_t buf = 0; + const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol); + if (proto->read(MP_STATE_PORT(mp_bthci_uart), (void *)&buf, 1, &errcode) < 0) { + error_printf("mp_bluetooth_hci_uart_readchar: failed to read UART %d\n", errcode); + return -1; + } + return buf; + } else { + debug_printf("mp_bluetooth_hci_uart_readchar: not ready\n"); + return -1; + } +} + +// Default (weak) implementation of the HCI controller interface. +// A driver (e.g. cywbt43.c) can override these for controller-specific +// functionality (i.e. power management). +MP_WEAK int mp_bluetooth_hci_controller_init(void) { + debug_printf("mp_bluetooth_hci_controller_init (default)\n"); + return 0; +} + +MP_WEAK int mp_bluetooth_hci_controller_deinit(void) { + debug_printf("mp_bluetooth_hci_controller_deinit (default)\n"); + return 0; +} + +MP_WEAK int mp_bluetooth_hci_controller_sleep_maybe(void) { + debug_printf("mp_bluetooth_hci_controller_sleep_maybe (default)\n"); + return 0; +} + +MP_WEAK bool mp_bluetooth_hci_controller_woken(void) { + debug_printf("mp_bluetooth_hci_controller_woken (default)\n"); + return true; +} + +MP_WEAK int mp_bluetooth_hci_controller_wakeup(void) { + debug_printf("mp_bluetooth_hci_controller_wakeup (default)\n"); + return 0; +} + +#endif // MICROPY_PY_BLUETOOTH diff --git a/ports/samd/mpbthciport.h b/ports/samd/mpbthciport.h new file mode 100644 index 0000000000000..a732f347d56e0 --- /dev/null +++ b/ports/samd/mpbthciport.h @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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_RP2_MPBTHCIPORT_H +#define MICROPY_INCLUDED_RP2_MPBTHCIPORT_H + +#include "mphalport.h" + +void mp_bluetooth_hci_config_interface(mp_obj_t uart, mp_obj_t cs, mp_obj_t busy, mp_obj_t rts, mp_obj_t cts); + +// Initialise the HCI subsystem (should be called once, early on). +void mp_bluetooth_hci_init(void); + +// Poll the HCI now, or after a certain timeout. +void mp_bluetooth_hci_poll_now(void); +void mp_bluetooth_hci_poll_in_ms(uint32_t ms); + +// Must be provided by the stack bindings (e.g. mpnimbleport.c or mpbtstackport.c). +// Request new data from the uart and pass to the stack, and run pending events/callouts. +// This is a low-level function and should not be called directly, use +// mp_bluetooth_hci_poll_now/mp_bluetooth_hci_poll_in_ms instead. +void mp_bluetooth_hci_poll(void); + +#endif // MICROPY_INCLUDED_RP2_MPBTHCIPORT_H diff --git a/ports/samd/mpnimbleport.c b/ports/samd/mpnimbleport.c new file mode 100644 index 0000000000000..74e9ecb02602a --- /dev/null +++ b/ports/samd/mpnimbleport.c @@ -0,0 +1,80 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * Copyright (c) 2020 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. + */ + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/stream.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + +#define DEBUG_printf(...) // printf("mpnimbleport.c: " __VA_ARGS__) + +#include "host/ble_hs.h" +#include "nimble/nimble_npl.h" + +#include "extmod/modbluetooth.h" +#include "extmod/mpbthci.h" +#include "extmod/nimble/modbluetooth_nimble.h" +#include "extmod/nimble/hal/hal_uart.h" +#include "mpbthciport.h" + +// Get any pending data from the UART and send it to NimBLE's HCI buffers. +// Any further processing by NimBLE will be run via its event queue. +void mp_bluetooth_hci_poll(void) { + if (mp_bluetooth_nimble_ble_state >= MP_BLUETOOTH_NIMBLE_BLE_STATE_WAITING_FOR_SYNC) { + // DEBUG_printf("mp_bluetooth_hci_poll_uart %d\n", mp_bluetooth_nimble_ble_state); + + // Run any timers. + mp_bluetooth_nimble_os_callout_process(); + + // Process incoming UART data, and run events as they are generated. + mp_bluetooth_nimble_hci_uart_process(true); + + // Run any remaining events (e.g. if there was no UART data). + mp_bluetooth_nimble_os_eventq_run_all(); + } + + if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { + // Call this function again in 128ms to check for new events. + // TODO: improve this by only calling back when needed. + mp_bluetooth_hci_poll_in_ms(128); + } +} + +// --- Port-specific helpers for the generic NimBLE bindings. ----------------- + +void mp_bluetooth_nimble_hci_uart_wfi(void) { + #if defined(__WFI) + __WFI(); + #endif + // This is called while NimBLE is waiting in ble_npl_sem_pend, i.e. waiting for an HCI ACK. + // Do not need to run events here (it must not invoke Python code), only processing incoming HCI data. + mp_bluetooth_nimble_hci_uart_process(false); +} + +#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE diff --git a/ports/samd/mpnimbleport.h b/ports/samd/mpnimbleport.h new file mode 100644 index 0000000000000..64debea33a828 --- /dev/null +++ b/ports/samd/mpnimbleport.h @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jim Mussared + * + * 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_RP2_MPNIMBLEPORT_H +#define MICROPY_INCLUDED_RP2_MPNIMBLEPORT_H + +#endif // MICROPY_INCLUDED_RP2_MPNIMBLEPORT_H From 4cb73533b5c15c8bc7086b777dedafc6e34cae22 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 20 Apr 2023 15:21:43 +0200 Subject: [PATCH 05/10] samd/BLE: Change main.c, pendsv.h, mpconfigxxx.h and makefiles for BLE. Signed-off-by: robert-hh --- ports/samd/Makefile | 1 + ports/samd/main.c | 9 ++++++--- ports/samd/mcu/samd51/manifest.py | 8 ++++++++ ports/samd/mcu/samd51/mpconfigmcu.mk | 18 ++++++++++++++++++ ports/samd/pendsv.h | 3 +++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 3d35be02df514..259af4b51d990 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -37,6 +37,7 @@ FROZEN_MANIFEST ?= boards/manifest.py # Include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk +include ${TOP}/extmod/nimble/nimble.mk GIT_SUBMODULES += lib/asf4 lib/tinyusb diff --git a/ports/samd/main.c b/ports/samd/main.c index 09a15e30c6b08..13d8e46eaa938 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -37,6 +37,8 @@ #include "shared/runtime/softtimer.h" #include "shared/tinyusb/mp_usbd.h" #include "clock_config.h" +#include "extmod/modbluetooth.h" +#include "mpbthciport.h" extern uint8_t _sstack, _estack, _sheap, _eheap; extern void adc_deinit_all(void); @@ -52,11 +54,12 @@ void samd_main(void) { gc_init(&_sheap, &_eheap); mp_init(); - // Initialise sub-systems. - readline_init0(); #if MICROPY_PY_BLUETOOTH - // mp_bluetooth_hci_init(); + mp_bluetooth_hci_init(); #endif + + // Initialise sub-systems. + readline_init0(); #if MICROPY_PY_NETWORK mod_network_init(); #endif diff --git a/ports/samd/mcu/samd51/manifest.py b/ports/samd/mcu/samd51/manifest.py index 2a19a843f8a9b..f9e96872bc1fd 100644 --- a/ports/samd/mcu/samd51/manifest.py +++ b/ports/samd/mcu/samd51/manifest.py @@ -3,3 +3,11 @@ require("onewire") require("ds18x20") require("dht") + +include( + "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py", + client=True, + central=True, + l2cap=True, + security=True, +) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 1439b6ee61cc0..324106a1877c7 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -10,16 +10,22 @@ 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 +MICROPY_PY_BLUETOOTH ?= 1 +MICROPY_BLUETOOTH_NIMBLE ?= 1 endif ifeq ($(MICROPY_HW_CODESIZE),1008K) MICROPY_PY_SSL ?= 1 MICROPY_SSL_MBEDTLS ?= 1 +MICROPY_PY_BLUETOOTH ?= 1 +MICROPY_BLUETOOTH_NIMBLE ?= 1 endif + endif ifeq ($(MICROPY_PY_NETWORK),1) @@ -59,3 +65,15 @@ SRC_C += \ nina_wifi_bsp.c endif + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE), 1) +SRC_C += \ + mpbthciport.c \ + mpnimbleport.c + +INC += \ + -I$(TOP)/extmod/nimble \ + -I$(TOP)/lib/mynewt-nimble/nimble/host/include \ + -I$(TOP)/lib/mynewt-nimble/nimble/include \ + -I$(TOP)/lib/mynewt-nimble/porting/nimble/include +endif diff --git a/ports/samd/pendsv.h b/ports/samd/pendsv.h index 6671fa4e28a84..b5c4e10d40c10 100644 --- a/ports/samd/pendsv.h +++ b/ports/samd/pendsv.h @@ -28,6 +28,9 @@ enum { PENDSV_DISPATCH_SOFT_TIMER, // For later & for having at least one entry + #if MICROPY_PY_BLUETOOTH && !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS + PENDSV_DISPATCH_BLUETOOTH_HCI, + #endif MICROPY_BOARD_PENDSV_ENTRIES PENDSV_DISPATCH_MAX }; From a0fef6e7195d399dc1c7ba15a935f0b99cdf3a3c Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 20 Apr 2023 15:27:46 +0200 Subject: [PATCH 06/10] samd/BLE: Add the BLE pin configuration to the mpconfigboard.h files. Signed-off-by: robert-hh --- .../ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h | 12 ++++++++++++ .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h | 13 +++++++++++++ .../SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h | 12 ++++++++++++ 3 files changed, 37 insertions(+) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h index 570355441fc94..c80fb70e3b989 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h @@ -16,3 +16,15 @@ #define MICROPY_HW_NINA_ACK (21) #define MICROPY_HW_NINA_CS (23) #define MICROPY_HW_NINA_RESET (22) + +// defines for BLE +#define MICROPY_PY_BLUETOOTH_NINAW10 (1) + +#define MICROPY_HW_BLE_UART_ID (5) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) + +#define MICROPY_HW_BLE_UART_TX (48) +#define MICROPY_HW_BLE_UART_RX (49) + +#define MICROPY_HW_NINA_RTS (55) +#define MICROPY_HW_NINA_CTS (21) diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h index e217a6e3aa1bc..1bda9991a9261 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -4,6 +4,7 @@ #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) @@ -16,3 +17,15 @@ #define MICROPY_HW_NINA_CS (22) #define MICROPY_HW_NINA_ACK (21) #define MICROPY_HW_NINA_RESET (23) + +// defines for BLE +#define MICROPY_PY_BLUETOOTH_NINAW10 (1) + +#define MICROPY_HW_BLE_UART_ID (3) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) + +#define MICROPY_HW_BLE_UART_TX (17) +#define MICROPY_HW_BLE_UART_RX (16) + +#define MICROPY_HW_NINA_RTS (0) +#define MICROPY_HW_NINA_CTS (21) diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h index bb70781e667aa..7a6266319222f 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h @@ -24,3 +24,15 @@ #define MICROPY_HW_NINA_ACK (16) #define MICROPY_HW_NINA_CS (17) #define MICROPY_HW_NINA_RESET (19) + +// defines for BLE +#define MICROPY_PY_BLUETOOTH_NINAW10 (1) + +#define MICROPY_HW_BLE_UART_ID (2) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) + +#define MICROPY_HW_BLE_UART_TX (12) +#define MICROPY_HW_BLE_UART_RX (13) + +#define MICROPY_HW_NINA_RTS (44) +#define MICROPY_HW_NINA_CTS (16) From 684bdbaf6145d77caa19e5baa89ba19561f71957 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 16 Nov 2023 21:16:56 +0100 Subject: [PATCH 07/10] samd: Re-arrange the makefiles for the Variants WLAN and WLAN_BLE. Variant WLAN: Support for WiFi. For the Adafruit Metro M4 board, this is the default. At boards with small available flash, SSL is not supported. Variant WLAN_BLE: Support for WiFi and BLE. Signed-off-by: robert-hh --- .../ADAFRUIT_FEATHER_M4_EXPRESS/board.json | 3 +- .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json | 3 +- .../ADAFRUIT_METRO_M4_EXPRESS/board.json | 3 + .../mpconfigboard.mk | 8 +- .../SPARKFUN_SAMD51_THING_PLUS/board.json | 3 +- ports/samd/main.c | 1 - ports/samd/mcu/samd51/manifest.py | 8 -- ports/samd/mcu/samd51/manifest_net.py | 8 ++ ports/samd/mcu/samd51/mpconfigmcu.mk | 101 +++++++----------- 9 files changed, 58 insertions(+), 80 deletions(-) diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json index faeb0c780e979..02eec091ccf11 100644 --- a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json @@ -15,7 +15,8 @@ ], "mcu": "samd51", "variants": { - "WLAN": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware", + "WLAN_BLE": "WiFi and BLE support using a ESP32 module with NINA firmware" }, "product": "Feather M4 Express", "thumbnail": "", diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json index c596b7a7ae359..4d0be6bbe4e13 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.json @@ -13,7 +13,8 @@ ], "mcu": "samd51", "variants": { - "WLAN": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware", + "WLAN_BLE": "WiFi and BLE support using a ESP32 module with NINA firmware" }, "product": "ItsyBitsy M4 Express", "thumbnail": "", diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json index 4a3158d71334c..bde0cd8fa9777 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/board.json @@ -15,6 +15,9 @@ "metro_m4_express_airlift.jpg" ], "mcu": "samd51", + "variants": { + "WLAN_BLE": "WiFi and BLE support using a ESP32 module with NINA firmware" + }, "product": "Metro M4 Express Airlift", "thumbnail": "", "url": "https://www.adafruit.com/product/4000", diff --git a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk index 4ab61a4b9da5e..d1826351a76e7 100644 --- a/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk +++ b/ports/samd/boards/ADAFRUIT_METRO_M4_EXPRESS/mpconfigboard.mk @@ -3,10 +3,6 @@ CMSIS_MCU = SAMD51J19A LD_FILES = boards/samd51x19a.ld sections.ld TEXT0 = 0x4000 -# MicroPython settings -MICROPY_PY_NETWORK = 1 -MICROPY_PY_NETWORK_NINAW10 = 1 -MICROPY_PY_SSL = 1 -MICROPY_SSL_MBEDTLS = 1 - MICROPY_HW_CODESIZE = 496K + +BOARD_VARIANT ?= WLAN diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json index 7dcb836512fe2..13ad1afc05c33 100644 --- a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json +++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json @@ -14,7 +14,8 @@ ], "mcu": "samd51", "variants": { - "WLAN": "WiFi support using a ESP32 module with NINA firmware" + "WLAN": "WiFi support using a ESP32 module with NINA firmware", + "WLAN_BLE": "WiFi and BLE support using a ESP32 module with NINA firmware" }, "product": "Sparkfun SAMD51 Thing Plus", "thumbnail": "", diff --git a/ports/samd/main.c b/ports/samd/main.c index 13d8e46eaa938..e9ba2971e212f 100644 --- a/ports/samd/main.c +++ b/ports/samd/main.c @@ -29,7 +29,6 @@ #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" diff --git a/ports/samd/mcu/samd51/manifest.py b/ports/samd/mcu/samd51/manifest.py index f9e96872bc1fd..2a19a843f8a9b 100644 --- a/ports/samd/mcu/samd51/manifest.py +++ b/ports/samd/mcu/samd51/manifest.py @@ -3,11 +3,3 @@ require("onewire") require("ds18x20") require("dht") - -include( - "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py", - client=True, - central=True, - l2cap=True, - security=True, -) diff --git a/ports/samd/mcu/samd51/manifest_net.py b/ports/samd/mcu/samd51/manifest_net.py index 6353bdb47eb6a..b0554adc1960e 100644 --- a/ports/samd/mcu/samd51/manifest_net.py +++ b/ports/samd/mcu/samd51/manifest_net.py @@ -6,3 +6,11 @@ require("dht") # Networking require("bundle-networking") +# BLE +include( + "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py", + client=True, + central=True, + l2cap=True, + security=True, +) diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk index 324106a1877c7..7dedcb1fdcbf2 100644 --- a/ports/samd/mcu/samd51/mpconfigmcu.mk +++ b/ports/samd/mcu/samd51/mpconfigmcu.mk @@ -9,71 +9,48 @@ 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 -MICROPY_PY_BLUETOOTH ?= 1 -MICROPY_BLUETOOTH_NIMBLE ?= 1 -endif -ifeq ($(MICROPY_HW_CODESIZE),1008K) -MICROPY_PY_SSL ?= 1 -MICROPY_SSL_MBEDTLS ?= 1 -MICROPY_PY_BLUETOOTH ?= 1 -MICROPY_BLUETOOTH_NIMBLE ?= 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 + fatfs_port.c UF2CONV_FLAGS += -f 0x55114460 -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 - -SRC_C += \ - nina_wifi_bsp.c - -endif - -ifeq ($(MICROPY_BLUETOOTH_NIMBLE), 1) -SRC_C += \ - mpbthciport.c \ - mpnimbleport.c - -INC += \ - -I$(TOP)/extmod/nimble \ - -I$(TOP)/lib/mynewt-nimble/nimble/host/include \ - -I$(TOP)/lib/mynewt-nimble/nimble/include \ - -I$(TOP)/lib/mynewt-nimble/porting/nimble/include +ifneq ($(BOARD_VARIANT),) + MICROPY_PY_NETWORK ?= 1 + CFLAGS += -DMICROPY_PY_NETWORK=1 + MICROPY_PY_NETWORK_NINAW10 ?= 1 + CFLAGS += -DMICROPY_PY_NETWORK_NINAW10=1 + + INC += -I$(TOP)/drivers/ninaw10 + SRC_C += \ + mbedtls/mbedtls_port.c\ + nina_wifi_bsp.c + SHARED_SRC_C += \ + shared/netutils/dhcpserver.c \ + shared/netutils/netutils.c \ + shared/netutils/trace.c + 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 + + ifeq ($(MICROPY_HW_CODESIZE),$(filter $(MICROPY_HW_CODESIZE), 496K 1008K)) + MICROPY_PY_SSL ?= 1 + MICROPY_SSL_MBEDTLS ?= 1 + + ifeq ($(BOARD_VARIANT),WLAN_BLE) + MICROPY_PY_BLUETOOTH ?= 1 + MICROPY_BLUETOOTH_NIMBLE ?= 1 + SRC_C += \ + mpbthciport.c \ + mpnimbleport.c + + INC += \ + -I$(TOP)/extmod/nimble + endif + endif + FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest_net.py +else + FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py endif From ef45e079f5c3dd0d9938c7fa7f2d6444e3ec389d Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 17 Nov 2023 15:18:47 +0100 Subject: [PATCH 08/10] samd: Add the WLAN/BLE pin-out documentation to the docs. Signed-off-by: robert-hh --- docs/samd/quickref.rst | 53 +++++++++++ docs/samd/wlan_pinout.rst | 189 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 docs/samd/wlan_pinout.rst diff --git a/docs/samd/quickref.rst b/docs/samd/quickref.rst index 25b5a8fc8ab2b..32d7138124ca0 100644 --- a/docs/samd/quickref.rst +++ b/docs/samd/quickref.rst @@ -18,6 +18,7 @@ working with this board it may be useful to get an overview of the microcontroll general.rst tutorial/intro.rst pinout.rst + wlan_pinout.rst Installing MicroPython @@ -511,6 +512,58 @@ with the Neopixel driver from the MicroPython driver library:: machine.bitstream() is set up for a SAMD21 clock frequency of 48MHz and a SAMD51 clock frequency of 120 MHz. At other clock frequencies, the timing will not fit. +WLAN and BLE +------------ + +Some boards can be combined with an ESP32 based WLAN module to support +WLAN and BLE connectivity. WLAN is then another class +of the the :mod:`network` module.:: + + import network + + wlan = network.WLAN(network.STA_IF) # create station interface + 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 + + ap = network.WLAN(network.AP_IF) # create access-point interface + ap.active(True) # activate the interface + ap.config(ssid='ESP-AP') # set the SSID of the access point + +A useful function for connecting to your local WiFi network is:: + + def do_connect(): + import network + wlan = network.WLAN(network.STA_IF) + wlan.active(True) + if not wlan.isconnected(): + print('connecting to network...') + wlan.connect('ssid', 'key') + while not wlan.isconnected(): + pass + print('network config:', wlan.ifconfig()) + +Once the network is established the :mod:`socket ` module can be used +to create and use TCP/UDP sockets as usual, and the ``requests`` module for +convenient HTTP requests. + +Supported boards are: + +- Adafruit Metro M4 Airlift: WLAN adapter built-in +- Adafruit ItsyBitsy M4 with e.g. the Adafruit ItsyBity Airlift boards +- Adafruit Feather M4 with e.g. the Adafruit Feather Airlift boards +- Sparkfun SAMD51 Things Plus with e.g. the Adafruit Feather Airlift boards +- Adafruit Grand Central M4 with e.g. the Adafruit Airlift Uno board + +More boards may support it. Basic WiFi support could even be provided +for SAMD21 board with external flash. As external +WLAN module, any ESP32 based breakout can be used. It has to be loaded +with the proper firmware and wired up accordingly. For the wiring +scheme, see the :ref:`WLAN connection scheme `. + Transferring files ------------------ diff --git a/docs/samd/wlan_pinout.rst b/docs/samd/wlan_pinout.rst new file mode 100644 index 0000000000000..799ca7923134b --- /dev/null +++ b/docs/samd/wlan_pinout.rst @@ -0,0 +1,189 @@ +.. _samd_wlan_pinout: + +Managing external WLAN/BLE adapters +=================================== + +Connection scheme for the SAMD WLAN adapters +-------------------------------------------- + +Mapping between the NINA/esp_hosted signals and board pins by name and number. + +======== ========== ======== ========= ========= ============== ========= ========== +NINAW10 esp_hosted Airlift ItsyBitsy Feather METRO M4 Sparkfun Grand Ctrl +Name Name Name M4 M4 Airlift SAMD51 M4 Express +======== ========== ======== ========= ========= ============== ========= ========== +MOSI/RTS MOSI MOSI MOSI (0) MOSI (55) MOSI (12) MOSI (44) D11 (55) +MISO MISO MISO MISO (55) MISO (54) MISO (14) MISO (43) D12 (32) +SCK SCK SCK SCK (1) SCK (17) SCK (13) SCK (45) D13 (33) +CS CS CS D13 (22) D13 (23) ESP_CS (15) D13 (17) D10 (54) +ACK/CTS HANDSHAKE Busy D11 (21) D11 (21) ESP_BUSY (36) D11 (16) D7 (117) +RESET RESET Reset D12 (23) D12 (22) ESP_RESET (37) D12 (19) D5 (85) +GPIO0 DATAREADY GP0 D10 (20) D10 (20) ESP_GPIO0 (33) D10 (18) D6 (116) +SPI # 1 1 1 4 5 +TX TX TX D0 (16) D0 (49) D0 (7) D0 (13) D1 (56) +RX TX RX D1 ( 17) D1 (48) D1 (4) D1 (12) D0 (57) +RTS MOSI/RTS RTS MOSI (0) MOSI (55) MOSI (12) MOSI (44) MOSI (55) +CTS CTS CTS D11 (21) D11 (21) ESP_BUSY (36) D11 (16) D7 (117) +UART # 3 5 0 2 ? +======== ========== ======== ========= ========= ============== ========= ========== + +Mapping between firmware signal names and ESP32 pins for the NINA firmware +and esp_hosted firmware + +======== ========== ======== ======= ======= +NINAW10 esp_hosted NINA Airlift Airlift +Name Name W102 pin Name pin +======== ========== ======== ======= ======= +MOSI MOSI 12 MOSI 14 +MISO MISO 23 MISO 23 +SCK SCK 18 SCK 18 +GPIO1/CS CS 5 CS 5 +ACK HANDSHAKE 33 Busy 33 +RESET RESET EN Reset EN +GPIO0 DATAREADY 0 GP0 0 +TX TX 1 TX 1 +RX TX 3 RX 3 +RTS MOSI/RTS 12 - 14 +CTS CTS 33 - 33 +======== ========== ======== ======= ======= + +Mapping between the NINA/esp_hosted signals and adapter pins by name. + +======== ========== ======= ========= ======== ========= ========== +NINAW10 esp_hosted Airlift ItsyBitsy Feather METRO M4 Airlift +Name Name Name Add-on Add-on Airlift Uno Shield +======== ========== ======= ========= ======== ========= ========== +MOSI MOSI MOSI MOSI MOSI MOSI MOSI +MISO MISO MISO MISO MISO MISO MISO +SCK SCK SCK SCK SCK SCK SCK +GPIO1/CS CS CS ECS ESPCS ESP_CS CS +ACK HANDSHAKE Busy EBSY ESPBUSY ESP_BUSY BUSY +RESET RESET Reset RST ESPRESET ESP_RESET RST +GPIO0 DATAREADY GP0 GPIO0 ESPGPIO0 ESP_GP0 G0 +TX TX TX ETX ESPTX ESP_TX TX +RX RX RX ERX ESPRX ESP_RX RX +======== ========== ======= ========= ======== ========= ========== + +Signals required for WiFi: + +- NinaW10: MISO/MOSI/SCK (SPI), CS, Busy (ACK), Reset +- esp_hosted: MISO/MOSI/SCK (SPI), CS, Handshake, Dataready, Reset + +Signals required for Bluetooth: + +- NinaW10: RX/TX (UART), RTS (MOSI), CS, RESET +- esp_hosted: RX/TX (UART), RTS (MOSI), CS, RESET + +CTS seems not to be used for the NINA firmware, but specified. + +Signals required for NINA/esp_hosted firmware upload: + +- RX/TX (UART), GPIO0, Reset. + +If the hardware supports it, pull RESET low (!). That keeps the +ESP32 with the NINA/esp_hosted firmware silent and at low power +when not being used. + + +.. _samd_wlan_firmware_upload: + +Instructions for WLAN/BLE firmware upload ESP32 module +------------------------------------------------------ + +The NINA firmware in the NINA module has to be updated for use with MicroPython. That can be done +using MicroPython and two small Python scripts. + +The firmware binaries are available at +https://github.com/micropython/micropython-lib/tree/master/micropython/espflash +There are the firmware files available for different esp32 modules. + +1. Adafruit Airlift modules with NINA firmware: NINA_FW_v1.5.0_Airlift.bin. +2. Adafruit Airlift modules with esp_hosted firmware: esp_hosted_airlift.bin +3. Arduino Nano RP2040 connect: NINA_FW_v1.5.0_W102.bin + +Depending on the firmware for the SAMD boards you need the file +NINA_FW_v1.5.0_Airlift.bin or esp_hosted_airlift.bin. + +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. See the tables above. +At the Adafruit Metro M4 board for instance, the UART is UART(5), and the Pin names +for reset and GPIO0 are ESP_RESET and ESP_GPIO0. +The firmware can be uploaded, using the espflash.py module, a short script +using espflash.py and mpremote. espflash.py 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("/") + + reset = Pin(37, Pin.OUT) + gpio0 = Pin(33, Pin.OUT) + uart = UART(0, 115200, tx=4, rx=7, timeout=350) + + md5sum = b"b0b9ab23da820a469e597c41364acb3a" + path = "/remote/NINA_FW_v1.5.0_Airlift.bin" + # md5sum = b"28ab84372ff4f07551b984671f7f9ff9" + # path = "/remote/esp_hosted_airlift.bin" + + esp = espflash.ESPFlash(reset, gpio0, uart) + # Enter bootloader download mode, at 115200 + esp.bootloader() + # Can now change to higher/lower baudrate + 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() + +The script shows the set-up for the Metro M4 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:: + + mpremote 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. From 4a3b64527cef74b228d5dbf6f9e0a5ab31a09870 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Fri, 1 Dec 2023 15:40:44 +0100 Subject: [PATCH 09/10] samd/mbedtls: Add time and date functions for mbedtls. Signed-off-by: robert-hh --- ...mbedtls_config.h => mbedtls_config_port.h} | 6 +++ ports/samd/mbedtls/mbedtls_port.c | 46 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) rename ports/samd/mbedtls/{mbedtls_config.h => mbedtls_config_port.h} (88%) diff --git a/ports/samd/mbedtls/mbedtls_config.h b/ports/samd/mbedtls/mbedtls_config_port.h similarity index 88% rename from ports/samd/mbedtls/mbedtls_config.h rename to ports/samd/mbedtls/mbedtls_config_port.h index 4140bb5145555..18cedbae10fc9 100644 --- a/ports/samd/mbedtls/mbedtls_config.h +++ b/ports/samd/mbedtls/mbedtls_config_port.h @@ -26,6 +26,12 @@ #ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H #define MICROPY_INCLUDED_MBEDTLS_CONFIG_H +// Time hook. +#include +extern time_t samd_rtctime_seconds(time_t *timer); +#define MBEDTLS_PLATFORM_TIME_MACRO samd_rtctime_seconds +#define MBEDTLS_PLATFORM_MS_TIME_ALT mbedtls_ms_time + // Set MicroPython-specific options. #define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) diff --git a/ports/samd/mbedtls/mbedtls_port.c b/ports/samd/mbedtls/mbedtls_port.c index d2509488bfa7a..da6059ca6b651 100644 --- a/ports/samd/mbedtls/mbedtls_port.c +++ b/ports/samd/mbedtls/mbedtls_port.c @@ -26,9 +26,16 @@ #ifdef MICROPY_SSL_MBEDTLS -#include "mbedtls_config.h" +#include "mbedtls_config_port.h" #include -uint32_t trng_random_u32(); +uint32_t trng_random_u32(void); +#if defined(MBEDTLS_HAVE_TIME) || defined(MBEDTLS_HAVE_TIME_DATE) +#include +#include "py/runtime.h" +#include "shared/timeutils/timeutils.h" +#include "mbedtls/platform_time.h" +extern void rtc_gettime(timeutils_struct_time_t *tm); +#endif int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { @@ -40,3 +47,38 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t } #endif + +#if defined(MBEDTLS_HAVE_TIME) +time_t samd_rtctime_seconds(time_t *timer) { + timeutils_struct_time_t tm; + rtc_gettime(&tm); + return timeutils_seconds_since_epoch(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); +} + +mbedtls_ms_time_t mbedtls_ms_time(void) { + time_t *tv = NULL; + mbedtls_ms_time_t current_ms; + current_ms = samd_rtctime_seconds(tv) * 1000; + return current_ms; +} +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) +struct tm *gmtime(const time_t *timep) { + static struct tm tm; + timeutils_struct_time_t tm_buf = {0}; + timeutils_seconds_since_epoch_to_struct_time(*timep, &tm_buf); + + tm.tm_sec = tm_buf.tm_sec; + tm.tm_min = tm_buf.tm_min; + tm.tm_hour = tm_buf.tm_hour; + tm.tm_mday = tm_buf.tm_mday; + tm.tm_mon = tm_buf.tm_mon - 1; + tm.tm_year = tm_buf.tm_year - 1900; + tm.tm_wday = tm_buf.tm_wday; + tm.tm_yday = tm_buf.tm_yday; + tm.tm_isdst = -1; + + return &tm; +} +#endif From 8cc39d50fc979be6e5427482b2b2cc4cadedd584 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sat, 18 May 2024 17:20:50 +0200 Subject: [PATCH 10/10] samd/boards/deploy.md: Update the deploy instructions. Telling how to update the firmware of the WiFi/BLE module. Signed-off-by: robert-hh --- ports/samd/boards/deploy.md | 167 ++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 5 deletions(-) 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. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy