Skip to content

Commit adbb915

Browse files
committed
[stm32wb_dma, stm32wb_uart, boards] Add DMA, IRQ, and async UART support for STM32WB
1 parent dccc647 commit adbb915

21 files changed

Lines changed: 1519 additions & 17 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,5 @@ dkms.conf
5959
compile_commands.json
6060

6161
tests/core/test_core
62+
63+
*.pdf

boards/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ build configuration.
1515
| Board | Platform | CPU | Directory |
1616
|-------|----------|-----|-----------|
1717
| Microchip PIC32CZ CA Curiosity Ultra | PIC32CZ | Cortex-M7 | `pic32cz_curiosity_ultra/` |
18-
| ST STM32WB55 Nucleo | STM32WB | Cortex-M4 | `stm32wb55xx_nucleo/` |
18+
| ST NUCLEO-C031C6 | STM32C0 | Cortex-M0+ | `stm32c031_nucleo/` |
19+
| WeAct BlackPill STM32F411 | STM32F4 | Cortex-M4 | `stm32f411_blackpill/` |
20+
| ST NUCLEO-H563ZI | STM32H5 | Cortex-M33 | `stm32h563zi_nucleo/` |
21+
| ST NUCLEO-WB55RG | STM32WB | Cortex-M4 | `stm32wb55xx_nucleo/` |
1922

2023
## Board Directory Contents
2124

boards/stm32wb55xx_nucleo/Makefile.inc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy
99

1010
CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
1111
-ffreestanding -nostdlib -mcpu=cortex-m4 \
12-
-DPLATFORM_STM32WB -MMD -MP
12+
-DPLATFORM_STM32WB -MMD -MP \
13+
$(if $(DMA),-DBOARD_DMA)
1314
LDFLAGS = --omagic -static
1415

1516
LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld
@@ -29,6 +30,9 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/spi.c)
2930
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c)
3031
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c)
3132
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c)
33+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/dma.c)
34+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/irq.c)
35+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/irq/cortex_m_nvic.c)
3236
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32wb_*.c)
3337
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c)
3438

boards/stm32wb55xx_nucleo/board.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <wolfHAL/platform/st/stm32wb55xx.h>
77
#include "peripheral.h"
88

9+
910
/* SysTick timing */
1011
volatile uint32_t g_tick = 0;
1112
volatile uint8_t g_waiting = 0;
@@ -30,6 +31,11 @@ whal_Timeout g_whalTimeout = {
3031
.GetTick = Board_GetTick,
3132
};
3233

34+
/* IRQ */
35+
whal_Irq g_whalIrq = {
36+
WHAL_CORTEX_M4_NVIC_DEVICE,
37+
};
38+
3339
/* Clock */
3440
whal_Clock g_whalClock = {
3541
WHAL_STM32WB55_RCC_PLL_DEVICE,
@@ -155,7 +161,43 @@ whal_Timer g_whalTimer = {
155161
},
156162
};
157163

164+
/* DMA */
165+
#ifdef BOARD_DMA
166+
/* DMA types already available via stm32wb_uart.h included through platform header */
167+
168+
whal_Dma g_whalDma1 = {
169+
WHAL_STM32WB55_DMA1_DEVICE,
170+
.cfg = &(whal_Stm32wbDma_Cfg){WHAL_STM32WB55_DMA1_CFG},
171+
};
172+
173+
static const whal_Stm32wbRcc_Clk g_dmaClock = {WHAL_STM32WB55_DMA1_CLOCK};
174+
static const whal_Stm32wbRcc_Clk g_dmamuxClock = {WHAL_STM32WB55_DMAMUX1_CLOCK};
175+
176+
void DMA1_Channel4_IRQHandler(void)
177+
{
178+
whal_Stm32wbDma_IRQHandler(&g_whalDma1, 3);
179+
}
180+
181+
void DMA1_Channel5_IRQHandler(void)
182+
{
183+
whal_Stm32wbDma_IRQHandler(&g_whalDma1, 4);
184+
}
185+
#endif
186+
158187
/* UART */
188+
#ifdef BOARD_DMA
189+
whal_Uart g_whalUart = {
190+
WHAL_STM32WB55_UART1_DEVICE,
191+
.driver = &whal_Stm32wbUartDma_Driver,
192+
.cfg = &(whal_Stm32wbUartDma_Cfg) {
193+
.brr = WHAL_STM32WB_UART_BRR(64000000, 115200),
194+
.timeout = &g_whalTimeout,
195+
.dma = &g_whalDma1,
196+
.txCh = 3,
197+
.rxCh = 4,
198+
},
199+
};
200+
#else
159201
whal_Uart g_whalUart = {
160202
WHAL_STM32WB55_UART1_DEVICE,
161203

@@ -165,6 +207,7 @@ whal_Uart g_whalUart = {
165207
.brr = WHAL_STM32WB_UART_BRR(64000000, 115200),
166208
},
167209
};
210+
#endif
168211

