From cf1ffd165930ed3e9b70f128318cd39c2bea2803 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Tue, 14 Apr 2026 21:34:15 -0400 Subject: [PATCH] [stm32wba, crypto] Implement support for the STM32WBA. Provide helper functions for crypto algos --- .claude/skills/port-stm32-platform/SKILL.md | 190 +++++ boards/peripheral/peripheral.c | 4 - boards/pic32cz_curiosity_ultra/Makefile.inc | 1 + boards/stm32c031_nucleo/Makefile.inc | 1 + boards/stm32f411_blackpill/Makefile.inc | 1 + boards/stm32h563zi_nucleo/Makefile.inc | 1 + boards/stm32wb55xx_nucleo/Makefile.inc | 5 +- boards/stm32wba55cg_nucleo/Makefile.inc | 51 ++ boards/stm32wba55cg_nucleo/board.c | 540 ++++++++++++++ boards/stm32wba55cg_nucleo/board.h | 53 ++ boards/stm32wba55cg_nucleo/ivt.c | 242 +++++++ boards/stm32wba55cg_nucleo/linker.ld | 128 ++++ docs/writing_a_driver.md | 98 ++- src/clock/stm32wba_rcc.c | 315 ++++++++ src/crypto/stm32wb_aes.c | 148 +++- src/crypto/stm32wba_aes.c | 1 + src/crypto/stm32wba_hash.c | 377 ++++++++++ src/dma/stm32wba_gpdma.c | 290 ++++++++ src/flash/stm32wba_flash.c | 280 ++++++++ src/gpio/stm32wba_gpio.c | 1 + src/i2c/stm32wba_i2c.c | 1 + src/rng/stm32wba_rng.c | 151 ++++ src/spi/stm32wba_spi.c | 1 + src/uart/stm32wb_uart.c | 9 +- src/uart/stm32wba_uart.c | 1 + src/uart/stm32wba_uart_dma.c | 213 ++++++ src/watchdog/stm32wba_iwdg.c | 1 + src/watchdog/stm32wba_wwdg.c | 1 + tests/crypto/test_crypto.c | 458 ++++++++---- tests/main.c | 18 +- wolfHAL/clock/stm32wba_rcc.h | 142 ++++ wolfHAL/crypto/crypto.h | 759 +++++++++++++++++++- wolfHAL/crypto/stm32wba_aes.h | 26 + wolfHAL/crypto/stm32wba_hash.h | 93 +++ wolfHAL/dma/stm32wba_gpdma.h | 91 +++ wolfHAL/endian.h | 36 + wolfHAL/flash/stm32wba_flash.h | 41 ++ wolfHAL/gpio/stm32wba_gpio.h | 69 ++ wolfHAL/i2c/stm32wba_i2c.h | 26 + wolfHAL/platform/arm/cortex_m33.h | 6 + wolfHAL/platform/st/stm32wba55cg.h | 295 ++++++++ wolfHAL/rng/stm32wba_rng.h | 25 + wolfHAL/spi/stm32wba_spi.h | 26 + wolfHAL/uart/stm32wba_uart.h | 31 + wolfHAL/uart/stm32wba_uart_dma.h | 51 ++ wolfHAL/watchdog/stm32wba_iwdg.h | 35 + wolfHAL/watchdog/stm32wba_wwdg.h | 36 + 47 files changed, 5103 insertions(+), 266 deletions(-) create mode 100644 .claude/skills/port-stm32-platform/SKILL.md create mode 100644 boards/stm32wba55cg_nucleo/Makefile.inc create mode 100644 boards/stm32wba55cg_nucleo/board.c create mode 100644 boards/stm32wba55cg_nucleo/board.h create mode 100644 boards/stm32wba55cg_nucleo/ivt.c create mode 100644 boards/stm32wba55cg_nucleo/linker.ld create mode 100644 src/clock/stm32wba_rcc.c create mode 100644 src/crypto/stm32wba_aes.c create mode 100644 src/crypto/stm32wba_hash.c create mode 100644 src/dma/stm32wba_gpdma.c create mode 100644 src/flash/stm32wba_flash.c create mode 100644 src/gpio/stm32wba_gpio.c create mode 100644 src/i2c/stm32wba_i2c.c create mode 100644 src/rng/stm32wba_rng.c create mode 100644 src/spi/stm32wba_spi.c create mode 100644 src/uart/stm32wba_uart.c create mode 100644 src/uart/stm32wba_uart_dma.c create mode 100644 src/watchdog/stm32wba_iwdg.c create mode 100644 src/watchdog/stm32wba_wwdg.c create mode 100644 wolfHAL/clock/stm32wba_rcc.h create mode 100644 wolfHAL/crypto/stm32wba_aes.h create mode 100644 wolfHAL/crypto/stm32wba_hash.h create mode 100644 wolfHAL/dma/stm32wba_gpdma.h create mode 100644 wolfHAL/flash/stm32wba_flash.h create mode 100644 wolfHAL/gpio/stm32wba_gpio.h create mode 100644 wolfHAL/i2c/stm32wba_i2c.h create mode 100644 wolfHAL/platform/st/stm32wba55cg.h create mode 100644 wolfHAL/rng/stm32wba_rng.h create mode 100644 wolfHAL/spi/stm32wba_spi.h create mode 100644 wolfHAL/uart/stm32wba_uart.h create mode 100644 wolfHAL/uart/stm32wba_uart_dma.h create mode 100644 wolfHAL/watchdog/stm32wba_iwdg.h create mode 100644 wolfHAL/watchdog/stm32wba_wwdg.h diff --git a/.claude/skills/port-stm32-platform/SKILL.md b/.claude/skills/port-stm32-platform/SKILL.md new file mode 100644 index 0000000..dc51474 --- /dev/null +++ b/.claude/skills/port-stm32-platform/SKILL.md @@ -0,0 +1,190 @@ +--- +name: port-stm32-platform +description: Port a new STM32 chip family to wolfHAL. Creates the platform header, scaffolds new drivers, adds alias header + stub .c for reused drivers, and optionally wires up a first board. +argument-hint: [chip-name] [board-name] +--- + +# Port a new STM32 chip family to wolfHAL + +You are helping the user port a new STM32 chip family (e.g., `stm32g4`, `stm32u5`, `stm32l5`) to wolfHAL. A "platform" in wolfHAL is a family of register-compatible chips that share drivers (e.g., `stm32wba` covers wba52/wba54/wba55). A specific chip (e.g., `stm32wba55cg`) gets its own platform header with concrete base addresses and clock macros. A board (e.g., `stm32wba55cg_nucleo`) ties a chip to a physical dev board. + +Arguments passed after the skill name identify the scope: +- `$1`: platform short name (required, e.g., `stm32g4`) +- `$2`: specific chip (optional, e.g., `stm32g431cb`) +- `$3`: board name (optional, e.g., `stm32g431_nucleo`) + +If any are missing, ask the user before starting the relevant phase. + +## Prerequisites — gather before starting + +Ask the user to provide (or confirm paths to): + +1. **Reference Manual (TRM) PDF** for the chip family — e.g., `stm32g4_trm.pdf`. Place at repo root. +2. **Datasheet PDF** for the specific chip — e.g., `stm32g431cb.pdf`. Place at repo root. +3. **Board user guide PDF** if adding a board — e.g., `nucleo_g431.pdf`. Place at repo root. + +Do NOT proceed with register layout work without the TRM — guessing from similar chips is the #1 source of silent bugs. STM32 family differences (bit positions, register offsets, new CONDRST/FIFO/voltage-scaling fields) are subtle and costly to debug later. + +## Phase 1 — Discovery (read-only, no code changes) + +Goal: figure out what is register-compatible with an existing wolfHAL driver vs what needs a new driver. + +For each device type below, use `pdftotext -layout -f -l ` on the TRM to extract the register map page, then compare against existing wolfHAL drivers in `src//`: + +| Device type | Existing drivers to diff against | What to check in TRM | +|---|---|---| +| Clock/RCC | `stm32wb_rcc.c`, `stm32wba_rcc.c`, `stm32h5_rcc.c`, `stm32f4_rcc.c` | PLL config register (PLLCFGR split vs unified), voltage scaling (PWR_VOSR), AHB/APB prescaler fields, HSI/HSE/LSI/LSE, peripheral clock enable register offsets (AHBxENR, APBxENR) | +| GPIO | `stm32wb_gpio.c`, `stm32f4_gpio.c` | MODER/OTYPER/OSPEEDR/PUPDR/AFRL/AFRH — usually compatible across STM32 | +| UART | `stm32wb_uart.c`, `stm32wba_uart.c`, `stm32wba_uart_dma.c`, `stm32h5_uart.c`, `stm32c0_uart.c`, `stm32f4_uart.c` | BRR calc (16x vs 8x oversample), FIFO enable (CR1.FIFOEN bit 29), ISR/ICR flags, TDR/RDR offsets | +| Flash | `stm32wb_flash.c`, `stm32wba_flash.c`, `stm32h5_flash.c`, `stm32c0_flash.c`, `stm32f4_flash.c` | NSKEYR/KEYR unlock sequence, SR bit positions (BSY, EOP, errors), CR bit positions (PG, PER, STRT, LOCK, PNB), page size | +| RNG | `stm32wb_rng.c`, `stm32wba_rng.c` | CR bits (RNGEN, CED, CONDRST), SR bits (DRDY, errors), clock source selection register (CCIPRx RNGSEL) | +| I2C | `stm32wb_i2c.c` | CR1/CR2/TIMINGR — usually compatible on modern STM32 (V2 I2C) | +| SPI | `stm32wb_spi.c`, `stm32h5_spi.c`, `stm32f4_spi.c` | CR1/CR2/SR layout (V1 SPI differs from V2 SPI used on newer chips) | +| AES | `stm32wb_aes.c`, `stm32wba_aes.c` | CR (KEYSIZE, MODE, CHMOD, DATATYPE, NPBLB, GCMPH), KEYR, IVR, DIN/DOUT | +| HASH | `stm32wba_hash.c` | CR (ALGO, MODE, DATATYPE, LKEY, INIT), STR (NBLW, DCAL), SR (BUSY), DIN, digest registers (HRx). Check ALGO bit positions — some chips split ALGO across non-contiguous bits | +| DMA | `stm32wb_dma.c` (classic DMA+DMAMUX), `stm32wba_gpdma.c` (GPDMA) | Is it DMA+DMAMUX (older) or GPDMA (newer)? Not compatible. GPDMA appears on U5/WBA/H5/C0/G0 variants. | +| Timer | `systick.c` (shared) | SysTick is architectural (Cortex-M), works unchanged | +| IRQ | `cortex_m4_nvic.c`, `cortex_m33_nvic.c` | NVIC is architectural per core (M4 vs M33) | +| Watchdog | `stm32wb_iwdg.c`, `stm32wb_wwdg.c`, `stm32wba_iwdg.c`, `stm32wba_wwdg.c` | IWDG/WWDG are very stable across STM32 | + +For each device type, decide **reuse existing driver (with alias)** OR **write a new driver**. Write the decision to a checklist and show the user before starting Phase 2. + +The clock driver is almost always new per family. GPIO, I2C, and IWDG/WWDG are almost always reusable. UART, flash, RNG, DMA require careful diffing. + +## Phase 2 — Platform header + +Create `wolfHAL/platform/st/.h` (e.g., `stm32g431cb.h`). Reference: `stm32wba55cg.h` (GPDMA chip) or `stm32wb55xx.h` (DMA+DMAMUX chip). + +Conventions: +1. Every driver include uses the **new platform's prefix** — for reused drivers that means the alias header created in Phase 3, not the original family's header. +2. Every device macro uses `.driver = &whal__Driver` — the alias header `#define`s this to the original symbol at preprocess time, so no renaming of actual code is needed but callers see the new-prefix name. +3. Defines clock enable macros and, when applicable, DMA request mapping macros. + +Skeleton: + +```c +#include /* or cortex_m33.h / cortex_m7.h */ + +/* Every include uses the new platform's prefix — aliased or newly written */ +#include _rcc.h> +#include _gpio.h> +#include _uart.h> +/* ...one include per device type... */ + +#define WHAL__USART1_DEVICE \ + .regmap = { .base = 0x, .size = 0x400 }, \ + .driver = &whal_Uart_Driver + +#define WHAL__USART1_CLOCK \ + .regOffset = 0x, \ + .enableMask = (1UL << ), \ + .enablePos = +``` + +## Phase 3 — Drivers + +### For each device type marked "write new" + +1. Read `docs/writing_a_driver.md` for the driver pattern. +2. Copy the closest existing driver as a starting point. +3. Update register offsets, bit positions, and sequences per the TRM. **Cross-check register-map diagrams against the textual bit descriptions** — they sometimes disagree, and the textual description is authoritative. +4. Match the existing naming: `whal__` for functions, `whal__Driver` for the vtable, `whal__Cfg` for the config struct. +5. Place files at `wolfHAL//_.h` and `src//_.c`. +6. Do not add cross-driver calls from inside a driver — clock enables, power sequencing, flash wait states, pin muxing are the board's responsibility. + +### For each device type marked "reuse existing driver" — create an alias header + stub .c + +Reference pattern in-tree: `wolfHAL/gpio/stm32f4_gpio.h` (alias header) and `src/gpio/stm32f4_gpio.c` (stub). Every symbol the caller sees must carry the new platform's prefix; aliasing is done at preprocess time via `typedef` and `#define`, so no code is duplicated and no GCC alias attribute is needed. + +**Alias header** — `wolfHAL//_.h`: + +```c +#ifndef WHAL___H +#define WHAL___H + +/* + * @file _.h + * @brief driver (alias for ). + * + * The peripheral is register-compatible with the + * . This header re-exports the driver + * types and symbols under -specific names. The underlying + * implementation is shared. + */ + +#include /_.h> + +/* Type aliases — one typedef per exposed type from the original header */ +typedef whal__Cfg whal__Cfg; +typedef whal__PinCfg whal__PinCfg; +/* ...repeat for every exposed type... */ + +/* Driver and function aliases — one #define per exposed function/driver */ +#define whal__Driver whal__Driver +#define whal__Init whal__Init +#define whal__Deinit whal__Deinit +/* ...repeat for every exposed function... */ + +/* Macro / enum-value aliases — one #define per user-facing macro */ +#define WHAL___ WHAL___ +/* ...repeat for every mode selector, port letter, pin-packing macro, etc... */ + +#endif /* WHAL___H */ +``` + +**Stub .c** — `src//_.c`: + +```c +#include "_.c" +``` + +That is the entire file. Examples in-tree: `src/gpio/stm32f4_gpio.c`, `src/gpio/stm32wba_gpio.c`, `src/i2c/stm32wba_i2c.c`, `src/uart/stm32wba_uart.c`, `src/watchdog/stm32wba_iwdg.c` — each is one line. The stub exists so the board's Makefile wildcard (`src/*/_*.c`) compiles the original implementation under the new-prefix filename. The original `.c` is NOT added to the Makefile separately; the `#include` pulls it into this translation unit exactly once. + +### Common driver pitfalls (from prior ports) +- **Flash**: check if already unlocked before writing keys — double-unlock hard-faults. Bit positions (LOCK, STRT, PNB) differ between families; do not copy-paste. +- **RNG**: CONDRST + per-config register sequence goes in Init, not per Generate call. Select RNG clock source via `RCC_CCIPR`/`CCIPR2` before Init — default is often LSE, which requires LSE running. +- **Clock**: on chips with voltage scaling, transition to VOS Range 1 BEFORE raising SYSCLK above ~16 MHz; skipping this hard-faults at the first PLL switch. +- **DMA + USART**: enable `CR1.FIFOEN` when available — DMA→USART without FIFO has produced silent byte drops. +- **Polling loops**: every hardware-flag wait must go through `whal_Timeout` — bare `while` loops violate a repo-wide preference. +- **One-time hardware setup** (clock sources, trimming, feature selects): belongs in Init, not in per-operation functions. + +## Phase 4 — Board (optional, only if $3 provided) + +Create `boards//` with: + +### `board.h` +Exports `extern whal_` instances and declares `Board_Init`/`Board_Deinit`/`Board_WaitMs`. Follow `docs/adding_a_board.md`. + +### `board.c` +Define each `whal_` global with its platform macro + board-specific config (pins, baud rates, timeout, DMA channel assignments). Implement `Board_Init` in dependency order: PWR → Clock → peripheral clock enables → GPIO → UART → Timer → the rest. Keep the watchdog out of `Board_Init` (the app starts it when ready to refresh) per `docs/adding_a_board.md`. Guard DMA-specific setup under `#ifdef BOARD_DMA`, matching `boards/stm32wba55cg_nucleo/board.c`. + +### `Makefile.inc` +Model on `boards/stm32wba55cg_nucleo/Makefile.inc`: +- `PLATFORM = ` — matches the prefix used in `src/*/_*.c` +- `TESTS ?= clock gpio flash timer rng crypto uart spi i2c irq` — trim to what the board supports +- `CFLAGS` — `-mcpu=cortex-m4`/`cortex-m33` to match the core, `-DPLATFORM_` for platform ifdefs +- `BOARD_SOURCE` wildcards over `$(WHAL_DIR)/src/*/_*.c` — picks up both native drivers and the alias stub `.c` files created in Phase 3. **Do NOT also wildcard over the original family's prefix**, or the original `.c` will compile twice (once directly, once through the stub's include) and you'll get duplicate-symbol errors at link time. + +### `linker.ld` +Copy from a similar board and update the `MEMORY` block's FLASH/RAM origins and lengths from the chip's datasheet. + +### `ivt.c` +Copy from a similar board with the same core (M4/M33). Update the vector table — vectors from position 16 onward are device-specific and listed in the TRM's interrupt mapping table. At minimum: SysTick plus any peripheral IRQs the tests exercise (USART1_IRQHandler, GPDMAx_ChannelY_IRQHandler, etc.). + +## Phase 5 — Build and validate + +1. `make BOARD=` from the repo root. Fix errors in order. Typical failures: + - Missing symbol for an aliased driver → the alias header is missing a `#define` for that function/type, or the stub `.c` isn't present. + - Duplicate symbol → the Makefile is picking up both `_*.c` and the original `_*.c`; restrict the wildcard to the new prefix only. + - Implicit declaration warnings for `whal_Reg_*` / `whal_SetBits` in a stub include → you probably wrote `#include ` with angle brackets in the stub instead of `#include "_.c"` with quotes. The stub must use quoted include so the preprocessor finds the sibling `.c` in the same directory. +2. Flash the binary (user runs this) and run the test suite. Each suite prints `PASS`, `FAIL`, or `SKIP`. +3. If UART output is garbled or missing bytes and the chip uses DMA, enable `CR1.FIFOEN` in the UART init before chasing further — DMA→USART without FIFO has caused byte drops on WBA. + +## Output to the user + +At each phase transition, summarize in under 10 lines: +- What was done +- Which existing drivers were reused (and note the alias header + stub `.c` pair created for each) vs newly written +- What the user should verify or flash + +Wait for the user to confirm before moving to the next phase, unless they asked for an all-in-one run upfront. diff --git a/boards/peripheral/peripheral.c b/boards/peripheral/peripheral.c index 979951d..49469c8 100644 --- a/boards/peripheral/peripheral.c +++ b/boards/peripheral/peripheral.c @@ -63,13 +63,11 @@ whal_Error Peripheral_Init(void) return err; } -#if PERIPHERAL_SENSOR_COUNT > 0 for (size_t i = 0; g_peripheralSensor[i].dev; i++) { err = whal_Sensor_Init(g_peripheralSensor[i].dev); if (err) return err; } -#endif return WHAL_SUCCESS; } @@ -78,13 +76,11 @@ whal_Error Peripheral_Deinit(void) { whal_Error err; -#if PERIPHERAL_SENSOR_COUNT > 0 for (size_t i = 0; g_peripheralSensor[i].dev; i++) { err = whal_Sensor_Deinit(g_peripheralSensor[i].dev); if (err) return err; } -#endif for (size_t i = 0; g_peripheralFlash[i].dev; i++) { err = whal_Flash_Deinit(g_peripheralFlash[i].dev); diff --git a/boards/pic32cz_curiosity_ultra/Makefile.inc b/boards/pic32cz_curiosity_ultra/Makefile.inc index cd71bab..7decfee 100644 --- a/boards/pic32cz_curiosity_ultra/Makefile.inc +++ b/boards/pic32cz_curiosity_ultra/Makefile.inc @@ -27,6 +27,7 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/timer.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/pic32cz_*.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) diff --git a/boards/stm32c031_nucleo/Makefile.inc b/boards/stm32c031_nucleo/Makefile.inc index b54d517..c0b69b6 100644 --- a/boards/stm32c031_nucleo/Makefile.inc +++ b/boards/stm32c031_nucleo/Makefile.inc @@ -29,6 +29,7 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32c0_*.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) diff --git a/boards/stm32f411_blackpill/Makefile.inc b/boards/stm32f411_blackpill/Makefile.inc index 6509c02..34e5d1b 100644 --- a/boards/stm32f411_blackpill/Makefile.inc +++ b/boards/stm32f411_blackpill/Makefile.inc @@ -29,6 +29,7 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32f4_*.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) diff --git a/boards/stm32h563zi_nucleo/Makefile.inc b/boards/stm32h563zi_nucleo/Makefile.inc index b641425..79b2558 100644 --- a/boards/stm32h563zi_nucleo/Makefile.inc +++ b/boards/stm32h563zi_nucleo/Makefile.inc @@ -31,6 +31,7 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32h5_*.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/lan8742a_*.c) BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) diff --git a/boards/stm32wb55xx_nucleo/Makefile.inc b/boards/stm32wb55xx_nucleo/Makefile.inc index 7aa7748..eb6a726 100644 --- a/boards/stm32wb55xx_nucleo/Makefile.inc +++ b/boards/stm32wb55xx_nucleo/Makefile.inc @@ -20,7 +20,10 @@ CFLAGS += -Wall -Werror $(INCLUDE) -g3 \ -DWHAL_CFG_CLOCK_API_MAPPING_STM32WB_PLL \ -DWHAL_CFG_RNG_API_MAPPING_STM32WB \ -DWHAL_CFG_DMA_API_MAPPING_STM32WB \ - -DWHAL_CFG_CRYPTO_API_MAPPING_STM32WB_AES + -DWHAL_CFG_CRYPTO_API_MAPPING_STM32WB_AES \ + -DWHAL_CFG_CRYPTO_AES_ECB -DWHAL_CFG_CRYPTO_AES_CBC \ + -DWHAL_CFG_CRYPTO_AES_CTR -DWHAL_CFG_CRYPTO_AES_GCM \ + -DWHAL_CFG_CRYPTO_AES_GMAC -DWHAL_CFG_CRYPTO_AES_CCM LDFLAGS = --omagic -static LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld diff --git a/boards/stm32wba55cg_nucleo/Makefile.inc b/boards/stm32wba55cg_nucleo/Makefile.inc new file mode 100644 index 0000000..080e03e --- /dev/null +++ b/boards/stm32wba55cg_nucleo/Makefile.inc @@ -0,0 +1,51 @@ +_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + +PLATFORM = stm32wba +TESTS ?= clock gpio flash timer rng crypto uart spi i2c irq + +GCC = $(GCC_PATH)arm-none-eabi-gcc +LD = $(GCC_PATH)arm-none-eabi-ld +OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy + +CFLAGS += -Wall -Werror $(INCLUDE) -g3 \ + -ffreestanding -nostdlib -mcpu=cortex-m33 -mthumb \ + -DPLATFORM_STM32WBA -MMD -MP \ + $(if $(DMA),-DBOARD_DMA) \ + $(if $(filter iwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_IWDG) \ + $(if $(filter wwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_WWDG) \ + -DWHAL_CFG_CRYPTO_AES_ECB -DWHAL_CFG_CRYPTO_AES_CBC \ + -DWHAL_CFG_CRYPTO_AES_CTR -DWHAL_CFG_CRYPTO_AES_GCM \ + -DWHAL_CFG_CRYPTO_AES_GMAC -DWHAL_CFG_CRYPTO_AES_CCM \ + -DWHAL_CFG_CRYPTO_SHA1 -DWHAL_CFG_CRYPTO_SHA224 \ + -DWHAL_CFG_CRYPTO_SHA256 -DWHAL_CFG_CRYPTO_HMAC_SHA1 \ + -DWHAL_CFG_CRYPTO_HMAC_SHA224 -DWHAL_CFG_CRYPTO_HMAC_SHA256 +LDFLAGS = --omagic -static + +LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld + +INCLUDE += -I$(_BOARD_DIR) -I$(WHAL_DIR)/boards/peripheral + +BOARD_SOURCE = $(_BOARD_DIR)/ivt.c +BOARD_SOURCE += $(_BOARD_DIR)/board.c +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/gpio.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/clock.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/uart.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/timer.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/spi.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/i2c.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/watchdog.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/dma.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/irq.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/irq/cortex_m4_nvic.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32wba_*.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) + +# Peripheral devices +include $(WHAL_DIR)/boards/peripheral/Makefile.inc diff --git a/boards/stm32wba55cg_nucleo/board.c b/boards/stm32wba55cg_nucleo/board.c new file mode 100644 index 0000000..c82998a --- /dev/null +++ b/boards/stm32wba55cg_nucleo/board.c @@ -0,0 +1,540 @@ +/* Board configuration for the STM32WBA55CG Nucleo (NUCLEO-WBA55CG) */ + +#include +#include +#include "board.h" +#include +#include "peripheral.h" + +/* SysTick timing */ +volatile uint32_t g_tick = 0; + +void SysTick_Handler(void) +{ + g_tick++; +} + +uint32_t Board_GetTick(void) +{ + return g_tick; +} + +whal_Timeout g_whalTimeout = { + .timeoutTicks = 1000, /* 1s timeout */ + .GetTick = Board_GetTick, +}; + +/* IRQ */ +whal_Irq g_whalIrq = { + .regmap = { WHAL_CORTEX_M33_NVIC_REGMAP }, + .driver = WHAL_CORTEX_M33_NVIC_DRIVER, +}; + +/* Clock: PLL1 from HSE32, targeting 100 MHz + * HSE32 = 32 MHz + * PLL1M = 1 (div 2) -> ref_ck = 16 MHz + * PLL1N = 25 -> VCO = 16 * 25 = 400 MHz + * PLL1R = 3 (div 4) -> pll1rclk = 100 MHz + * PLL1RGE = 3 (8-16 MHz range) + */ +whal_Clock g_whalClock = { + .regmap = { WHAL_STM32WBA55_RCC_PLL_REGMAP }, + .driver = WHAL_STM32WBA55_RCC_PLL_DRIVER, + + .cfg = &(whal_Stm32wbaRcc_Cfg) { + .sysClkSrc = WHAL_STM32WBA_RCC_SYSCLK_SRC_PLL1, + .sysClkCfg = &(whal_Stm32wbaRcc_Pll1Cfg) { + .clkSrc = WHAL_STM32WBA_RCC_PLL1SRC_HSE32, + .rge = WHAL_STM32WBA_RCC_PLL1RGE_8_16, + .m = 1, /* div 2 */ + .n = 25, /* VCO = 400 MHz */ + .r = 3, /* div 4 -> 100 MHz */ + .q = 0, + .p = 0, + }, + }, +}; + +static const whal_Stm32wbaRcc_Clk g_flashClock = {WHAL_STM32WBA55_FLASH_CLOCK}; + +static const whal_Stm32wbaRcc_Clk g_clocks[] = { + {WHAL_STM32WBA55_GPIOA_CLOCK}, + {WHAL_STM32WBA55_GPIOB_CLOCK}, + {WHAL_STM32WBA55_GPIOC_CLOCK}, + {WHAL_STM32WBA55_USART1_CLOCK}, + {WHAL_STM32WBA55_SPI1_CLOCK}, + {WHAL_STM32WBA55_RNG_CLOCK}, + {WHAL_STM32WBA55_AES_CLOCK}, + {WHAL_STM32WBA55_HASH_CLOCK}, + {WHAL_STM32WBA55_I2C1_CLOCK}, +#ifdef BOARD_WATCHDOG_WWDG + {WHAL_STM32WBA55_WWDG_CLOCK}, +#endif +}; +#define CLOCK_COUNT (sizeof(g_clocks) / sizeof(g_clocks[0])) + +/* GPIO */ +whal_Gpio g_whalGpio = { + .regmap = { WHAL_STM32WBA55_GPIO_REGMAP }, + .driver = WHAL_STM32WBA55_GPIO_DRIVER, + + .cfg = &(whal_Stm32wbaGpio_Cfg) { + .pinCfg = (whal_Stm32wbaGpio_PinCfg[PIN_COUNT]) { + /* LED: PA9 (LD2, Green), output, push-pull, low speed, pull-up */ + [LED_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_A, 9, WHAL_STM32WBA_GPIO_MODE_OUT, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_LOW, + WHAL_STM32WBA_GPIO_PULL_UP, 0), + /* USART1 TX: PB12, AF7 */ + [UART_TX_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_B, 12, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_UP, 7), + /* USART1 RX: PA8, AF7 */ + [UART_RX_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_A, 8, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_UP, 7), + /* SPI1 SCK: PB4, AF5 */ + [SPI_SCK_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_B, 4, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_NONE, 5), + /* SPI1 MISO: PB3, AF5 */ + [SPI_MISO_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_B, 3, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_NONE, 5), + /* SPI1 MOSI: PA15, AF5 */ + [SPI_MOSI_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_A, 15, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_NONE, 5), + /* SPI CS: PA12, output, push-pull */ + [SPI_CS_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_A, 12, WHAL_STM32WBA_GPIO_MODE_OUT, + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_UP, 0), + /* I2C1 SCL: PB2, AF4, open-drain */ + [I2C_SCL_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_B, 2, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_UP, 4), + /* I2C1 SDA: PB1, AF4, open-drain */ + [I2C_SDA_PIN] = WHAL_STM32WBA_GPIO_PIN( + WHAL_STM32WBA_GPIO_PORT_B, 1, WHAL_STM32WBA_GPIO_MODE_ALTFN, + WHAL_STM32WBA_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32WBA_GPIO_SPEED_FAST, + WHAL_STM32WBA_GPIO_PULL_UP, 4), + }, + .pinCount = PIN_COUNT, + }, +}; + +/* I2C */ +whal_I2c g_whalI2c = { + .regmap = { WHAL_STM32WBA55_I2C1_REGMAP }, + .driver = WHAL_STM32WBA55_I2C1_DRIVER, + + .cfg = &(whal_Stm32wbaI2c_Cfg) { + .pclk = 100000000, + .timeout = &g_whalTimeout, + }, +}; + +/* SPI */ +whal_Spi g_whalSpi = { + .regmap = { WHAL_STM32WBA55_SPI1_REGMAP }, + .driver = WHAL_STM32WBA55_SPI1_DRIVER, + + .cfg = &(whal_Stm32wbaSpi_Cfg) { + .pclk = 100000000, + .timeout = &g_whalTimeout, + }, +}; + +/* Timer (SysTick at 100 MHz) */ +whal_Timer g_whalTimer = { + .regmap = { WHAL_CORTEX_M33_SYSTICK_REGMAP }, + .driver = WHAL_CORTEX_M33_SYSTICK_DRIVER, + + .cfg = &(whal_SysTick_Cfg) { + .cyclesPerTick = 100000000 / 1000, + .clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK, + .tickInt = WHAL_SYSTICK_TICKINT_ENABLED, + }, +}; + +/* DMA */ +#ifdef BOARD_DMA + +whal_Dma g_whalDma1 = { + .regmap = { WHAL_STM32WBA55_GPDMA1_REGMAP }, + .driver = WHAL_STM32WBA55_GPDMA1_DRIVER, + .cfg = &(whal_Stm32wbaGpdma_Cfg){ + .numChannels = 8, + .timeout = &g_whalTimeout, + }, +}; + +static const whal_Stm32wbaRcc_Clk g_dmaClock = {WHAL_STM32WBA55_GPDMA1_CLOCK}; + +void GPDMA1_Channel0_IRQHandler(void) +{ + whal_Stm32wbaGpdma_IRQHandler(&g_whalDma1, 0, + whal_Stm32wbaUartDma_TxCallback, + g_whalUart.cfg); +} + +void GPDMA1_Channel1_IRQHandler(void) +{ + whal_Stm32wbaGpdma_IRQHandler(&g_whalDma1, 1, + whal_Stm32wbaUartDma_RxCallback, + g_whalUart.cfg); +} +#endif + +/* UART (USART1 via VCP at 115200 baud) */ +#ifdef BOARD_DMA +whal_Uart g_whalUart = { + .regmap = { WHAL_STM32WBA55_USART1_REGMAP }, + .driver = &whal_Stm32wbaUartDma_Driver, + .cfg = &(whal_Stm32wbaUartDma_Cfg) { + .base = { + .brr = WHAL_STM32WBA_UART_BRR(100000000, 115200), + .timeout = &g_whalTimeout, + }, + .dma = &g_whalDma1, + .txCh = 0, + .rxCh = 1, + .txChCfg = &(whal_Stm32wbaGpdma_ChCfg){WHAL_STM32WBA55_USART1_TX_DMA_CFG}, + .rxChCfg = &(whal_Stm32wbaGpdma_ChCfg){WHAL_STM32WBA55_USART1_RX_DMA_CFG}, + }, +}; +#else +whal_Uart g_whalUart = { + .regmap = { WHAL_STM32WBA55_USART1_REGMAP }, + .driver = WHAL_STM32WBA55_USART1_DRIVER, + + .cfg = &(whal_Stm32wbaUart_Cfg) { + .timeout = &g_whalTimeout, + .brr = WHAL_STM32WBA_UART_BRR(100000000, 115200), + }, +}; +#endif + +/* Flash */ +whal_Flash g_whalFlash = { + .regmap = { WHAL_STM32WBA55_FLASH_REGMAP }, + .driver = WHAL_STM32WBA55_FLASH_DRIVER, + + .cfg = &(whal_Stm32wbaFlash_Cfg) { + .timeout = &g_whalTimeout, + .startAddr = 0x08000000, + .size = 0x100000, /* 1 MB */ + }, +}; + +/* RNG */ +whal_Rng g_whalRng = { + .regmap = { WHAL_STM32WBA55_RNG_REGMAP }, + .driver = WHAL_STM32WBA55_RNG_DRIVER, + + .cfg = &(whal_Stm32wbaRng_Cfg) { + .timeout = &g_whalTimeout, + }, +}; + +/* Crypto (AES hardware accelerator) */ +whal_Crypto g_whalCrypto = { + .regmap = { WHAL_STM32WBA55_AES_REGMAP }, + .driver = WHAL_STM32WBA55_AES_DRIVER, + + .cfg = &(whal_Stm32wbaAes_Cfg) { + .timeout = &g_whalTimeout, + }, +}; + +/* Hash (HASH hardware accelerator) */ +whal_Crypto g_whalHash = { + .regmap = { WHAL_STM32WBA55_HASH_REGMAP }, + .driver = WHAL_STM32WBA55_HASH_DRIVER, + + .cfg = &(whal_Stm32wbaHash_Cfg) { + .timeout = &g_whalTimeout, + }, +}; + +#ifdef BOARD_WATCHDOG_IWDG +whal_Watchdog g_whalWatchdog = { + .regmap = { WHAL_STM32WBA55_IWDG_REGMAP }, + .driver = WHAL_STM32WBA55_IWDG_DRIVER, + + .cfg = &(whal_Stm32wbaIwdg_Cfg) { + .prescaler = WHAL_STM32WBA_IWDG_PR_32, + .reload = 100, + .timeout = &g_whalTimeout, + }, +}; +#elif defined(BOARD_WATCHDOG_WWDG) +whal_Watchdog g_whalWatchdog = { + .regmap = { WHAL_STM32WBA55_WWDG_REGMAP }, + .driver = WHAL_STM32WBA55_WWDG_DRIVER, + + .cfg = &(whal_Stm32wbaWwdg_Cfg) { + .prescaler = WHAL_STM32WBA_WWDG_TB_128, + .window = 0x7F, + .counter = 0x7F, + }, +}; +#endif + +void Board_WaitMs(size_t ms) +{ + uint32_t startCount = g_tick; + while (g_tick - startCount < ms); +} + +/* + * Switch PWR voltage scaling to Range 1 (required for >16 MHz operation). + * After reset the device is in Range 2 (max 16 MHz). Must switch to Range 1 + * before configuring PLL or increasing SYSCLK. + * + * PWR base: 0x46020800 + * PWR_VOSR offset: 0x00C + * bit 16 VOS: 0=Range2, 1=Range1 + * bit 15 VOSRDY: read-only, 1 when stable + */ +#define PWR_BASE 0x46020800 +#define PWR_VOSR_REG 0x00C +#define PWR_VOSR_VOS_Msk (1UL << 16) +#define PWR_VOSR_VOSRDY_Msk (1UL << 15) + +static whal_Error Board_SetVosRange1(void) +{ + /* Set VOS to Range 1 */ + whal_Reg_Update(PWR_BASE, PWR_VOSR_REG, PWR_VOSR_VOS_Msk, PWR_VOSR_VOS_Msk); + + /* Wait for VOSRDY */ + while (!(whal_Reg_Read(PWR_BASE, PWR_VOSR_REG) & PWR_VOSR_VOSRDY_Msk)) + ; + + return WHAL_SUCCESS; +} + +whal_Error Board_Init(void) +{ + whal_Error err; + + /* Enable PWR clock (RCC_AHB4ENR bit 2) -- required to access PWR registers */ + static const whal_Stm32wbaRcc_Clk pwrClock = {WHAL_STM32WBA55_PWR_CLOCK}; + err = whal_Clock_Enable(&g_whalClock, &pwrClock); + if (err) + return err; + + /* Switch to voltage Range 1 (required for >16 MHz operation). + * After reset device is in Range 2 which caps SYSCLK at 16 MHz. */ + err = Board_SetVosRange1(); + if (err) + return err; + + /* Enable flash clock and set latency before increasing clock speed. + * At 100 MHz, 3.3V: 3 wait states required (RM0493 Table 69). */ + err = whal_Clock_Enable(&g_whalClock, &g_flashClock); + if (err) + return err; + + err = whal_Stm32wbaFlash_Ext_SetLatency(&g_whalFlash, 3); + if (err) + return err; + + /* Set HPRE5 to div 4 before switching to PLL (AHB5 max 32 MHz). + * 100 MHz / 4 = 25 MHz. Value 0b101 = div 4. */ + err = whal_Stm32wbaRcc_Ext_SetHpre5(&g_whalClock, 5); + if (err) + return err; + + err = whal_Clock_Init(&g_whalClock); + if (err) + return err; + +#ifdef BOARD_WATCHDOG_IWDG + /* Enable LSI oscillator required by IWDG */ + err = whal_Stm32wbaRcc_Ext_EnableLsi(&g_whalClock, 1); + if (err) + return err; +#endif + + /* Select HSI16 as RNG kernel clock source. + * Default after reset is LSE which is not enabled. HSI16 is always on. */ + err = whal_Stm32wbaRcc_Ext_SetRngClockSrc(&g_whalClock, + WHAL_STM32WBA_RCC_RNGSEL_HSI16); + if (err) + return err; + + /* Enable peripheral clocks */ + for (size_t i = 0; i < CLOCK_COUNT; i++) { + err = whal_Clock_Enable(&g_whalClock, &g_clocks[i]); + if (err) + return err; + } + + err = whal_Irq_Init(&g_whalIrq); + if (err) + return err; + +#ifdef BOARD_DMA + err = whal_Clock_Enable(&g_whalClock, &g_dmaClock); + if (err) + return err; + err = whal_Dma_Init(&g_whalDma1); + if (err) + return err; + + /* Enable NVIC interrupts for GPDMA1 channel 0 (IRQ 29) and channel 1 (IRQ 30) */ + err = whal_Irq_Enable(&g_whalIrq, 29, NULL); + if (err) + return err; + err = whal_Irq_Enable(&g_whalIrq, 30, NULL); + if (err) + return err; +#endif + + err = whal_Gpio_Init(&g_whalGpio); + if (err) + return err; + + err = whal_Uart_Init(&g_whalUart); + if (err) + return err; + + err = whal_Spi_Init(&g_whalSpi); + if (err) + return err; + + err = whal_I2c_Init(&g_whalI2c); + if (err) + return err; + + err = whal_Flash_Init(&g_whalFlash); + if (err) + return err; + + err = whal_Rng_Init(&g_whalRng); + if (err) + return err; + + err = whal_Crypto_Init(&g_whalCrypto); + if (err) + return err; + + err = whal_Crypto_Init(&g_whalHash); + if (err) + return err; + + err = whal_Timer_Init(&g_whalTimer); + if (err) + return err; + + err = whal_Timer_Start(&g_whalTimer); + if (err) + return err; + + err = Peripheral_Init(); + if (err) + return err; + + return WHAL_SUCCESS; +} + +whal_Error Board_Deinit(void) +{ + whal_Error err; + + err = Peripheral_Deinit(); + if (err) + return err; + + err = whal_Timer_Stop(&g_whalTimer); + if (err) + return err; + + err = whal_Timer_Deinit(&g_whalTimer); + if (err) + return err; + + err = whal_Crypto_Deinit(&g_whalHash); + if (err) + return err; + + err = whal_Crypto_Deinit(&g_whalCrypto); + if (err) + return err; + + err = whal_Rng_Deinit(&g_whalRng); + if (err) + return err; + + err = whal_Flash_Deinit(&g_whalFlash); + if (err) + return err; + + err = whal_I2c_Deinit(&g_whalI2c); + if (err) + return err; + + err = whal_Spi_Deinit(&g_whalSpi); + if (err) + return err; + + err = whal_Uart_Deinit(&g_whalUart); + if (err) + return err; + + err = whal_Gpio_Deinit(&g_whalGpio); + if (err) + return err; + +#ifdef BOARD_DMA + whal_Irq_Disable(&g_whalIrq, 29); + whal_Irq_Disable(&g_whalIrq, 30); + + err = whal_Dma_Deinit(&g_whalDma1); + if (err) + return err; + err = whal_Clock_Disable(&g_whalClock, &g_dmaClock); + if (err) + return err; +#endif + + err = whal_Irq_Deinit(&g_whalIrq); + if (err) + return err; + + /* Disable peripheral clocks */ + for (size_t i = 0; i < CLOCK_COUNT; i++) { + err = whal_Clock_Disable(&g_whalClock, &g_clocks[i]); + if (err) + return err; + } + +#ifdef BOARD_WATCHDOG_IWDG + err = whal_Stm32wbaRcc_Ext_EnableLsi(&g_whalClock, 0); + if (err) + return err; +#endif + + err = whal_Clock_Deinit(&g_whalClock); + if (err) + return err; + + /* Reduce flash latency then disable flash clock */ + err = whal_Stm32wbaFlash_Ext_SetLatency(&g_whalFlash, 0); + if (err) + return err; + + err = whal_Clock_Disable(&g_whalClock, &g_flashClock); + if (err) + return err; + + return WHAL_SUCCESS; +} diff --git a/boards/stm32wba55cg_nucleo/board.h b/boards/stm32wba55cg_nucleo/board.h new file mode 100644 index 0000000..a6068df --- /dev/null +++ b/boards/stm32wba55cg_nucleo/board.h @@ -0,0 +1,53 @@ +#ifndef BOARD_H +#define BOARD_H + +#include +#include +#include + +extern whal_Clock g_whalClock; +extern whal_Gpio g_whalGpio; +extern whal_Timer g_whalTimer; +extern whal_Uart g_whalUart; +extern whal_Spi g_whalSpi; +extern whal_Flash g_whalFlash; +extern whal_Rng g_whalRng; +extern whal_I2c g_whalI2c; +extern whal_Crypto g_whalCrypto; +extern whal_Crypto g_whalHash; +extern whal_Irq g_whalIrq; +extern whal_Watchdog g_whalWatchdog; +#ifdef BOARD_DMA +extern whal_Dma g_whalDma1; +#endif + +extern whal_Timeout g_whalTimeout; +extern volatile uint32_t g_tick; + +enum { + LED_PIN, + UART_TX_PIN, + UART_RX_PIN, + SPI_SCK_PIN, + SPI_MISO_PIN, + SPI_MOSI_PIN, + SPI_CS_PIN, + I2C_SCL_PIN, + I2C_SDA_PIN, + PIN_COUNT, +}; + +/* LD2 (Green) on PA9 -- avoids conflict with SPI1_SCK on PB4 (LD1) */ +#define BOARD_LED_PIN 0 +#define BOARD_LED_PORT_OFFSET 0x000 /* GPIOA */ +#define BOARD_LED_PIN_NUM 9 +#define BOARD_FLASH_START_ADDR 0x08000000 +#define BOARD_FLASH_SIZE 0x100000 /* 1 MB */ +#define BOARD_FLASH_TEST_ADDR 0x080FE000 +#define BOARD_FLASH_SECTOR_SZ 0x2000 /* 8 KB */ + +whal_Error Board_Init(void); +whal_Error Board_Deinit(void); +void Board_WaitMs(size_t ms); + +#endif /* BOARD_H */ diff --git a/boards/stm32wba55cg_nucleo/ivt.c b/boards/stm32wba55cg_nucleo/ivt.c new file mode 100644 index 0000000..9bd79e6 --- /dev/null +++ b/boards/stm32wba55cg_nucleo/ivt.c @@ -0,0 +1,242 @@ +#include +#include + +extern uint32_t _estack[]; +extern uint32_t _sidata[]; +extern uint32_t _sdata[]; +extern uint32_t _edata[]; +extern uint32_t _sbss[]; +extern uint32_t _ebss[]; + +extern void main(); + +void __attribute__((naked,noreturn)) Default_Handler() +{ + while(1); +} + +void Reset_Handler() __attribute__((weak)); +void NMI_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HardFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void MemManage_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void BusFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void UsageFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SecureFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SVC_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DebugMon_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PendSV_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SysTick_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); + +/* STM32WBA55 IRQ handlers (positions 0-71 from RM0493 Table 135) */ +void WWDG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PVD_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RTC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RTC_S_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TAMP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RAMCFG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void FLASH_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void FLASH_S_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GTZC_TZIC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RCC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RCC_S_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI0_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI5_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI6_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI7_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI8_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI9_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI10_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI11_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI12_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI13_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI14_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI15_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void IWDG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SAES_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel0_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel5_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel6_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPDMA1_Channel7_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_BRK_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_UP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_TRG_COM_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_CC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C1_EV_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C1_ER_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SPI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void USART1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void USART2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPUART1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPTIM1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPTIM2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM16_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM17_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void COMP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C3_EV_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C3_ER_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SAI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TSC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void AES_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RNG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void FPU_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HASH_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PKA_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SPI3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void ICACHE_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void ADC4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RADIO_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void WKUP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HSEM_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HSEM_S_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void WKUP_S_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RCC_AUDIO_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); + +#define RESERVED Default_Handler + +/* + * Cortex-M33 vector table for STM32WBA55. + * Positions from RM0493 Table 135 (pages 591-594). + */ +void (* const interrupt_vector_table[])() __attribute__((section(".isr_vector"))) = { + (void (*)())_estack, /* Initial stack pointer */ + Reset_Handler, /* Reset */ + NMI_Handler, /* NMI */ + HardFault_Handler, /* Hard fault */ + MemManage_Handler, /* Memory management fault */ + BusFault_Handler, /* Bus fault */ + UsageFault_Handler, /* Usage fault */ + SecureFault_Handler, /* Secure fault (Cortex-M33) */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + SVC_Handler, /* SVCall */ + DebugMon_Handler, /* Debug monitor */ + RESERVED, /* Reserved */ + PendSV_Handler, /* PendSV */ + SysTick_Handler, /* SysTick */ + /* External interrupts (position 0-71) */ + WWDG_IRQHandler, /* 0: Window watchdog */ + PVD_IRQHandler, /* 1: PVD */ + RTC_IRQHandler, /* 2: RTC non-secure */ + RTC_S_IRQHandler, /* 3: RTC secure */ + TAMP_IRQHandler, /* 4: Tamper */ + RAMCFG_IRQHandler, /* 5: RAMCFG */ + FLASH_IRQHandler, /* 6: Flash non-secure */ + FLASH_S_IRQHandler, /* 7: Flash secure */ + GTZC_TZIC_IRQHandler, /* 8: GTZC TZIC */ + RCC_IRQHandler, /* 9: RCC non-secure */ + RCC_S_IRQHandler, /* 10: RCC secure */ + EXTI0_IRQHandler, /* 11: EXTI line 0 */ + EXTI1_IRQHandler, /* 12: EXTI line 1 */ + EXTI2_IRQHandler, /* 13: EXTI line 2 */ + EXTI3_IRQHandler, /* 14: EXTI line 3 */ + EXTI4_IRQHandler, /* 15: EXTI line 4 */ + EXTI5_IRQHandler, /* 16: EXTI line 5 */ + EXTI6_IRQHandler, /* 17: EXTI line 6 */ + EXTI7_IRQHandler, /* 18: EXTI line 7 */ + EXTI8_IRQHandler, /* 19: EXTI line 8 */ + EXTI9_IRQHandler, /* 20: EXTI line 9 */ + EXTI10_IRQHandler, /* 21: EXTI line 10 */ + EXTI11_IRQHandler, /* 22: EXTI line 11 */ + EXTI12_IRQHandler, /* 23: EXTI line 12 */ + EXTI13_IRQHandler, /* 24: EXTI line 13 */ + EXTI14_IRQHandler, /* 25: EXTI line 14 */ + EXTI15_IRQHandler, /* 26: EXTI line 15 */ + IWDG_IRQHandler, /* 27: IWDG */ + SAES_IRQHandler, /* 28: Secure AES */ + GPDMA1_Channel0_IRQHandler, /* 29: GPDMA1 channel 0 */ + GPDMA1_Channel1_IRQHandler, /* 30: GPDMA1 channel 1 */ + GPDMA1_Channel2_IRQHandler, /* 31: GPDMA1 channel 2 */ + GPDMA1_Channel3_IRQHandler, /* 32: GPDMA1 channel 3 */ + GPDMA1_Channel4_IRQHandler, /* 33: GPDMA1 channel 4 */ + GPDMA1_Channel5_IRQHandler, /* 34: GPDMA1 channel 5 */ + GPDMA1_Channel6_IRQHandler, /* 35: GPDMA1 channel 6 */ + GPDMA1_Channel7_IRQHandler, /* 36: GPDMA1 channel 7 */ + TIM1_BRK_IRQHandler, /* 37: TIM1 break */ + TIM1_UP_IRQHandler, /* 38: TIM1 update */ + TIM1_TRG_COM_IRQHandler, /* 39: TIM1 trigger/commutation */ + TIM1_CC_IRQHandler, /* 40: TIM1 capture compare */ + TIM2_IRQHandler, /* 41: TIM2 */ + TIM3_IRQHandler, /* 42: TIM3 */ + I2C1_EV_IRQHandler, /* 43: I2C1 event */ + I2C1_ER_IRQHandler, /* 44: I2C1 error */ + SPI1_IRQHandler, /* 45: SPI1 */ + USART1_IRQHandler, /* 46: USART1 */ + USART2_IRQHandler, /* 47: USART2 */ + LPUART1_IRQHandler, /* 48: LPUART1 */ + LPTIM1_IRQHandler, /* 49: LPTIM1 */ + LPTIM2_IRQHandler, /* 50: LPTIM2 */ + TIM16_IRQHandler, /* 51: TIM16 */ + TIM17_IRQHandler, /* 52: TIM17 */ + COMP_IRQHandler, /* 53: COMP */ + I2C3_EV_IRQHandler, /* 54: I2C3 event */ + I2C3_ER_IRQHandler, /* 55: I2C3 error */ + SAI1_IRQHandler, /* 56: SAI1 */ + TSC_IRQHandler, /* 57: TSC */ + AES_IRQHandler, /* 58: AES */ + RNG_IRQHandler, /* 59: RNG */ + FPU_IRQHandler, /* 60: FPU */ + HASH_IRQHandler, /* 61: HASH */ + PKA_IRQHandler, /* 62: PKA */ + SPI3_IRQHandler, /* 63: SPI3 */ + ICACHE_IRQHandler, /* 64: ICACHE */ + ADC4_IRQHandler, /* 65: ADC4 */ + RADIO_IRQHandler, /* 66: 2.4 GHz RADIO */ + WKUP_IRQHandler, /* 67: WKUP */ + HSEM_IRQHandler, /* 68: HSEM non-secure */ + HSEM_S_IRQHandler, /* 69: HSEM secure */ + WKUP_S_IRQHandler, /* 70: WKUP secure */ + RCC_AUDIO_IRQHandler, /* 71: RCC audio sync */ +}; + +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + for (size_t i = 0; i < n; i++) + d[i] = s[i]; + + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = s; + unsigned char v = (unsigned char)c; + + for (size_t i = 0; i < n; i++) + p[i] = v; + + return s; +} + +void __attribute__((naked)) Reset_Handler() +{ + __asm__("ldr r0, =_estack\n\t" + "mov sp, r0"); + + /* Copy data section from flash to RAM */ + uint32_t data_section_size = _edata - _sdata; + memcpy(_sdata, _sidata, data_section_size*4); + + /* Zero out bss */ + uint32_t bss_section_size = _ebss - _sbss; + memset(_sbss, 0, bss_section_size*4); + + /* Set Interrupt Vector Table Offset */ + uint32_t *vtor = (uint32_t *)0xE000ED08; + *vtor = (uint32_t)interrupt_vector_table; + + main(); +} diff --git a/boards/stm32wba55cg_nucleo/linker.ld b/boards/stm32wba55cg_nucleo/linker.ld new file mode 100644 index 0000000..df5403a --- /dev/null +++ b/boards/stm32wba55cg_nucleo/linker.ld @@ -0,0 +1,128 @@ +/* + * Linker script for STM32WBA55CG (NUCLEO-WBA55CG) + * + * Flash: 1 MB at 0x08000000 + * SRAM1: 64 KB at 0x20000000 + * SRAM2: 64 KB at 0x20010000 (contiguous with SRAM1) + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of 128 KB RAM */ +/* Generate a link error if the stack doesn't fit into RAM */ +_Min_Stack_Size = 0x500; + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +RAM1 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000 +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM1 AT> FLASH + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM1 + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM1 +} diff --git a/docs/writing_a_driver.md b/docs/writing_a_driver.md index f91dbb9..2785c70 100644 --- a/docs/writing_a_driver.md +++ b/docs/writing_a_driver.md @@ -905,30 +905,39 @@ consumption and avoid unnecessary entropy source wear. Header: `wolfHAL/crypto/crypto.h` -The crypto driver provides access to hardware cryptographic accelerators. Unlike -other device types, the crypto driver uses an **ops table** dispatch model -instead of a fixed vtable — each supported algorithm is a function pointer in a -board-defined ops table, indexed by a board-defined enum. This allows different -platforms to expose different subsets of algorithms without changing the generic -interface. +The crypto driver provides access to hardware cryptographic accelerators +(ciphers, hashes, MACs, and public key operations). The driver vtable uses a +unified **StartOp / Process / EndOp** pattern that supports both one-shot and +streaming use cases. ### Device Struct -The crypto device struct extends the standard model with an ops table: - ```c struct whal_Crypto { const whal_Regmap regmap; const whal_CryptoDriver *driver; - const whal_Crypto_OpFunc *ops; - size_t opsCount; const void *cfg; }; ``` -The `driver` vtable handles Init/Deinit. The `ops` table maps algorithm indices -to operation functions. The board defines the enum values and populates the ops -table. +### Driver Vtable + +```c +typedef struct { + whal_Error (*Init)(whal_Crypto *cryptoDev); + whal_Error (*Deinit)(whal_Crypto *cryptoDev); + whal_Error (*StartOp)(whal_Crypto *cryptoDev, size_t opId, void *opArgs); + whal_Error (*Process)(whal_Crypto *cryptoDev, size_t opId, void *opArgs); + whal_Error (*EndOp)(whal_Crypto *cryptoDev, size_t opId, void *opArgs); +} whal_CryptoDriver; +``` + +The `opId` parameter is a framework-defined enum value (e.g. `WHAL_CRYPTO_AES_GCM`, +`WHAL_CRYPTO_SHA256`). The `opArgs` parameter is a pointer to an +algorithm-specific argument struct (e.g., `whal_Crypto_AesGcmArgs`, +`whal_Crypto_HashArgs`). The driver casts it to the correct type based on +`opId`. See `wolfHAL/crypto/crypto.h` for the full set of argument structs and +operation IDs. ### Init / Deinit @@ -937,36 +946,63 @@ disable the crypto accelerator peripheral. ### Operations -Each operation function has the signature: +Each crypto operation is split into three phases: + +- **StartOp** — Configure hardware, load key/IV, process AAD for AEAD modes. +- **Process** — Feed data through the hardware. May be called multiple times + for streaming. Optional for single-shot operations (e.g. GMAC has no + payload). +- **EndOp** — Finalize the operation, read output (tag, digest), release + hardware. On StartOp failure, the driver cleans up internally and EndOp + should not be called. + +Unsupported `opId` values return `WHAL_ENOTSUP`. Unsupported parameter +combinations (e.g. AES-192 on hardware that only supports 128/256) also +return `WHAL_ENOTSUP`. + +### Convenience Wrappers + +`crypto.h` provides typed inline wrappers for each algorithm. One-shot +wrappers call all three phases in sequence: ```c -whal_Error myOp(whal_Crypto *cryptoDev, void *opArgs); +whal_Crypto_AesGcmArgs args = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = key, .keySz = 32, + .iv = iv, .ivSz = 12, + .in = plaintext, .out = ct, .sz = sizeof(plaintext), + .aad = aad, .aadSz = sizeof(aad), + .tag = tag, .tagSz = 16, +}; +whal_Crypto_AesGcm(&g_whalCrypto, &args); ``` -The `opArgs` parameter is a pointer to an algorithm-specific argument struct -(e.g., `whal_Crypto_AesEcbArgs`, `whal_Crypto_AesGcmArgs`). The operation -function casts it to the correct type. See `wolfHAL/crypto/crypto.h` for the -full set of argument structs. +Streaming wrappers expose each phase individually with typed parameters: + +```c +whal_Crypto_Sha256_Start(&g_whalHash); +whal_Crypto_Sha256_Update(&g_whalHash, chunk1, chunk1Sz); +whal_Crypto_Sha256_Update(&g_whalHash, chunk2, chunk2Sz); +whal_Crypto_Sha256_Finalize(&g_whalHash, digest, 32); +``` + +Both wrapper styles are guarded by `WHAL_CFG_CRYPTO_` defines (e.g. +`WHAL_CFG_CRYPTO_AES_GCM`, `WHAL_CFG_CRYPTO_SHA256`). ### Board Integration -The board defines an enum of supported operations and a corresponding ops table: +The board enables supported algorithms via `-D` flags in `board.mk` and +instantiates the crypto device: ```c -enum { - BOARD_CRYPTO_AES_ECB, - BOARD_CRYPTO_AES_CBC, - BOARD_CRYPTO_OP_COUNT, -}; - -static const whal_Crypto_OpFunc cryptoOps[BOARD_CRYPTO_OP_COUNT] = { - [BOARD_CRYPTO_AES_ECB] = whal_Stm32wbAes_AesEcb, - [BOARD_CRYPTO_AES_CBC] = whal_Stm32wbAes_AesCbc, +whal_Crypto g_whalCrypto = { + .regmap = { WHAL_STM32WB55_AES1_REGMAP }, + .cfg = &(whal_Stm32wbAes_Cfg) { .timeout = &g_whalTimeout }, }; ``` -Callers use `whal_Crypto_Op(&g_whalCrypto, BOARD_CRYPTO_AES_ECB, &args)` to -invoke an operation. +When API mapping is active (e.g. `-DWHAL_CFG_CRYPTO_API_MAPPING_STM32WB_AES`), +the driver functions are mapped directly to the top-level API, eliminating the +vtable indirection. --- diff --git a/src/clock/stm32wba_rcc.c b/src/clock/stm32wba_rcc.c new file mode 100644 index 0000000..6a333b2 --- /dev/null +++ b/src/clock/stm32wba_rcc.c @@ -0,0 +1,315 @@ +#include +#include +#include +#include +#include + +/* + * STM32WBA RCC Register Definitions (RM0493) + * + * RCC base: 0x46020C00 + */ + +/* RCC_CR (offset 0x000) - Clock control */ +#define RCC_CR_REG 0x000 +#define RCC_CR_HSEON_Pos 16 +#define RCC_CR_HSEON_Msk (1UL << RCC_CR_HSEON_Pos) +#define RCC_CR_HSERDY_Pos 17 +#define RCC_CR_HSERDY_Msk (1UL << RCC_CR_HSERDY_Pos) +#define RCC_CR_HSEPRE_Pos 20 +#define RCC_CR_HSEPRE_Msk (1UL << RCC_CR_HSEPRE_Pos) +#define RCC_CR_PLL1ON_Pos 24 +#define RCC_CR_PLL1ON_Msk (1UL << RCC_CR_PLL1ON_Pos) +#define RCC_CR_PLL1RDY_Pos 25 +#define RCC_CR_PLL1RDY_Msk (1UL << RCC_CR_PLL1RDY_Pos) +#define RCC_CR_HSION_Pos 8 +#define RCC_CR_HSION_Msk (1UL << RCC_CR_HSION_Pos) +#define RCC_CR_HSIRDY_Pos 10 +#define RCC_CR_HSIRDY_Msk (1UL << RCC_CR_HSIRDY_Pos) + +/* RCC_CFGR1 (offset 0x01C) - Clock configuration 1 */ +#define RCC_CFGR1_REG 0x01C +#define RCC_CFGR1_SW_Pos 0 +#define RCC_CFGR1_SW_Msk (3UL << RCC_CFGR1_SW_Pos) +#define RCC_CFGR1_SWS_Pos 2 +#define RCC_CFGR1_SWS_Msk (3UL << RCC_CFGR1_SWS_Pos) + +/* RCC_CFGR2 (offset 0x020) - Clock configuration 2 (prescalers) */ +#define RCC_CFGR2_REG 0x020 +#define RCC_CFGR2_HPRE_Pos 0 +#define RCC_CFGR2_HPRE_Msk (7UL << RCC_CFGR2_HPRE_Pos) +#define RCC_CFGR2_PPRE1_Pos 4 +#define RCC_CFGR2_PPRE1_Msk (7UL << RCC_CFGR2_PPRE1_Pos) +#define RCC_CFGR2_PPRE2_Pos 8 +#define RCC_CFGR2_PPRE2_Msk (7UL << RCC_CFGR2_PPRE2_Pos) + +/* RCC_CFGR3 (offset 0x024) - Clock configuration 3 (APB7, HPRE5) */ +#define RCC_CFGR3_REG 0x024 +#define RCC_CFGR3_PPRE7_Pos 4 +#define RCC_CFGR3_PPRE7_Msk (7UL << RCC_CFGR3_PPRE7_Pos) + +/* RCC_PLL1CFGR (offset 0x028) - PLL1 configuration */ +#define RCC_PLL1CFGR_REG 0x028 +#define RCC_PLL1CFGR_SRC_Pos 0 +#define RCC_PLL1CFGR_SRC_Msk (3UL << RCC_PLL1CFGR_SRC_Pos) +#define RCC_PLL1CFGR_RGE_Pos 2 +#define RCC_PLL1CFGR_RGE_Msk (3UL << RCC_PLL1CFGR_RGE_Pos) +#define RCC_PLL1CFGR_FRACEN_Pos 4 +#define RCC_PLL1CFGR_FRACEN_Msk (1UL << RCC_PLL1CFGR_FRACEN_Pos) +#define RCC_PLL1CFGR_M_Pos 8 +#define RCC_PLL1CFGR_M_Msk (7UL << RCC_PLL1CFGR_M_Pos) +#define RCC_PLL1CFGR_PEN_Pos 16 +#define RCC_PLL1CFGR_PEN_Msk (1UL << RCC_PLL1CFGR_PEN_Pos) +#define RCC_PLL1CFGR_QEN_Pos 17 +#define RCC_PLL1CFGR_QEN_Msk (1UL << RCC_PLL1CFGR_QEN_Pos) +#define RCC_PLL1CFGR_REN_Pos 18 +#define RCC_PLL1CFGR_REN_Msk (1UL << RCC_PLL1CFGR_REN_Pos) + +/* RCC_PLL1DIVR (offset 0x034) - PLL1 dividers */ +#define RCC_PLL1DIVR_REG 0x034 +#define RCC_PLL1DIVR_N_Pos 0 +#define RCC_PLL1DIVR_N_Msk (0x1FFUL << RCC_PLL1DIVR_N_Pos) +#define RCC_PLL1DIVR_P_Pos 9 +#define RCC_PLL1DIVR_P_Msk (0x7FUL << RCC_PLL1DIVR_P_Pos) +#define RCC_PLL1DIVR_Q_Pos 16 +#define RCC_PLL1DIVR_Q_Msk (0x7FUL << RCC_PLL1DIVR_Q_Pos) +#define RCC_PLL1DIVR_R_Pos 24 +#define RCC_PLL1DIVR_R_Msk (0x7FUL << RCC_PLL1DIVR_R_Pos) + +/* RCC_BDCR1 (offset 0x0C8) - Backup domain control 1 */ +#define RCC_BDCR1_REG 0x0C8 +#define RCC_BDCR1_LSI1ON_Pos 2 +#define RCC_BDCR1_LSI1ON_Msk (1UL << RCC_BDCR1_LSI1ON_Pos) +#define RCC_BDCR1_LSI1RDY_Pos 3 +#define RCC_BDCR1_LSI1RDY_Msk (1UL << RCC_BDCR1_LSI1RDY_Pos) + +/* RCC_CFGR4 (offset 0x080) - HPRE5 prescaler */ +#define RCC_CFGR4_REG 0x080 +#define RCC_CFGR4_HPRE5_Pos 0 +#define RCC_CFGR4_HPRE5_Msk (7UL << RCC_CFGR4_HPRE5_Pos) + +/* RCC_CCIPR2 (offset 0x0E4) - Peripheral independent clock config 2 */ +#define RCC_CCIPR2_REG 0x0E4 +#define RCC_CCIPR2_RNGSEL_Pos 12 +#define RCC_CCIPR2_RNGSEL_Msk (3UL << RCC_CCIPR2_RNGSEL_Pos) + +whal_Error whal_Stm32wbaRccPll_Init(whal_Clock *clkDev) +{ + whal_Stm32wbaRcc_Cfg *cfg; + whal_Stm32wbaRcc_Pll1Cfg *pllCfg; + size_t base; + + if (!clkDev || !clkDev->cfg) + return WHAL_EINVAL; + + cfg = (whal_Stm32wbaRcc_Cfg *)clkDev->cfg; + pllCfg = (whal_Stm32wbaRcc_Pll1Cfg *)cfg->sysClkCfg; + base = clkDev->regmap.base; + + /* Enable HSE32 oscillator */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_HSEON_Msk, + whal_SetBits(RCC_CR_HSEON_Msk, RCC_CR_HSEON_Pos, 1)); + + /* Wait for HSE32 ready */ + while (!(whal_Reg_Read(base, RCC_CR_REG) & RCC_CR_HSERDY_Msk)) + ; + + /* Ensure PLL1 is off before configuring */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_PLL1ON_Msk, 0); + while (whal_Reg_Read(base, RCC_CR_REG) & RCC_CR_PLL1RDY_Msk) + ; + + /* Configure PLL1CFGR: source, M divider, RGE, enable R output */ + whal_Reg_Write(base, RCC_PLL1CFGR_REG, + whal_SetBits(RCC_PLL1CFGR_SRC_Msk, RCC_PLL1CFGR_SRC_Pos, pllCfg->clkSrc) | + whal_SetBits(RCC_PLL1CFGR_RGE_Msk, RCC_PLL1CFGR_RGE_Pos, pllCfg->rge) | + whal_SetBits(RCC_PLL1CFGR_M_Msk, RCC_PLL1CFGR_M_Pos, pllCfg->m) | + whal_SetBits(RCC_PLL1CFGR_REN_Msk, RCC_PLL1CFGR_REN_Pos, 1)); + + /* Configure PLL1DIVR: N, P, Q, R dividers */ + whal_Reg_Write(base, RCC_PLL1DIVR_REG, + whal_SetBits(RCC_PLL1DIVR_N_Msk, RCC_PLL1DIVR_N_Pos, pllCfg->n) | + whal_SetBits(RCC_PLL1DIVR_P_Msk, RCC_PLL1DIVR_P_Pos, pllCfg->p) | + whal_SetBits(RCC_PLL1DIVR_Q_Msk, RCC_PLL1DIVR_Q_Pos, pllCfg->q) | + whal_SetBits(RCC_PLL1DIVR_R_Msk, RCC_PLL1DIVR_R_Pos, pllCfg->r)); + + /* Enable PLL1 */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_PLL1ON_Msk, + whal_SetBits(RCC_CR_PLL1ON_Msk, RCC_CR_PLL1ON_Pos, 1)); + + /* Wait for PLL1 lock */ + while (!(whal_Reg_Read(base, RCC_CR_REG) & RCC_CR_PLL1RDY_Msk)) + ; + + /* Switch system clock to PLL1 */ + whal_Reg_Update(base, RCC_CFGR1_REG, RCC_CFGR1_SW_Msk, + whal_SetBits(RCC_CFGR1_SW_Msk, RCC_CFGR1_SW_Pos, cfg->sysClkSrc)); + + /* Wait for switch to complete */ + while ((whal_Reg_Read(base, RCC_CFGR1_REG) & RCC_CFGR1_SWS_Msk) != + whal_SetBits(RCC_CFGR1_SWS_Msk, RCC_CFGR1_SWS_Pos, cfg->sysClkSrc)) + ; + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRccPll_Deinit(whal_Clock *clkDev) +{ + size_t base; + + if (!clkDev) + return WHAL_EINVAL; + + base = clkDev->regmap.base; + + /* Switch back to HSI16 */ + whal_Reg_Update(base, RCC_CFGR1_REG, RCC_CFGR1_SW_Msk, + whal_SetBits(RCC_CFGR1_SW_Msk, RCC_CFGR1_SW_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16)); + + while ((whal_Reg_Read(base, RCC_CFGR1_REG) & RCC_CFGR1_SWS_Msk) != + whal_SetBits(RCC_CFGR1_SWS_Msk, RCC_CFGR1_SWS_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16)) + ; + + /* Disable PLL1 */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_PLL1ON_Msk, 0); + + /* Disable HSE32 */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_HSEON_Msk, 0); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRccHse_Init(whal_Clock *clkDev) +{ + size_t base; + + if (!clkDev || !clkDev->cfg) + return WHAL_EINVAL; + + base = clkDev->regmap.base; + + /* Enable HSE32 */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_HSEON_Msk, + whal_SetBits(RCC_CR_HSEON_Msk, RCC_CR_HSEON_Pos, 1)); + + while (!(whal_Reg_Read(base, RCC_CR_REG) & RCC_CR_HSERDY_Msk)) + ; + + /* Switch to HSE32 */ + whal_Reg_Update(base, RCC_CFGR1_REG, RCC_CFGR1_SW_Msk, + whal_SetBits(RCC_CFGR1_SW_Msk, RCC_CFGR1_SW_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSE32)); + + while ((whal_Reg_Read(base, RCC_CFGR1_REG) & RCC_CFGR1_SWS_Msk) != + whal_SetBits(RCC_CFGR1_SWS_Msk, RCC_CFGR1_SWS_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSE32)) + ; + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRccHse_Deinit(whal_Clock *clkDev) +{ + size_t base; + + if (!clkDev) + return WHAL_EINVAL; + + base = clkDev->regmap.base; + + /* Switch back to HSI16 */ + whal_Reg_Update(base, RCC_CFGR1_REG, RCC_CFGR1_SW_Msk, + whal_SetBits(RCC_CFGR1_SW_Msk, RCC_CFGR1_SW_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16)); + + while ((whal_Reg_Read(base, RCC_CFGR1_REG) & RCC_CFGR1_SWS_Msk) != + whal_SetBits(RCC_CFGR1_SWS_Msk, RCC_CFGR1_SWS_Pos, + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16)) + ; + + /* Disable HSE32 */ + whal_Reg_Update(base, RCC_CR_REG, RCC_CR_HSEON_Msk, 0); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRcc_Enable(whal_Clock *clkDev, const void *clk) +{ + const whal_Stm32wbaRcc_Clk *stClk = (const whal_Stm32wbaRcc_Clk *)clk; + + whal_Reg_Update(clkDev->regmap.base, stClk->regOffset, stClk->enableMask, + whal_SetBits(stClk->enableMask, stClk->enablePos, 1)); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRcc_Disable(whal_Clock *clkDev, const void *clk) +{ + const whal_Stm32wbaRcc_Clk *stClk = (const whal_Stm32wbaRcc_Clk *)clk; + + whal_Reg_Update(clkDev->regmap.base, stClk->regOffset, stClk->enableMask, + whal_SetBits(stClk->enableMask, stClk->enablePos, 0)); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRcc_Ext_EnableLsi(whal_Clock *clkDev, uint8_t enable) +{ + size_t base; + + if (!clkDev) + return WHAL_EINVAL; + + base = clkDev->regmap.base; + + whal_Reg_Update(base, RCC_BDCR1_REG, RCC_BDCR1_LSI1ON_Msk, + whal_SetBits(RCC_BDCR1_LSI1ON_Msk, RCC_BDCR1_LSI1ON_Pos, enable)); + + if (enable) { + while (!(whal_Reg_Read(base, RCC_BDCR1_REG) & RCC_BDCR1_LSI1RDY_Msk)) + ; + } + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRcc_Ext_SetRngClockSrc(whal_Clock *clkDev, + whal_Stm32wbaRcc_RngSrc src) +{ + if (!clkDev) + return WHAL_EINVAL; + + whal_Reg_Update(clkDev->regmap.base, RCC_CCIPR2_REG, + RCC_CCIPR2_RNGSEL_Msk, + whal_SetBits(RCC_CCIPR2_RNGSEL_Msk, + RCC_CCIPR2_RNGSEL_Pos, src)); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRcc_Ext_SetHpre5(whal_Clock *clkDev, uint8_t hpre5) +{ + if (!clkDev) + return WHAL_EINVAL; + + whal_Reg_Update(clkDev->regmap.base, RCC_CFGR4_REG, RCC_CFGR4_HPRE5_Msk, + whal_SetBits(RCC_CFGR4_HPRE5_Msk, RCC_CFGR4_HPRE5_Pos, hpre5)); + + return WHAL_SUCCESS; +} + +const whal_ClockDriver whal_Stm32wbaRccPll_Driver = { + .Init = whal_Stm32wbaRccPll_Init, + .Deinit = whal_Stm32wbaRccPll_Deinit, + .Enable = whal_Stm32wbaRcc_Enable, + .Disable = whal_Stm32wbaRcc_Disable, +}; + +const whal_ClockDriver whal_Stm32wbaRccHse_Driver = { + .Init = whal_Stm32wbaRccHse_Init, + .Deinit = whal_Stm32wbaRccHse_Deinit, + .Enable = whal_Stm32wbaRcc_Enable, + .Disable = whal_Stm32wbaRcc_Disable, +}; diff --git a/src/crypto/stm32wb_aes.c b/src/crypto/stm32wb_aes.c index 8bf48c2..383d55a 100644 --- a/src/crypto/stm32wb_aes.c +++ b/src/crypto/stm32wb_aes.c @@ -172,6 +172,7 @@ whal_Error whal_Stm32wbAes_Deinit(whal_Crypto *cryptoDev) return WHAL_SUCCESS; } +#ifdef WHAL_CFG_CRYPTO_AES_ECB static whal_Error StartOp_AesEcb(whal_Crypto *cryptoDev, void *opArgs) { whal_Crypto_AesEcbArgs *args = (whal_Crypto_AesEcbArgs *)opArgs; @@ -208,7 +209,9 @@ static whal_Error StartOp_AesEcb(whal_Crypto *cryptoDev, void *opArgs) return WHAL_SUCCESS; } +#endif /* WHAL_CFG_CRYPTO_AES_ECB */ +#ifdef WHAL_CFG_CRYPTO_AES_CBC static whal_Error StartOp_AesCbc(whal_Crypto *cryptoDev, void *opArgs) { whal_Crypto_AesCbcArgs *args = (whal_Crypto_AesCbcArgs *)opArgs; @@ -246,7 +249,9 @@ static whal_Error StartOp_AesCbc(whal_Crypto *cryptoDev, void *opArgs) return WHAL_SUCCESS; } +#endif /* WHAL_CFG_CRYPTO_AES_CBC */ +#ifdef WHAL_CFG_CRYPTO_AES_CTR static whal_Error StartOp_AesCtr(whal_Crypto *cryptoDev, void *opArgs) { whal_Crypto_AesCtrArgs *args = (whal_Crypto_AesCtrArgs *)opArgs; @@ -282,7 +287,10 @@ static whal_Error StartOp_AesCtr(whal_Crypto *cryptoDev, void *opArgs) return WHAL_SUCCESS; } +#endif /* WHAL_CFG_CRYPTO_AES_CTR */ +#if defined(WHAL_CFG_CRYPTO_AES_ECB) || defined(WHAL_CFG_CRYPTO_AES_CBC) || \ + defined(WHAL_CFG_CRYPTO_AES_CTR) static whal_Error Process_BlockCipher(whal_Crypto *cryptoDev, const uint8_t *in, uint8_t *out, size_t sz) @@ -321,7 +329,9 @@ static whal_Error EndOp_BlockCipher(whal_Crypto *cryptoDev) return WHAL_SUCCESS; } +#endif /* WHAL_CFG_CRYPTO_AES_ECB || CBC || CTR */ +#ifdef WHAL_CFG_CRYPTO_AES_GCM static whal_Error StartOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) { whal_Error err; @@ -329,12 +339,17 @@ static whal_Error StartOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + const uint8_t *iv; + const uint8_t *aad; size_t keySizeBit; size_t i; - if (!args->key || !args->iv || !args->tag) + if (!args->key || !args->iv) return WHAL_EINVAL; + iv = (const uint8_t *)args->iv; + aad = (const uint8_t *)args->aad; + if (args->keySz != 16 && args->keySz != 32) return WHAL_ENOTSUP; @@ -347,9 +362,6 @@ static whal_Error StartOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) if (args->aadSz > 0 && !args->aad) return WHAL_EINVAL; - if (args->tagSz == 0 || args->tagSz > 16) - return WHAL_EINVAL; - keySizeBit = (args->keySz == 32) ? 1 : 0; whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, 0); @@ -371,9 +383,9 @@ static whal_Error StartOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) WriteKey(base, args->key, args->keySz); - whal_Reg_Write(base, AES_IVR3_REG, whal_LoadBe32(args->iv)); - whal_Reg_Write(base, AES_IVR2_REG, whal_LoadBe32(args->iv + 4)); - whal_Reg_Write(base, AES_IVR1_REG, whal_LoadBe32(args->iv + 8)); + whal_Reg_Write(base, AES_IVR3_REG, whal_LoadBe32(iv)); + whal_Reg_Write(base, AES_IVR2_REG, whal_LoadBe32(iv + 4)); + whal_Reg_Write(base, AES_IVR1_REG, whal_LoadBe32(iv + 8)); whal_Reg_Write(base, AES_IVR0_REG, 0x00000002); whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); @@ -393,16 +405,16 @@ static whal_Error StartOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); for (i = 0; i < args->aadSz; i += 16) { - const uint8_t *aad = args->aad + i; + const uint8_t *blkAad = aad + i; size_t remain = args->aadSz - i; uint8_t block[16] = {0}; size_t j; if (remain >= 16) { - WriteBlock(base, aad); + WriteBlock(base, blkAad); } else { for (j = 0; j < remain; j++) - block[j] = aad[j]; + block[j] = blkAad[j]; WriteBlock(base, block); } @@ -448,8 +460,8 @@ static whal_Error Process_AesGcm(whal_Crypto *cryptoDev, void *opArgs) whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); for (i = 0; i < args->sz; i += 16) { - const uint8_t *in = args->in + i; - uint8_t *out = args->out + i; + const uint8_t *in = (const uint8_t *)args->in + i; + uint8_t *out = (uint8_t *)args->out + i; size_t remain = args->sz - i; uint8_t block[16] = {0}; size_t j; @@ -490,10 +502,16 @@ static whal_Error EndOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + uint8_t *tag; whal_Error err; uint8_t tagBuf[16]; size_t i; + if (!args->tag || args->tagSz == 0 || args->tagSz > 16) + return WHAL_EINVAL; + + tag = (uint8_t *)args->tag; + whal_Reg_Update(base, AES_CR_REG, AES_CR_MODE_Msk | AES_CR_GCMPH_Msk, whal_SetBits(AES_CR_MODE_Msk, AES_CR_MODE_Pos, @@ -516,14 +534,16 @@ static whal_Error EndOp_AesGcm(whal_Crypto *cryptoDev, void *opArgs) ReadBlock(base, tagBuf); for (i = 0; i < args->tagSz; i++) - args->tag[i] = tagBuf[i]; + tag[i] = tagBuf[i]; cleanup: whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, 0); return err; } +#endif /* WHAL_CFG_CRYPTO_AES_GCM */ +#ifdef WHAL_CFG_CRYPTO_AES_GMAC static whal_Error StartOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) { whal_Error err; @@ -531,12 +551,17 @@ static whal_Error StartOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + const uint8_t *iv; + const uint8_t *aad; size_t keySizeBit; size_t i; - if (!args->key || !args->iv || !args->tag) + if (!args->key || !args->iv) return WHAL_EINVAL; + iv = (const uint8_t *)args->iv; + aad = (const uint8_t *)args->aad; + if (args->keySz != 16 && args->keySz != 32) return WHAL_ENOTSUP; @@ -546,9 +571,6 @@ static whal_Error StartOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) if (args->aadSz > 0 && !args->aad) return WHAL_EINVAL; - if (args->tagSz == 0 || args->tagSz > 16) - return WHAL_EINVAL; - keySizeBit = (args->keySz == 32) ? 1 : 0; whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, 0); @@ -570,9 +592,9 @@ static whal_Error StartOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) WriteKey(base, args->key, args->keySz); - whal_Reg_Write(base, AES_IVR3_REG, whal_LoadBe32(args->iv)); - whal_Reg_Write(base, AES_IVR2_REG, whal_LoadBe32(args->iv + 4)); - whal_Reg_Write(base, AES_IVR1_REG, whal_LoadBe32(args->iv + 8)); + whal_Reg_Write(base, AES_IVR3_REG, whal_LoadBe32(iv)); + whal_Reg_Write(base, AES_IVR2_REG, whal_LoadBe32(iv + 4)); + whal_Reg_Write(base, AES_IVR1_REG, whal_LoadBe32(iv + 8)); whal_Reg_Write(base, AES_IVR0_REG, 0x00000002); whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); @@ -592,16 +614,16 @@ static whal_Error StartOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); for (i = 0; i < args->aadSz; i += 16) { - const uint8_t *aad = args->aad + i; + const uint8_t *blkAad = aad + i; size_t remain = args->aadSz - i; uint8_t block[16] = {0}; size_t j; if (remain >= 16) { - WriteBlock(base, aad); + WriteBlock(base, blkAad); } else { for (j = 0; j < remain; j++) - block[j] = aad[j]; + block[j] = blkAad[j]; WriteBlock(base, block); } @@ -624,10 +646,16 @@ static whal_Error EndOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + uint8_t *tag; whal_Error err; uint8_t tagBuf[16]; size_t i; + if (!args->tag || args->tagSz == 0 || args->tagSz > 16) + return WHAL_EINVAL; + + tag = (uint8_t *)args->tag; + whal_Reg_Update(base, AES_CR_REG, AES_CR_MODE_Msk | AES_CR_GCMPH_Msk, whal_SetBits(AES_CR_MODE_Msk, AES_CR_MODE_Pos, @@ -650,14 +678,16 @@ static whal_Error EndOp_AesGmac(whal_Crypto *cryptoDev, void *opArgs) ReadBlock(base, tagBuf); for (i = 0; i < args->tagSz; i++) - args->tag[i] = tagBuf[i]; + tag[i] = tagBuf[i]; cleanup: whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, 0); return err; } +#endif /* WHAL_CFG_CRYPTO_AES_GMAC */ +#ifdef WHAL_CFG_CRYPTO_AES_CCM static whal_Error StartOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) { whal_Error err; @@ -665,11 +695,13 @@ static whal_Error StartOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + const uint8_t *nonce = (const uint8_t *)args->nonce; + const uint8_t *aad = (const uint8_t *)args->aad; size_t keySizeBit; size_t i; uint8_t b0[16]; - if (!args->key || !args->nonce || !args->tag) + if (!args->key || !args->nonce) return WHAL_EINVAL; if (args->keySz != 16 && args->keySz != 32) @@ -697,7 +729,7 @@ static whal_Error StartOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) (q - 1)); b0[0] = flags; for (i = 0; i < args->nonceSz; i++) - b0[1 + i] = args->nonce[i]; + b0[1 + i] = nonce[i]; { size_t msgLen = args->sz; @@ -756,7 +788,7 @@ static whal_Error StartOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) hdrOff = 2; while (hdrOff < 16 && aadOff < args->aadSz) { - hdrBuf[hdrOff++] = args->aad[aadOff++]; + hdrBuf[hdrOff++] = aad[aadOff++]; } WriteBlock(base, hdrBuf); @@ -768,7 +800,7 @@ static whal_Error StartOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) uint8_t block[16] = {0}; for (j = 0; j < 16 && aadOff < args->aadSz; j++) - block[j] = args->aad[aadOff++]; + block[j] = aad[aadOff++]; WriteBlock(base, block); err = WaitForCCF(base, cfg->timeout); @@ -814,8 +846,8 @@ static whal_Error Process_AesCcm(whal_Crypto *cryptoDev, void *opArgs) whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, AES_CR_EN_Msk); for (i = 0; i < args->sz; i += 16) { - const uint8_t *in = args->in + i; - uint8_t *out = args->out + i; + const uint8_t *in = (const uint8_t *)args->in + i; + uint8_t *out = (uint8_t *)args->out + i; size_t remain = args->sz - i; uint8_t block[16] = {0}; size_t j; @@ -856,10 +888,17 @@ static whal_Error EndOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) const whal_Stm32wbAes_Cfg *cfg = (const whal_Stm32wbAes_Cfg *)cryptoDev->cfg; size_t base = cryptoDev->regmap.base; + uint8_t *tag; whal_Error err; uint8_t tagBuf[16]; size_t i; + if (!args->tag || args->tagSz < 4 || args->tagSz > 16 || + (args->tagSz & 1) != 0) + return WHAL_EINVAL; + + tag = (uint8_t *)args->tag; + whal_Reg_Update(base, AES_CR_REG, AES_CR_MODE_Msk | AES_CR_GCMPH_Msk, whal_SetBits(AES_CR_MODE_Msk, AES_CR_MODE_Pos, @@ -882,15 +921,14 @@ static whal_Error EndOp_AesCcm(whal_Crypto *cryptoDev, void *opArgs) ReadBlock(base, tagBuf); for (i = 0; i < args->tagSz; i++) - args->tag[i] = tagBuf[i]; + tag[i] = tagBuf[i]; cleanup: whal_Reg_Update(base, AES_CR_REG, AES_CR_EN_Msk, 0); return err; } - - +#endif /* WHAL_CFG_CRYPTO_AES_CCM */ whal_Error whal_Stm32wbAes_StartOp(whal_Crypto *cryptoDev, size_t opId, @@ -900,20 +938,32 @@ whal_Error whal_Stm32wbAes_StartOp(whal_Crypto *cryptoDev, size_t opId, return WHAL_EINVAL; switch (opId) { +#ifdef WHAL_CFG_CRYPTO_AES_ECB case WHAL_CRYPTO_AES_ECB: return StartOp_AesEcb(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CBC case WHAL_CRYPTO_AES_CBC: return StartOp_AesCbc(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CTR case WHAL_CRYPTO_AES_CTR: return StartOp_AesCtr(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GCM case WHAL_CRYPTO_AES_GCM: return StartOp_AesGcm(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GMAC case WHAL_CRYPTO_AES_GMAC: return StartOp_AesGmac(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CCM case WHAL_CRYPTO_AES_CCM: return StartOp_AesCcm(cryptoDev, opArgs); +#endif default: - return WHAL_EINVAL; + return WHAL_ENOTSUP; } } @@ -924,26 +974,38 @@ whal_Error whal_Stm32wbAes_Process(whal_Crypto *cryptoDev, size_t opId, return WHAL_EINVAL; switch (opId) { +#ifdef WHAL_CFG_CRYPTO_AES_ECB case WHAL_CRYPTO_AES_ECB: { whal_Crypto_AesEcbArgs *args = (whal_Crypto_AesEcbArgs *)opArgs; return Process_BlockCipher(cryptoDev, args->in, args->out, args->sz); } +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CBC case WHAL_CRYPTO_AES_CBC: { whal_Crypto_AesCbcArgs *args = (whal_Crypto_AesCbcArgs *)opArgs; return Process_BlockCipher(cryptoDev, args->in, args->out, args->sz); } +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CTR case WHAL_CRYPTO_AES_CTR: { whal_Crypto_AesCtrArgs *args = (whal_Crypto_AesCtrArgs *)opArgs; return Process_BlockCipher(cryptoDev, args->in, args->out, args->sz); } +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GCM case WHAL_CRYPTO_AES_GCM: return Process_AesGcm(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GMAC case WHAL_CRYPTO_AES_GMAC: return WHAL_SUCCESS; +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CCM case WHAL_CRYPTO_AES_CCM: return Process_AesCcm(cryptoDev, opArgs); +#endif default: - return WHAL_EINVAL; + return WHAL_ENOTSUP; } } @@ -954,18 +1016,32 @@ whal_Error whal_Stm32wbAes_EndOp(whal_Crypto *cryptoDev, size_t opId, return WHAL_EINVAL; switch (opId) { +#ifdef WHAL_CFG_CRYPTO_AES_ECB case WHAL_CRYPTO_AES_ECB: + return EndOp_BlockCipher(cryptoDev); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CBC case WHAL_CRYPTO_AES_CBC: + return EndOp_BlockCipher(cryptoDev); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CTR case WHAL_CRYPTO_AES_CTR: return EndOp_BlockCipher(cryptoDev); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GCM case WHAL_CRYPTO_AES_GCM: return EndOp_AesGcm(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GMAC case WHAL_CRYPTO_AES_GMAC: return EndOp_AesGmac(cryptoDev, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CCM case WHAL_CRYPTO_AES_CCM: return EndOp_AesCcm(cryptoDev, opArgs); +#endif default: - return WHAL_EINVAL; + return WHAL_ENOTSUP; } } diff --git a/src/crypto/stm32wba_aes.c b/src/crypto/stm32wba_aes.c new file mode 100644 index 0000000..c82b2f2 --- /dev/null +++ b/src/crypto/stm32wba_aes.c @@ -0,0 +1 @@ +#include "stm32wb_aes.c" diff --git a/src/crypto/stm32wba_hash.c b/src/crypto/stm32wba_hash.c new file mode 100644 index 0000000..152c332 --- /dev/null +++ b/src/crypto/stm32wba_hash.c @@ -0,0 +1,377 @@ +#include +#include +#include +#include +#include +#include +#include + +/* Control Register */ +#define HASH_CR_REG 0x00 + +#define HASH_CR_INIT_Pos 2 +#define HASH_CR_INIT_Msk (1UL << HASH_CR_INIT_Pos) + +#define HASH_CR_DATATYPE_Pos 4 +#define HASH_CR_DATATYPE_Msk (3UL << HASH_CR_DATATYPE_Pos) + +#define HASH_CR_MODE_Pos 6 +#define HASH_CR_MODE_Msk (1UL << HASH_CR_MODE_Pos) + +#define HASH_CR_LKEY_Pos 16 +#define HASH_CR_LKEY_Msk (1UL << HASH_CR_LKEY_Pos) + +#define HASH_CR_ALGO_Pos 17 +#define HASH_CR_ALGO_Msk (3UL << HASH_CR_ALGO_Pos) + +/* Data Input Register */ +#define HASH_DIN_REG 0x04 + +/* Start Register */ +#define HASH_STR_REG 0x08 + +#define HASH_STR_NBLW_Pos 0 +#define HASH_STR_NBLW_Msk (0x1FUL << HASH_STR_NBLW_Pos) + +#define HASH_STR_DCAL_Pos 8 +#define HASH_STR_DCAL_Msk (1UL << HASH_STR_DCAL_Pos) + +/* Status Register */ +#define HASH_SR_REG 0x24 + +#define HASH_SR_BUSY_Pos 3 +#define HASH_SR_BUSY_Msk (1UL << HASH_SR_BUSY_Pos) + +/* Digest Result Registers */ +#define HASH_HR_BASE_REG 0x310 + +/* Algorithm encoding: ALGO[1:0] at bits 18:17 */ +#define HASH_ALGO_SHA1 0 +#define HASH_ALGO_SHA224 2 +#define HASH_ALGO_SHA256 3 + +#define HASH_MODE_HASH 0 +#define HASH_MODE_HMAC 1 + +static uint32_t AlgoBits(size_t algo) +{ + return whal_SetBits(HASH_CR_ALGO_Msk, HASH_CR_ALGO_Pos, algo); +} + +static whal_Error WaitForReady(size_t base, whal_Timeout *timeout) +{ + return whal_Reg_ReadPoll(base, HASH_SR_REG, HASH_SR_BUSY_Msk, 0, timeout); +} + +static void WriteData(size_t base, const uint8_t *in, size_t inSz) +{ + while (inSz >= 4) { + whal_Reg_Write(base, HASH_DIN_REG, whal_LoadBe32(in)); + in += 4; + inSz -= 4; + } + + if (inSz > 0) { + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_NBLW_Msk, + whal_SetBits(HASH_STR_NBLW_Msk, HASH_STR_NBLW_Pos, + inSz * 8)); + whal_Reg_Write(base, HASH_DIN_REG, whal_LoadBe32Partial(in, inSz)); + } +} + +static void ReadDigest(size_t base, uint8_t *digest, size_t digestSz) +{ + size_t words = digestSz / 4; + size_t i; + + for (i = 0; i < words; i++) + whal_StoreBe32(digest + i * 4, + whal_Reg_Read(base, HASH_HR_BASE_REG + i * 4)); +} + +static whal_Error Process_Hash(whal_Crypto *cryptoDev, const void *in, + size_t inSz) +{ + if (inSz == 0) + return WHAL_SUCCESS; + + if (!in) + return WHAL_EINVAL; + + WriteData(cryptoDev->regmap.base, (const uint8_t *)in, inSz); + + return WHAL_SUCCESS; +} + + +#ifdef WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_HASH +#define whal_Stm32wbaHash_Init whal_Crypto_Init +#define whal_Stm32wbaHash_Deinit whal_Crypto_Deinit +#define whal_Stm32wbaHash_StartOp whal_Crypto_StartOp +#define whal_Stm32wbaHash_Process whal_Crypto_Process +#define whal_Stm32wbaHash_EndOp whal_Crypto_EndOp +#endif + +whal_Error whal_Stm32wbaHash_Init(whal_Crypto *cryptoDev) +{ + if (!cryptoDev || !cryptoDev->cfg) + return WHAL_EINVAL; + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaHash_Deinit(whal_Crypto *cryptoDev) +{ + if (!cryptoDev || !cryptoDev->cfg) + return WHAL_EINVAL; + + return WHAL_SUCCESS; +} + +/* --- SHA-1 / SHA-224 / SHA-256 --- */ + +#if defined(WHAL_CFG_CRYPTO_SHA1) || defined(WHAL_CFG_CRYPTO_SHA224) || \ + defined(WHAL_CFG_CRYPTO_SHA256) +static whal_Error StartOp_Hash(whal_Crypto *cryptoDev, size_t algo) +{ + size_t base = cryptoDev->regmap.base; + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_NBLW_Msk, 0); + + whal_Reg_Update(base, HASH_CR_REG, + HASH_CR_ALGO_Msk | HASH_CR_DATATYPE_Msk | + HASH_CR_MODE_Msk | HASH_CR_LKEY_Msk | HASH_CR_INIT_Msk, + AlgoBits(algo) | HASH_CR_INIT_Msk); + + return WHAL_SUCCESS; +} + +static whal_Error EndOp_Hash(whal_Crypto *cryptoDev, size_t expectedDigestSz, + void *opArgs) +{ + whal_Crypto_HashArgs *args = (whal_Crypto_HashArgs *)opArgs; + const whal_Stm32wbaHash_Cfg *cfg = + (const whal_Stm32wbaHash_Cfg *)cryptoDev->cfg; + size_t base = cryptoDev->regmap.base; + whal_Error err; + + if (!args->digest || args->digestSz != expectedDigestSz) + return WHAL_EINVAL; + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_DCAL_Msk, + HASH_STR_DCAL_Msk); + + err = WaitForReady(base, cfg->timeout); + if (err) + return err; + + ReadDigest(base, (uint8_t *)args->digest, args->digestSz); + + return WHAL_SUCCESS; +} +#endif /* WHAL_CFG_CRYPTO_SHA1 || SHA224 || SHA256 */ + +/* --- HMAC-SHA-1 / HMAC-SHA-224 / HMAC-SHA-256 --- */ + +#if defined(WHAL_CFG_CRYPTO_HMAC_SHA1) || defined(WHAL_CFG_CRYPTO_HMAC_SHA224) || \ + defined(WHAL_CFG_CRYPTO_HMAC_SHA256) +static whal_Error StartOp_Hmac(whal_Crypto *cryptoDev, size_t algo, + void *opArgs) +{ + whal_Crypto_HmacArgs *args = (whal_Crypto_HmacArgs *)opArgs; + const whal_Stm32wbaHash_Cfg *cfg = + (const whal_Stm32wbaHash_Cfg *)cryptoDev->cfg; + size_t base = cryptoDev->regmap.base; + size_t lkey; + whal_Error err; + + if (!args->key) + return WHAL_EINVAL; + + lkey = (args->keySz > 64) ? 1 : 0; + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_NBLW_Msk, 0); + + whal_Reg_Update(base, HASH_CR_REG, + HASH_CR_ALGO_Msk | HASH_CR_DATATYPE_Msk | + HASH_CR_MODE_Msk | HASH_CR_LKEY_Msk | HASH_CR_INIT_Msk, + AlgoBits(algo) | + whal_SetBits(HASH_CR_MODE_Msk, HASH_CR_MODE_Pos, + HASH_MODE_HMAC) | + whal_SetBits(HASH_CR_LKEY_Msk, HASH_CR_LKEY_Pos, lkey) | + HASH_CR_INIT_Msk); + + WriteData(base, (const uint8_t *)args->key, args->keySz); + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_DCAL_Msk, + HASH_STR_DCAL_Msk); + + err = WaitForReady(base, cfg->timeout); + if (err) + return err; + + return WHAL_SUCCESS; +} + +static whal_Error EndOp_Hmac(whal_Crypto *cryptoDev, size_t expectedDigestSz, + void *opArgs) +{ + whal_Crypto_HmacArgs *args = (whal_Crypto_HmacArgs *)opArgs; + const whal_Stm32wbaHash_Cfg *cfg = + (const whal_Stm32wbaHash_Cfg *)cryptoDev->cfg; + size_t base = cryptoDev->regmap.base; + whal_Error err; + + if (!args->key || !args->digest || args->digestSz != expectedDigestSz) + return WHAL_EINVAL; + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_DCAL_Msk, + HASH_STR_DCAL_Msk); + + err = WaitForReady(base, cfg->timeout); + if (err) + return err; + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_NBLW_Msk, 0); + WriteData(base, (const uint8_t *)args->key, args->keySz); + + whal_Reg_Update(base, HASH_STR_REG, HASH_STR_DCAL_Msk, + HASH_STR_DCAL_Msk); + + err = WaitForReady(base, cfg->timeout); + if (err) + return err; + + ReadDigest(base, (uint8_t *)args->digest, args->digestSz); + + return WHAL_SUCCESS; +} +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA1 || HMAC_SHA224 || HMAC_SHA256 */ + +/* --- Dispatch --- */ + +whal_Error whal_Stm32wbaHash_StartOp(whal_Crypto *cryptoDev, size_t opId, + void *opArgs) +{ + if (!cryptoDev) + return WHAL_EINVAL; + + switch (opId) { +#ifdef WHAL_CFG_CRYPTO_SHA1 + case WHAL_CRYPTO_SHA1: + return StartOp_Hash(cryptoDev, HASH_ALGO_SHA1); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA224 + case WHAL_CRYPTO_SHA224: + return StartOp_Hash(cryptoDev, HASH_ALGO_SHA224); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA256 + case WHAL_CRYPTO_SHA256: + return StartOp_Hash(cryptoDev, HASH_ALGO_SHA256); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 + case WHAL_CRYPTO_HMAC_SHA1: + return StartOp_Hmac(cryptoDev, HASH_ALGO_SHA1, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 + case WHAL_CRYPTO_HMAC_SHA224: + return StartOp_Hmac(cryptoDev, HASH_ALGO_SHA224, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 + case WHAL_CRYPTO_HMAC_SHA256: + return StartOp_Hmac(cryptoDev, HASH_ALGO_SHA256, opArgs); +#endif + default: + return WHAL_ENOTSUP; + } +} + +whal_Error whal_Stm32wbaHash_Process(whal_Crypto *cryptoDev, size_t opId, + void *opArgs) +{ + if (!cryptoDev || !opArgs) + return WHAL_EINVAL; + + switch (opId) { +#ifdef WHAL_CFG_CRYPTO_SHA1 + case WHAL_CRYPTO_SHA1: +#endif +#ifdef WHAL_CFG_CRYPTO_SHA224 + case WHAL_CRYPTO_SHA224: +#endif +#ifdef WHAL_CFG_CRYPTO_SHA256 + case WHAL_CRYPTO_SHA256: +#endif +#if defined(WHAL_CFG_CRYPTO_SHA1) || defined(WHAL_CFG_CRYPTO_SHA224) || \ + defined(WHAL_CFG_CRYPTO_SHA256) + { + whal_Crypto_HashArgs *args = (whal_Crypto_HashArgs *)opArgs; + return Process_Hash(cryptoDev, args->in, args->inSz); + } +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 + case WHAL_CRYPTO_HMAC_SHA1: +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 + case WHAL_CRYPTO_HMAC_SHA224: +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 + case WHAL_CRYPTO_HMAC_SHA256: +#endif +#if defined(WHAL_CFG_CRYPTO_HMAC_SHA1) || defined(WHAL_CFG_CRYPTO_HMAC_SHA224) || \ + defined(WHAL_CFG_CRYPTO_HMAC_SHA256) + { + whal_Crypto_HmacArgs *args = (whal_Crypto_HmacArgs *)opArgs; + return Process_Hash(cryptoDev, args->in, args->inSz); + } +#endif + default: + return WHAL_ENOTSUP; + } +} + +whal_Error whal_Stm32wbaHash_EndOp(whal_Crypto *cryptoDev, size_t opId, + void *opArgs) +{ + if (!cryptoDev || !opArgs) + return WHAL_EINVAL; + + switch (opId) { +#ifdef WHAL_CFG_CRYPTO_SHA1 + case WHAL_CRYPTO_SHA1: + return EndOp_Hash(cryptoDev, 20, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA224 + case WHAL_CRYPTO_SHA224: + return EndOp_Hash(cryptoDev, 28, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA256 + case WHAL_CRYPTO_SHA256: + return EndOp_Hash(cryptoDev, 32, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 + case WHAL_CRYPTO_HMAC_SHA1: + return EndOp_Hmac(cryptoDev, 20, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 + case WHAL_CRYPTO_HMAC_SHA224: + return EndOp_Hmac(cryptoDev, 28, opArgs); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 + case WHAL_CRYPTO_HMAC_SHA256: + return EndOp_Hmac(cryptoDev, 32, opArgs); +#endif + default: + return WHAL_ENOTSUP; + } +} + +#ifndef WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_HASH +const whal_CryptoDriver whal_Stm32wbaHash_Driver = { + .Init = whal_Stm32wbaHash_Init, + .Deinit = whal_Stm32wbaHash_Deinit, + .StartOp = whal_Stm32wbaHash_StartOp, + .Process = whal_Stm32wbaHash_Process, + .EndOp = whal_Stm32wbaHash_EndOp, +}; +#endif /* !WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_HASH */ diff --git a/src/dma/stm32wba_gpdma.c b/src/dma/stm32wba_gpdma.c new file mode 100644 index 0000000..875da83 --- /dev/null +++ b/src/dma/stm32wba_gpdma.c @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * STM32WBA GPDMA Register Definitions (RM0493 chapter 17) + * + * Base: 0x40020000 + * Each channel x (0-7) occupies 0x80 bytes starting at 0x50 + 0x80*x. + */ + +/* Global registers */ +#define GPDMA_SECCFGR_REG 0x00 +#define GPDMA_PRIVCFGR_REG 0x04 +#define GPDMA_RCFGLOCKR_REG 0x08 +#define GPDMA_MISR_REG 0x0C +#define GPDMA_SMISR_REG 0x10 + +/* Per-channel register offsets (add 0x50 + 0x80*ch) */ +#define GPDMA_CH_BASE(ch) (0x50 + ((ch) * 0x80)) + +#define GPDMA_CxLBAR(ch) (GPDMA_CH_BASE(ch) + 0x00) +#define GPDMA_CxFCR(ch) (GPDMA_CH_BASE(ch) + 0x0C) +#define GPDMA_CxSR(ch) (GPDMA_CH_BASE(ch) + 0x10) +#define GPDMA_CxCR(ch) (GPDMA_CH_BASE(ch) + 0x14) +#define GPDMA_CxTR1(ch) (GPDMA_CH_BASE(ch) + 0x40) +#define GPDMA_CxTR2(ch) (GPDMA_CH_BASE(ch) + 0x44) +#define GPDMA_CxBR1(ch) (GPDMA_CH_BASE(ch) + 0x48) +#define GPDMA_CxSAR(ch) (GPDMA_CH_BASE(ch) + 0x4C) +#define GPDMA_CxDAR(ch) (GPDMA_CH_BASE(ch) + 0x50) +#define GPDMA_CxLLR(ch) (GPDMA_CH_BASE(ch) + 0x7C) + +/* CxSR bits */ +#define GPDMA_CxSR_IDLEF_Pos 0 +#define GPDMA_CxSR_IDLEF_Msk (1UL << GPDMA_CxSR_IDLEF_Pos) +#define GPDMA_CxSR_TCF_Pos 8 +#define GPDMA_CxSR_TCF_Msk (1UL << GPDMA_CxSR_TCF_Pos) +#define GPDMA_CxSR_HTF_Pos 9 +#define GPDMA_CxSR_HTF_Msk (1UL << GPDMA_CxSR_HTF_Pos) +#define GPDMA_CxSR_DTEF_Pos 10 +#define GPDMA_CxSR_DTEF_Msk (1UL << GPDMA_CxSR_DTEF_Pos) +#define GPDMA_CxSR_ULEF_Pos 11 +#define GPDMA_CxSR_ULEF_Msk (1UL << GPDMA_CxSR_ULEF_Pos) +#define GPDMA_CxSR_USEF_Pos 12 +#define GPDMA_CxSR_USEF_Msk (1UL << GPDMA_CxSR_USEF_Pos) +#define GPDMA_CxSR_SUSPF_Pos 13 +#define GPDMA_CxSR_SUSPF_Msk (1UL << GPDMA_CxSR_SUSPF_Pos) +#define GPDMA_CxSR_TOF_Pos 14 +#define GPDMA_CxSR_TOF_Msk (1UL << GPDMA_CxSR_TOF_Pos) + +#define GPDMA_CxSR_ALL_ERR (GPDMA_CxSR_DTEF_Msk | GPDMA_CxSR_ULEF_Msk | \ + GPDMA_CxSR_USEF_Msk) + +/* CxFCR bits (write 1 to clear) -- same positions as CxSR flags */ +#define GPDMA_CxFCR_ALL (GPDMA_CxSR_TCF_Msk | GPDMA_CxSR_HTF_Msk | \ + GPDMA_CxSR_DTEF_Msk | GPDMA_CxSR_ULEF_Msk | \ + GPDMA_CxSR_USEF_Msk | GPDMA_CxSR_SUSPF_Msk | \ + GPDMA_CxSR_TOF_Msk) + +/* CxCR bits */ +#define GPDMA_CxCR_EN_Pos 0 +#define GPDMA_CxCR_EN_Msk (1UL << GPDMA_CxCR_EN_Pos) +#define GPDMA_CxCR_RESET_Pos 1 +#define GPDMA_CxCR_RESET_Msk (1UL << GPDMA_CxCR_RESET_Pos) +#define GPDMA_CxCR_SUSP_Pos 2 +#define GPDMA_CxCR_SUSP_Msk (1UL << GPDMA_CxCR_SUSP_Pos) +#define GPDMA_CxCR_TCIE_Pos 8 +#define GPDMA_CxCR_TCIE_Msk (1UL << GPDMA_CxCR_TCIE_Pos) +#define GPDMA_CxCR_HTIE_Pos 9 +#define GPDMA_CxCR_HTIE_Msk (1UL << GPDMA_CxCR_HTIE_Pos) +#define GPDMA_CxCR_DTEIE_Pos 10 +#define GPDMA_CxCR_DTEIE_Msk (1UL << GPDMA_CxCR_DTEIE_Pos) +#define GPDMA_CxCR_ULEIE_Pos 11 +#define GPDMA_CxCR_ULEIE_Msk (1UL << GPDMA_CxCR_ULEIE_Pos) +#define GPDMA_CxCR_USEIE_Pos 12 +#define GPDMA_CxCR_USEIE_Msk (1UL << GPDMA_CxCR_USEIE_Pos) +#define GPDMA_CxCR_PRIO_Pos 22 +#define GPDMA_CxCR_PRIO_Msk (3UL << GPDMA_CxCR_PRIO_Pos) + +/* CxTR1 bits */ +#define GPDMA_CxTR1_SDW_Pos 0 /* Source data width (log2) */ +#define GPDMA_CxTR1_SDW_Msk (3UL << GPDMA_CxTR1_SDW_Pos) +#define GPDMA_CxTR1_SINC_Pos 3 /* Source increment */ +#define GPDMA_CxTR1_SINC_Msk (1UL << GPDMA_CxTR1_SINC_Pos) +#define GPDMA_CxTR1_SAP_Pos 14 /* Source allocated port (0 or 1) */ +#define GPDMA_CxTR1_SAP_Msk (1UL << GPDMA_CxTR1_SAP_Pos) +#define GPDMA_CxTR1_DDW_Pos 16 /* Destination data width (log2) */ +#define GPDMA_CxTR1_DDW_Msk (3UL << GPDMA_CxTR1_DDW_Pos) +#define GPDMA_CxTR1_DINC_Pos 19 /* Destination increment */ +#define GPDMA_CxTR1_DINC_Msk (1UL << GPDMA_CxTR1_DINC_Pos) +#define GPDMA_CxTR1_DAP_Pos 30 /* Destination allocated port (0 or 1) */ +#define GPDMA_CxTR1_DAP_Msk (1UL << GPDMA_CxTR1_DAP_Pos) + +/* CxTR2 bits */ +#define GPDMA_CxTR2_REQSEL_Pos 0 /* Hardware request selection */ +#define GPDMA_CxTR2_REQSEL_Msk (0x3FUL << GPDMA_CxTR2_REQSEL_Pos) +#define GPDMA_CxTR2_SWREQ_Pos 9 /* Software request (memory-to-memory) */ +#define GPDMA_CxTR2_SWREQ_Msk (1UL << GPDMA_CxTR2_SWREQ_Pos) +#define GPDMA_CxTR2_DREQ_Pos 10 /* Direction: 0=src periph, 1=dst periph */ +#define GPDMA_CxTR2_DREQ_Msk (1UL << GPDMA_CxTR2_DREQ_Pos) + +whal_Error whal_Stm32wbaGpdma_Init(whal_Dma *dmaDev) +{ + if (!dmaDev || !dmaDev->cfg) + return WHAL_EINVAL; + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaGpdma_Deinit(whal_Dma *dmaDev) +{ + const whal_Stm32wbaGpdma_Cfg *cfg; + + if (!dmaDev || !dmaDev->cfg) + return WHAL_EINVAL; + + cfg = (const whal_Stm32wbaGpdma_Cfg *)dmaDev->cfg; + + /* Reset all channels */ + for (uint8_t ch = 0; ch < cfg->numChannels; ch++) { + whal_Reg_Write(dmaDev->regmap.base, GPDMA_CxCR(ch), + GPDMA_CxCR_RESET_Msk); + } + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaGpdma_Configure(whal_Dma *dmaDev, size_t ch, + const void *chCfg) +{ + const whal_Stm32wbaGpdma_Cfg *cfg; + const whal_Stm32wbaGpdma_ChCfg *ccfg; + size_t base; + size_t tr1, tr2; + whal_Error err; + + if (!dmaDev || !dmaDev->cfg || !chCfg) + return WHAL_EINVAL; + + cfg = (const whal_Stm32wbaGpdma_Cfg *)dmaDev->cfg; + ccfg = (const whal_Stm32wbaGpdma_ChCfg *)chCfg; + base = dmaDev->regmap.base; + + if (ch >= cfg->numChannels) + return WHAL_EINVAL; + + if (ccfg->nbytes == 0 || ccfg->nbytes > 0xFFFF) + return WHAL_EINVAL; + + /* Reset the channel and wait for idle */ + whal_Reg_Write(base, GPDMA_CxCR(ch), GPDMA_CxCR_RESET_Msk); + err = whal_Reg_ReadPoll(base, GPDMA_CxSR(ch), GPDMA_CxSR_IDLEF_Msk, + GPDMA_CxSR_IDLEF_Msk, cfg->timeout); + if (err) + return err; + + /* Clear any pending flags */ + whal_Reg_Write(base, GPDMA_CxFCR(ch), GPDMA_CxFCR_ALL); + + /* Build CxTR1: source and destination widths and increment modes. + * Route the memory side to port 1 and the peripheral side to port 0 + * so the two halves of each transfer don't serialize on the same AHB + * port. Mem-to-mem leaves both on port 0. */ + tr1 = whal_SetBits(GPDMA_CxTR1_SDW_Msk, GPDMA_CxTR1_SDW_Pos, ccfg->srcWidth) | + whal_SetBits(GPDMA_CxTR1_SINC_Msk, GPDMA_CxTR1_SINC_Pos, ccfg->srcInc) | + whal_SetBits(GPDMA_CxTR1_DDW_Msk, GPDMA_CxTR1_DDW_Pos, ccfg->dstWidth) | + whal_SetBits(GPDMA_CxTR1_DINC_Msk, GPDMA_CxTR1_DINC_Pos, ccfg->dstInc); + + if (ccfg->dir == WHAL_STM32WBA_GPDMA_DIR_MEM_TO_PERIPH) + tr1 |= GPDMA_CxTR1_SAP_Msk; + else if (ccfg->dir == WHAL_STM32WBA_GPDMA_DIR_PERIPH_TO_MEM) + tr1 |= GPDMA_CxTR1_DAP_Msk; + + whal_Reg_Write(base, GPDMA_CxTR1(ch), tr1); + + /* Build CxTR2: request selection and direction */ + tr2 = 0; + if (ccfg->dir == WHAL_STM32WBA_GPDMA_DIR_MEM_TO_MEM) { + tr2 |= GPDMA_CxTR2_SWREQ_Msk; + } else { + tr2 |= whal_SetBits(GPDMA_CxTR2_REQSEL_Msk, GPDMA_CxTR2_REQSEL_Pos, + ccfg->reqSel); + if (ccfg->dir == WHAL_STM32WBA_GPDMA_DIR_MEM_TO_PERIPH) + tr2 |= GPDMA_CxTR2_DREQ_Msk; + } + whal_Reg_Write(base, GPDMA_CxTR2(ch), tr2); + + /* Byte count and addresses */ + whal_Reg_Write(base, GPDMA_CxBR1(ch), ccfg->nbytes); + whal_Reg_Write(base, GPDMA_CxSAR(ch), ccfg->srcAddr); + whal_Reg_Write(base, GPDMA_CxDAR(ch), ccfg->dstAddr); + + /* No linked-list */ + whal_Reg_Write(base, GPDMA_CxLLR(ch), 0); + + /* Enable transfer complete and error interrupts. Run the channel at + * high priority so it isn't starved by concurrent CPU/AHB traffic. */ + whal_Reg_Write(base, GPDMA_CxCR(ch), + GPDMA_CxCR_TCIE_Msk | GPDMA_CxCR_DTEIE_Msk | + GPDMA_CxCR_ULEIE_Msk | GPDMA_CxCR_USEIE_Msk | + whal_SetBits(GPDMA_CxCR_PRIO_Msk, GPDMA_CxCR_PRIO_Pos, 3)); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaGpdma_Start(whal_Dma *dmaDev, size_t ch) +{ + const whal_Stm32wbaGpdma_Cfg *cfg; + + if (!dmaDev || !dmaDev->cfg) + return WHAL_EINVAL; + + cfg = (const whal_Stm32wbaGpdma_Cfg *)dmaDev->cfg; + + if (ch >= cfg->numChannels) + return WHAL_EINVAL; + + /* Clear any stale flags from the previous transfer before enabling */ + whal_Reg_Write(dmaDev->regmap.base, GPDMA_CxFCR(ch), GPDMA_CxFCR_ALL); + + /* Set EN bit without disturbing the already-configured interrupt enables */ + whal_Reg_Update(dmaDev->regmap.base, GPDMA_CxCR(ch), GPDMA_CxCR_EN_Msk, + GPDMA_CxCR_EN_Msk); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaGpdma_Stop(whal_Dma *dmaDev, size_t ch) +{ + const whal_Stm32wbaGpdma_Cfg *cfg; + size_t base; + + if (!dmaDev || !dmaDev->cfg) + return WHAL_EINVAL; + + cfg = (const whal_Stm32wbaGpdma_Cfg *)dmaDev->cfg; + base = dmaDev->regmap.base; + + if (ch >= cfg->numChannels) + return WHAL_EINVAL; + + whal_Reg_Update(base, GPDMA_CxCR(ch), GPDMA_CxCR_EN_Msk, 0); + + whal_Reg_Write(base, GPDMA_CxFCR(ch), GPDMA_CxFCR_ALL); + + return WHAL_SUCCESS; +} + +void whal_Stm32wbaGpdma_IRQHandler(whal_Dma *dmaDev, size_t ch, + whal_Stm32wbaGpdma_Callback cb, void *ctx) +{ + size_t base; + size_t sr; + + if (!dmaDev) + return; + + base = dmaDev->regmap.base; + sr = whal_Reg_Read(base, GPDMA_CxSR(ch)); + + if (sr & GPDMA_CxSR_ALL_ERR) { + whal_Reg_Write(base, GPDMA_CxFCR(ch), GPDMA_CxSR_ALL_ERR); + if (cb) + cb(ctx, WHAL_EHARDWARE); + return; + } + + if (sr & GPDMA_CxSR_TCF_Msk) { + whal_Reg_Write(base, GPDMA_CxFCR(ch), GPDMA_CxSR_TCF_Msk); + if (cb) + cb(ctx, WHAL_SUCCESS); + } + + if (sr & GPDMA_CxSR_HTF_Msk) { + whal_Reg_Write(base, GPDMA_CxFCR(ch), GPDMA_CxSR_HTF_Msk); + } +} + +const whal_DmaDriver whal_Stm32wbaGpdma_Driver = { + .Init = whal_Stm32wbaGpdma_Init, + .Deinit = whal_Stm32wbaGpdma_Deinit, + .Configure = whal_Stm32wbaGpdma_Configure, + .Start = whal_Stm32wbaGpdma_Start, + .Stop = whal_Stm32wbaGpdma_Stop, +}; diff --git a/src/flash/stm32wba_flash.c b/src/flash/stm32wba_flash.c new file mode 100644 index 0000000..56a7b34 --- /dev/null +++ b/src/flash/stm32wba_flash.c @@ -0,0 +1,280 @@ +#include +#include +#include +#include +#include +#include + +/* + * STM32WBA Flash Register Definitions (RM0493) + * + * Flash interface base: 0x40022000 + */ + +/* Access Control Register */ +#define FLASH_ACR_REG 0x000 +#define FLASH_ACR_LATENCY_Msk 0x0FUL + +/* Non-Secure Key Register - unlock sequence */ +#define FLASH_NSKEYR_REG 0x008 + +/* Non-Secure Status Register (RM0493 section 7.9.6, page 217) */ +#define FLASH_NSSR_REG 0x020 +#define FLASH_NSSR_EOP_Pos 0 +#define FLASH_NSSR_EOP_Msk (1UL << FLASH_NSSR_EOP_Pos) +#define FLASH_NSSR_OPERR_Pos 1 +#define FLASH_NSSR_OPERR_Msk (1UL << FLASH_NSSR_OPERR_Pos) +#define FLASH_NSSR_PROGERR_Pos 3 +#define FLASH_NSSR_PROGERR_Msk (1UL << FLASH_NSSR_PROGERR_Pos) +#define FLASH_NSSR_WRPERR_Pos 4 +#define FLASH_NSSR_WRPERR_Msk (1UL << FLASH_NSSR_WRPERR_Pos) +#define FLASH_NSSR_PGAERR_Pos 5 +#define FLASH_NSSR_PGAERR_Msk (1UL << FLASH_NSSR_PGAERR_Pos) +#define FLASH_NSSR_SIZERR_Pos 6 +#define FLASH_NSSR_SIZERR_Msk (1UL << FLASH_NSSR_SIZERR_Pos) +#define FLASH_NSSR_PGSERR_Pos 7 +#define FLASH_NSSR_PGSERR_Msk (1UL << FLASH_NSSR_PGSERR_Pos) +#define FLASH_NSSR_OPTWERR_Pos 13 +#define FLASH_NSSR_OPTWERR_Msk (1UL << FLASH_NSSR_OPTWERR_Pos) +#define FLASH_NSSR_BSY_Pos 16 +#define FLASH_NSSR_BSY_Msk (1UL << FLASH_NSSR_BSY_Pos) +#define FLASH_NSSR_WDW_Pos 17 +#define FLASH_NSSR_WDW_Msk (1UL << FLASH_NSSR_WDW_Pos) + +#define FLASH_NSSR_ALL_ERR (FLASH_NSSR_OPERR_Msk | FLASH_NSSR_PROGERR_Msk | \ + FLASH_NSSR_WRPERR_Msk | FLASH_NSSR_PGAERR_Msk | \ + FLASH_NSSR_SIZERR_Msk | FLASH_NSSR_PGSERR_Msk | \ + FLASH_NSSR_OPTWERR_Msk) + +/* Non-Secure Control Register 1 (RM0493 section 7.9.8, page 220) */ +#define FLASH_NSCR1_REG 0x028 +#define FLASH_NSCR1_PG_Pos 0 +#define FLASH_NSCR1_PG_Msk (1UL << FLASH_NSCR1_PG_Pos) +#define FLASH_NSCR1_PER_Pos 1 +#define FLASH_NSCR1_PER_Msk (1UL << FLASH_NSCR1_PER_Pos) +#define FLASH_NSCR1_MER_Pos 2 +#define FLASH_NSCR1_MER_Msk (1UL << FLASH_NSCR1_MER_Pos) +#define FLASH_NSCR1_PNB_Pos 3 +#define FLASH_NSCR1_PNB_Msk (0x7FUL << FLASH_NSCR1_PNB_Pos) +#define FLASH_NSCR1_BWR_Pos 14 +#define FLASH_NSCR1_BWR_Msk (1UL << FLASH_NSCR1_BWR_Pos) +#define FLASH_NSCR1_STRT_Pos 16 +#define FLASH_NSCR1_STRT_Msk (1UL << FLASH_NSCR1_STRT_Pos) +#define FLASH_NSCR1_LOCK_Pos 31 +#define FLASH_NSCR1_LOCK_Msk (1UL << FLASH_NSCR1_LOCK_Pos) + +/* Unlock keys */ +#define FLASH_KEY1 0x45670123UL +#define FLASH_KEY2 0xCDEF89ABUL + +/* Sector size: 8 KB */ +#define FLASH_SECTOR_SIZE 0x2000 +#define FLASH_SECTOR_SHIFT 13 + +whal_Error whal_Stm32wbaFlash_Init(whal_Flash *flashDev) +{ + (void)flashDev; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaFlash_Deinit(whal_Flash *flashDev) +{ + (void)flashDev; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaFlash_Lock(whal_Flash *flashDev, size_t addr, size_t len) +{ + (void)addr; + (void)len; + + if (!flashDev) + return WHAL_EINVAL; + + whal_Reg_Update(flashDev->regmap.base, FLASH_NSCR1_REG, FLASH_NSCR1_LOCK_Msk, + whal_SetBits(FLASH_NSCR1_LOCK_Msk, FLASH_NSCR1_LOCK_Pos, 1)); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaFlash_Unlock(whal_Flash *flashDev, size_t addr, size_t len) +{ + (void)addr; + (void)len; + + if (!flashDev) + return WHAL_EINVAL; + + /* Only write the unlock sequence if LOCK bit is set */ + if (whal_Reg_Read(flashDev->regmap.base, FLASH_NSCR1_REG) & FLASH_NSCR1_LOCK_Msk) { + whal_Reg_Write(flashDev->regmap.base, FLASH_NSKEYR_REG, FLASH_KEY1); + whal_Reg_Write(flashDev->regmap.base, FLASH_NSKEYR_REG, FLASH_KEY2); + } + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaFlash_Read(whal_Flash *flashDev, size_t addr, void *data, size_t dataSz) +{ + uint8_t *dataBuf = (uint8_t *)data; + whal_Stm32wbaFlash_Cfg *cfg; + + if (!flashDev || !flashDev->cfg || !data) + return WHAL_EINVAL; + + cfg = flashDev->cfg; + + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + + uint8_t *flashAddr = (uint8_t *)addr; + for (size_t i = 0; i < dataSz; ++i) + dataBuf[i] = flashAddr[i]; + + return WHAL_SUCCESS; +} + +static whal_Error WaitNotBusy(size_t base, whal_Timeout *timeout) +{ + return whal_Reg_ReadPoll(base, FLASH_NSSR_REG, FLASH_NSSR_BSY_Msk, 0, timeout); +} + +static whal_Error CheckAndClearErrors(size_t base) +{ + size_t sr = whal_Reg_Read(base, FLASH_NSSR_REG); + if (sr & FLASH_NSSR_ALL_ERR) { + /* Clear error flags by writing 1 to them */ + whal_Reg_Write(base, FLASH_NSSR_REG, sr & FLASH_NSSR_ALL_ERR); + return WHAL_EHARDWARE; + } + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaFlash_Write(whal_Flash *flashDev, size_t addr, + const void *data, size_t dataSz) +{ + const uint8_t *dataBuf = (const uint8_t *)data; + whal_Stm32wbaFlash_Cfg *cfg; + const whal_Regmap *regmap; + whal_Error err; + + if (!flashDev || !flashDev->cfg || !data) + return WHAL_EINVAL; + + cfg = flashDev->cfg; + regmap = &flashDev->regmap; + + /* Address and size must be 16-byte aligned (128-bit flash-word) */ + if ((addr & 0xF) || (dataSz & 0xF)) + return WHAL_EINVAL; + + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + + err = WaitNotBusy(regmap->base, cfg->timeout); + if (err) + return err; + + /* Clear error flags */ + whal_Reg_Write(regmap->base, FLASH_NSSR_REG, + whal_Reg_Read(regmap->base, FLASH_NSSR_REG) & FLASH_NSSR_ALL_ERR); + + /* Enable programming */ + whal_Reg_Update(regmap->base, FLASH_NSCR1_REG, FLASH_NSCR1_PG_Msk, + whal_SetBits(FLASH_NSCR1_PG_Msk, FLASH_NSCR1_PG_Pos, 1)); + + /* Program in 128-bit (16 byte) flash-word chunks */ + for (size_t i = 0; i < dataSz; i += 16) { + uint32_t *flashAddr = (uint32_t *)(addr + i); + const uint32_t *dataAddr = (const uint32_t *)(dataBuf + i); + + flashAddr[0] = dataAddr[0]; + flashAddr[1] = dataAddr[1]; + flashAddr[2] = dataAddr[2]; + flashAddr[3] = dataAddr[3]; + + err = WaitNotBusy(regmap->base, cfg->timeout); + if (err) + goto cleanup; + + err = CheckAndClearErrors(regmap->base); + if (err) + goto cleanup; + } + +cleanup: + whal_Reg_Update(regmap->base, FLASH_NSCR1_REG, FLASH_NSCR1_PG_Msk, 0); + return err; +} + +whal_Error whal_Stm32wbaFlash_Erase(whal_Flash *flashDev, size_t addr, size_t dataSz) +{ + whal_Stm32wbaFlash_Cfg *cfg; + const whal_Regmap *regmap; + whal_Error err; + size_t offset, startPage, endPage; + + if (!flashDev || !flashDev->cfg) + return WHAL_EINVAL; + + cfg = flashDev->cfg; + regmap = &flashDev->regmap; + + if (dataSz == 0) + return WHAL_SUCCESS; + + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + + err = WaitNotBusy(regmap->base, cfg->timeout); + if (err) + return err; + + /* Clear error flags */ + whal_Reg_Write(regmap->base, FLASH_NSSR_REG, + whal_Reg_Read(regmap->base, FLASH_NSSR_REG) & FLASH_NSSR_ALL_ERR); + + offset = addr - cfg->startAddr; + startPage = offset >> FLASH_SECTOR_SHIFT; + endPage = (offset + dataSz - 1) >> FLASH_SECTOR_SHIFT; + + for (size_t page = startPage; page <= endPage; page++) { + /* Configure page erase: PER=1, PNB=page, STRT=1 */ + whal_Reg_Update(regmap->base, FLASH_NSCR1_REG, + FLASH_NSCR1_PER_Msk | FLASH_NSCR1_PNB_Msk | FLASH_NSCR1_STRT_Msk, + whal_SetBits(FLASH_NSCR1_PER_Msk, FLASH_NSCR1_PER_Pos, 1) | + whal_SetBits(FLASH_NSCR1_PNB_Msk, FLASH_NSCR1_PNB_Pos, page) | + whal_SetBits(FLASH_NSCR1_STRT_Msk, FLASH_NSCR1_STRT_Pos, 1)); + + err = WaitNotBusy(regmap->base, cfg->timeout); + if (err) + goto cleanup; + + err = CheckAndClearErrors(regmap->base); + if (err) + goto cleanup; + } + +cleanup: + whal_Reg_Update(regmap->base, FLASH_NSCR1_REG, FLASH_NSCR1_PER_Msk, 0); + return err; +} + +whal_Error whal_Stm32wbaFlash_Ext_SetLatency(whal_Flash *flashDev, uint8_t latency) +{ + if (!flashDev) + return WHAL_EINVAL; + + whal_Reg_Update(flashDev->regmap.base, FLASH_ACR_REG, FLASH_ACR_LATENCY_Msk, latency); + return WHAL_SUCCESS; +} + +const whal_FlashDriver whal_Stm32wbaFlash_Driver = { + .Init = whal_Stm32wbaFlash_Init, + .Deinit = whal_Stm32wbaFlash_Deinit, + .Lock = whal_Stm32wbaFlash_Lock, + .Unlock = whal_Stm32wbaFlash_Unlock, + .Read = whal_Stm32wbaFlash_Read, + .Write = whal_Stm32wbaFlash_Write, + .Erase = whal_Stm32wbaFlash_Erase, +}; diff --git a/src/gpio/stm32wba_gpio.c b/src/gpio/stm32wba_gpio.c new file mode 100644 index 0000000..7ddf812 --- /dev/null +++ b/src/gpio/stm32wba_gpio.c @@ -0,0 +1 @@ +#include "stm32wb_gpio.c" diff --git a/src/i2c/stm32wba_i2c.c b/src/i2c/stm32wba_i2c.c new file mode 100644 index 0000000..394f909 --- /dev/null +++ b/src/i2c/stm32wba_i2c.c @@ -0,0 +1 @@ +#include "stm32wb_i2c.c" diff --git a/src/rng/stm32wba_rng.c b/src/rng/stm32wba_rng.c new file mode 100644 index 0000000..1b77bfb --- /dev/null +++ b/src/rng/stm32wba_rng.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include + +/* + * STM32WBA RNG Register Definitions (RM0493 section 24.7) + */ + +/* Control Register (offset 0x000, reset 0x0080 0D00) */ +#define RNG_CR_REG 0x00 +#define RNG_CR_RNGEN_Pos 2 +#define RNG_CR_RNGEN_Msk (1UL << RNG_CR_RNGEN_Pos) +#define RNG_CR_IE_Pos 3 +#define RNG_CR_IE_Msk (1UL << RNG_CR_IE_Pos) +#define RNG_CR_CED_Pos 5 +#define RNG_CR_CED_Msk (1UL << RNG_CR_CED_Pos) +#define RNG_CR_ARDIS_Pos 7 +#define RNG_CR_ARDIS_Msk (1UL << RNG_CR_ARDIS_Pos) +#define RNG_CR_RNG_CONFIG3_Pos 8 +#define RNG_CR_RNG_CONFIG3_Msk (0xFUL << RNG_CR_RNG_CONFIG3_Pos) +#define RNG_CR_NISTC_Pos 12 +#define RNG_CR_NISTC_Msk (1UL << RNG_CR_NISTC_Pos) +#define RNG_CR_RNG_CONFIG2_Pos 13 +#define RNG_CR_RNG_CONFIG2_Msk (7UL << RNG_CR_RNG_CONFIG2_Pos) +#define RNG_CR_CLKDIV_Pos 16 +#define RNG_CR_CLKDIV_Msk (0xFUL << RNG_CR_CLKDIV_Pos) +#define RNG_CR_RNG_CONFIG1_Pos 20 +#define RNG_CR_RNG_CONFIG1_Msk (0x3FUL << RNG_CR_RNG_CONFIG1_Pos) +#define RNG_CR_CONDRST_Pos 30 +#define RNG_CR_CONDRST_Msk (1UL << RNG_CR_CONDRST_Pos) +#define RNG_CR_CONFIGLOCK_Pos 31 +#define RNG_CR_CONFIGLOCK_Msk (1UL << RNG_CR_CONFIGLOCK_Pos) + +/* Status Register (offset 0x004) */ +#define RNG_SR_REG 0x04 +#define RNG_SR_DRDY_Pos 0 +#define RNG_SR_DRDY_Msk (1UL << RNG_SR_DRDY_Pos) +#define RNG_SR_CECS_Pos 1 +#define RNG_SR_CECS_Msk (1UL << RNG_SR_CECS_Pos) +#define RNG_SR_SECS_Pos 2 +#define RNG_SR_SECS_Msk (1UL << RNG_SR_SECS_Pos) +#define RNG_SR_CEIS_Pos 5 +#define RNG_SR_CEIS_Msk (1UL << RNG_SR_CEIS_Pos) +#define RNG_SR_SEIS_Pos 6 +#define RNG_SR_SEIS_Msk (1UL << RNG_SR_SEIS_Pos) + +/* Data Register (offset 0x008) */ +#define RNG_DR_REG 0x08 + +/* + * Configuration C values (RM0493 Table 178): + * NISTC=0, RNG_CONFIG1=0x0F, CLKDIV=0x0, RNG_CONFIG2=0x0, + * RNG_CONFIG3=0xD, CED=0, N=2 + */ +#define RNG_CR_CONFIG_C (whal_SetBits(RNG_CR_RNG_CONFIG1_Msk, RNG_CR_RNG_CONFIG1_Pos, 0x0F) | \ + whal_SetBits(RNG_CR_RNG_CONFIG3_Msk, RNG_CR_RNG_CONFIG3_Pos, 0x0D)) + +whal_Error whal_Stm32wbaRng_Init(whal_Rng *rngDev) +{ + const whal_Stm32wbaRng_Cfg *cfg; + const whal_Regmap *reg; + + if (!rngDev || !rngDev->cfg) + return WHAL_EINVAL; + + cfg = (const whal_Stm32wbaRng_Cfg *)rngDev->cfg; + reg = &rngDev->regmap; + + /* Apply Configuration C with CONDRST=1 and RNGEN=1 */ + whal_Reg_Write(reg->base, RNG_CR_REG, + RNG_CR_CONDRST_Msk | RNG_CR_CONFIG_C | RNG_CR_RNGEN_Msk); + + /* Clear CONDRST to start conditioning */ + whal_Reg_Write(reg->base, RNG_CR_REG, + RNG_CR_CONFIG_C | RNG_CR_RNGEN_Msk); + + /* Wait for CONDRST to self-clear */ + return whal_Reg_ReadPoll(reg->base, RNG_CR_REG, RNG_CR_CONDRST_Msk, 0, + cfg->timeout); +} + +whal_Error whal_Stm32wbaRng_Deinit(whal_Rng *rngDev) +{ + if (!rngDev || !rngDev->cfg) + return WHAL_EINVAL; + + /* Disable RNG */ + whal_Reg_Update(rngDev->regmap.base, RNG_CR_REG, RNG_CR_RNGEN_Msk, 0); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaRng_Generate(whal_Rng *rngDev, void *rngData, size_t rngDataSz) +{ + uint8_t *rngBuf = (uint8_t *)rngData; + whal_Error err = WHAL_SUCCESS; + whal_Stm32wbaRng_Cfg *cfg; + const whal_Regmap *reg; + size_t sr; + size_t offset = 0; + + if (!rngDev || !rngDev->cfg || !rngData) + return WHAL_EINVAL; + + cfg = (whal_Stm32wbaRng_Cfg *)rngDev->cfg; + reg = &rngDev->regmap; +#ifdef WHAL_CFG_NO_TIMEOUT + (void)(cfg); +#endif + + while (offset < rngDataSz) { + WHAL_TIMEOUT_START(cfg->timeout); + while (1) { + if (WHAL_TIMEOUT_EXPIRED(cfg->timeout)) { + err = WHAL_ETIMEOUT; + goto exit; + } + + sr = whal_Reg_Read(reg->base, RNG_SR_REG); + + if (sr & RNG_SR_SECS_Msk) { + err = WHAL_EHARDWARE; + goto exit; + } + if (sr & RNG_SR_CECS_Msk) { + err = WHAL_EHARDWARE; + goto exit; + } + + if (sr & RNG_SR_DRDY_Msk) + break; + } + + uint32_t rnd = *(volatile uint32_t *)(reg->base + RNG_DR_REG); + + for (size_t i = 0; i < 4 && offset < rngDataSz; i++, offset++) + rngBuf[offset] = (uint8_t)(rnd >> (i * 8)); + } + +exit: + return err; +} + +const whal_RngDriver whal_Stm32wbaRng_Driver = { + .Init = whal_Stm32wbaRng_Init, + .Deinit = whal_Stm32wbaRng_Deinit, + .Generate = whal_Stm32wbaRng_Generate, +}; diff --git a/src/spi/stm32wba_spi.c b/src/spi/stm32wba_spi.c new file mode 100644 index 0000000..8d79c94 --- /dev/null +++ b/src/spi/stm32wba_spi.c @@ -0,0 +1 @@ +#include "stm32h5_spi.c" diff --git a/src/uart/stm32wb_uart.c b/src/uart/stm32wb_uart.c index 70c9592..c8734ba 100644 --- a/src/uart/stm32wb_uart.c +++ b/src/uart/stm32wb_uart.c @@ -16,6 +16,9 @@ #define UART_CR1_TE_Pos 3 #define UART_CR1_TE_Msk (1UL << UART_CR1_TE_Pos) +#define UART_CR1_FIFOEN_Pos 29 +#define UART_CR1_FIFOEN_Msk (1UL << UART_CR1_FIFOEN_Pos) + #define UART_BRR_REG 0x0C #define UART_BRR_Pos 0 #define UART_BRR_Msk (WHAL_BITMASK(20) << UART_BRR_Pos) @@ -73,10 +76,12 @@ whal_Error whal_Stm32wbUart_Init(whal_Uart *uartDev) UART_BRR_Msk, whal_SetBits(UART_BRR_Msk, UART_BRR_Pos, brr)); whal_Reg_Update(reg->base, UART_CR1_REG, - UART_CR1_UE_Msk | UART_CR1_RE_Msk | UART_CR1_TE_Msk, + UART_CR1_UE_Msk | UART_CR1_RE_Msk | UART_CR1_TE_Msk | + UART_CR1_FIFOEN_Msk, whal_SetBits(UART_CR1_UE_Msk, UART_CR1_UE_Pos, 1) | whal_SetBits(UART_CR1_RE_Msk, UART_CR1_RE_Pos, 1) | - whal_SetBits(UART_CR1_TE_Msk, UART_CR1_TE_Pos, 1)); + whal_SetBits(UART_CR1_TE_Msk, UART_CR1_TE_Pos, 1) | + whal_SetBits(UART_CR1_FIFOEN_Msk, UART_CR1_FIFOEN_Pos, 1)); return WHAL_SUCCESS; } diff --git a/src/uart/stm32wba_uart.c b/src/uart/stm32wba_uart.c new file mode 100644 index 0000000..feaed0c --- /dev/null +++ b/src/uart/stm32wba_uart.c @@ -0,0 +1 @@ +#include "stm32wb_uart.c" diff --git a/src/uart/stm32wba_uart_dma.c b/src/uart/stm32wba_uart_dma.c new file mode 100644 index 0000000..6d3d3d2 --- /dev/null +++ b/src/uart/stm32wba_uart_dma.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include + +/* USART register offsets (same on STM32WBA as STM32WB) */ +#define UART_CR3_REG 0x08 +#define UART_CR3_DMAR_Pos 6 +#define UART_CR3_DMAR_Msk (1UL << UART_CR3_DMAR_Pos) +#define UART_CR3_DMAT_Pos 7 +#define UART_CR3_DMAT_Msk (1UL << UART_CR3_DMAT_Pos) + +#define UART_ISR_REG 0x1C +#define UART_ISR_TC_Pos 6 +#define UART_ISR_TC_Msk (1UL << UART_ISR_TC_Pos) + +#define UART_ICR_REG 0x20 +#define UART_ICR_TCCF_Pos 6 +#define UART_ICR_TCCF_Msk (1UL << UART_ICR_TCCF_Pos) + +#define UART_RDR_REG 0x24 +#define UART_TDR_REG 0x28 + +whal_Error whal_Stm32wbaUartDma_SendAsync(whal_Uart *uartDev, const void *data, + size_t dataSz) +{ + whal_Stm32wbaUartDma_Cfg *cfg; + const whal_Regmap *reg; + whal_Error err; + + if (!uartDev || !uartDev->cfg || !data || dataSz > 0xFFFF) + return WHAL_EINVAL; + + if (dataSz == 0) + return WHAL_SUCCESS; + + cfg = (whal_Stm32wbaUartDma_Cfg *)uartDev->cfg; + + if (cfg->txResult == WHAL_ENOTREADY) + return WHAL_ENOTREADY; + + reg = &uartDev->regmap; + + /* Single-byte DMA from flash fails on GPDMA — bounce through SRAM */ + static volatile uint8_t txBounce; + if (dataSz == 1) { + txBounce = *(const uint8_t *)data; + cfg->txChCfg->srcAddr = (size_t)&txBounce; + } else { + cfg->txChCfg->srcAddr = (size_t)data; + } + cfg->txChCfg->dstAddr = reg->base + UART_TDR_REG; + cfg->txChCfg->nbytes = dataSz; + + cfg->txResult = WHAL_ENOTREADY; + + err = whal_Dma_Configure(cfg->dma, cfg->txCh, cfg->txChCfg); + if (err) { + cfg->txResult = err; + return err; + } + + err = whal_Dma_Start(cfg->dma, cfg->txCh); + if (err) { + cfg->txResult = err; + return err; + } + + whal_Reg_Write(reg->base, UART_ICR_REG, UART_ICR_TCCF_Msk); + + whal_Reg_Update(reg->base, UART_CR3_REG, UART_CR3_DMAT_Msk, + UART_CR3_DMAT_Msk); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaUartDma_RecvAsync(whal_Uart *uartDev, void *data, + size_t dataSz) +{ + whal_Stm32wbaUartDma_Cfg *cfg; + const whal_Regmap *reg; + whal_Error err; + + if (!uartDev || !uartDev->cfg || !data || dataSz > 0xFFFF) + return WHAL_EINVAL; + + if (dataSz == 0) + return WHAL_SUCCESS; + + cfg = (whal_Stm32wbaUartDma_Cfg *)uartDev->cfg; + + if (cfg->rxResult == WHAL_ENOTREADY) + return WHAL_ENOTREADY; + + reg = &uartDev->regmap; + + cfg->rxChCfg->srcAddr = reg->base + UART_RDR_REG; + cfg->rxChCfg->dstAddr = (size_t)data; + cfg->rxChCfg->nbytes = dataSz; + + cfg->rxResult = WHAL_ENOTREADY; + + err = whal_Dma_Configure(cfg->dma, cfg->rxCh, cfg->rxChCfg); + if (err) { + cfg->rxResult = err; + return err; + } + + whal_Reg_Update(reg->base, UART_CR3_REG, UART_CR3_DMAR_Msk, + UART_CR3_DMAR_Msk); + + err = whal_Dma_Start(cfg->dma, cfg->rxCh); + if (err) { + whal_Reg_Update(reg->base, UART_CR3_REG, UART_CR3_DMAR_Msk, 0); + cfg->rxResult = err; + return err; + } + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wbaUartDma_Send(whal_Uart *uartDev, const void *data, + size_t dataSz) +{ + whal_Stm32wbaUartDma_Cfg *cfg; + whal_Error err; + + err = whal_Stm32wbaUartDma_SendAsync(uartDev, data, dataSz); + if (err) + return err; + + cfg = (whal_Stm32wbaUartDma_Cfg *)uartDev->cfg; + + WHAL_TIMEOUT_START(cfg->base.timeout); + while (cfg->txResult == WHAL_ENOTREADY) { + if (WHAL_TIMEOUT_EXPIRED(cfg->base.timeout)) { + err = WHAL_ETIMEOUT; + goto cleanup; + } + } + + if (cfg->txResult != WHAL_SUCCESS) { + err = cfg->txResult; + goto cleanup; + } + + /* Wait for TC (transmission complete) so the last byte has shifted out + * before we tear down the DMA channel */ + err = whal_Reg_ReadPoll(uartDev->regmap.base, UART_ISR_REG, + UART_ISR_TC_Msk, UART_ISR_TC_Msk, + cfg->base.timeout); + +cleanup: + whal_Dma_Stop(cfg->dma, cfg->txCh); + whal_Reg_Update(uartDev->regmap.base, UART_CR3_REG, UART_CR3_DMAT_Msk, 0); + cfg->txResult = err; + + return err; +} + +whal_Error whal_Stm32wbaUartDma_Recv(whal_Uart *uartDev, void *data, + size_t dataSz) +{ + whal_Stm32wbaUartDma_Cfg *cfg; + whal_Error err; + + err = whal_Stm32wbaUartDma_RecvAsync(uartDev, data, dataSz); + if (err) + return err; + + cfg = (whal_Stm32wbaUartDma_Cfg *)uartDev->cfg; + + WHAL_TIMEOUT_START(cfg->base.timeout); + while (cfg->rxResult == WHAL_ENOTREADY) { + if (WHAL_TIMEOUT_EXPIRED(cfg->base.timeout)) { + err = WHAL_ETIMEOUT; + goto cleanup; + } + } + + err = cfg->rxResult; + +cleanup: + whal_Dma_Stop(cfg->dma, cfg->rxCh); + whal_Reg_Update(uartDev->regmap.base, UART_CR3_REG, UART_CR3_DMAR_Msk, 0); + cfg->rxResult = err; + + return err; +} + +void whal_Stm32wbaUartDma_TxCallback(void *ctx, whal_Error err) +{ + whal_Stm32wbaUartDma_Cfg *cfg = (whal_Stm32wbaUartDma_Cfg *)ctx; + cfg->txResult = err; +} + +void whal_Stm32wbaUartDma_RxCallback(void *ctx, whal_Error err) +{ + whal_Stm32wbaUartDma_Cfg *cfg = (whal_Stm32wbaUartDma_Cfg *)ctx; + cfg->rxResult = err; +} + +const whal_UartDriver whal_Stm32wbaUartDma_Driver = { + .Init = whal_Stm32wbUart_Init, + .Deinit = whal_Stm32wbUart_Deinit, + .Send = whal_Stm32wbaUartDma_Send, + .Recv = whal_Stm32wbaUartDma_Recv, + .SendAsync = whal_Stm32wbaUartDma_SendAsync, + .RecvAsync = whal_Stm32wbaUartDma_RecvAsync, +}; diff --git a/src/watchdog/stm32wba_iwdg.c b/src/watchdog/stm32wba_iwdg.c new file mode 100644 index 0000000..130c617 --- /dev/null +++ b/src/watchdog/stm32wba_iwdg.c @@ -0,0 +1 @@ +#include "stm32wb_iwdg.c" diff --git a/src/watchdog/stm32wba_wwdg.c b/src/watchdog/stm32wba_wwdg.c new file mode 100644 index 0000000..69fd495 --- /dev/null +++ b/src/watchdog/stm32wba_wwdg.c @@ -0,0 +1 @@ +#include "stm32wb_wwdg.c" diff --git a/tests/crypto/test_crypto.c b/tests/crypto/test_crypto.c index 288023a..f278558 100644 --- a/tests/crypto/test_crypto.c +++ b/tests/crypto/test_crypto.c @@ -45,12 +45,16 @@ static const uint8_t nistPt[16] = { 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, }; +#ifdef WHAL_CFG_CRYPTO_AES_ECB /* NIST SP 800-38A F.1.5 AES-256-ECB expected ciphertext */ static const uint8_t nistEcbCt[16] = { 0xF3, 0xEE, 0xD1, 0xBD, 0xB5, 0xD2, 0xA0, 0x3C, 0x06, 0x4B, 0x5A, 0x7E, 0x3D, 0xB1, 0x81, 0xF8, }; +#endif /* WHAL_CFG_CRYPTO_AES_ECB */ + +#ifdef WHAL_CFG_CRYPTO_AES_CBC /* NIST SP 800-38A F.2.5 AES-256-CBC expected ciphertext */ static const uint8_t nistCbcIv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -62,6 +66,9 @@ static const uint8_t nistCbcCt[16] = { 0x77, 0x9E, 0xAB, 0xFB, 0x5F, 0x7B, 0xFB, 0xD6, }; +#endif /* WHAL_CFG_CRYPTO_AES_CBC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CTR /* NIST SP 800-38A F.5.5 AES-256-CTR expected ciphertext */ static const uint8_t nistCtrIv[16] = { 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, @@ -73,6 +80,9 @@ static const uint8_t nistCtrCt[16] = { 0xB7, 0xA7, 0xF5, 0x04, 0xBB, 0xF3, 0xD2, 0x28, }; +#endif /* WHAL_CFG_CRYPTO_AES_CTR */ + +#ifdef WHAL_CFG_CRYPTO_AES_GCM /* GCM spec Test Case 15: AES-256-GCM, 64-byte payload, no AAD */ static const uint8_t gcmKey[32] = { 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, @@ -148,6 +158,9 @@ static const uint8_t gcm16Tag[16] = { 0xCD, 0xDF, 0x88, 0x53, 0xBB, 0x2D, 0x55, 0x1B, }; +#endif /* WHAL_CFG_CRYPTO_AES_GCM */ + +#ifdef WHAL_CFG_CRYPTO_AES_GMAC /* NIST CAVP gcmEncryptExtIV256.rsp: Keylen=256, IVlen=96, PTlen=0, AADlen=128, Taglen=128, Count=0 */ static const uint8_t gmacKey[32] = { 0x78, 0xDC, 0x4E, 0x0A, 0xAF, 0x52, 0xD9, 0x35, @@ -171,6 +184,9 @@ static const uint8_t gmacTag[16] = { 0xE0, 0x40, 0xB8, 0x57, 0x23, 0xA0, 0x6E, 0x76, }; +#endif /* WHAL_CFG_CRYPTO_AES_GMAC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CCM /* NIST CAVP DVPT256.rsp: Alen=32, Plen=24, Nlen=13, Tlen=16, Count=225 */ static const uint8_t ccmKey[32] = { 0x31, 0x4A, 0x20, 0x2F, 0x83, 0x6F, 0x9F, 0x25, @@ -208,6 +224,9 @@ static const uint8_t ccmTag[16] = { 0x3C, 0xA5, 0x07, 0x95, 0xAC, 0xD9, 0x02, 0x03, }; +#endif /* WHAL_CFG_CRYPTO_AES_CCM */ + +#ifdef WHAL_CFG_CRYPTO_AES_ECB static void Test_Crypto_AesEcb_Basic(void) { uint8_t ct[32] = {0}; @@ -217,27 +236,35 @@ static void Test_Crypto_AesEcb_Basic(void) .dir = WHAL_CRYPTO_ENCRYPT, .key = key, .keySz = 32, .in = plaintext, .out = ct, .sz = sizeof(plaintext), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesEcb(&g_whalCrypto, &enc), WHAL_SUCCESS); whal_Crypto_AesEcbArgs dec = { .dir = WHAL_CRYPTO_DECRYPT, .key = key, .keySz = 32, .in = ct, .out = pt, .sz = sizeof(ct), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &dec), + WHAL_ASSERT_EQ(whal_Crypto_AesEcb(&g_whalCrypto, &dec), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(pt, plaintext, sizeof(plaintext)); } +static void Test_Crypto_AesEcb_KnownAnswer(void) +{ + uint8_t ct[16] = {0}; + + whal_Crypto_AesEcbArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, + .in = nistPt, .out = ct, .sz = sizeof(nistPt), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesEcb(&g_whalCrypto, &enc), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(ct, nistEcbCt, sizeof(nistEcbCt)); +} +#endif /* WHAL_CFG_CRYPTO_AES_ECB */ + +#ifdef WHAL_CFG_CRYPTO_AES_CBC static void Test_Crypto_AesCbc_Basic(void) { uint8_t ct[32] = {0}; @@ -247,27 +274,35 @@ static void Test_Crypto_AesCbc_Basic(void) .dir = WHAL_CRYPTO_ENCRYPT, .key = key, .keySz = 32, .iv = iv, .in = plaintext, .out = ct, .sz = sizeof(plaintext), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesCbc(&g_whalCrypto, &enc), WHAL_SUCCESS); whal_Crypto_AesCbcArgs dec = { .dir = WHAL_CRYPTO_DECRYPT, .key = key, .keySz = 32, .iv = iv, .in = ct, .out = pt, .sz = sizeof(ct), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &dec), + WHAL_ASSERT_EQ(whal_Crypto_AesCbc(&g_whalCrypto, &dec), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(pt, plaintext, sizeof(plaintext)); } +static void Test_Crypto_AesCbc_KnownAnswer(void) +{ + uint8_t ct[16] = {0}; + + whal_Crypto_AesCbcArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, + .iv = nistCbcIv, .in = nistPt, .out = ct, .sz = sizeof(nistPt), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesCbc(&g_whalCrypto, &enc), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(ct, nistCbcCt, sizeof(nistCbcCt)); +} +#endif /* WHAL_CFG_CRYPTO_AES_CBC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CTR static void Test_Crypto_AesCtr_Basic(void) { uint8_t ct[32] = {0}; @@ -277,27 +312,35 @@ static void Test_Crypto_AesCtr_Basic(void) .dir = WHAL_CRYPTO_ENCRYPT, .key = key, .keySz = 32, .iv = iv, .in = plaintext, .out = ct, .sz = sizeof(plaintext), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesCtr(&g_whalCrypto, &enc), WHAL_SUCCESS); whal_Crypto_AesCtrArgs dec = { .dir = WHAL_CRYPTO_DECRYPT, .key = key, .keySz = 32, .iv = iv, .in = ct, .out = pt, .sz = sizeof(ct), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &dec), + WHAL_ASSERT_EQ(whal_Crypto_AesCtr(&g_whalCrypto, &dec), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(pt, plaintext, sizeof(plaintext)); } +static void Test_Crypto_AesCtr_KnownAnswer(void) +{ + uint8_t ct[16] = {0}; + + whal_Crypto_AesCtrArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, + .iv = nistCtrIv, .in = nistPt, .out = ct, .sz = sizeof(nistPt), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesCtr(&g_whalCrypto, &enc), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(ct, nistCtrCt, sizeof(nistCtrCt)); +} +#endif /* WHAL_CFG_CRYPTO_AES_CTR */ + +#ifdef WHAL_CFG_CRYPTO_AES_GCM static void Test_Crypto_AesGcm_Basic(void) { uint8_t ct[32] = {0}; @@ -312,11 +355,7 @@ static void Test_Crypto_AesGcm_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = encTag, .tagSz = sizeof(encTag), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesGcm(&g_whalCrypto, &enc), WHAL_SUCCESS); whal_Crypto_AesGcmArgs dec = { @@ -326,17 +365,53 @@ static void Test_Crypto_AesGcm_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = decTag, .tagSz = sizeof(decTag), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &dec), + WHAL_ASSERT_EQ(whal_Crypto_AesGcm(&g_whalCrypto, &dec), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(pt, plaintext, sizeof(plaintext)); WHAL_ASSERT_MEM_EQ(decTag, encTag, sizeof(encTag)); } +static void Test_Crypto_AesGcm_KnownAnswer(void) +{ + uint8_t ct[64] = {0}; + uint8_t tag[16] = {0}; + + whal_Crypto_AesGcmArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = gcmKey, .keySz = 32, + .iv = gcmIv, .ivSz = sizeof(gcmIv), + .in = gcmPt, .out = ct, .sz = sizeof(gcmPt), + .aad = NULL, .aadSz = 0, + .tag = tag, .tagSz = sizeof(tag), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesGcm(&g_whalCrypto, &enc), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(ct, gcmCt, sizeof(gcmCt)); + WHAL_ASSERT_MEM_EQ(tag, gcmTag, sizeof(gcmTag)); +} + +static void Test_Crypto_AesGcm_KnownAnswer_PartialBlocks(void) +{ + uint8_t ct[sizeof(gcm16Pt)] = {0}; + uint8_t tag[16] = {0}; + + whal_Crypto_AesGcmArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = gcmKey, .keySz = 32, + .iv = gcmIv, .ivSz = sizeof(gcmIv), + .in = gcm16Pt, .out = ct, .sz = sizeof(gcm16Pt), + .aad = gcm16Aad, .aadSz = sizeof(gcm16Aad), + .tag = tag, .tagSz = sizeof(tag), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesGcm(&g_whalCrypto, &enc), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(ct, gcm16Ct, sizeof(gcm16Ct)); + WHAL_ASSERT_MEM_EQ(tag, gcm16Tag, sizeof(gcm16Tag)); +} +#endif /* WHAL_CFG_CRYPTO_AES_GCM */ + +#ifdef WHAL_CFG_CRYPTO_AES_GMAC static void Test_Crypto_AesGmac_Basic(void) { uint8_t tag1[16] = {0}; @@ -348,11 +423,7 @@ static void Test_Crypto_AesGmac_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = tag1, .tagSz = sizeof(tag1), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args1), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args1), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args1), + WHAL_ASSERT_EQ(whal_Crypto_AesGmac(&g_whalCrypto, &args1), WHAL_SUCCESS); whal_Crypto_AesGmacArgs args2 = { @@ -361,16 +432,30 @@ static void Test_Crypto_AesGmac_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = tag2, .tagSz = sizeof(tag2), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args2), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args2), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args2), + WHAL_ASSERT_EQ(whal_Crypto_AesGmac(&g_whalCrypto, &args2), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(tag1, tag2, sizeof(tag1)); } +static void Test_Crypto_AesGmac_KnownAnswer(void) +{ + uint8_t tag[16] = {0}; + + whal_Crypto_AesGmacArgs args = { + .key = gmacKey, .keySz = 32, + .iv = gmacIv, .ivSz = sizeof(gmacIv), + .aad = gmacAad, .aadSz = sizeof(gmacAad), + .tag = tag, .tagSz = sizeof(tag), + }; + WHAL_ASSERT_EQ(whal_Crypto_AesGmac(&g_whalCrypto, &args), + WHAL_SUCCESS); + + WHAL_ASSERT_MEM_EQ(tag, gmacTag, sizeof(gmacTag)); +} +#endif /* WHAL_CFG_CRYPTO_AES_GMAC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CCM static void Test_Crypto_AesCcm_Basic(void) { uint8_t ct[32] = {0}; @@ -385,11 +470,7 @@ static void Test_Crypto_AesCcm_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = encTag, .tagSz = sizeof(encTag), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesCcm(&g_whalCrypto, &enc), WHAL_SUCCESS); whal_Crypto_AesCcmArgs dec = { @@ -399,159 +480,198 @@ static void Test_Crypto_AesCcm_Basic(void) .aad = aad, .aadSz = sizeof(aad), .tag = decTag, .tagSz = sizeof(decTag), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &dec), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &dec), + WHAL_ASSERT_EQ(whal_Crypto_AesCcm(&g_whalCrypto, &dec), WHAL_SUCCESS); WHAL_ASSERT_MEM_EQ(pt, plaintext, sizeof(plaintext)); WHAL_ASSERT_MEM_EQ(decTag, encTag, sizeof(encTag)); } -static void Test_Crypto_AesEcb_KnownAnswer(void) +static void Test_Crypto_AesCcm_KnownAnswer(void) { - uint8_t ct[16] = {0}; + uint8_t ct[24] = {0}; + uint8_t tag[16] = {0}; - whal_Crypto_AesEcbArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, - .in = nistPt, .out = ct, .sz = sizeof(nistPt), + whal_Crypto_AesCcmArgs enc = { + .dir = WHAL_CRYPTO_ENCRYPT, .key = ccmKey, .keySz = 32, + .nonce = ccmNonce, .nonceSz = sizeof(ccmNonce), + .in = ccmPt, .out = ct, .sz = sizeof(ccmPt), + .aad = ccmAad, .aadSz = sizeof(ccmAad), + .tag = tag, .tagSz = sizeof(tag), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_ECB, &enc), + WHAL_ASSERT_EQ(whal_Crypto_AesCcm(&g_whalCrypto, &enc), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, nistEcbCt, sizeof(nistEcbCt)); + WHAL_ASSERT_MEM_EQ(ct, ccmCt, sizeof(ccmCt)); + WHAL_ASSERT_MEM_EQ(tag, ccmTag, sizeof(ccmTag)); } +#endif /* WHAL_CFG_CRYPTO_AES_CCM */ -static void Test_Crypto_AesCbc_KnownAnswer(void) +/* --- Hash / HMAC known-answer vectors --- */ + +#if defined(WHAL_CFG_CRYPTO_SHA1) || defined(WHAL_CFG_CRYPTO_SHA224) || \ + defined(WHAL_CFG_CRYPTO_SHA256) +static const uint8_t hashInput[] = { 'a', 'b', 'c' }; +#endif + +#ifdef WHAL_CFG_CRYPTO_SHA1 +/* NIST FIPS 180-4: SHA-1("abc") */ +static const uint8_t sha1Digest[20] = { + 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, + 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, + 0x9C, 0xD0, 0xD8, 0x9D, +}; + +static void Test_Crypto_Sha1_KnownAnswer(void) { - uint8_t ct[16] = {0}; + uint8_t digest[20] = {0}; - whal_Crypto_AesCbcArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, - .iv = nistCbcIv, .in = nistPt, .out = ct, .sz = sizeof(nistPt), + whal_Crypto_HashArgs args = { + .in = hashInput, .inSz = sizeof(hashInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CBC, &enc), + WHAL_ASSERT_EQ(whal_Crypto_Sha1(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, nistCbcCt, sizeof(nistCbcCt)); + WHAL_ASSERT_MEM_EQ(digest, sha1Digest, sizeof(sha1Digest)); } +#endif /* WHAL_CFG_CRYPTO_SHA1 */ + +#ifdef WHAL_CFG_CRYPTO_SHA224 +/* NIST FIPS 180-4: SHA-224("abc") */ +static const uint8_t sha224Digest[28] = { + 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7, +}; -static void Test_Crypto_AesCtr_KnownAnswer(void) +static void Test_Crypto_Sha224_KnownAnswer(void) { - uint8_t ct[16] = {0}; + uint8_t digest[28] = {0}; - whal_Crypto_AesCtrArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = nistKey, .keySz = 32, - .iv = nistCtrIv, .in = nistPt, .out = ct, .sz = sizeof(nistPt), + whal_Crypto_HashArgs args = { + .in = hashInput, .inSz = sizeof(hashInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CTR, &enc), + WHAL_ASSERT_EQ(whal_Crypto_Sha224(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, nistCtrCt, sizeof(nistCtrCt)); + WHAL_ASSERT_MEM_EQ(digest, sha224Digest, sizeof(sha224Digest)); } +#endif /* WHAL_CFG_CRYPTO_SHA224 */ + +#ifdef WHAL_CFG_CRYPTO_SHA256 +/* NIST FIPS 180-4: SHA-256("abc") */ +static const uint8_t sha256Digest[32] = { + 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD, +}; -static void Test_Crypto_AesGcm_KnownAnswer(void) +static void Test_Crypto_Sha256_KnownAnswer(void) { - uint8_t ct[64] = {0}; - uint8_t tag[16] = {0}; + uint8_t digest[32] = {0}; - whal_Crypto_AesGcmArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = gcmKey, .keySz = 32, - .iv = gcmIv, .ivSz = sizeof(gcmIv), - .in = gcmPt, .out = ct, .sz = sizeof(gcmPt), - .aad = NULL, .aadSz = 0, - .tag = tag, .tagSz = sizeof(tag), + whal_Crypto_HashArgs args = { + .in = hashInput, .inSz = sizeof(hashInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), + WHAL_ASSERT_EQ(whal_Crypto_Sha256(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, gcmCt, sizeof(gcmCt)); - WHAL_ASSERT_MEM_EQ(tag, gcmTag, sizeof(gcmTag)); + WHAL_ASSERT_MEM_EQ(digest, sha256Digest, sizeof(sha256Digest)); } +#endif /* WHAL_CFG_CRYPTO_SHA256 */ + +#if defined(WHAL_CFG_CRYPTO_HMAC_SHA1) || defined(WHAL_CFG_CRYPTO_HMAC_SHA224) || \ + defined(WHAL_CFG_CRYPTO_HMAC_SHA256) +/* RFC 2202 / RFC 4231 Test Case 1: HMAC with 20-byte 0x0b key, "Hi There" */ +static const uint8_t hmacKey[20] = { + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0B, 0x0B, 0x0B, 0x0B, +}; -static void Test_Crypto_AesGcm_KnownAnswer_PartialBlocks(void) +static const uint8_t hmacInput[] = { + 'H', 'i', ' ', 'T', 'h', 'e', 'r', 'e', +}; +#endif + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 +/* RFC 2202 section 3, Test Case 1 */ +static const uint8_t hmacSha1Digest[20] = { + 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xE2, 0x8B, 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, + 0xF1, 0x46, 0xBE, 0x00, +}; + +static void Test_Crypto_HmacSha1_KnownAnswer(void) { - uint8_t ct[sizeof(gcm16Pt)] = {0}; - uint8_t tag[16] = {0}; + uint8_t digest[20] = {0}; - whal_Crypto_AesGcmArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = gcmKey, .keySz = 32, - .iv = gcmIv, .ivSz = sizeof(gcmIv), - .in = gcm16Pt, .out = ct, .sz = sizeof(gcm16Pt), - .aad = gcm16Aad, .aadSz = sizeof(gcm16Aad), - .tag = tag, .tagSz = sizeof(tag), + whal_Crypto_HmacArgs args = { + .key = hmacKey, .keySz = sizeof(hmacKey), + .in = hmacInput, .inSz = sizeof(hmacInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GCM, &enc), + WHAL_ASSERT_EQ(whal_Crypto_HmacSha1(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, gcm16Ct, sizeof(gcm16Ct)); - WHAL_ASSERT_MEM_EQ(tag, gcm16Tag, sizeof(gcm16Tag)); + WHAL_ASSERT_MEM_EQ(digest, hmacSha1Digest, sizeof(hmacSha1Digest)); } +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA1 */ + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 +/* RFC 4231 section 4, Test Case 1 */ +static const uint8_t hmacSha224Digest[28] = { + 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, + 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, + 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, + 0x53, 0x68, 0x4B, 0x22, +}; -static void Test_Crypto_AesGmac_KnownAnswer(void) +static void Test_Crypto_HmacSha224_KnownAnswer(void) { - uint8_t tag[16] = {0}; + uint8_t digest[28] = {0}; - whal_Crypto_AesGmacArgs args = { - .key = gmacKey, .keySz = 32, - .iv = gmacIv, .ivSz = sizeof(gmacIv), - .aad = gmacAad, .aadSz = sizeof(gmacAad), - .tag = tag, .tagSz = sizeof(tag), + whal_Crypto_HmacArgs args = { + .key = hmacKey, .keySz = sizeof(hmacKey), + .in = hmacInput, .inSz = sizeof(hmacInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_GMAC, &args), + WHAL_ASSERT_EQ(whal_Crypto_HmacSha224(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(tag, gmacTag, sizeof(gmacTag)); + WHAL_ASSERT_MEM_EQ(digest, hmacSha224Digest, sizeof(hmacSha224Digest)); } +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA224 */ + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 +/* RFC 4231 section 4, Test Case 1 */ +static const uint8_t hmacSha256Digest[32] = { + 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, + 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, + 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, + 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7, +}; -static void Test_Crypto_AesCcm_KnownAnswer(void) +static void Test_Crypto_HmacSha256_KnownAnswer(void) { - uint8_t ct[24] = {0}; - uint8_t tag[16] = {0}; + uint8_t digest[32] = {0}; - whal_Crypto_AesCcmArgs enc = { - .dir = WHAL_CRYPTO_ENCRYPT, .key = ccmKey, .keySz = 32, - .nonce = ccmNonce, .nonceSz = sizeof(ccmNonce), - .in = ccmPt, .out = ct, .sz = sizeof(ccmPt), - .aad = ccmAad, .aadSz = sizeof(ccmAad), - .tag = tag, .tagSz = sizeof(tag), + whal_Crypto_HmacArgs args = { + .key = hmacKey, .keySz = sizeof(hmacKey), + .in = hmacInput, .inSz = sizeof(hmacInput), + .digest = digest, .digestSz = sizeof(digest), }; - WHAL_ASSERT_EQ(whal_Crypto_StartOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_Process(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), - WHAL_SUCCESS); - WHAL_ASSERT_EQ(whal_Crypto_EndOp(&g_whalCrypto, WHAL_CRYPTO_AES_CCM, &enc), + WHAL_ASSERT_EQ(whal_Crypto_HmacSha256(&g_whalHash, &args), WHAL_SUCCESS); - WHAL_ASSERT_MEM_EQ(ct, ccmCt, sizeof(ccmCt)); - WHAL_ASSERT_MEM_EQ(tag, ccmTag, sizeof(ccmTag)); + WHAL_ASSERT_MEM_EQ(digest, hmacSha256Digest, sizeof(hmacSha256Digest)); } +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA256 */ static void Test_Crypto_Api(void) { @@ -571,18 +691,48 @@ void whal_Test_Crypto(void) { WHAL_TEST_SUITE_START("cipher"); WHAL_TEST(Test_Crypto_Api); +#ifdef WHAL_CFG_CRYPTO_AES_ECB WHAL_TEST(Test_Crypto_AesEcb_Basic); WHAL_TEST(Test_Crypto_AesEcb_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CBC WHAL_TEST(Test_Crypto_AesCbc_Basic); WHAL_TEST(Test_Crypto_AesCbc_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CTR WHAL_TEST(Test_Crypto_AesCtr_Basic); WHAL_TEST(Test_Crypto_AesCtr_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GCM WHAL_TEST(Test_Crypto_AesGcm_Basic); WHAL_TEST(Test_Crypto_AesGcm_KnownAnswer); WHAL_TEST(Test_Crypto_AesGcm_KnownAnswer_PartialBlocks); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_GMAC WHAL_TEST(Test_Crypto_AesGmac_Basic); WHAL_TEST(Test_Crypto_AesGmac_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_AES_CCM WHAL_TEST(Test_Crypto_AesCcm_Basic); WHAL_TEST(Test_Crypto_AesCcm_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA1 + WHAL_TEST(Test_Crypto_Sha1_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA224 + WHAL_TEST(Test_Crypto_Sha224_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_SHA256 + WHAL_TEST(Test_Crypto_Sha256_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 + WHAL_TEST(Test_Crypto_HmacSha1_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 + WHAL_TEST(Test_Crypto_HmacSha224_KnownAnswer); +#endif +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 + WHAL_TEST(Test_Crypto_HmacSha256_KnownAnswer); +#endif WHAL_TEST_SUITE_END(); } diff --git a/tests/main.c b/tests/main.c index adb2fb8..0b93fff 100644 --- a/tests/main.c +++ b/tests/main.c @@ -128,13 +128,17 @@ int g_whalTestCurSkipped; void whal_Test_Puts(const char *s) { - while (*s) { - if (*s == '\n') - whal_Uart_Send(&g_whalUart, "\r\n", 2); - else - whal_Uart_Send(&g_whalUart, s, 1); - s++; - } + size_t len = 0; + while (s[len]) + len++; + + if (len == 0) + return; + + whal_Uart_Send(&g_whalUart, s, len); + + if (s[len - 1] == '\n') + whal_Uart_Send(&g_whalUart, "\r", 1); } void main(void) diff --git a/wolfHAL/clock/stm32wba_rcc.h b/wolfHAL/clock/stm32wba_rcc.h new file mode 100644 index 0000000..fe8366e --- /dev/null +++ b/wolfHAL/clock/stm32wba_rcc.h @@ -0,0 +1,142 @@ +#ifndef WHAL_STM32WBA_RCC_H +#define WHAL_STM32WBA_RCC_H + +#include +#include +#include + +/* + * @file stm32wba_rcc.h + * @brief STM32WBA RCC (Reset and Clock Control) driver configuration. + * + * The STM32WBA RCC peripheral controls: + * - System clock source selection (HSI16, HSE32, PLL1) + * - PLL1 configuration for up to 100 MHz operation + * - Peripheral clock gating (AHB1-5, APB1-2, APB7 buses) + * - Bus clock prescalers (HPRE, PPRE1, PPRE2, PPRE7, HPRE5) + * + * Key differences from STM32WB RCC: + * - No MSI oscillator + * - HSE is 32 MHz (HSE32) + * - PLL configuration split across RCC_PLL1CFGR and RCC_PLL1DIVR + * - HPRE5 prescaler for AHB5 domain (max 32 MHz) + * - Different register offsets throughout + */ + +/* + * @brief System clock source selection. + */ +typedef enum { + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16 = 0, /* 16 MHz High-Speed Internal */ + WHAL_STM32WBA_RCC_SYSCLK_SRC_HSE32 = 2, /* 32 MHz High-Speed External */ + WHAL_STM32WBA_RCC_SYSCLK_SRC_PLL1 = 3, /* PLL1 output */ +} whal_Stm32wbaRcc_SysClockSrc; + +/* + * @brief PLL1 input clock source selection. + */ +typedef enum { + WHAL_STM32WBA_RCC_PLL1SRC_NONE = 0, /* No clock (PLL disabled) */ + WHAL_STM32WBA_RCC_PLL1SRC_HSI16 = 2, /* HSI16 as PLL input */ + WHAL_STM32WBA_RCC_PLL1SRC_HSE32 = 3, /* HSE32 as PLL input */ +} whal_Stm32wbaRcc_Pll1Src; + +/* + * @brief PLL1 input reference frequency range. + */ +typedef enum { + WHAL_STM32WBA_RCC_PLL1RGE_4_8 = 2, /* 4-8 MHz */ + WHAL_STM32WBA_RCC_PLL1RGE_8_16 = 3, /* 8-16 MHz */ +} whal_Stm32wbaRcc_Pll1Rge; + +/* + * @brief PLL1 configuration parameters. + * + * The PLL1 output frequency is calculated as: + * f_ref = f_input / (PLL1M + 1) [must be 4-16 MHz] + * f_vco = f_ref * PLL1N [must be 128-544 MHz] + * f_pll1r = f_vco / (PLL1R + 1) [SYSCLK output, max 100 MHz] + * + * For 100 MHz from 32 MHz HSE: + * PLL1M = 1 (div by 2, ref = 16 MHz) + * PLL1N = 25 (VCO = 400 MHz) + * PLL1R = 3 (div by 4, out = 100 MHz) + * PLL1RGE = 3 (8-16 MHz range) + */ +typedef struct whal_Stm32wbaRcc_Pll1Cfg { + whal_Stm32wbaRcc_Pll1Src clkSrc; /* PLL1 input source */ + whal_Stm32wbaRcc_Pll1Rge rge; /* PLL1 input frequency range */ + uint8_t m; /* PLL1M prescaler (0-7 maps to div 1-8) */ + uint16_t n; /* PLL1N multiplier (4-512, written to PLL1N[8:0]) */ + uint8_t r; /* PLL1R divider (0=VCO, 1=div2, 2=div3, 3=div4, ...) */ + uint8_t q; /* PLL1Q divider (0=VCO, 1=div2, ...) */ + uint8_t p; /* PLL1P divider (0=VCO, 1=div2, ...) */ +} whal_Stm32wbaRcc_Pll1Cfg; + +/* + * @brief Peripheral clock enable descriptor. + * + * Same structure as STM32WB -- describes register offset and bit to toggle. + */ +typedef struct whal_Stm32wbaRcc_Clk { + size_t regOffset; /* Offset from RCC base to enable register */ + size_t enableMask; /* Bit mask for the peripheral enable bit */ + size_t enablePos; /* Bit position for the peripheral enable bit */ +} whal_Stm32wbaRcc_Clk; + +/* + * @brief RCC driver configuration. + */ +typedef struct whal_Stm32wbaRcc_Cfg { + whal_Stm32wbaRcc_SysClockSrc sysClkSrc; + void *sysClkCfg; /* Pointer to Pll1Cfg when sysClkSrc is PLL1 */ +} whal_Stm32wbaRcc_Cfg; + +extern const whal_ClockDriver whal_Stm32wbaRccPll_Driver; +extern const whal_ClockDriver whal_Stm32wbaRccHse_Driver; + +whal_Error whal_Stm32wbaRccPll_Init(whal_Clock *clkDev); +whal_Error whal_Stm32wbaRccPll_Deinit(whal_Clock *clkDev); +whal_Error whal_Stm32wbaRccHse_Init(whal_Clock *clkDev); +whal_Error whal_Stm32wbaRccHse_Deinit(whal_Clock *clkDev); +whal_Error whal_Stm32wbaRcc_Enable(whal_Clock *clkDev, const void *clk); +whal_Error whal_Stm32wbaRcc_Disable(whal_Clock *clkDev, const void *clk); + +/* + * @brief RNG kernel clock source selection (RCC_CCIPR2.RNGSEL). + */ +typedef enum { + WHAL_STM32WBA_RCC_RNGSEL_LSE = 0, + WHAL_STM32WBA_RCC_RNGSEL_LSI = 1, + WHAL_STM32WBA_RCC_RNGSEL_HSI16 = 2, + WHAL_STM32WBA_RCC_RNGSEL_PLL1Q_D2 = 3, +} whal_Stm32wbaRcc_RngSrc; + +/* + * @brief Enable or disable the LSI1 oscillator required by the IWDG. + */ +whal_Error whal_Stm32wbaRcc_Ext_EnableLsi(whal_Clock *clkDev, uint8_t enable); + +/* + * @brief Select the RNG kernel clock source (RCC_CCIPR2.RNGSEL). + * + * Default after reset is LSE, which is typically not enabled. HSI16 is the + * usual choice since it is always running. + */ +whal_Error whal_Stm32wbaRcc_Ext_SetRngClockSrc(whal_Clock *clkDev, + whal_Stm32wbaRcc_RngSrc src); + +/* + * @brief Set the HPRE5 prescaler for the AHB5 domain. + * + * The AHB5 domain (radio, PTACONV) must not exceed 32 MHz. + * @param hpre5 HPRE5 value in RCC_CFGR3 bits[6:4]: + * 0xx: not divided + * 100: div 2 + * 101: div 4 + * 110: div 8 + * 111: div 16 + */ +whal_Error whal_Stm32wbaRcc_Ext_SetHpre5(whal_Clock *clkDev, uint8_t hpre5); + +#endif /* WHAL_STM32WBA_RCC_H */ diff --git a/wolfHAL/crypto/crypto.h b/wolfHAL/crypto/crypto.h index e3604a9..45771f3 100644 --- a/wolfHAL/crypto/crypto.h +++ b/wolfHAL/crypto/crypto.h @@ -25,6 +25,12 @@ enum { WHAL_CRYPTO_AES_GCM, WHAL_CRYPTO_AES_GMAC, WHAL_CRYPTO_AES_CCM, + WHAL_CRYPTO_SHA1, + WHAL_CRYPTO_SHA224, + WHAL_CRYPTO_SHA256, + WHAL_CRYPTO_HMAC_SHA1, + WHAL_CRYPTO_HMAC_SHA224, + WHAL_CRYPTO_HMAC_SHA256, }; /* ---- Per-algorithm argument structs ---- */ @@ -34,10 +40,10 @@ enum { */ typedef struct { whal_Crypto_Dir dir; - const uint8_t *key; + const void *key; size_t keySz; /* 16, 24, or 32 */ - const uint8_t *in; - uint8_t *out; + const void *in; + void *out; size_t sz; /* Must be a multiple of 16 */ } whal_Crypto_AesEcbArgs; @@ -46,11 +52,11 @@ typedef struct { */ typedef struct { whal_Crypto_Dir dir; - const uint8_t *key; + const void *key; size_t keySz; /* 16, 24, or 32 */ - const uint8_t *iv; /* 16 bytes */ - const uint8_t *in; - uint8_t *out; + const void *iv; /* 16 bytes */ + const void *in; + void *out; size_t sz; /* Must be a multiple of 16 */ } whal_Crypto_AesCbcArgs; @@ -59,11 +65,11 @@ typedef struct { */ typedef struct { whal_Crypto_Dir dir; - const uint8_t *key; + const void *key; size_t keySz; /* 16, 24, or 32 */ - const uint8_t *iv; /* 16 bytes (initial counter block) */ - const uint8_t *in; - uint8_t *out; + const void *iv; /* 16 bytes (initial counter block) */ + const void *in; + void *out; size_t sz; } whal_Crypto_AesCtrArgs; @@ -72,16 +78,16 @@ typedef struct { */ typedef struct { whal_Crypto_Dir dir; - const uint8_t *key; + const void *key; size_t keySz; /* 16, 24, or 32 */ - const uint8_t *iv; + const void *iv; size_t ivSz; /* Typically 12 */ - const uint8_t *in; - uint8_t *out; + const void *in; + void *out; size_t sz; - const uint8_t *aad; + const void *aad; size_t aadSz; - uint8_t *tag; + void *tag; size_t tagSz; /* Up to 16 */ } whal_Crypto_AesGcmArgs; @@ -90,16 +96,16 @@ typedef struct { */ typedef struct { whal_Crypto_Dir dir; - const uint8_t *key; + const void *key; size_t keySz; /* 16, 24, or 32 */ - const uint8_t *nonce; + const void *nonce; size_t nonceSz; /* 7-13 */ - const uint8_t *in; - uint8_t *out; + const void *in; + void *out; size_t sz; - const uint8_t *aad; + const void *aad; size_t aadSz; - uint8_t *tag; + void *tag; size_t tagSz; /* 4, 6, 8, 10, 12, 14, or 16 */ } whal_Crypto_AesCcmArgs; @@ -107,16 +113,38 @@ typedef struct { * @brief Arguments for AES-GMAC (authentication only, no payload). */ typedef struct { - const uint8_t *key; - size_t keySz; /* 16, 24, or 32 */ - const uint8_t *iv; - size_t ivSz; /* Typically 12 */ - const uint8_t *aad; - size_t aadSz; - uint8_t *tag; - size_t tagSz; /* Up to 16 */ + const void *key; + size_t keySz; /* 16, 24, or 32 */ + const void *iv; + size_t ivSz; /* Typically 12 */ + const void *aad; + size_t aadSz; + void *tag; + size_t tagSz; /* Up to 16 */ } whal_Crypto_AesGmacArgs; +/* + * @brief Arguments for one-shot hash (SHA-1/224/256/...). + */ +typedef struct { + const void *in; + size_t inSz; + void *digest; + size_t digestSz; /* Algorithm-specific (20/28/32/48/64) */ +} whal_Crypto_HashArgs; + +/* + * @brief Arguments for one-shot HMAC (HMAC-SHA-1/224/256/...). + */ +typedef struct { + const void *key; + size_t keySz; + const void *in; + size_t inSz; + void *digest; + size_t digestSz; /* Algorithm-specific (20/28/32/48/64) */ +} whal_Crypto_HmacArgs; + /* ---- Device and driver ---- */ typedef struct whal_Crypto whal_Crypto; @@ -239,4 +267,673 @@ whal_Error whal_Crypto_EndOp(whal_Crypto *cryptoDev, size_t opId, void *opArgs); #endif +/* ---- Per-algorithm inline wrappers ---- */ +#ifdef WHAL_CFG_CRYPTO_AES_ECB + +/* AES-ECB */ + +static inline whal_Error whal_Crypto_AesEcb(whal_Crypto *dev, + whal_Crypto_AesEcbArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_ECB, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_ECB, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_ECB, args); +} + +static inline whal_Error whal_Crypto_AesEcb_Start(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *key, size_t keySz) +{ + whal_Crypto_AesEcbArgs args = {0}; + + args.dir = dir; + args.key = key; + args.keySz = keySz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_ECB, &args); +} + +static inline whal_Error whal_Crypto_AesEcb_Update(whal_Crypto *dev, + const void *in, void *out, + size_t sz) +{ + whal_Crypto_AesEcbArgs args = {0}; + + args.in = in; + args.out = out; + args.sz = sz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_AES_ECB, &args); +} + +static inline whal_Error whal_Crypto_AesEcb_Finalize(whal_Crypto *dev) +{ + whal_Crypto_AesEcbArgs args = {0}; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_ECB, &args); +} +#endif /* WHAL_CFG_CRYPTO_AES_ECB */ + +#ifdef WHAL_CFG_CRYPTO_AES_CBC + +/* AES-CBC */ + +static inline whal_Error whal_Crypto_AesCbc(whal_Crypto *dev, + whal_Crypto_AesCbcArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CBC, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CBC, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CBC, args); +} + +static inline whal_Error whal_Crypto_AesCbc_Start(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *key, size_t keySz, + const void *iv) +{ + whal_Crypto_AesCbcArgs args = {0}; + + args.dir = dir; + args.key = key; + args.keySz = keySz; + args.iv = iv; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CBC, &args); +} + +static inline whal_Error whal_Crypto_AesCbc_Update(whal_Crypto *dev, + const void *in, void *out, + size_t sz) +{ + whal_Crypto_AesCbcArgs args = {0}; + + args.in = in; + args.out = out; + args.sz = sz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CBC, &args); +} + +static inline whal_Error whal_Crypto_AesCbc_Finalize(whal_Crypto *dev) +{ + whal_Crypto_AesCbcArgs args = {0}; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CBC, &args); +} +#endif /* WHAL_CFG_CRYPTO_AES_CBC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CTR + +/* AES-CTR */ + +static inline whal_Error whal_Crypto_AesCtr(whal_Crypto *dev, + whal_Crypto_AesCtrArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CTR, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CTR, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CTR, args); +} + +static inline whal_Error whal_Crypto_AesCtr_Start(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *key, size_t keySz, + const void *iv) +{ + whal_Crypto_AesCtrArgs args = {0}; + + args.dir = dir; + args.key = key; + args.keySz = keySz; + args.iv = iv; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CTR, &args); +} + +static inline whal_Error whal_Crypto_AesCtr_Update(whal_Crypto *dev, + const void *in, void *out, + size_t sz) +{ + whal_Crypto_AesCtrArgs args = {0}; + + args.in = in; + args.out = out; + args.sz = sz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CTR, &args); +} + +static inline whal_Error whal_Crypto_AesCtr_Finalize(whal_Crypto *dev) +{ + whal_Crypto_AesCtrArgs args = {0}; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CTR, &args); +} +#endif /* WHAL_CFG_CRYPTO_AES_CTR */ + +#ifdef WHAL_CFG_CRYPTO_AES_GCM + +/* AES-GCM */ + +static inline whal_Error whal_Crypto_AesGcm(whal_Crypto *dev, + whal_Crypto_AesGcmArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_GCM, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_GCM, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_GCM, args); +} + +static inline whal_Error whal_Crypto_AesGcm_Start(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *key, size_t keySz, + const void *iv, size_t ivSz, + const void *aad, size_t aadSz) +{ + whal_Crypto_AesGcmArgs args = {0}; + + args.dir = dir; + args.key = key; + args.keySz = keySz; + args.iv = iv; + args.ivSz = ivSz; + args.aad = aad; + args.aadSz = aadSz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_GCM, &args); +} + +static inline whal_Error whal_Crypto_AesGcm_Update(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *in, void *out, + size_t sz, size_t aadSz) +{ + whal_Crypto_AesGcmArgs args = {0}; + + args.dir = dir; + args.in = in; + args.out = out; + args.sz = sz; + args.aadSz = aadSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_AES_GCM, &args); +} + +static inline whal_Error whal_Crypto_AesGcm_Finalize(whal_Crypto *dev, + void *tag, size_t tagSz, + size_t aadSz, size_t sz) +{ + whal_Crypto_AesGcmArgs args = {0}; + + args.tag = tag; + args.tagSz = tagSz; + args.aadSz = aadSz; + args.sz = sz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_GCM, &args); +} +#endif /* WHAL_CFG_CRYPTO_AES_GCM */ + +#ifdef WHAL_CFG_CRYPTO_AES_GMAC + +/* AES-GMAC */ + +static inline whal_Error whal_Crypto_AesGmac(whal_Crypto *dev, + whal_Crypto_AesGmacArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_GMAC, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_GMAC, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_GMAC, args); +} +#endif /* WHAL_CFG_CRYPTO_AES_GMAC */ + +#ifdef WHAL_CFG_CRYPTO_AES_CCM + +/* AES-CCM */ + +static inline whal_Error whal_Crypto_AesCcm(whal_Crypto *dev, + whal_Crypto_AesCcmArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CCM, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CCM, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CCM, args); +} + +static inline whal_Error whal_Crypto_AesCcm_Start(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *key, size_t keySz, + const void *nonce, + size_t nonceSz, + const void *aad, size_t aadSz, + size_t tagSz, size_t sz) +{ + whal_Crypto_AesCcmArgs args = {0}; + + args.dir = dir; + args.key = key; + args.keySz = keySz; + args.nonce = nonce; + args.nonceSz = nonceSz; + args.aad = aad; + args.aadSz = aadSz; + args.tagSz = tagSz; + args.sz = sz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_AES_CCM, &args); +} + +static inline whal_Error whal_Crypto_AesCcm_Update(whal_Crypto *dev, + whal_Crypto_Dir dir, + const void *in, void *out, + size_t sz, size_t aadSz) +{ + whal_Crypto_AesCcmArgs args = {0}; + + args.dir = dir; + args.in = in; + args.out = out; + args.sz = sz; + args.aadSz = aadSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_AES_CCM, &args); +} + +static inline whal_Error whal_Crypto_AesCcm_Finalize(whal_Crypto *dev, + void *tag, size_t tagSz, + size_t aadSz, size_t sz) +{ + whal_Crypto_AesCcmArgs args = {0}; + + args.tag = tag; + args.tagSz = tagSz; + args.aadSz = aadSz; + args.sz = sz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_AES_CCM, &args); +} +#endif /* WHAL_CFG_CRYPTO_AES_CCM */ + +#ifdef WHAL_CFG_CRYPTO_SHA1 + +/* SHA-1 */ + +static inline whal_Error whal_Crypto_Sha1(whal_Crypto *dev, + whal_Crypto_HashArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA1, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_SHA1, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA1, args); +} + +static inline whal_Error whal_Crypto_Sha1_Start(whal_Crypto *dev) +{ + whal_Crypto_HashArgs args = {0}; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA1, &args); +} + +static inline whal_Error whal_Crypto_Sha1_Update(whal_Crypto *dev, + const void *in, size_t inSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_SHA1, &args); +} + +static inline whal_Error whal_Crypto_Sha1_Finalize(whal_Crypto *dev, + void *digest, + size_t digestSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA1, &args); +} +#endif /* WHAL_CFG_CRYPTO_SHA1 */ + +#ifdef WHAL_CFG_CRYPTO_SHA224 + +/* SHA-224 */ + +static inline whal_Error whal_Crypto_Sha224(whal_Crypto *dev, + whal_Crypto_HashArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA224, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_SHA224, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA224, args); +} + +static inline whal_Error whal_Crypto_Sha224_Start(whal_Crypto *dev) +{ + whal_Crypto_HashArgs args = {0}; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA224, &args); +} + +static inline whal_Error whal_Crypto_Sha224_Update(whal_Crypto *dev, + const void *in, size_t inSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_SHA224, &args); +} + +static inline whal_Error whal_Crypto_Sha224_Finalize(whal_Crypto *dev, + void *digest, + size_t digestSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA224, &args); +} +#endif /* WHAL_CFG_CRYPTO_SHA224 */ + +#ifdef WHAL_CFG_CRYPTO_SHA256 + +/* SHA-256 */ + +static inline whal_Error whal_Crypto_Sha256(whal_Crypto *dev, + whal_Crypto_HashArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA256, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_SHA256, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA256, args); +} + +static inline whal_Error whal_Crypto_Sha256_Start(whal_Crypto *dev) +{ + whal_Crypto_HashArgs args = {0}; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_SHA256, &args); +} + +static inline whal_Error whal_Crypto_Sha256_Update(whal_Crypto *dev, + const void *in, size_t inSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_SHA256, &args); +} + +static inline whal_Error whal_Crypto_Sha256_Finalize(whal_Crypto *dev, + void *digest, + size_t digestSz) +{ + whal_Crypto_HashArgs args = {0}; + + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_SHA256, &args); +} +#endif /* WHAL_CFG_CRYPTO_SHA256 */ + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA1 + +/* HMAC-SHA-1 */ + +static inline whal_Error whal_Crypto_HmacSha1(whal_Crypto *dev, + whal_Crypto_HmacArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA1, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA1, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA1, args); +} + +static inline whal_Error whal_Crypto_HmacSha1_Start(whal_Crypto *dev, + const void *key, + size_t keySz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA1, &args); +} + +static inline whal_Error whal_Crypto_HmacSha1_Update(whal_Crypto *dev, + const void *in, + size_t inSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA1, &args); +} + +static inline whal_Error whal_Crypto_HmacSha1_Finalize(whal_Crypto *dev, + const void *key, + size_t keySz, + void *digest, + size_t digestSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA1, &args); +} +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA1 */ + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA224 + +/* HMAC-SHA-224 */ + +static inline whal_Error whal_Crypto_HmacSha224(whal_Crypto *dev, + whal_Crypto_HmacArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA224, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA224, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA224, args); +} + +static inline whal_Error whal_Crypto_HmacSha224_Start(whal_Crypto *dev, + const void *key, + size_t keySz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA224, &args); +} + +static inline whal_Error whal_Crypto_HmacSha224_Update(whal_Crypto *dev, + const void *in, + size_t inSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA224, &args); +} + +static inline whal_Error whal_Crypto_HmacSha224_Finalize(whal_Crypto *dev, + const void *key, + size_t keySz, + void *digest, + size_t digestSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA224, &args); +} +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA224 */ + +#ifdef WHAL_CFG_CRYPTO_HMAC_SHA256 + +/* HMAC-SHA-256 */ + +static inline whal_Error whal_Crypto_HmacSha256(whal_Crypto *dev, + whal_Crypto_HmacArgs *args) +{ + whal_Error err; + + err = whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA256, args); + if (err) + return err; + + err = whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA256, args); + if (err) + return err; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA256, args); +} + +static inline whal_Error whal_Crypto_HmacSha256_Start(whal_Crypto *dev, + const void *key, + size_t keySz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + + return whal_Crypto_StartOp(dev, WHAL_CRYPTO_HMAC_SHA256, &args); +} + +static inline whal_Error whal_Crypto_HmacSha256_Update(whal_Crypto *dev, + const void *in, + size_t inSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.in = in; + args.inSz = inSz; + + return whal_Crypto_Process(dev, WHAL_CRYPTO_HMAC_SHA256, &args); +} + +static inline whal_Error whal_Crypto_HmacSha256_Finalize(whal_Crypto *dev, + const void *key, + size_t keySz, + void *digest, + size_t digestSz) +{ + whal_Crypto_HmacArgs args = {0}; + + args.key = key; + args.keySz = keySz; + args.digest = digest; + args.digestSz = digestSz; + + return whal_Crypto_EndOp(dev, WHAL_CRYPTO_HMAC_SHA256, &args); +} + +#endif /* WHAL_CFG_CRYPTO_HMAC_SHA256 */ + #endif /* WHAL_CRYPTO_H */ diff --git a/wolfHAL/crypto/stm32wba_aes.h b/wolfHAL/crypto/stm32wba_aes.h new file mode 100644 index 0000000..38a6b9a --- /dev/null +++ b/wolfHAL/crypto/stm32wba_aes.h @@ -0,0 +1,26 @@ +#ifndef WHAL_STM32WBA_AES_H +#define WHAL_STM32WBA_AES_H + +/* + * @file stm32wba_aes.h + * @brief STM32WBA AES driver (alias for STM32WB AES). + * + * The STM32WBA AES peripheral is register-compatible with the STM32WB AES. + * This header re-exports the STM32WB AES driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32wbAes_Cfg whal_Stm32wbaAes_Cfg; + +#ifndef WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_AES +#define whal_Stm32wbaAes_Driver whal_Stm32wbAes_Driver +#define whal_Stm32wbaAes_Init whal_Stm32wbAes_Init +#define whal_Stm32wbaAes_Deinit whal_Stm32wbAes_Deinit +#define whal_Stm32wbaAes_StartOp whal_Stm32wbAes_StartOp +#define whal_Stm32wbaAes_Process whal_Stm32wbAes_Process +#define whal_Stm32wbaAes_EndOp whal_Stm32wbAes_EndOp +#endif /* !WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_AES */ + +#endif /* WHAL_STM32WBA_AES_H */ diff --git a/wolfHAL/crypto/stm32wba_hash.h b/wolfHAL/crypto/stm32wba_hash.h new file mode 100644 index 0000000..8527f16 --- /dev/null +++ b/wolfHAL/crypto/stm32wba_hash.h @@ -0,0 +1,93 @@ +#ifndef WHAL_STM32WBA_HASH_H +#define WHAL_STM32WBA_HASH_H + +#include +#include +#include + +/* + * @file stm32wba_hash.h + * @brief STM32WBA HASH hardware accelerator driver. + * + * The STM32WBA HASH peripheral supports SHA-1, SHA-224, SHA-256 and HMAC + * variants. This driver exposes those algorithms through the generic + * whal_Crypto interface using the StartOp/Process/EndOp pattern. + */ + +/* + * @brief HASH device configuration. + */ +typedef struct { + whal_Timeout *timeout; +} whal_Stm32wbaHash_Cfg; + +#ifndef WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_HASH +/* + * @brief Driver instance for STM32WBA HASH peripheral. + */ +extern const whal_CryptoDriver whal_Stm32wbaHash_Driver; + +/* + * @brief Initialize the STM32WBA HASH peripheral. + * + * @param cryptoDev Crypto device instance. + * + * @retval WHAL_SUCCESS Initialization completed. + * @retval WHAL_EINVAL Invalid arguments. + */ +whal_Error whal_Stm32wbaHash_Init(whal_Crypto *cryptoDev); + +/* + * @brief Deinitialize the STM32WBA HASH peripheral. + * + * @param cryptoDev Crypto device instance. + * + * @retval WHAL_SUCCESS Deinit completed. + * @retval WHAL_EINVAL Invalid arguments. + */ +whal_Error whal_Stm32wbaHash_Deinit(whal_Crypto *cryptoDev); + +/* + * @brief Start a hash/HMAC operation. + * + * @param cryptoDev Crypto device instance. + * @param opId Algorithm identifier (WHAL_CRYPTO_SHA* / WHAL_CRYPTO_HMAC_SHA*). + * @param opArgs Pointer to whal_Crypto_HashArgs or whal_Crypto_HmacArgs. + * + * @retval WHAL_SUCCESS Operation started. + * @retval WHAL_EINVAL Invalid arguments. + * @retval WHAL_EHARDWARE Hardware error during setup. + */ +whal_Error whal_Stm32wbaHash_StartOp(whal_Crypto *cryptoDev, size_t opId, + void *opArgs); + +/* + * @brief Feed data into an active hash/HMAC operation. + * + * @param cryptoDev Crypto device instance. + * @param opId Algorithm identifier. + * @param opArgs Pointer to whal_Crypto_HashArgs or whal_Crypto_HmacArgs. + * + * @retval WHAL_SUCCESS Data processed. + * @retval WHAL_EINVAL Invalid arguments. + * @retval WHAL_EHARDWARE Hardware error during processing. + */ +whal_Error whal_Stm32wbaHash_Process(whal_Crypto *cryptoDev, size_t opId, + void *opArgs); + +/* + * @brief End a hash/HMAC operation and read the digest. + * + * @param cryptoDev Crypto device instance. + * @param opId Algorithm identifier. + * @param opArgs Pointer to whal_Crypto_HashArgs or whal_Crypto_HmacArgs. + * + * @retval WHAL_SUCCESS Operation finalized. + * @retval WHAL_EINVAL Invalid arguments. + * @retval WHAL_EHARDWARE Hardware error during finalization. + */ +whal_Error whal_Stm32wbaHash_EndOp(whal_Crypto *cryptoDev, size_t opId, + void *opArgs); +#endif /* !WHAL_CFG_CRYPTO_API_MAPPING_STM32WBA_HASH */ + +#endif /* WHAL_STM32WBA_HASH_H */ diff --git a/wolfHAL/dma/stm32wba_gpdma.h b/wolfHAL/dma/stm32wba_gpdma.h new file mode 100644 index 0000000..0430426 --- /dev/null +++ b/wolfHAL/dma/stm32wba_gpdma.h @@ -0,0 +1,91 @@ +#ifndef WHAL_STM32WBA_GPDMA_H +#define WHAL_STM32WBA_GPDMA_H + +#include +#include +#include +#include + +/* + * @file stm32wba_gpdma.h + * @brief STM32WBA GPDMA controller driver configuration types. + * + * The GPDMA (General Purpose DMA) controller provides 8 independent + * channels supporting memory-to-memory, memory-to-peripheral, and + * peripheral-to-memory transfers. + * + * This driver supports direct-programming mode for run-to-completion + * transfers. Linked-list mode is not supported. + * + * Each channel occupies 0x80 bytes starting at offset 0x50 from the + * GPDMA base address. + */ + +/* + * @brief Transfer direction. + */ +typedef enum { + WHAL_STM32WBA_GPDMA_DIR_PERIPH_TO_MEM, /* Peripheral to memory */ + WHAL_STM32WBA_GPDMA_DIR_MEM_TO_PERIPH, /* Memory to peripheral */ + WHAL_STM32WBA_GPDMA_DIR_MEM_TO_MEM, /* Software request memory-to-memory */ +} whal_Stm32wbaGpdma_Dir; + +/* + * @brief Data width for transfers. + */ +typedef enum { + WHAL_STM32WBA_GPDMA_WIDTH_8BIT = 0, + WHAL_STM32WBA_GPDMA_WIDTH_16BIT = 1, + WHAL_STM32WBA_GPDMA_WIDTH_32BIT = 2, +} whal_Stm32wbaGpdma_Width; + +/* + * @brief Address increment mode. + */ +typedef enum { + WHAL_STM32WBA_GPDMA_INC_DISABLE = 0, /* Fixed address */ + WHAL_STM32WBA_GPDMA_INC_ENABLE = 1, /* Incremented address */ +} whal_Stm32wbaGpdma_Inc; + +/* + * @brief Per-channel transfer configuration. + * + * For hardware-paced transfers, reqSel selects the peripheral request line + * (REQSEL[5:0] from TRM Table 208 - e.g. 11=USART1_RX, 12=USART1_TX). + */ +typedef struct { + whal_Stm32wbaGpdma_Dir dir; + size_t srcAddr; + size_t dstAddr; + size_t nbytes; /* Byte count (max 65535) */ + whal_Stm32wbaGpdma_Width srcWidth; + whal_Stm32wbaGpdma_Width dstWidth; + whal_Stm32wbaGpdma_Inc srcInc; + whal_Stm32wbaGpdma_Inc dstInc; + uint8_t reqSel; /* REQSEL[5:0] (ignored for MEM_TO_MEM) */ +} whal_Stm32wbaGpdma_ChCfg; + +/* + * @brief Controller-level configuration. + */ +typedef struct { + uint8_t numChannels; /* 8 for the STM32WBA GPDMA1 controller */ + whal_Timeout *timeout; /* Timeout for channel reset/suspend polling */ +} whal_Stm32wbaGpdma_Cfg; + +extern const whal_DmaDriver whal_Stm32wbaGpdma_Driver; + +/* + * @brief DMA completion callback invoked from the channel IRQ handler. + */ +typedef void (*whal_Stm32wbaGpdma_Callback)(void *ctx, whal_Error err); + +/* + * @brief Handle a GPDMA channel interrupt. + * + * Clears TCF/error flags and invokes the callback with the completion status. + */ +void whal_Stm32wbaGpdma_IRQHandler(whal_Dma *dmaDev, size_t ch, + whal_Stm32wbaGpdma_Callback cb, void *ctx); + +#endif /* WHAL_STM32WBA_GPDMA_H */ diff --git a/wolfHAL/endian.h b/wolfHAL/endian.h index d0db593..2b06de3 100644 --- a/wolfHAL/endian.h +++ b/wolfHAL/endian.h @@ -7,6 +7,7 @@ */ #include +#include /* * @brief Load a 32-bit value from a big-endian byte array. @@ -28,4 +29,39 @@ static inline void whal_StoreBe32(uint8_t *p, uint32_t v) p[3] = (uint8_t)v; } +/* + * @brief Load n bytes from a byte array into a 32-bit big-endian value. + * + * The first byte becomes the MSB and the remaining (4-n) bytes are zero. + * Equivalent to whal_LoadBe32 when n == 4. + * + * @param p Source byte array. + * @param n Number of bytes to load (must be 0..4). + */ +static inline uint32_t whal_LoadBe32Partial(const uint8_t *p, size_t n) +{ + uint32_t v = 0; + size_t i; + for (i = 0; i < n; i++) + v |= (uint32_t)p[i] << (24 - i * 8); + return v; +} + +/* + * @brief Load n bytes from a byte array into a 32-bit little-endian value. + * + * The first byte becomes the LSB and the remaining (4-n) bytes are zero. + * + * @param p Source byte array. + * @param n Number of bytes to load (must be 0..4). + */ +static inline uint32_t whal_LoadLe32Partial(const uint8_t *p, size_t n) +{ + uint32_t v = 0; + size_t i; + for (i = 0; i < n; i++) + v |= (uint32_t)p[i] << (i * 8); + return v; +} + #endif /* WHAL_ENDIAN_H */ diff --git a/wolfHAL/flash/stm32wba_flash.h b/wolfHAL/flash/stm32wba_flash.h new file mode 100644 index 0000000..c5eb072 --- /dev/null +++ b/wolfHAL/flash/stm32wba_flash.h @@ -0,0 +1,41 @@ +#ifndef WHAL_STM32WBA_FLASH_H +#define WHAL_STM32WBA_FLASH_H + +#include +#include + +/* + * @file stm32wba_flash.h + * @brief STM32WBA flash driver configuration. + * + * The STM32WBA embedded flash provides: + * - Up to 1 MB organized in 8 KB pages (128 pages) + * - 128-bit (flash-word) programming + * - Non-secure register variants (NSCR1, NSSR, NSKEYR) + * - TrustZone support (this driver uses non-secure registers) + * + * Key register differences from STM32H5: + * - NSKEYR at offset 0x008 (not 0x004) + * - No separate NSCCR register (errors cleared via NSSR) + * - Single bank (no BKSEL bit) + */ + +typedef struct whal_Stm32wbaFlash_Cfg { + size_t startAddr; + size_t size; + whal_Timeout *timeout; +} whal_Stm32wbaFlash_Cfg; + +extern const whal_FlashDriver whal_Stm32wbaFlash_Driver; + +whal_Error whal_Stm32wbaFlash_Init(whal_Flash *flashDev); +whal_Error whal_Stm32wbaFlash_Deinit(whal_Flash *flashDev); +whal_Error whal_Stm32wbaFlash_Lock(whal_Flash *flashDev, size_t addr, size_t len); +whal_Error whal_Stm32wbaFlash_Unlock(whal_Flash *flashDev, size_t addr, size_t len); +whal_Error whal_Stm32wbaFlash_Read(whal_Flash *flashDev, size_t addr, void *data, size_t dataSz); +whal_Error whal_Stm32wbaFlash_Write(whal_Flash *flashDev, size_t addr, const void *data, size_t dataSz); +whal_Error whal_Stm32wbaFlash_Erase(whal_Flash *flashDev, size_t addr, size_t dataSz); + +whal_Error whal_Stm32wbaFlash_Ext_SetLatency(whal_Flash *flashDev, uint8_t latency); + +#endif /* WHAL_STM32WBA_FLASH_H */ diff --git a/wolfHAL/gpio/stm32wba_gpio.h b/wolfHAL/gpio/stm32wba_gpio.h new file mode 100644 index 0000000..bb65449 --- /dev/null +++ b/wolfHAL/gpio/stm32wba_gpio.h @@ -0,0 +1,69 @@ +#ifndef WHAL_STM32WBA_GPIO_H +#define WHAL_STM32WBA_GPIO_H + +/* + * @file stm32wba_gpio.h + * @brief STM32WBA GPIO driver (alias for STM32WB GPIO). + * + * The STM32WBA GPIO peripheral is register-compatible with the STM32WB GPIO. + * This header re-exports the STM32WB GPIO driver types and symbols under + * STM32WBA-specific names. The underlying implementation is shared. + */ + +#include + +typedef whal_Stm32wbGpio_Cfg whal_Stm32wbaGpio_Cfg; +typedef whal_Stm32wbGpio_PinCfg whal_Stm32wbaGpio_PinCfg; + +#ifndef WHAL_CFG_GPIO_API_MAPPING_STM32WBA +#define whal_Stm32wbaGpio_Driver whal_Stm32wbGpio_Driver +#define whal_Stm32wbaGpio_Init whal_Stm32wbGpio_Init +#define whal_Stm32wbaGpio_Deinit whal_Stm32wbGpio_Deinit +#define whal_Stm32wbaGpio_Get whal_Stm32wbGpio_Get +#define whal_Stm32wbaGpio_Set whal_Stm32wbGpio_Set +#endif /* !WHAL_CFG_GPIO_API_MAPPING_STM32WBA */ + +/* + * @brief GPIO mode selection (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_GPIO_MODE_IN WHAL_STM32WB_GPIO_MODE_IN +#define WHAL_STM32WBA_GPIO_MODE_OUT WHAL_STM32WB_GPIO_MODE_OUT +#define WHAL_STM32WBA_GPIO_MODE_ALTFN WHAL_STM32WB_GPIO_MODE_ALTFN +#define WHAL_STM32WBA_GPIO_MODE_ANALOG WHAL_STM32WB_GPIO_MODE_ANALOG + +/* + * @brief GPIO output type (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL +#define WHAL_STM32WBA_GPIO_OUTTYPE_OPENDRAIN WHAL_STM32WB_GPIO_OUTTYPE_OPENDRAIN + +/* + * @brief GPIO speed selection (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_GPIO_SPEED_LOW WHAL_STM32WB_GPIO_SPEED_LOW +#define WHAL_STM32WBA_GPIO_SPEED_MEDIUM WHAL_STM32WB_GPIO_SPEED_MEDIUM +#define WHAL_STM32WBA_GPIO_SPEED_FAST WHAL_STM32WB_GPIO_SPEED_FAST +#define WHAL_STM32WBA_GPIO_SPEED_HIGH WHAL_STM32WB_GPIO_SPEED_HIGH + +/* + * @brief GPIO pull-up/pull-down selection (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_GPIO_PULL_NONE WHAL_STM32WB_GPIO_PULL_NONE +#define WHAL_STM32WBA_GPIO_PULL_UP WHAL_STM32WB_GPIO_PULL_UP +#define WHAL_STM32WBA_GPIO_PULL_DOWN WHAL_STM32WB_GPIO_PULL_DOWN + +/* + * @brief GPIO port selection (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_GPIO_PORT_A WHAL_STM32WB_GPIO_PORT_A +#define WHAL_STM32WBA_GPIO_PORT_B WHAL_STM32WB_GPIO_PORT_B +#define WHAL_STM32WBA_GPIO_PORT_C WHAL_STM32WB_GPIO_PORT_C +#define WHAL_STM32WBA_GPIO_PORT_H WHAL_STM32WB_GPIO_PORT_H + +/* + * @brief Pack a GPIO pin configuration into a single word (re-exported from + * STM32WB). + */ +#define WHAL_STM32WBA_GPIO_PIN WHAL_STM32WB_GPIO_PIN + +#endif /* WHAL_STM32WBA_GPIO_H */ diff --git a/wolfHAL/i2c/stm32wba_i2c.h b/wolfHAL/i2c/stm32wba_i2c.h new file mode 100644 index 0000000..49d3d4c --- /dev/null +++ b/wolfHAL/i2c/stm32wba_i2c.h @@ -0,0 +1,26 @@ +#ifndef WHAL_STM32WBA_I2C_H +#define WHAL_STM32WBA_I2C_H + +/* + * @file stm32wba_i2c.h + * @brief STM32WBA I2C driver (alias for STM32WB I2C). + * + * The STM32WBA I2C peripheral is register-compatible with the STM32WB I2C. + * This header re-exports the STM32WB I2C driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32wbI2c_Cfg whal_Stm32wbaI2c_Cfg; + +#ifndef WHAL_CFG_I2C_API_MAPPING_STM32WBA +#define whal_Stm32wbaI2c_Driver whal_Stm32wbI2c_Driver +#define whal_Stm32wbaI2c_Init whal_Stm32wbI2c_Init +#define whal_Stm32wbaI2c_Deinit whal_Stm32wbI2c_Deinit +#define whal_Stm32wbaI2c_StartCom whal_Stm32wbI2c_StartCom +#define whal_Stm32wbaI2c_EndCom whal_Stm32wbI2c_EndCom +#define whal_Stm32wbaI2c_Transfer whal_Stm32wbI2c_Transfer +#endif /* !WHAL_CFG_I2C_API_MAPPING_STM32WBA */ + +#endif /* WHAL_STM32WBA_I2C_H */ diff --git a/wolfHAL/platform/arm/cortex_m33.h b/wolfHAL/platform/arm/cortex_m33.h index 9ab025a..18f70be 100644 --- a/wolfHAL/platform/arm/cortex_m33.h +++ b/wolfHAL/platform/arm/cortex_m33.h @@ -2,10 +2,16 @@ #define WHAL_CORTEX_M33_H #include +#include #define WHAL_CORTEX_M33_SYSTICK_REGMAP \ .base = 0xE000E010, \ .size = 0x400 #define WHAL_CORTEX_M33_SYSTICK_DRIVER &whal_SysTick_Driver +#define WHAL_CORTEX_M33_NVIC_REGMAP \ + .base = 0xE000E100, \ + .size = 0x400 +#define WHAL_CORTEX_M33_NVIC_DRIVER &whal_Nvic_Driver + #endif /* WHAL_CORTEX_M33_H */ diff --git a/wolfHAL/platform/st/stm32wba55cg.h b/wolfHAL/platform/st/stm32wba55cg.h new file mode 100644 index 0000000..f33ff52 --- /dev/null +++ b/wolfHAL/platform/st/stm32wba55cg.h @@ -0,0 +1,295 @@ +#ifndef WHAL_STM32WBA55CG_H +#define WHAL_STM32WBA55CG_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * @file stm32wba55cg.h + * @brief Convenience initializers for STM32WBA55CG device instances. + * + * Base addresses from RM0493 Table 5 (memory map). + * GPIO: 0x42020000 (port A), 0x400 spacing per port (A, B, C, H) + * RCC: 0x46020C00 + * USART1: 0x40013800 + * SPI1: 0x40013000 + * I2C1: 0x40005400 + * Flash interface: 0x40022000 + * RNG: 0x420C0800 + * AES: 0x420C0000 + */ + +/* --- Regmap and driver macros --- */ + +#define WHAL_STM32WBA55_RCC_PLL_REGMAP \ + .base = 0x46020C00, \ + .size = 0x400 +#define WHAL_STM32WBA55_RCC_PLL_DRIVER &whal_Stm32wbaRccPll_Driver + +#define WHAL_STM32WBA55_RCC_HSE_REGMAP \ + .base = 0x46020C00, \ + .size = 0x400 +#define WHAL_STM32WBA55_RCC_HSE_DRIVER &whal_Stm32wbaRccHse_Driver + +#define WHAL_STM32WBA55_GPIO_REGMAP \ + .base = 0x42020000, \ + .size = 0x2000 +#define WHAL_STM32WBA55_GPIO_DRIVER &whal_Stm32wbaGpio_Driver + +#define WHAL_STM32WBA55_USART1_REGMAP \ + .base = 0x40013800, \ + .size = 0x400 +#define WHAL_STM32WBA55_USART1_DRIVER &whal_Stm32wbaUart_Driver + +#define WHAL_STM32WBA55_USART2_REGMAP \ + .base = 0x40004400, \ + .size = 0x400 +#define WHAL_STM32WBA55_USART2_DRIVER &whal_Stm32wbaUart_Driver + +#define WHAL_STM32WBA55_LPUART1_REGMAP \ + .base = 0x46002400, \ + .size = 0x400 +#define WHAL_STM32WBA55_LPUART1_DRIVER &whal_Stm32wbaUart_Driver + +#define WHAL_STM32WBA55_SPI1_REGMAP \ + .base = 0x40013000, \ + .size = 0x400 +#define WHAL_STM32WBA55_SPI1_DRIVER &whal_Stm32wbaSpi_Driver + +#define WHAL_STM32WBA55_I2C1_REGMAP \ + .base = 0x40005400, \ + .size = 0x400 +#define WHAL_STM32WBA55_I2C1_DRIVER &whal_Stm32wbaI2c_Driver + +#define WHAL_STM32WBA55_I2C3_REGMAP \ + .base = 0x46002800, \ + .size = 0x400 +#define WHAL_STM32WBA55_I2C3_DRIVER &whal_Stm32wbaI2c_Driver + +#define WHAL_STM32WBA55_FLASH_REGMAP \ + .base = 0x40022000, \ + .size = 0x400 +#define WHAL_STM32WBA55_FLASH_DRIVER &whal_Stm32wbaFlash_Driver + +#define WHAL_STM32WBA55_RNG_REGMAP \ + .base = 0x420C0800, \ + .size = 0x400 +#define WHAL_STM32WBA55_RNG_DRIVER &whal_Stm32wbaRng_Driver + +#define WHAL_STM32WBA55_GPDMA1_REGMAP \ + .base = 0x40020000, \ + .size = 0x1000 +#define WHAL_STM32WBA55_GPDMA1_DRIVER &whal_Stm32wbaGpdma_Driver + +#define WHAL_STM32WBA55_AES_REGMAP \ + .base = 0x420C0000, \ + .size = 0x400 +#define WHAL_STM32WBA55_AES_DRIVER &whal_Stm32wbaAes_Driver + +#define WHAL_STM32WBA55_HASH_REGMAP \ + .base = 0x420C0400, \ + .size = 0x400 +#define WHAL_STM32WBA55_HASH_DRIVER &whal_Stm32wbaHash_Driver + +#define WHAL_STM32WBA55_IWDG_REGMAP \ + .base = 0x40003000, \ + .size = 0x400 +#define WHAL_STM32WBA55_IWDG_DRIVER &whal_Stm32wbaIwdg_Driver + +#define WHAL_STM32WBA55_WWDG_REGMAP \ + .base = 0x40002C00, \ + .size = 0x400 +#define WHAL_STM32WBA55_WWDG_DRIVER &whal_Stm32wbaWwdg_Driver + +/* --- Clock gate macros --- */ +/* RCC base: 0x46020C00, offsets from base */ + +/* RCC_AHB1ENR (offset 0x088) */ +#define WHAL_STM32WBA55_FLASH_CLOCK \ + .regOffset = 0x088, \ + .enableMask = (1UL << 8), \ + .enablePos = 8 + +/* USART1 TX DMA configuration: memory-to-peripheral, 8-bit, REQSEL=12 */ +#define WHAL_STM32WBA55_USART1_TX_DMA_CFG \ + .dir = WHAL_STM32WBA_GPDMA_DIR_MEM_TO_PERIPH, \ + .srcWidth = WHAL_STM32WBA_GPDMA_WIDTH_8BIT, \ + .dstWidth = WHAL_STM32WBA_GPDMA_WIDTH_8BIT, \ + .srcInc = WHAL_STM32WBA_GPDMA_INC_ENABLE, \ + .dstInc = WHAL_STM32WBA_GPDMA_INC_DISABLE, \ + .reqSel = 12 + +/* USART1 RX DMA configuration: peripheral-to-memory, 8-bit, REQSEL=11 */ +#define WHAL_STM32WBA55_USART1_RX_DMA_CFG \ + .dir = WHAL_STM32WBA_GPDMA_DIR_PERIPH_TO_MEM, \ + .srcWidth = WHAL_STM32WBA_GPDMA_WIDTH_8BIT, \ + .dstWidth = WHAL_STM32WBA_GPDMA_WIDTH_8BIT, \ + .srcInc = WHAL_STM32WBA_GPDMA_INC_DISABLE, \ + .dstInc = WHAL_STM32WBA_GPDMA_INC_ENABLE, \ + .reqSel = 11 + +#define WHAL_STM32WBA55_GPDMA1_CLOCK \ + .regOffset = 0x088, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +/* RCC_AHB2ENR (offset 0x08C) */ +#define WHAL_STM32WBA55_GPIOA_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +#define WHAL_STM32WBA55_GPIOB_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 1), \ + .enablePos = 1 + +#define WHAL_STM32WBA55_GPIOC_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 2), \ + .enablePos = 2 + +#define WHAL_STM32WBA55_GPIOH_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 7), \ + .enablePos = 7 + +#define WHAL_STM32WBA55_AES_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 16), \ + .enablePos = 16 + +#define WHAL_STM32WBA55_HASH_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 17), \ + .enablePos = 17 + +#define WHAL_STM32WBA55_RNG_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 18), \ + .enablePos = 18 + +#define WHAL_STM32WBA55_SAES_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 19), \ + .enablePos = 19 + +#define WHAL_STM32WBA55_HSEM_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 20), \ + .enablePos = 20 + +#define WHAL_STM32WBA55_PKA_CLOCK \ + .regOffset = 0x08C, \ + .enableMask = (1UL << 21), \ + .enablePos = 21 + +/* RCC_AHB4ENR (offset 0x094) */ +#define WHAL_STM32WBA55_PWR_CLOCK \ + .regOffset = 0x094, \ + .enableMask = (1UL << 2), \ + .enablePos = 2 + +#define WHAL_STM32WBA55_ADC4_CLOCK \ + .regOffset = 0x094, \ + .enableMask = (1UL << 5), \ + .enablePos = 5 + +/* RCC_AHB5ENR (offset 0x098) */ +#define WHAL_STM32WBA55_RADIO_CLOCK \ + .regOffset = 0x098, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +/* RCC_APB1ENR1 (offset 0x09C) */ +#define WHAL_STM32WBA55_TIM2_CLOCK \ + .regOffset = 0x09C, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +#define WHAL_STM32WBA55_TIM3_CLOCK \ + .regOffset = 0x09C, \ + .enableMask = (1UL << 1), \ + .enablePos = 1 + +#define WHAL_STM32WBA55_WWDG_CLOCK \ + .regOffset = 0x09C, \ + .enableMask = (1UL << 11), \ + .enablePos = 11 + +#define WHAL_STM32WBA55_USART2_CLOCK \ + .regOffset = 0x09C, \ + .enableMask = (1UL << 17), \ + .enablePos = 17 + +#define WHAL_STM32WBA55_I2C1_CLOCK \ + .regOffset = 0x09C, \ + .enableMask = (1UL << 21), \ + .enablePos = 21 + +/* RCC_APB2ENR (offset 0x0A4) */ +#define WHAL_STM32WBA55_TIM1_CLOCK \ + .regOffset = 0x0A4, \ + .enableMask = (1UL << 11), \ + .enablePos = 11 + +#define WHAL_STM32WBA55_SPI1_CLOCK \ + .regOffset = 0x0A4, \ + .enableMask = (1UL << 12), \ + .enablePos = 12 + +#define WHAL_STM32WBA55_USART1_CLOCK \ + .regOffset = 0x0A4, \ + .enableMask = (1UL << 14), \ + .enablePos = 14 + +#define WHAL_STM32WBA55_TIM16_CLOCK \ + .regOffset = 0x0A4, \ + .enableMask = (1UL << 17), \ + .enablePos = 17 + +#define WHAL_STM32WBA55_TIM17_CLOCK \ + .regOffset = 0x0A4, \ + .enableMask = (1UL << 18), \ + .enablePos = 18 + +/* RCC_APB7ENR (offset 0x0A8) */ +#define WHAL_STM32WBA55_SYSCFG_CLOCK \ + .regOffset = 0x0A8, \ + .enableMask = (1UL << 1), \ + .enablePos = 1 + +#define WHAL_STM32WBA55_SPI3_CLOCK \ + .regOffset = 0x0A8, \ + .enableMask = (1UL << 5), \ + .enablePos = 5 + +#define WHAL_STM32WBA55_LPUART1_CLOCK \ + .regOffset = 0x0A8, \ + .enableMask = (1UL << 6), \ + .enablePos = 6 + +#define WHAL_STM32WBA55_I2C3_CLOCK \ + .regOffset = 0x0A8, \ + .enableMask = (1UL << 7), \ + .enablePos = 7 + +#define WHAL_STM32WBA55_LPTIM1_CLOCK \ + .regOffset = 0x0A8, \ + .enableMask = (1UL << 11), \ + .enablePos = 11 + +#endif /* WHAL_STM32WBA55CG_H */ diff --git a/wolfHAL/rng/stm32wba_rng.h b/wolfHAL/rng/stm32wba_rng.h new file mode 100644 index 0000000..70d8001 --- /dev/null +++ b/wolfHAL/rng/stm32wba_rng.h @@ -0,0 +1,25 @@ +#ifndef WHAL_STM32WBA_RNG_H +#define WHAL_STM32WBA_RNG_H + +#include +#include + +/* + * @file stm32wba_rng.h + * @brief STM32WBA RNG driver configuration. + * + * The RNG kernel clock source must be selected in RCC_CCIPR2.RNGSEL + * before using the RNG. Default after reset is LSE (often not enabled). + */ + +typedef struct whal_Stm32wbaRng_Cfg { + whal_Timeout *timeout; +} whal_Stm32wbaRng_Cfg; + +extern const whal_RngDriver whal_Stm32wbaRng_Driver; + +whal_Error whal_Stm32wbaRng_Init(whal_Rng *rngDev); +whal_Error whal_Stm32wbaRng_Deinit(whal_Rng *rngDev); +whal_Error whal_Stm32wbaRng_Generate(whal_Rng *rngDev, void *rngData, size_t rngDataSz); + +#endif /* WHAL_STM32WBA_RNG_H */ diff --git a/wolfHAL/spi/stm32wba_spi.h b/wolfHAL/spi/stm32wba_spi.h new file mode 100644 index 0000000..915079a --- /dev/null +++ b/wolfHAL/spi/stm32wba_spi.h @@ -0,0 +1,26 @@ +#ifndef WHAL_STM32WBA_SPI_H +#define WHAL_STM32WBA_SPI_H + +/* + * @file stm32wba_spi.h + * @brief STM32WBA SPI driver (alias for STM32H5 SPI). + * + * The STM32WBA SPI peripheral is register-compatible with the STM32H5 SPI. + * This header re-exports the STM32H5 SPI driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32h5Spi_Cfg whal_Stm32wbaSpi_Cfg; + +#ifndef WHAL_CFG_SPI_API_MAPPING_STM32WBA +#define whal_Stm32wbaSpi_Driver whal_Stm32h5Spi_Driver +#define whal_Stm32wbaSpi_Init whal_Stm32h5Spi_Init +#define whal_Stm32wbaSpi_Deinit whal_Stm32h5Spi_Deinit +#define whal_Stm32wbaSpi_StartCom whal_Stm32h5Spi_StartCom +#define whal_Stm32wbaSpi_EndCom whal_Stm32h5Spi_EndCom +#define whal_Stm32wbaSpi_SendRecv whal_Stm32h5Spi_SendRecv +#endif /* !WHAL_CFG_SPI_API_MAPPING_STM32WBA */ + +#endif /* WHAL_STM32WBA_SPI_H */ diff --git a/wolfHAL/uart/stm32wba_uart.h b/wolfHAL/uart/stm32wba_uart.h new file mode 100644 index 0000000..b398134 --- /dev/null +++ b/wolfHAL/uart/stm32wba_uart.h @@ -0,0 +1,31 @@ +#ifndef WHAL_STM32WBA_UART_H +#define WHAL_STM32WBA_UART_H + +/* + * @file stm32wba_uart.h + * @brief STM32WBA UART driver (alias for STM32WB UART). + * + * The STM32WBA USART peripheral is register-compatible with the STM32WB USART. + * This header re-exports the STM32WB UART driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32wbUart_Cfg whal_Stm32wbaUart_Cfg; + +#ifndef WHAL_CFG_UART_API_MAPPING_STM32WBA +#define whal_Stm32wbaUart_Driver whal_Stm32wbUart_Driver +#define whal_Stm32wbaUart_Init whal_Stm32wbUart_Init +#define whal_Stm32wbaUart_Deinit whal_Stm32wbUart_Deinit +#define whal_Stm32wbaUart_Send whal_Stm32wbUart_Send +#define whal_Stm32wbaUart_Recv whal_Stm32wbUart_Recv +#endif /* !WHAL_CFG_UART_API_MAPPING_STM32WBA */ + +/* + * @brief Baud rate register helpers (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_UART_BRR WHAL_STM32WB_UART_BRR +#define WHAL_STM32WBA_LPUART_BRR WHAL_STM32WB_LPUART_BRR + +#endif /* WHAL_STM32WBA_UART_H */ diff --git a/wolfHAL/uart/stm32wba_uart_dma.h b/wolfHAL/uart/stm32wba_uart_dma.h new file mode 100644 index 0000000..66024f0 --- /dev/null +++ b/wolfHAL/uart/stm32wba_uart_dma.h @@ -0,0 +1,51 @@ +#ifndef WHAL_STM32WBA_UART_DMA_H +#define WHAL_STM32WBA_UART_DMA_H + +#include +#include +#include +#include +#include + +/* + * @file stm32wba_uart_dma.h + * @brief STM32WBA UART driver -- GPDMA-backed variant. + * + * Uses the STM32WBA GPDMA controller to move bytes between memory and the + * USART TDR/RDR registers. Init/Deinit reuse the polled UART driver; Send/Recv + * block using DMA; SendAsync/RecvAsync return immediately. + * + * The GPDMA request lines for USART are (RM0493 Table 208): + * REQSEL 11 = USART1_RX + * REQSEL 12 = USART1_TX + * REQSEL 13 = USART2_RX + * REQSEL 14 = USART2_TX + */ + +typedef struct { + whal_Stm32wbUart_Cfg base; + whal_Dma *dma; + size_t txCh; + size_t rxCh; + whal_Stm32wbaGpdma_ChCfg *txChCfg; + whal_Stm32wbaGpdma_ChCfg *rxChCfg; + volatile whal_Error txResult; + volatile whal_Error rxResult; +} whal_Stm32wbaUartDma_Cfg; + +extern const whal_UartDriver whal_Stm32wbaUartDma_Driver; + +whal_Error whal_Stm32wbaUartDma_Send(whal_Uart *uartDev, const void *data, + size_t dataSz); +whal_Error whal_Stm32wbaUartDma_Recv(whal_Uart *uartDev, void *data, + size_t dataSz); +whal_Error whal_Stm32wbaUartDma_SendAsync(whal_Uart *uartDev, const void *data, + size_t dataSz); +whal_Error whal_Stm32wbaUartDma_RecvAsync(whal_Uart *uartDev, void *data, + size_t dataSz); + +/* DMA channel completion callbacks. Pass the UART DMA cfg as ctx. */ +void whal_Stm32wbaUartDma_TxCallback(void *ctx, whal_Error err); +void whal_Stm32wbaUartDma_RxCallback(void *ctx, whal_Error err); + +#endif /* WHAL_STM32WBA_UART_DMA_H */ diff --git a/wolfHAL/watchdog/stm32wba_iwdg.h b/wolfHAL/watchdog/stm32wba_iwdg.h new file mode 100644 index 0000000..2fa00a8 --- /dev/null +++ b/wolfHAL/watchdog/stm32wba_iwdg.h @@ -0,0 +1,35 @@ +#ifndef WHAL_STM32WBA_IWDG_H +#define WHAL_STM32WBA_IWDG_H + +/* + * @file stm32wba_iwdg.h + * @brief STM32WBA IWDG driver (alias for STM32WB IWDG). + * + * The STM32WBA IWDG peripheral is register-compatible with the STM32WB IWDG. + * This header re-exports the STM32WB IWDG driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32wbIwdg_Cfg whal_Stm32wbaIwdg_Cfg; + +#ifndef WHAL_CFG_WATCHDOG_API_MAPPING_STM32WBA_IWDG +#define whal_Stm32wbaIwdg_Driver whal_Stm32wbIwdg_Driver +#define whal_Stm32wbaIwdg_Init whal_Stm32wbIwdg_Init +#define whal_Stm32wbaIwdg_Deinit whal_Stm32wbIwdg_Deinit +#define whal_Stm32wbaIwdg_Refresh whal_Stm32wbIwdg_Refresh +#endif /* !WHAL_CFG_WATCHDOG_API_MAPPING_STM32WBA_IWDG */ + +/* + * @brief Prescaler values (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_IWDG_PR_4 WHAL_STM32WB_IWDG_PR_4 +#define WHAL_STM32WBA_IWDG_PR_8 WHAL_STM32WB_IWDG_PR_8 +#define WHAL_STM32WBA_IWDG_PR_16 WHAL_STM32WB_IWDG_PR_16 +#define WHAL_STM32WBA_IWDG_PR_32 WHAL_STM32WB_IWDG_PR_32 +#define WHAL_STM32WBA_IWDG_PR_64 WHAL_STM32WB_IWDG_PR_64 +#define WHAL_STM32WBA_IWDG_PR_128 WHAL_STM32WB_IWDG_PR_128 +#define WHAL_STM32WBA_IWDG_PR_256 WHAL_STM32WB_IWDG_PR_256 + +#endif /* WHAL_STM32WBA_IWDG_H */ diff --git a/wolfHAL/watchdog/stm32wba_wwdg.h b/wolfHAL/watchdog/stm32wba_wwdg.h new file mode 100644 index 0000000..eab2386 --- /dev/null +++ b/wolfHAL/watchdog/stm32wba_wwdg.h @@ -0,0 +1,36 @@ +#ifndef WHAL_STM32WBA_WWDG_H +#define WHAL_STM32WBA_WWDG_H + +/* + * @file stm32wba_wwdg.h + * @brief STM32WBA WWDG driver (alias for STM32WB WWDG). + * + * The STM32WBA WWDG peripheral is register-compatible with the STM32WB WWDG. + * This header re-exports the STM32WB WWDG driver types and symbols under + * STM32WBA-specific names. + */ + +#include + +typedef whal_Stm32wbWwdg_Cfg whal_Stm32wbaWwdg_Cfg; + +#ifndef WHAL_CFG_WATCHDOG_API_MAPPING_STM32WBA_WWDG +#define whal_Stm32wbaWwdg_Driver whal_Stm32wbWwdg_Driver +#define whal_Stm32wbaWwdg_Init whal_Stm32wbWwdg_Init +#define whal_Stm32wbaWwdg_Deinit whal_Stm32wbWwdg_Deinit +#define whal_Stm32wbaWwdg_Refresh whal_Stm32wbWwdg_Refresh +#endif /* !WHAL_CFG_WATCHDOG_API_MAPPING_STM32WBA_WWDG */ + +/* + * @brief Timebase prescaler values (re-exported from STM32WB). + */ +#define WHAL_STM32WBA_WWDG_TB_1 WHAL_STM32WB_WWDG_TB_1 +#define WHAL_STM32WBA_WWDG_TB_2 WHAL_STM32WB_WWDG_TB_2 +#define WHAL_STM32WBA_WWDG_TB_4 WHAL_STM32WB_WWDG_TB_4 +#define WHAL_STM32WBA_WWDG_TB_8 WHAL_STM32WB_WWDG_TB_8 +#define WHAL_STM32WBA_WWDG_TB_16 WHAL_STM32WB_WWDG_TB_16 +#define WHAL_STM32WBA_WWDG_TB_32 WHAL_STM32WB_WWDG_TB_32 +#define WHAL_STM32WBA_WWDG_TB_64 WHAL_STM32WB_WWDG_TB_64 +#define WHAL_STM32WBA_WWDG_TB_128 WHAL_STM32WB_WWDG_TB_128 + +#endif /* WHAL_STM32WBA_WWDG_H */