This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit bdb997f1430e9df05e3f2ac862e4e703b72a875d Author: Alan Carvalho de Assis <[email protected]> AuthorDate: Sat Oct 17 17:54:59 2026 -0300 boards/weact-stm32h743: add Wi-Fi HaLow support Add support for a Morse Micro based Wi-Fi HaLow module (Seeed Studio XIAO Wi-Fi HaLow, Quectel FGH100M-H) connected to SPI1 and a new "halow" configuration with networking, wapi and DHCP. - stm32_morse.c: Morse driver lower half (RESET PA2, IRQ PA1/EXTI1, CS PA4). WAKE (PA3) and BUSY (PA0) are only used with CONFIG_WEACT_STM32H743_HALOW_POWERSAVE, since they are not connected on the Seeed module. - SPI1 pins use the lowest slew rate: with jumper wires faster edges double clock the module. - SPI123 kernel clock from PLL2P (75 MHz): PLL1Q (240 MHz) exceeds the 200 MHz limit and SPI1 could not be enabled. - Add the missing sources and the linker script to the CMake build. - halow: enable the RNG and HSI48 (RNG kernel clock) needed by WPA3-SAE. Signed-off-by: Alan Carvalho de Assis <[email protected]> Assisted-by: Claude Code Opus 5.5 --- boards/arm/stm32h7/weact-stm32h743/Kconfig | 12 ++ .../weact-stm32h743/configs/halow/defconfig | 79 ++++++++ boards/arm/stm32h7/weact-stm32h743/include/board.h | 14 +- .../arm/stm32h7/weact-stm32h743/src/CMakeLists.txt | 8 +- boards/arm/stm32h7/weact-stm32h743/src/Make.defs | 4 + .../stm32h7/weact-stm32h743/src/stm32_bringup.c | 11 ++ .../arm/stm32h7/weact-stm32h743/src/stm32_morse.c | 206 +++++++++++++++++++++ boards/arm/stm32h7/weact-stm32h743/src/stm32_spi.c | 23 +++ .../stm32h7/weact-stm32h743/src/weact-stm32h743.h | 24 +++ 9 files changed, 378 insertions(+), 3 deletions(-) diff --git a/boards/arm/stm32h7/weact-stm32h743/Kconfig b/boards/arm/stm32h7/weact-stm32h743/Kconfig index 8b54c4f53ab..dba616a7cc8 100644 --- a/boards/arm/stm32h7/weact-stm32h743/Kconfig +++ b/boards/arm/stm32h7/weact-stm32h743/Kconfig @@ -5,4 +5,16 @@ if ARCH_BOARD_WEACT_STM32H743 +config WEACT_STM32H743_HALOW_POWERSAVE + bool "HaLow module WAKE and BUSY lines connected" + default n + depends on IEEE80211_MORSE + ---help--- + Select this if the WAKE (PA3) and BUSY (PA0) lines of the Morse + Micro HaLow module are connected, which enables the chip power + save. On the Seeed Studio XIAO Wi-Fi HaLow module (Quectel + FGH100M-H) these signals are not connected by default (the series + resistors are not populated), in which case the chip is kept + always awake. + endif # ARCH_BOARD_WEACT_STM32H743 diff --git a/boards/arm/stm32h7/weact-stm32h743/configs/halow/defconfig b/boards/arm/stm32h7/weact-stm32h743/configs/halow/defconfig new file mode 100644 index 00000000000..91e0035b9e2 --- /dev/null +++ b/boards/arm/stm32h7/weact-stm32h743/configs/halow/defconfig @@ -0,0 +1,79 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_NETINIT is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="weact-stm32h743" +CONFIG_ARCH_BOARD_WEACT_STM32H743=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32H743VI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_URANDOM=y +CONFIG_DEV_URANDOM_XORSHIFT128=y +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IEEE80211_MORSE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_INTELHEX_BINARY=y +CONFIG_IOB_NBUFFERS=64 +CONFIG_LINE_MAX=64 +CONFIG_MM_REGIONS=4 +CONFIG_NET=y +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_IPERF=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_TCP=y +CONFIG_NET_UDP=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_VCONFIG=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=11 +CONFIG_START_MONTH=5 +CONFIG_START_YEAR=2024 +CONFIG_STM32_HSI48=y +CONFIG_STM32_RNG=y +CONFIG_STM32_SPI1=y +CONFIG_STM32_USART1=y +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TASK_NAME_SIZE=16 +CONFIG_USART1_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y +CONFIG_WIRELESS_WAPI_STACKSIZE=4096 diff --git a/boards/arm/stm32h7/weact-stm32h743/include/board.h b/boards/arm/stm32h7/weact-stm32h743/include/board.h index 706e25d66e0..940e49b158c 100644 --- a/boards/arm/stm32h7/weact-stm32h743/include/board.h +++ b/boards/arm/stm32h7/weact-stm32h743/include/board.h @@ -239,9 +239,9 @@ #define STM32_RCC_D3CCIPR_I2C4SRC RCC_D3CCIPR_I2C4SEL_HSI -/* SPI123 clock source - PLL1Q */ +/* SPI123 clock source - PLL2P (75 MHz, kernel clock must be <= 200 MHz) */ -#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL1 +#define STM32_RCC_D2CCIP1R_SPI123SRC RCC_D2CCIP1R_SPI123SEL_PLL2 /* SPI45 clock source - APB (PCLK2?) */ @@ -375,6 +375,16 @@ #define GPIO_SPI4_MOSI (GPIO_SPI4_MOSI_1 | GPIO_SPEED_50MHz) /* PE14 */ #define GPIO_SPI4_MISO 0 +/* SPI1 - Morse Micro HaLow module (Quectel FGH100M) + * + * SCK and MOSI use the lowest slew rate: with jumper wires the ringing of + * fast edges double clocks the module SPI interface. + */ + +#define GPIO_SPI1_SCK (GPIO_SPI1_SCK_1 | GPIO_SPEED_2MHz) /* PA5 */ +#define GPIO_SPI1_MISO (GPIO_SPI1_MISO_1 | GPIO_SPEED_2MHz) /* PA6 */ +#define GPIO_SPI1_MOSI (GPIO_SPI1_MOSI_1 | GPIO_SPEED_2MHz) /* PA7 */ + /* OTGFS */ #define GPIO_OTGFS_DM (GPIO_OTGFS_DM_0|GPIO_SPEED_100MHz) /* PA11 */ diff --git a/boards/arm/stm32h7/weact-stm32h743/src/CMakeLists.txt b/boards/arm/stm32h7/weact-stm32h743/src/CMakeLists.txt index a6cc9b3cca4..a9a92c5fd27 100644 --- a/boards/arm/stm32h7/weact-stm32h743/src/CMakeLists.txt +++ b/boards/arm/stm32h7/weact-stm32h743/src/CMakeLists.txt @@ -20,7 +20,7 @@ # # ############################################################################## -set(SRCS stm32_boot.c stm32_bringup.c) +set(SRCS stm32_boot.c stm32_bringup.c stm32_usb.c stm32_ioctl.c stm32_spi.c) if(CONFIG_ARCH_LEDS) list(APPEND SRCS stm32_autoleds.c) @@ -36,12 +36,18 @@ if(CONFIG_STM32_SDMMC) list(APPEND SRCS stm32_sdmmc.c) endif() +if(CONFIG_IEEE80211_MORSE) + list(APPEND SRCS stm32_morse.c) +endif() + if(CONFIG_FAT_DMAMEMORY) list(APPEND SRCS stm32_dma_alloc.c) endif() target_sources(board PRIVATE ${SRCS}) +set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") + if(NOT CONFIG_BUILD_FLAT) add_subdirectory(${NUTTX_BOARD_DIR}/kernel) set_property( diff --git a/boards/arm/stm32h7/weact-stm32h743/src/Make.defs b/boards/arm/stm32h7/weact-stm32h743/src/Make.defs index e80f8d117c9..e9a06f29c03 100644 --- a/boards/arm/stm32h7/weact-stm32h743/src/Make.defs +++ b/boards/arm/stm32h7/weact-stm32h743/src/Make.defs @@ -36,6 +36,10 @@ ifeq ($(CONFIG_STM32_SDMMC),y) CSRCS += stm32_sdmmc.c endif +ifeq ($(CONFIG_IEEE80211_MORSE),y) +CSRCS += stm32_morse.c +endif + ifeq ($(CONFIG_FAT_DMAMEMORY),y) CSRCS += stm32_dma_alloc.c endif diff --git a/boards/arm/stm32h7/weact-stm32h743/src/stm32_bringup.c b/boards/arm/stm32h7/weact-stm32h743/src/stm32_bringup.c index a69d806e8bf..e6438853fce 100644 --- a/boards/arm/stm32h7/weact-stm32h743/src/stm32_bringup.c +++ b/boards/arm/stm32h7/weact-stm32h743/src/stm32_bringup.c @@ -96,6 +96,17 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_IEEE80211_MORSE + /* Initialize the Morse Micro HaLow network driver */ + + ret = stm32_morse_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_morse_initialize() failed: %d\n", + ret); + } +#endif + #ifdef CONFIG_VIDEO_FB /* Initialize and register the framebuffer driver */ diff --git a/boards/arm/stm32h7/weact-stm32h743/src/stm32_morse.c b/boards/arm/stm32h7/weact-stm32h743/src/stm32_morse.c new file mode 100644 index 00000000000..fee519997e4 --- /dev/null +++ b/boards/arm/stm32h7/weact-stm32h743/src/stm32_morse.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * boards/arm/stm32h7/weact-stm32h743/src/stm32_morse.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <debug.h> +#include <errno.h> +#include <stdbool.h> + +#include <nuttx/arch.h> +#include <nuttx/spi/spi.h> +#include <nuttx/wireless/morse.h> + +#include "stm32_gpio.h" +#include "stm32_spi.h" +#include "weact-stm32h743.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The HaLow module is wired to SPI1 */ + +#define HALOW_SPI_BUS 1 + +/* EXTI line interrupts of the IRQ (PA1) and BUSY (PA0) pins */ + +#define HALOW_IRQ_IRQ STM32_IRQ_EXTI1 +#define HALOW_BUSY_IRQ STM32_IRQ_EXTI0 + +/* With jumper wires the SPI clock ringing limits the bus to ~20 MHz */ + +#define HALOW_SPI_FREQ 20000000 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void halow_reset(const struct morse_lower_s *lower, bool assert); +#ifdef CONFIG_WEACT_STM32H743_HALOW_POWERSAVE +static void halow_wake(const struct morse_lower_s *lower, bool assert); +static bool halow_busy(const struct morse_lower_s *lower); +static int halow_busy_attach(const struct morse_lower_s *lower, + xcpt_t handler, void *arg); +static void halow_busy_enable(const struct morse_lower_s *lower, + bool enable); +#endif +static bool halow_irq_asserted(const struct morse_lower_s *lower); +static int halow_irq_attach(const struct morse_lower_s *lower, + xcpt_t handler, void *arg); +static void halow_irq_enable(const struct morse_lower_s *lower, + bool enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct morse_lower_s g_halow_lower = +{ + .devid = SPIDEV_WIRELESS(0), + .frequency = HALOW_SPI_FREQ, + .reset = halow_reset, +#ifdef CONFIG_WEACT_STM32H743_HALOW_POWERSAVE + .wake = halow_wake, + .busy = halow_busy, + .busy_attach = halow_busy_attach, + .busy_enable = halow_busy_enable, +#endif + .irq_asserted = halow_irq_asserted, + .irq_attach = halow_irq_attach, + .irq_enable = halow_irq_enable, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void halow_reset(const struct morse_lower_s *lower, bool assert) +{ + stm32_gpiowrite(GPIO_HALOW_RESET, !assert); +} + +static bool halow_irq_asserted(const struct morse_lower_s *lower) +{ + return !stm32_gpioread(GPIO_HALOW_IRQ); +} + +static int halow_irq_attach(const struct morse_lower_s *lower, + xcpt_t handler, void *arg) +{ + /* The IRQ line is active low: interrupt on the falling edge */ + + return stm32_gpiosetevent(GPIO_HALOW_IRQ, false, true, true, + handler, arg); +} + +static void halow_irq_enable(const struct morse_lower_s *lower, + bool enable) +{ + /* EXTI1 has a dedicated NVIC vector: this is safe from an ISR */ + + if (enable) + { + up_enable_irq(HALOW_IRQ_IRQ); + } + else + { + up_disable_irq(HALOW_IRQ_IRQ); + } +} + +#ifdef CONFIG_WEACT_STM32H743_HALOW_POWERSAVE +static void halow_wake(const struct morse_lower_s *lower, bool assert) +{ + stm32_gpiowrite(GPIO_HALOW_WAKE, assert); +} + +static bool halow_busy(const struct morse_lower_s *lower) +{ + return stm32_gpioread(GPIO_HALOW_BUSY); +} + +static int halow_busy_attach(const struct morse_lower_s *lower, + xcpt_t handler, void *arg) +{ + return stm32_gpiosetevent(GPIO_HALOW_BUSY, true, false, true, + handler, arg); +} + +static void halow_busy_enable(const struct morse_lower_s *lower, + bool enable) +{ + if (enable) + { + up_enable_irq(HALOW_BUSY_IRQ); + } + else + { + up_disable_irq(HALOW_BUSY_IRQ); + } +} +#endif /* CONFIG_WEACT_STM32H743_HALOW_POWERSAVE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_morse_initialize + * + * Description: + * Configure the HaLow module control lines and register the Morse Micro + * HaLow network driver. + * + ****************************************************************************/ + +int stm32_morse_initialize(void) +{ + struct spi_dev_s *spi; + + /* RESET_N is held low until the driver boots the chip */ + + stm32_configgpio(GPIO_HALOW_RESET); + stm32_configgpio(GPIO_HALOW_IRQ); + stm32_configgpio(GPIO_HALOW_WAKE); + +#ifdef CONFIG_WEACT_STM32H743_HALOW_POWERSAVE + stm32_configgpio(GPIO_HALOW_BUSY); +#else + /* Keep WAKE asserted in case the line is connected anyway */ + + stm32_gpiowrite(GPIO_HALOW_WAKE, true); +#endif + + spi = stm32_spibus_initialize(HALOW_SPI_BUS); + if (spi == NULL) + { + wlerr("ERROR: failed to initialize SPI%d\n", HALOW_SPI_BUS); + return -ENODEV; + } + + return morse_register(spi, &g_halow_lower); +} diff --git a/boards/arm/stm32h7/weact-stm32h743/src/stm32_spi.c b/boards/arm/stm32h7/weact-stm32h743/src/stm32_spi.c index 91513bcf091..65479b8d3c7 100644 --- a/boards/arm/stm32h7/weact-stm32h743/src/stm32_spi.c +++ b/boards/arm/stm32h7/weact-stm32h743/src/stm32_spi.c @@ -56,6 +56,10 @@ void stm32_spidev_initialize(void) { +#ifdef CONFIG_STM32_SPI1 + stm32_configgpio(GPIO_HALOW_CS); /* HaLow module chip select */ +#endif + #ifdef CONFIG_LCD_ST7735 stm32_configgpio(GPIO_LCD_CS); /* ST7735 chip select */ #endif @@ -87,6 +91,25 @@ void stm32_spidev_initialize(void) * ****************************************************************************/ +#ifdef CONFIG_STM32_SPI1 +void stm32_spi1select(struct spi_dev_s *dev, + uint32_t devid, bool selected) +{ + spiinfo("devid: %d CS: %s\n", + (int)devid, selected ? "assert" : "de-assert"); + + if (devid == SPIDEV_WIRELESS(0)) + { + stm32_gpiowrite(GPIO_HALOW_CS, !selected); + } +} + +uint8_t stm32_spi1status(struct spi_dev_s *dev, uint32_t devid) +{ + return 0; +} +#endif + #ifdef CONFIG_STM32_SPI4 void stm32_spi4select(struct spi_dev_s *dev, uint32_t devid, bool selected) diff --git a/boards/arm/stm32h7/weact-stm32h743/src/weact-stm32h743.h b/boards/arm/stm32h7/weact-stm32h743/src/weact-stm32h743.h index c97eb79129b..181c5f838f3 100644 --- a/boards/arm/stm32h7/weact-stm32h743/src/weact-stm32h743.h +++ b/boards/arm/stm32h7/weact-stm32h743/src/weact-stm32h743.h @@ -126,6 +126,26 @@ #define GPIO_LCD_LED (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ GPIO_OUTPUT_CLEAR | GPIO_PORTE | GPIO_PIN10) +/* Morse Micro HaLow module (Quectel FGH100M) on SPI1 + * + * PA4 - CS GPIO output, idle high + * PA2 - RESET_N GPIO output, held low (in reset) at boot + * PA3 - WAKE GPIO output, active high + * PA1 - SPI_IRQ GPIO input, active low, EXTI1 + * PA0 - BUSY GPIO input, active high, EXTI0 + */ + +#define GPIO_HALOW_CS (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_100MHz | \ + GPIO_OUTPUT_SET | GPIO_PORTA | GPIO_PIN4) +#define GPIO_HALOW_RESET (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTA | GPIO_PIN2) +#define GPIO_HALOW_WAKE (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_50MHz | \ + GPIO_OUTPUT_CLEAR | GPIO_PORTA | GPIO_PIN3) +#define GPIO_HALOW_IRQ (GPIO_INPUT | GPIO_PULLUP | GPIO_EXTI | \ + GPIO_PORTA | GPIO_PIN1) +#define GPIO_HALOW_BUSY (GPIO_INPUT | GPIO_PULLDOWN | GPIO_EXTI | \ + GPIO_PORTA | GPIO_PIN0) + /* SD Card * * PD4 Card detected pin @@ -172,6 +192,10 @@ void weak_function stm32_spidev_initialize(void); int stm32_bringup(void); +#ifdef CONFIG_IEEE80211_MORSE +int stm32_morse_initialize(void); +#endif + /**************************************************************************** * Name: stm32_dma_alloc_init *