169212
/* Flash */
170213
whal_Flash g_whalFlash = {
@@ -174,7 +217,7 @@ whal_Flash g_whalFlash = {
174217
.timeout = &g_whalTimeout,
175218

176219
.startAddr = 0x08000000,
177-
.size = 0x100000,
220+
.size = 0x80000, /* 512 KB (upper half reserved for BLE stack) */
178221
},
179222
};
180223

@@ -260,6 +303,26 @@ whal_Error Board_Init(void)
260303
return err;
261304
}
262305

306+
err = whal_Irq_Init(&g_whalIrq);
307+
if (err)
308+
return err;
309+
310+
#ifdef BOARD_DMA
311+
err = whal_Clock_Enable(&g_whalClock, &g_dmaClock);
312+
if (err)
313+
return err;
314+
err = whal_Clock_Enable(&g_whalClock, &g_dmamuxClock);
315+
if (err)
316+
return err;
317+
err = whal_Dma_Init(&g_whalDma1);
318+
if (err)
319+
return err;
320+
321+
/* Enable NVIC interrupts for DMA1 channel 4 (IRQ 14) and channel 5 (IRQ 15) */
322+
whal_Irq_Enable(&g_whalIrq, 14, NULL);
323+
whal_Irq_Enable(&g_whalIrq, 15, NULL);
324+
#endif
325+
263326
err = whal_Gpio_Init(&g_whalGpio);
264327
if (err) {
265328
return err;
@@ -357,6 +420,25 @@ whal_Error Board_Deinit(void)
357420
return err;
358421
}
359422

