diff --git a/boards/st/nucleo_wba65ri/Kconfig.defconfig b/boards/st/nucleo_wba65ri/Kconfig.defconfig new file mode 100644 index 0000000000000..8e937f2a6ad12 --- /dev/null +++ b/boards/st/nucleo_wba65ri/Kconfig.defconfig @@ -0,0 +1,13 @@ +# STM32WBA65RI Nucleo board configuration + +# Copyright (c) 2025 STMicroelectronics + +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NUCLEO_WBA65RI + +config SPI_STM32_INTERRUPT + default y + depends on SPI + +endif # BOARD_NUCLEO_WBA65RI diff --git a/boards/st/nucleo_wba65ri/Kconfig.nucleo_wba65ri b/boards/st/nucleo_wba65ri/Kconfig.nucleo_wba65ri new file mode 100644 index 0000000000000..35b3adb2ab3c1 --- /dev/null +++ b/boards/st/nucleo_wba65ri/Kconfig.nucleo_wba65ri @@ -0,0 +1,5 @@ +# Copyright (c) 2025 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_WBA65RI + select SOC_STM32WBA65XX diff --git a/boards/st/nucleo_wba65ri/arduino_r3_connector.dtsi b/boards/st/nucleo_wba65ri/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..44e824e46644e --- /dev/null +++ b/boards/st/nucleo_wba65ri/arduino_r3_connector.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioa 4 0>, /* A0 */ + <1 0 &gpioa 6 0>, /* A1 */ + <2 0 &gpioa 2 0>, /* A2 */ + <3 0 &gpioa 1 0>, /* A3 */ + <4 0 &gpioa 5 0>, /* A4 */ + <5 0 &gpioa 0 0>, /* A5 */ + <6 0 &gpioa 11 0>, /* D0 */ + <7 0 &gpioa 12 0>, /* D1 */ + <8 0 &gpioe 0 0>, /* D2 */ + <9 0 &gpiob 13 0>, /* D3 */ + <10 0 &gpioa 3 0>, /* D4 */ + <11 0 &gpiob 14 0>, /* D5 */ + <12 0 &gpiob 0 0>, /* D6 */ + <13 0 &gpiod 14 0>, /* D7 */ + <14 0 &gpioa 10 0>, /* D8 */ + <15 0 &gpiob 11 0>, /* D9 */ + <16 0 &gpiob 9 0>, /* D10 */ + <17 0 &gpioc 3 0>, /* D11 */ + <18 0 &gpioa 9 0>, /* D12 */ + <19 0 &gpiob 10 0>, /* D13 */ + <20 0 &gpiob 1 0>, /* D14 */ + <21 0 &gpiob 2 0>; /* D15 */ + }; +}; + +arduino_i2c: &i2c1 {}; +arduino_spi: &spi1 {}; diff --git a/boards/st/nucleo_wba65ri/board.cmake b/boards/st/nucleo_wba65ri/board.cmake new file mode 100644 index 0000000000000..5243407fcc0d1 --- /dev/null +++ b/boards/st/nucleo_wba65ri/board.cmake @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/nucleo_wba65ri/board.yml b/boards/st/nucleo_wba65ri/board.yml new file mode 100644 index 0000000000000..01a51d7715d1e --- /dev/null +++ b/boards/st/nucleo_wba65ri/board.yml @@ -0,0 +1,6 @@ +board: + name: nucleo_wba65ri + full_name: Nucleo WBA65RI + vendor: st + socs: + - name: stm32wba65xx diff --git a/boards/st/nucleo_wba65ri/doc/img/nucleo_wba65ri.webp b/boards/st/nucleo_wba65ri/doc/img/nucleo_wba65ri.webp new file mode 100644 index 0000000000000..a9959ba55a900 Binary files /dev/null and b/boards/st/nucleo_wba65ri/doc/img/nucleo_wba65ri.webp differ diff --git a/boards/st/nucleo_wba65ri/doc/nucleo_wba65ri.rst b/boards/st/nucleo_wba65ri/doc/nucleo_wba65ri.rst new file mode 100644 index 0000000000000..1452d65987a31 --- /dev/null +++ b/boards/st/nucleo_wba65ri/doc/nucleo_wba65ri.rst @@ -0,0 +1,241 @@ +.. zephyr:board:: nucleo_wba65ri + +Overview +******** + +NUCLEO-WBA65RI is a Bluetooth® Low Energy, 802.15.4 and Zigbee® wireless +and ultra-low-power board embedding a powerful and ultra-low-power radio +compliant with the Bluetooth® Low Energy SIG specification v5.4 +with IEEE 802.15.4-2015 and Zigbee® specifications. + +The ARDUINO® Uno V3 connectivity support and the ST morpho headers allow the +easy expansion of the functionality of the STM32 Nucleo open development +platform with a wide choice of specialized shields. + +- Ultra-low-power wireless STM32WBA65RI microcontroller based on the Arm® + Cortex®‑M33 core, featuring 2 Mbyte of flash memory and 512 Kbytes of SRAM in + a VFQFPN68 package + +- MCU RF board (MB2130): + + - 2.4 GHz RF transceiver supporting Bluetooth® specification v5.4 + - Arm® Cortex® M33 CPU with TrustZone®, MPU, DSP, and FPU + - Integrated PCB antenna + +- Three user LEDs +- Three user and one reset push-buttons + +- Board connectors: + + - 2 USB Type-C + - ARDUINO® Uno V3 expansion connector + - ST morpho headers for full access to all STM32 I/Os + +- Flexible power-supply options: ST-LINK USB VBUS or external sources +- On-board STLINK-V3MODS debugger/programmer with USB re-enumeration capability: + mass storage, Virtual COM port, and debug port + +Hardware +******** + +The STM32WBA65xx multiprotocol wireless and ultralow power devices embed a +powerful and ultralow power radio compliant with the Bluetooth® SIG Low Energy +specification 5.4. They contain a high-performance Arm Cortex-M33 32-bit RISC +core. They operate at a frequency of up to 100 MHz. + +- Includes ST state-of-the-art patented technology + +- Ultra low power radio: + + - 2.4 GHz radio + - RF transceiver supporting Bluetooth® Low Energy 5.4 specification + IEEE 802.15.4-2015 PHY and MAC, supporting Thread, Matter and Zigbee® + - Proprietary protocols + - RX sensitivity: -96 dBm (Bluetooth® Low Energy at 1 Mbps) + and -100 dBm (IEEE 802.15.4 at 250 kbps) + - Programmable output power, up to +10 dBm with 1 dB steps + - Support for external PA + - Integrated balun to reduce BOM + - Suitable for systems requiring compliance with radio frequency regulations + ETSI EN 300 328, EN 300 440, FCC CFR47 Part 15 and ARIB STD-T66 + +- Ultra low power platform with FlexPowerControl: + + - 1.71 to 3.6 V power supply + - - 40 °C to 85 °C temperature range + - Autonomous peripherals with DMA, functional down to Stop 1 mode + - TBD nA Standby mode (16 wake-up pins) + - TBD nA Standby mode with RTC + - TBD µA Standby mode with 64 KB SRAM + - TBD µA Stop 2 mode with 64 KB SRAM + - TBD µA/MHz Run mode at 3.3 V + - Radio: Rx TBD mA / Tx at 0 dBm TBD mA + +- Core: Arm® 32-bit Cortex®-M33 CPU with TrustZone®, MPU, DSP, and FPU +- ART Accelerator™: 8-Kbyte instruction cache allowing 0-wait-state execution + from flash memory (frequency up to 100 MHz, 150 DMIPS) +- Power management: embedded regulator LDO and SMPS step-down converter +- Supporting switch on-the-fly and voltage scaling + +- Benchmarks: + + - 1.5 DMIPS/MHz (Drystone 2.1) + - 410 CoreMark® (4.10 CoreMark/MHz) + +- Clock sources: + + - 32 MHz crystal oscillator + - 32 kHz crystal oscillator (LSE) + - Internal low-power 32 kHz (±5%) RC + - Internal 16 MHz factory trimmed RC (±1%) + - PLL for system clock and ADC + +- Memories: + + - 2 MB flash memory with ECC, including 256 Kbytes with 100 cycles + - 512 KB SRAM, including 64 KB with parity check + - 512-byte (32 rows) OTP + +- Rich analog peripherals (independent supply): + + - 12-bit ADC 2.5 Msps with hardware oversampling + +- Communication peripherals: + + - Four UARTs (ISO 7816, IrDA, modem) + - Three SPIs + - Four I2C Fm+ (1 Mbit/s), SMBus/PMBus® + +- System peripherals: + + - Touch sensing controller, up to 24 sensors, supporting touch key, linear, + rotary touch sensors + - One 16-bit, advanced motor control timer + - Three 16-bit timers + - Two 32-bit timer + - Two low-power 16-bit timers (available in Stop mode) + - Two Systick timers + - RTC with hardware calendar and calibration + - Two watchdogs + - 8-channel DMA controller, functional in Stop mode + +- Security and cryptography: + + - Arm® TrustZone® and securable I/Os, memories, and peripherals + - Flexible life cycle scheme with RDP and password protected debug + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - SFI (secure firmware installation) thanks to embedded RSS (root secure services) + - Secure data storage with root hardware unique key (RHUK) + - Secure firmware upgrade support with TF-M + - Two AES co-processors, including one with DPA resistance + - Public key accelerator, DPA resistant + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - Active tampers + - CRC calculation unit + +- Up to 86 I/Os (most of them 5 V-tolerant) with interrupt capability + +- Development support: + + - Serial wire debug (SWD), JTAG + +- ECOPACK2 compliant package + +More information about STM32WBA series can be found here: + +- `STM32WBA Series on www.st.com`_ + +Supported Features +================== + +.. zephyr:board-supported-hw:: + +Connections and IOs +=================== + +Nucleo WBA65RI Board has 4 GPIO controllers. These controllers are responsible for pin muxing, +input/output, pull-up, etc. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +.. rst-class:: rst-columns + +- USART_1 TX/RX : PB12/PA8 +- I2C_1_SCL : PB2 +- I2C_1_SDA : PB1 +- USER_PB : PC13 +- LD1 : PD8 +- SPI_1_NSS : PA12 (arduino_spi) +- SPI_1_SCK : PB4 (arduino_spi) +- SPI_1_MISO : PB3 (arduino_spi) +- SPI_1_MOSI : PA15 (arduino_spi) + +System Clock +------------ + +Nucleo WBA65RI System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by HSE+PLL clock at 100MHz. + +Serial Port +----------- + +Nucleo WBA65RI board has 3 U(S)ARTs. The Zephyr console output is assigned to USART1. +Default settings are 115200 8N1. + + +Programming and Debugging +************************* + +.. zephyr:board-supported-runners:: + +Nucleo WBA65RI board includes an ST-LINK/V3 embedded debug tool interface. +It could be used for flash and debug using either OpenOCD or STM32Cube ecosystem tools. + +Flashing +======== + +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its :ref:`installation ` is required. + +Alternatively, openocd can also be used to flash the board using +the ``--runner`` (or ``-r``) option: + +.. code-block:: console + + $ west flash --runner openocd + +Flashing an application to Nucleo WBA65RI +----------------------------------------- + +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_wba65ri + :goals: build flash + +You will see the LED blinking every second. + +Debugging +========= + +Debugging using OpenOCD +----------------------- + +You can debug an application in the usual way using OpenOCD. Here is an example for the +:zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_wba65ri + :maybe-skip-config: + :goals: debug + +.. _STM32WBA Series on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32wba-series.html + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_wba65ri/nucleo_wba65ri.dts b/boards/st/nucleo_wba65ri/nucleo_wba65ri.dts new file mode 100644 index 0000000000000..47ddf62fe038e --- /dev/null +++ b/boards/st/nucleo_wba65ri/nucleo_wba65ri.dts @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + model = "STMicroelectronics STM32WBA65RI-NUCLEO board"; + compatible = "st,stm32wba65ri-nucleo"; + + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,bt-c2h-uart = &usart1; + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds: leds { + compatible = "gpio-leds"; + + blue_led_1: led_0 { + gpios = <&gpiod 8 GPIO_ACTIVE_LOW>; + label = "User LD1"; + }; + + green_led_2: led_1 { + gpios = <&gpioc 4 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + + red_led_3: led_2 { + gpios = <&gpiob 8 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button_1: button_0 { + label = "User B1"; + gpios = <&gpioc 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + + user_button_2: button_1 { + label = "User B2"; + gpios = <&gpioc 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + + user_button_3: button_2 { + label = "User B3"; + gpios = <&gpiob 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &blue_led_1; + led1 = &green_led_2; + led2 = &red_led_3; + sw0 = &user_button_1; + sw1 = &user_button_2; + sw2 = &user_button_3; + mcuboot-led0 = &blue_led_1; + mcuboot-button0 = &user_button_1; + }; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_hse { + hse-div2; + status = "okay"; +}; + +&clk_hsi { + status = "okay"; +}; + +&rcc { + clocks = <&clk_hse>; + clock-frequency = ; + ahb-prescaler = <1>; + ahb5-prescaler = <2>; + apb1-prescaler = <1>; + apb2-prescaler = <2>; + apb7-prescaler = <1>; +}; + +&iwdg { + status = "okay"; +}; + +&rtc { + status = "okay"; + clocks = <&rcc STM32_CLOCK(APB7, 21)>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + prescaler = <32768>; +}; + +&usart1 { + clocks = <&rcc STM32_CLOCK(APB2, 14)>, + <&rcc STM32_SRC_HSI16 USART1_SEL(2)>; + pinctrl-0 = <&usart1_tx_pb12 &usart1_rx_pa8>; + pinctrl-1 = <&analog_pb12 &analog_pa8>; + pinctrl-names = "default", "sleep"; + current-speed = <115200>; + status = "okay"; +}; + +&spi1 { + pinctrl-0 = <&spi1_nss_pa12 &spi1_sck_pb4 + &spi1_miso_pb3 &spi1_mosi_pa15>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb2 &i2c1_sda_pb1>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&adc4 { + pinctrl-0 = <&adc4_in8_pa1>; + pinctrl-names = "default"; + st,adc-clock-source = "ASYNC"; + st,adc-prescaler = <4>; + status = "okay"; +}; + +stm32_lp_tick_source: &lptim1 { + clocks = <&rcc STM32_CLOCK(APB7, 11)>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@1c0000 { + label = "storage"; + reg = <0x001c0000 DT_SIZE_K(256)>; + }; + }; +}; diff --git a/boards/st/nucleo_wba65ri/nucleo_wba65ri.yaml b/boards/st/nucleo_wba65ri/nucleo_wba65ri.yaml new file mode 100644 index 0000000000000..78617e1b26282 --- /dev/null +++ b/boards/st/nucleo_wba65ri/nucleo_wba65ri.yaml @@ -0,0 +1,19 @@ +identifier: nucleo_wba65ri +name: ST Nucleo WBA65RI +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio + - i2c + - spi + - adc + - rng + - arduino_gpio + - arduino_i2c + - arduino_spi +ram: 512 +flash: 2048 +vendor: st diff --git a/boards/st/nucleo_wba65ri/nucleo_wba65ri_defconfig b/boards/st/nucleo_wba65ri/nucleo_wba65ri_defconfig new file mode 100644 index 0000000000000..24ca108f2456a --- /dev/null +++ b/boards/st/nucleo_wba65ri/nucleo_wba65ri_defconfig @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 STMicroelectronics + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable the internal SMPS regulator +CONFIG_POWER_SUPPLY_DIRECT_SMPS=y diff --git a/boards/st/nucleo_wba65ri/support/openocd.cfg b/boards/st/nucleo_wba65ri/support/openocd.cfg new file mode 100644 index 0000000000000..0532f11f83a10 --- /dev/null +++ b/boards/st/nucleo_wba65ri/support/openocd.cfg @@ -0,0 +1,26 @@ +# Note: Using OpenOCD using nucleo_wba65ri requires using openocd fork. +# See board documentation for more information + +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate + +source [find target/stm32wbax.cfg] + +gdb_memory_map disable diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index 01d0c21d3f5fe..3480f152b4cdf 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -131,7 +131,12 @@ struct flash_stm32_priv { #define FLASH_STM32_NSPNB_POS FLASH_NSCR1_PNB_Pos #define FLASH_STM32_NSPNB FLASH_NSCR1_PNB #define FLASH_STM32_NSSTRT FLASH_NSCR1_STRT +/* STM32WBA6x has DUAL bank flash */ +#if defined(FLASH_OPTR_DUAL_BANK) +#define FLASH_STM32_DBANK FLASH_OPTR_DUAL_BANK +#endif /* FLASH_OPTR_DUAL_BANK */ #endif /* CONFIG_SOC_SERIES_STM32U5X */ + #if defined(FLASH_OPTR_DBANK) #define FLASH_STM32_DBANK FLASH_OPTR_DBANK #endif /* FLASH_OPTR_DBANK */ diff --git a/drivers/flash/flash_stm32wbax.c b/drivers/flash/flash_stm32wbax.c index 8660d46c26500..d7abb3ff928db 100644 --- a/drivers/flash/flash_stm32wbax.c +++ b/drivers/flash/flash_stm32wbax.c @@ -20,7 +20,20 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include "flash_stm32.h" +#if defined(FLASH_OPTR_DUAL_BANK) +/* The stm32wba6x MCUs have 2MB dual-bank */ +#define STM32_SERIES_MAX_FLASH 2048 +#define STM32_FLASH_HAS_2_BANKS(flash_device) \ + ((FLASH_STM32_REGS(flash_device)->OPTR & FLASH_STM32_DBANK) \ + == FLASH_STM32_DBANK) +#else #define STM32_SERIES_MAX_FLASH 1024 +#define STM32_FLASH_HAS_2_BANKS(flash_device) (false) +#endif /* FLASH_OPTR_DUAL_BANK */ + +#define PAGES_PER_BANK ((FLASH_SIZE / FLASH_PAGE_SIZE) / 2) + +#define BANK2_OFFSET (KB(STM32_SERIES_MAX_FLASH) / 2) #define ICACHE_DISABLE_TIMEOUT_VALUE 1U /* 1ms */ #define ICACHE_INVALIDATE_TIMEOUT_VALUE 1U /* 1ms */ @@ -105,6 +118,34 @@ static int icache_wait_for_invalidate_complete(void) return status; } +/* + * offset and len must be aligned on write-block-size for write, + * positive and not beyond end of flash + */ +bool flash_stm32_valid_range(const struct device *dev, off_t offset, + uint32_t len, bool write) +{ + if (STM32_FLASH_HAS_2_BANKS(dev) && + (CONFIG_FLASH_SIZE < STM32_SERIES_MAX_FLASH)) { + /* + * In case of bank1/2 discontinuity, the range should not + * start before bank2 and end beyond bank1 at the same time. + * Locations beyond bank2 are caught by + * flash_stm32_range_exists. + */ + if ((offset < BANK2_OFFSET) && + (offset + len > FLASH_SIZE / 2)) { + return false; + } + } + + if (write && !flash_stm32_valid_write(offset, len)) { + return false; + } + + return flash_stm32_range_exists(dev, offset, len); +} + static int write_qword(const struct device *dev, off_t offset, const uint32_t *buff) { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); @@ -172,9 +213,40 @@ static int erase_page(const struct device *dev, unsigned int offset) return rc; } +#if defined(FLASH_OPTR_DUAL_BANK) + bool bank_swap; + /* Check whether bank1/2 are swapped */ + bank_swap = + ((regs->OPTR & FLASH_OPTR_SWAP_BANK) == FLASH_OPTR_SWAP_BANK); + + if ((offset < (FLASH_SIZE / 2)) && !bank_swap) { + /* The pages to be erased is in bank 1 */ + regs->NSCR &= ~FLASH_STM32_NSBKER_MSK; + page = offset / FLASH_PAGE_SIZE; + LOG_DBG("Erase page %d on bank 1", page); + } else if ((offset >= BANK2_OFFSET) && bank_swap) { + /* The pages to be erased is in bank 1 */ + regs->NSCR &= ~FLASH_STM32_NSBKER_MSK; + page = (offset - BANK2_OFFSET) / FLASH_PAGE_SIZE; + LOG_DBG("Erase page %d on bank 1", page); + } else if ((offset < (FLASH_SIZE / 2)) && bank_swap) { + /* The pages to be erased is in bank 2 */ + regs->NSCR |= FLASH_STM32_NSBKER; + page = offset / FLASH_PAGE_SIZE; + LOG_DBG("Erase page %d on bank 2", page); + } else if ((offset >= BANK2_OFFSET) && !bank_swap) { + /* The pages to be erased is in bank 2 */ + regs->NSCR |= FLASH_STM32_NSBKER; + page = (offset - BANK2_OFFSET) / FLASH_PAGE_SIZE; + LOG_DBG("Erase page %d on bank 2", page); + } else { + LOG_ERR("Offset %d does not exist", offset); + return -EINVAL; + } +#else page = offset / FLASH_PAGE_SIZE; LOG_DBG("Erase page %d\n", page); - +#endif /* Set the NSPER bit and select the page you wish to erase */ regs->NSCR |= FLASH_STM32_NSPER; regs->NSCR &= ~FLASH_STM32_NSPNB_MSK; @@ -282,6 +354,55 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, return rc; } +#if defined(FLASH_OPTR_DUAL_BANK) +/* The STM32WBA6x has a dual-bank flash */ +void flash_stm32_page_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + static struct flash_pages_layout stm32_flash_layout[3]; + static size_t stm32_flash_layout_size; + + *layout = stm32_flash_layout; + + if (stm32_flash_layout[0].pages_count != 0) { + /* Short circuit calculation logic if already performed (size is known) */ + *layout_size = stm32_flash_layout_size; + return; + } + + if (STM32_FLASH_HAS_2_BANKS(dev) && + (CONFIG_FLASH_SIZE < STM32_SERIES_MAX_FLASH)) { + /* For device, which has space between banks 1 and 2 */ + + /* Bank1 */ + stm32_flash_layout[0].pages_count = PAGES_PER_BANK; + stm32_flash_layout[0].pages_size = FLASH_PAGE_SIZE; + + /* Dummy page corresponding to space between banks 1 and 2 */ + stm32_flash_layout[1].pages_count = 1; + stm32_flash_layout[1].pages_size = BANK2_OFFSET + - (PAGES_PER_BANK * FLASH_PAGE_SIZE); + + /* Bank2 */ + stm32_flash_layout[2].pages_count = PAGES_PER_BANK; + stm32_flash_layout[2].pages_size = FLASH_PAGE_SIZE; + + stm32_flash_layout_size = ARRAY_SIZE(stm32_flash_layout); + } else { + /* + * For device, which has no space between banks 1 and 2 + * Considering one layout of full flash size, even with 2 banks + */ + stm32_flash_layout[0].pages_count = FLASH_SIZE / FLASH_PAGE_SIZE; + stm32_flash_layout[0].pages_size = FLASH_PAGE_SIZE; + + stm32_flash_layout_size = 1; + } + + *layout_size = stm32_flash_layout_size; +} +#else void flash_stm32_page_layout(const struct device *dev, const struct flash_pages_layout **layout, size_t *layout_size) @@ -301,3 +422,4 @@ void flash_stm32_page_layout(const struct device *dev, *layout = &stm32wba_flash_layout; *layout_size = 1; } +#endif /* FLASH_OPTR_DUAL_BANK */ diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index 697d7789b03c4..5385e7f7ff579 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -502,7 +502,7 @@ compatible = "swj-connector"; pinctrl-0 = <&debug_jtms_swdio_pa13 &debug_jtck_swclk_pa14 &debug_jtdi_pa15 &debug_jtdo_swo_pb3 - &debug_jtrst_pb4>; + &debug_njtrst_pb4>; pinctrl-1 = <&analog_pa13 &analog_pa14 &analog_pa15 &analog_pb3 &analog_pb4>; pinctrl-names = "default", "sleep"; diff --git a/dts/arm/st/wba/stm32wba65.dtsi b/dts/arm/st/wba/stm32wba65.dtsi new file mode 100644 index 0000000000000..6f6e0eaa14f4e --- /dev/null +++ b/dts/arm/st/wba/stm32wba65.dtsi @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/ { + soc { + compatible = "st,stm32wba65", "st,stm32wba", "simple-bus"; + + pinctrl: pin-controller@42020000 { + gpiod: gpio@42020c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42020c00 0x400>; + clocks = <&rcc STM32_CLOCK(AHB2, 3)>; + }; + + gpioe: gpio@42021000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42021000 0x400>; + clocks = <&rcc STM32_CLOCK(AHB2, 4)>; + }; + + gpiog: gpio@42021800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + /* GPIOG has an independent IO supply VDDIO2 */ + reg = <0x42021800 0x400>; + clocks = <&rcc STM32_CLOCK(AHB2, 6)>; + }; + }; + + usart3: serial@40004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 18)>; + resets = <&rctl STM32_RESET(APB1L, 18U)>; + interrupts = <79 0>; + status = "disabled"; + }; + + spi2: spi@40003800 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + interrupts = <75 5>; + clocks = <&rcc STM32_CLOCK(APB1, 14)>; + status = "disabled"; + }; + + timers4: timers@40000800 { + compatible = "st,stm32-timers"; + reg = <0x40000800 0x400>; + clocks = <&rcc STM32_CLOCK(APB1, 2)>; + resets = <&rctl STM32_RESET(APB1L, 2U)>; + interrupts = <72 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + }; +}; diff --git a/dts/arm/st/wba/stm32wba65Xi.dtsi b/dts/arm/st/wba/stm32wba65Xi.dtsi new file mode 100644 index 0000000000000..422ae59aa3bdd --- /dev/null +++ b/dts/arm/st/wba/stm32wba65Xi.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(448)>; + }; + + sram1: memory@20070000 { + compatible = "mmio-sram"; + reg = <0x20070000 DT_SIZE_K(64)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_M(2)>; + }; + }; + }; +}; diff --git a/include/zephyr/dt-bindings/clock/stm32wba_clock.h b/include/zephyr/dt-bindings/clock/stm32wba_clock.h index 23ceac25c0119..d77dfba5cbeec 100644 --- a/include/zephyr/dt-bindings/clock/stm32wba_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32wba_clock.h @@ -10,7 +10,8 @@ /** Peripheral clock sources */ -/* RM0493, Figure 30, clock tree */ +/* RM0493, Figure 34, clock tree */ +/* RM0515, Figure 36, clock tree */ /** System clock */ /* defined in stm32_common_clocks.h */ @@ -56,7 +57,11 @@ /** CCIPR1 devices */ #define USART1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 0, CCIPR1_REG) #define USART2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 2, CCIPR1_REG) +#define USART3_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 4, CCIPR1_REG) #define I2C1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 10, CCIPR1_REG) +#define I2C2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 12, CCIPR1_REG) +#define I2C4_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 14, CCIPR1_REG) +#define SPI2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 16, CCIPR1_REG) #define LPTIM2_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 18, CCIPR1_REG) #define SPI1_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 20, CCIPR1_REG) #define SYSTICK_SEL(val) STM32_DT_CLOCK_SELECT((val), 3, 22, CCIPR1_REG) diff --git a/soc/st/stm32/Kconfig b/soc/st/stm32/Kconfig index 4f3371ab79b48..59a245fb17a9f 100644 --- a/soc/st/stm32/Kconfig +++ b/soc/st/stm32/Kconfig @@ -60,7 +60,7 @@ choice POWER_SUPPLY_CHOICE prompt "STM32 power supply configuration" default POWER_SUPPLY_LDO depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || \ - SOC_SERIES_STM32U5X || SOC_STM32WBA55XX + SOC_SERIES_STM32U5X || SOC_STM32WBA55XX || SOC_STM32WBA65XX config POWER_SUPPLY_LDO bool "LDO supply" diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index 7999b323ebee2..2467265470a9a 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -221,6 +221,7 @@ family: socs: - name: stm32wba52xx - name: stm32wba55xx + - name: stm32wba65xx - name: stm32wlx socs: - name: stm32wle4xx diff --git a/soc/st/stm32/stm32wbax/Kconfig.defconfig.stm32wba65xx b/soc/st/stm32/stm32wbax/Kconfig.defconfig.stm32wba65xx new file mode 100644 index 0000000000000..bd811b035ef8b --- /dev/null +++ b/soc/st/stm32/stm32wbax/Kconfig.defconfig.stm32wba65xx @@ -0,0 +1,11 @@ +# ST Microelectronics STM32WBA65XX MCU + +# Copyright (c) 2025 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32WBA65XX + +config NUM_IRQS + default 82 + +endif # SOC_STM32WBA65XX diff --git a/soc/st/stm32/stm32wbax/Kconfig.soc b/soc/st/stm32/stm32wbax/Kconfig.soc index 104a3923989bd..cee2f81308f88 100644 --- a/soc/st/stm32/stm32wbax/Kconfig.soc +++ b/soc/st/stm32/stm32wbax/Kconfig.soc @@ -18,6 +18,11 @@ config SOC_STM32WBA55XX bool select SOC_SERIES_STM32WBAX +config SOC_STM32WBA65XX + bool + select SOC_SERIES_STM32WBAX + config SOC default "stm32wba52xx" if SOC_STM32WBA52XX default "stm32wba55xx" if SOC_STM32WBA55XX + default "stm32wba65xx" if SOC_STM32WBA65XX diff --git a/tests/drivers/adc/adc_api/boards/nucleo_wba65ri.overlay b/tests/drivers/adc/adc_api/boards/nucleo_wba65ri.overlay new file mode 100644 index 0000000000000..4a6e6546c487e --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nucleo_wba65ri.overlay @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc4 7>, <&adc4 8>; + }; +}; + +&adc4 { + pinctrl-0 = <&adc4_in7_pa2 &adc4_in8_pa1>; + #address-cells = <1>; + #size-cells = <0>; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@8 { + reg = <8>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/testcase.yaml b/tests/drivers/adc/adc_api/testcase.yaml index c7b9d985dac72..c7b147669a44e 100644 --- a/tests/drivers/adc/adc_api/testcase.yaml +++ b/tests/drivers/adc/adc_api/testcase.yaml @@ -48,6 +48,7 @@ tests: - nucleo_u575zi_q - nucleo_wb55rg - nucleo_wba55cg + - nucleo_wba65ri - nucleo_wl55jc - stm32f3_disco - stm32h573i_dk diff --git a/west.yml b/west.yml index 35d6a7cba6bf5..f18d597402e35 100644 --- a/west.yml +++ b/west.yml @@ -238,7 +238,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: 46c5ca5ac099ac1ed530975ea2bb5dc4ebb4dfb2 + revision: f467d8e039216b4f5f9b55dd8a1ffa8582fc516d path: modules/hal/stm32 groups: - hal