423+
#ifdef BOARD_DMA
424+
whal_Irq_Disable(&g_whalIrq, 14);
425+
whal_Irq_Disable(&g_whalIrq, 15);
426+
427+
err = whal_Dma_Deinit(&g_whalDma1);
428+
if (err)
429+
return err;
430+
err = whal_Clock_Disable(&g_whalClock, &g_dmamuxClock);
431+
if (err)
432+
return err;
433+
err = whal_Clock_Disable(&g_whalClock, &g_dmaClock);
434+
if (err)
435+
return err;
436+
#endif
437+
438+
err = whal_Irq_Deinit(&g_whalIrq);
439+
if (err)
440+
return err;
441+
360442
/* Disable clocks */
361443
for (size_t i = 0; i < CLOCK_COUNT; i++) {
362444
err = whal_Clock_Disable(&g_whalClock, &g_clocks[i]);

boards/stm32wb55xx_nucleo/board.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern whal_Spi g_whalSpi;
1313
extern whal_Flash g_whalFlash;
1414
extern whal_Rng g_whalRng;
1515
extern whal_Crypto g_whalCrypto;
16+
extern whal_Irq g_whalIrq;
1617

1718
extern whal_Timeout g_whalTimeout;
1819
extern volatile uint32_t g_tick;
@@ -32,8 +33,8 @@ enum {
3233
#define BOARD_LED_PORT_OFFSET 0x400 /* GPIOB */
3334
#define BOARD_LED_PIN_NUM 5
3435
#define BOARD_FLASH_START_ADDR 0x08000000
35-
#define BOARD_FLASH_SIZE 0x100000
36-
#define BOARD_FLASH_TEST_ADDR 0x08080000
36+
#define BOARD_FLASH_SIZE 0x80000 /* 512 KB (upper half reserved for BLE stack) */
37+
#define BOARD_FLASH_TEST_ADDR 0x0807F000
3738
#define BOARD_FLASH_SECTOR_SZ 0x1000
3839

3940
enum {

docs/writing_a_driver.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,51 @@ Receive `dataSz` bytes into the provided buffer. For each byte:
437437
is available
438438
2. Read the byte from the receive data register and store it in the buffer
439439
440+
### SendAsync
441+
442+
Start a non-blocking transmit. Returns immediately after initiating the
443+
transfer. The buffer must remain valid until the transfer completes. The
444+
driver signals completion through a platform-specific mechanism.
445+
446+
Drivers that do not support async should set SendAsync to NULL in the vtable.
447+
The dispatch layer returns WHAL_EINVAL when the caller tries to use a NULL
448+
async function.
449+
450+
### RecvAsync
451+
452+
Start a non-blocking receive. Returns immediately after initiating the
453+
transfer. The buffer must remain valid until the transfer completes.
454+
455+
The async variants are optional — a driver vtable only needs to populate
456+
them if the platform supports non-blocking transfers. Polled-only drivers
457+
leave these NULL.
458+
459+
---
460+
461+
## IRQ
462+
463+
Header: `wolfHAL/irq/irq.h`
464+
465+
The IRQ driver controls an interrupt controller. It provides a
466+
platform-independent way to enable and disable individual interrupt lines.
467+
468+
### Init
469+
470+
Initialize the interrupt controller.
471+
472+
### Deinit
473+
474+
Shut down the interrupt controller.
475+
476+
### Enable
477+
478+
Enable an interrupt line. The `irqCfg` parameter is platform-specific and
479+
can contain settings such as priority. Pass NULL for defaults.
480+
481+
### Disable
482+
483+
Disable an interrupt line.
484+
440485
---
441486
442487
## SPI
@@ -857,6 +902,65 @@ issue the write command and poll for completion with a timeout.
857902

858903
---
859904

905+
## DMA
906+
907+
Header: `wolfHAL/dma/dma.h`
908+
909+
The DMA driver controls a DMA controller. A single device instance represents
910+
one controller, and individual channels are identified by index. Channel
911+
configuration is platform-specific and passed as an opaque pointer.
912+
913+
DMA is a service peripheral — peripheral drivers (UART, SPI) consume it
914+
internally. The application never calls the DMA API directly. Peripheral
915+
drivers receive a `whal_Dma` pointer and channel number through their
916+
configuration struct and use them to set up transfers.
917+
918+
### Init
919+
920+
Initialize the DMA controller. Clear any pending interrupt flags and reset
921+
controller state. The board must enable the DMA controller clock before calling
922+
Init.
923+
924+
### Deinit
925+
926+
Shut down the DMA controller.
927+
928+
### Configure
929+
930+
Configure a DMA channel for transfers. The `chCfg` parameter is a
931+
platform-specific struct containing:
932+
933+
- Transfer direction (memory-to-peripheral, peripheral-to-memory, etc.)
934+
- Source and destination addresses
935+
- Transfer width (8, 16, 32 bit)
936+
- Buffer address and length
937+
- Burst size (if supported)
938+
- Peripheral request mapping (e.g., DMAMUX request ID)
939+
- Completion callback and context pointer
940+
941+
The completion callback runs in ISR context — the DMA driver owns the ISR
942+
entry in the vector table and dispatches to the registered callback when a
943+
channel transfer completes. Peripheral drivers use this to signal transfer
944+
completion without polling.
945+
946+
Configure sets up all channel registers but does not start the transfer.
947+
Call Start to begin. A channel can be reconfigured between transfers (e.g.,
948+
to change the buffer address and length) by calling Configure again.
949+
950+
### Start
951+
952+
Start a previously configured DMA channel. This enables the channel,
953+
beginning the transfer. The channel must have been configured via Configure
954+
before calling Start.
955+
956+
### Stop
957+
958+
Stop a DMA channel. This aborts any in-progress transfer and disables the
959+
channel. The peripheral driver should call Stop in its cleanup path or when
960+
a transfer needs to be cancelled.
961+
962+
---
963+
860964
## EthPhy
861965

862966
Header: `wolfHAL/eth_phy/eth_phy.h`

src/dma/dma.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <wolfHAL/dma/dma.h>
2+
3+
inline whal_Error whal_Dma_Init(whal_Dma *dmaDev)
4+
{
5+
if (!dmaDev || !dmaDev->driver || !dmaDev->driver->Init) {
6+
return WHAL_EINVAL;
7+
}
8+
9+
return dmaDev->driver->Init(dmaDev);
10+
}
11+
12+
inline whal_Error whal_Dma_Deinit(whal_Dma *dmaDev)
13+
{
14+
if (!dmaDev || !dmaDev->driver || !dmaDev->driver->Deinit) {
15+
return WHAL_EINVAL;
16+
}
17+
18+
return dmaDev->driver->Deinit(dmaDev);
19+
}
20+
21+
inline whal_Error whal_Dma_Configure(whal_Dma *dmaDev, size_t ch,
22+
const void *chCfg)
23+
{
24+
if (!dmaDev || !dmaDev->driver || !dmaDev->driver->Configure || !chCfg) {
25+
return WHAL_EINVAL;
26+
}
27+
28+
return dmaDev->driver->Configure(dmaDev, ch, chCfg);
29+
}
30+
31+
inline whal_Error whal_Dma_Start(whal_Dma *dmaDev, size_t ch)
32+
{
33+
if (!dmaDev || !dmaDev->driver || !dmaDev->driver->Start) {
34+
return WHAL_EINVAL;
35+
}
36+
37+
return dmaDev->driver->Start(dmaDev, ch);
38+
}
39+
40+
inline whal_Error whal_Dma_Stop(whal_Dma *dmaDev, size_t ch)
41+
{
42+
if (!dmaDev || !dmaDev->driver || !dmaDev->driver->Stop) {
43+
return WHAL_EINVAL;
44+
}
45+
46+
return dmaDev->driver->Stop(dmaDev, ch);
47+
}

0 commit comments

Comments
 (0)