Skip to content

Commit a0694ae

Browse files
authored
Merge pull request #35 from AlexLanzano/stm32f3
[stm32f3] Implement initial support for stm32f3
2 parents 9c1b142 + dca6275 commit a0694ae

34 files changed

Lines changed: 1700 additions & 26 deletions

.claude/skills/port-stm32-platform/SKILL.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,28 @@ typedef whal_<OrigPlatform><Type>_PinCfg whal_<NewPlatform><Type>_PinCfg;
140140

141141
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/*/<newplatform>_*.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.
142142

143+
**API mapping macros stay in the leaf driver, not in the alias .c.** Most leaf drivers contain a guarded block that aliases the platform-specific function names directly to the generic `whal_<Type>_*` API:
144+
145+
```c
146+
/* in src/<type>/<origplatform>_<type>.c — the LEAF */
147+
#if defined(WHAL_CFG_<TYPE>_API_MAPPING_<ORIGPLATFORM>) || \
148+
defined(WHAL_CFG_<TYPE>_API_MAPPING_<NEWPLATFORM>)
149+
#define whal_<OrigPlatform><Type>_Init whal_<Type>_Init
150+
/* ...one #define per driver entry point... */
151+
#endif
152+
153+
/* ...driver implementation... */
154+
155+
#if !defined(WHAL_CFG_<TYPE>_API_MAPPING_<ORIGPLATFORM>) && \
156+
!defined(WHAL_CFG_<TYPE>_API_MAPPING_<NEWPLATFORM>)
157+
const whal_<Type>Driver whal_<OrigPlatform><Type>_Driver = { ... };
158+
#endif
159+
```
160+
161+
Add the new platform's `WHAL_CFG_<TYPE>_API_MAPPING_<NEWPLATFORM>` macro to **both** guards in the leaf driver. Do **not** translate the macro inside the alias `.c` stub like `#ifdef <NEW> #define <ORIG> #endif` — every leaf has to learn about every alias platform anyway, and putting the recognition in two places (alias shim + leaf driver) creates drift. Keep the alias `.c` as a single `#include` line.
162+
163+
**Alias the leaf directly — never daisy-chain.** If `<origplatform>` itself aliases another driver, alias `<newplatform>` to the **leaf** (the one with the actual implementation), not to the intermediate alias. Two-hop chains (`<new>``<intermediate>``<leaf>`) make every macro recognition twice as painful and obscure the dependency graph. Trace the include chain in the existing `.h` and `.c` files until you find the file with real driver code, and point your new alias at that.
164+
143165
**Test alias** — when a driver is reused via alias AND the original driver already has a platform-specific test file (`tests/<type>/test_<origplatform>_<type>.c`), create a matching test alias at `tests/<type>/test_<newplatform>_<type>.c`:
144166

145167
```c

.github/workflows/boards.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-latest
1212
strategy:
1313
matrix:
14-
board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo]
14+
board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo]
1515
extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"]
1616
include:
1717
- board: stm32wb55xx_nucleo

boards/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ build configuration.
1717
| Microchip PIC32CZ CA Curiosity Ultra | PIC32CZ | Cortex-M7 | `pic32cz_curiosity_ultra/` |
1818
| ST NUCLEO-C031C6 | STM32C0 | Cortex-M0+ | `stm32c031_nucleo/` |
1919
| ST NUCLEO-F091RC | STM32F0 | Cortex-M0 | `stm32f091rc_nucleo/` |
20+
| ST NUCLEO-F302R8 | STM32F3 | Cortex-M4 | `stm32f302r8_nucleo/` |
2021
| WeAct BlackPill STM32F411 | STM32F4 | Cortex-M4 | `stm32f411_blackpill/` |
2122
| ST NUCLEO-H563ZI | STM32H5 | Cortex-M33 | `stm32h563zi_nucleo/` |
2223
| ST NUCLEO-WB55RG | STM32WB | Cortex-M4 | `stm32wb55xx_nucleo/` |
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
2+
3+
PLATFORM = stm32f3
4+
TESTS ?= clock gpio timer flash uart spi
5+
6+
GCC = $(GCC_PATH)arm-none-eabi-gcc
7+
LD = $(GCC_PATH)arm-none-eabi-gcc
8+
OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy
9+
10+
CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
11+
-ffreestanding -nostdlib \
12+
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
13+
-DPLATFORM_STM32F3 -MMD -MP \
14+
-DWHAL_CFG_GPIO_API_MAPPING_STM32F3 \
15+
-DWHAL_CFG_CLOCK_API_MAPPING_STM32F3 \
16+
-DWHAL_CFG_UART_API_MAPPING_STM32F3 \
17+
-DWHAL_CFG_SPI_API_MAPPING_STM32F3 \
18+
-DWHAL_CFG_I2C_API_MAPPING_STM32F3 \
19+
$(if $(filter iwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_IWDG) \
20+
$(if $(filter wwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_WWDG)
21+
LDFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
22+
-ffreestanding -nostartfiles -Wl,--omagic -static
23+
24+
LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld
25+
26+
INCLUDE += -I$(_BOARD_DIR) -I$(WHAL_DIR)/boards/peripheral
27+
28+
BOARD_SOURCE = $(_BOARD_DIR)/ivt.c
29+
BOARD_SOURCE += $(_BOARD_DIR)/board.c
30+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*.c)
31+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/timer.c)
32+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c)
33+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c)
34+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c)
35+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c)
36+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c)
37+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c)
38+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/watchdog.c)
39+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32f3_*.c)
40+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c)
41+
42+
# Peripheral devices
43+
include $(WHAL_DIR)/boards/peripheral/Makefile.inc

boards/stm32f302r8_nucleo/board.c

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
#include <stdint.h>
2+
#include <stddef.h>
3+
#include "board.h"
4+
#include <wolfHAL/platform/st/stm32f302r8.h>
5+
#include "peripheral.h"
6+
7+
volatile uint32_t g_tick = 0;
8+
volatile uint8_t g_waiting = 0;
9+
volatile uint8_t g_tickOverflow = 0;
10+
11+
void SysTick_Handler()
12+
{
13+
uint32_t tickBefore = g_tick++;
14+
if (g_waiting) {
15+
if (tickBefore > g_tick)
16+
g_tickOverflow = 1;
17+
}
18+
}
19+
20+
uint32_t Board_GetTick(void)
21+
{
22+
return g_tick;
23+
}
24+
25+
whal_Timeout g_whalTimeout = {
26+
.timeoutTicks = 1000,
27+
.GetTick = Board_GetTick,
28+
};
29+
30+
/* Clock — PLL at 48 MHz (HSI/2 * 12) */
31+
whal_Clock g_whalClock = {
32+
.regmap = { WHAL_STM32F302_RCC_REGMAP },
33+
34+
.cfg = &(whal_Stm32f3Rcc_Cfg) {
35+
.sysClkSrc = WHAL_STM32F3_RCC_SYSCLK_SRC_PLL,
36+
.pllCfg = &(whal_Stm32f3Rcc_PllCfg) {
37+
.clkSrc = WHAL_STM32F3_RCC_PLLSRC_HSI_DIV2,
38+
.prediv = 1,
39+
.pllmul = 12,
40+
},
41+
},
42+
};
43+
44+
static const whal_Stm32f3Rcc_Clk g_clocks[] = {
45+
{WHAL_STM32F302_GPIOA_CLOCK},
46+
{WHAL_STM32F302_GPIOB_CLOCK},
47+
{WHAL_STM32F302_GPIOC_CLOCK},
48+
{WHAL_STM32F302_USART2_CLOCK},
49+
{WHAL_STM32F302_SPI3_CLOCK},
50+
{WHAL_STM32F302_I2C1_CLOCK},
51+
#ifdef BOARD_WATCHDOG_WWDG
52+
{WHAL_STM32F302_WWDG_CLOCK},
53+
#endif
54+
};
55+
#define CLOCK_COUNT (sizeof(g_clocks) / sizeof(g_clocks[0]))
56+
57+
/* GPIO */
58+
whal_Gpio g_whalGpio = {
59+
.regmap = { WHAL_STM32F302_GPIO_REGMAP },
60+
61+
.cfg = &(whal_Stm32f3Gpio_Cfg) {
62+
.pinCfg = (whal_Stm32f3Gpio_PinCfg[PIN_COUNT]) {
63+
/* LD2 Green LED on PB13 (per UM1724 Figure 14, NUCLEO-F302R8) */
64+
[LED_PIN] = WHAL_STM32F3_GPIO_PIN(
65+
WHAL_STM32F3_GPIO_PORT_B, 13, WHAL_STM32F3_GPIO_MODE_OUT,
66+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_LOW,
67+
WHAL_STM32F3_GPIO_PULL_NONE, 0),
68+
/* USART2 TX on PA2, AF7 */
69+
[UART_TX_PIN] = WHAL_STM32F3_GPIO_PIN(
70+
WHAL_STM32F3_GPIO_PORT_A, 2, WHAL_STM32F3_GPIO_MODE_ALTFN,
71+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
72+
WHAL_STM32F3_GPIO_PULL_UP, 7),
73+
/* USART2 RX on PA3, AF7 */
74+
[UART_RX_PIN] = WHAL_STM32F3_GPIO_PIN(
75+
WHAL_STM32F3_GPIO_PORT_A, 3, WHAL_STM32F3_GPIO_MODE_ALTFN,
76+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
77+
WHAL_STM32F3_GPIO_PULL_UP, 7),
78+
/* SPI3 SCK on PB3, AF6 */
79+
[SPI_SCK_PIN] = WHAL_STM32F3_GPIO_PIN(
80+
WHAL_STM32F3_GPIO_PORT_B, 3, WHAL_STM32F3_GPIO_MODE_ALTFN,
81+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
82+
WHAL_STM32F3_GPIO_PULL_NONE, 6),
83+
/* SPI3 MISO on PB4, AF6 */
84+
[SPI_MISO_PIN] = WHAL_STM32F3_GPIO_PIN(
85+
WHAL_STM32F3_GPIO_PORT_B, 4, WHAL_STM32F3_GPIO_MODE_ALTFN,
86+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
87+
WHAL_STM32F3_GPIO_PULL_NONE, 6),
88+
/* SPI3 MOSI on PB5, AF6 */
89+
[SPI_MOSI_PIN] = WHAL_STM32F3_GPIO_PIN(
90+
WHAL_STM32F3_GPIO_PORT_B, 5, WHAL_STM32F3_GPIO_MODE_ALTFN,
91+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
92+
WHAL_STM32F3_GPIO_PULL_NONE, 6),
93+
/* SPI CS on PB12, output, push-pull */
94+
[SPI_CS_PIN] = WHAL_STM32F3_GPIO_PIN(
95+
WHAL_STM32F3_GPIO_PORT_B, 12, WHAL_STM32F3_GPIO_MODE_OUT,
96+
WHAL_STM32F3_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32F3_GPIO_SPEED_FAST,
97+
WHAL_STM32F3_GPIO_PULL_UP, 0),
98+
/* I2C1 SCL on PB8, AF4, open-drain */
99+
[I2C_SCL_PIN] = WHAL_STM32F3_GPIO_PIN(
100+
WHAL_STM32F3_GPIO_PORT_B, 8, WHAL_STM32F3_GPIO_MODE_ALTFN,
101+
WHAL_STM32F3_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32F3_GPIO_SPEED_FAST,
102+
WHAL_STM32F3_GPIO_PULL_UP, 4),
103+
/* I2C1 SDA on PB9, AF4, open-drain */
104+
[I2C_SDA_PIN] = WHAL_STM32F3_GPIO_PIN(
105+
WHAL_STM32F3_GPIO_PORT_B, 9, WHAL_STM32F3_GPIO_MODE_ALTFN,
106+
WHAL_STM32F3_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32F3_GPIO_SPEED_FAST,
107+
WHAL_STM32F3_GPIO_PULL_UP, 4),
108+
},
109+
.pinCount = PIN_COUNT,
110+
},
111+
};
112+
113+
/* Timer — SysTick at 1 ms */
114+
whal_Timer g_whalTimer = {
115+
.regmap = { WHAL_CORTEX_M4_SYSTICK_REGMAP },
116+
.driver = WHAL_CORTEX_M4_SYSTICK_DRIVER,
117+
118+
.cfg = &(whal_SysTick_Cfg) {
119+
.cyclesPerTick = 48000000 / 1000,
120+
.clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK,
121+
.tickInt = WHAL_SYSTICK_TICKINT_ENABLED,
122+
},
123+
};
124+
125+
/* UART — USART2 at 115200 baud */
126+
whal_Uart g_whalUart = {
127+
.regmap = { WHAL_STM32F302_USART2_REGMAP },
128+
129+
.cfg = &(whal_Stm32f3Uart_Cfg) {
130+
.timeout = &g_whalTimeout,
131+
.brr = WHAL_STM32F3_UART_BRR(48000000, 115200),
132+
},
133+
};
134+
135+
/* SPI — SPI3 */
136+
whal_Spi g_whalSpi = {
137+
.regmap = { WHAL_STM32F302_SPI3_REGMAP },
138+
139+
.cfg = &(whal_Stm32f3Spi_Cfg) {
140+
.pclk = 48000000,
141+
.timeout = &g_whalTimeout,
142+
},
143+
};
144+
145+
/* I2C — I2C1 (HSI at 8 MHz per RCC_CFGR3.I2C1SW reset default) */
146+
whal_I2c g_whalI2c = {
147+
.regmap = { WHAL_STM32F302_I2C1_REGMAP },
148+
149+
.cfg = &(whal_Stm32f3I2c_Cfg) {
150+
.pclk = 8000000,
151+
.timeout = &g_whalTimeout,
152+
},
153+
};
154+
155+
/* Flash — 64 KB */
156+
whal_Flash g_whalFlash = {
157+
.regmap = { WHAL_STM32F302_FLASH_REGMAP },
158+
.driver = WHAL_STM32F302_FLASH_DRIVER,
159+
160+
.cfg = &(whal_Stm32f3Flash_Cfg) {
161+
.startAddr = 0x08000000,
162+
.size = 0x10000,
163+
.timeout = &g_whalTimeout,
164+
},
165+
};
166+
167+
#ifdef BOARD_WATCHDOG_IWDG
168+
whal_Watchdog g_whalWatchdog = {
169+
.regmap = { WHAL_STM32F302_IWDG_REGMAP },
170+
.driver = WHAL_STM32F302_IWDG_DRIVER,
171+
172+
.cfg = &(whal_Stm32f3Iwdg_Cfg) {
173+
.prescaler = WHAL_STM32F3_IWDG_PR_64,
174+
.reload = 500,
175+
.timeout = &g_whalTimeout,
176+
},
177+
};
178+
#elif defined(BOARD_WATCHDOG_WWDG)
179+
whal_Watchdog g_whalWatchdog = {
180+
.regmap = { WHAL_STM32F302_WWDG_REGMAP },
181+
.driver = WHAL_STM32F302_WWDG_DRIVER,
182+
183+
.cfg = &(whal_Stm32f3Wwdg_Cfg) {
184+
.prescaler = 3,
185+
.window = 0x7F,
186+
.counter = 0x7F,
187+
},
188+
};
189+
#endif
190+
191+
void Board_WaitMs(size_t ms)
192+
{
193+
uint32_t startCount = g_tick;
194+
while ((g_tick - startCount) < ms)
195+
;
196+
}
197+
198+
whal_Error Board_Init(void)
199+
{
200+
whal_Error err;
201+
202+
/* Set flash latency before increasing clock speed.
203+
* STM32F3: 0 WS for HCLK <= 24 MHz, 1 WS for 24 < HCLK <= 48 MHz,
204+
* 2 WS for 48 < HCLK <= 72 MHz. */
205+
err = whal_Stm32f3Flash_Ext_SetLatency(&g_whalFlash,
206+
WHAL_STM32F3_FLASH_LATENCY_1);
207+
if (err)
208+
return err;
209+
210+
err = whal_Clock_Init(&g_whalClock);
211+
if (err)
212+
return err;
213+
214+
for (size_t i = 0; i < CLOCK_COUNT; i++) {
215+
err = whal_Clock_Enable(&g_whalClock, &g_clocks[i]);
216+
if (err)
217+
return err;
218+
}
219+
220+
err = whal_Gpio_Init(&g_whalGpio);
221+
if (err)
222+
return err;
223+
224+
err = whal_Uart_Init(&g_whalUart);
225+
if (err)
226+
return err;
227+
228+
err = whal_Spi_Init(&g_whalSpi);
229+
if (err)
230+
return err;
231+
232+
err = whal_I2c_Init(&g_whalI2c);
233+
if (err)
234+
return err;
235+
236+
err = whal_Timer_Init(&g_whalTimer);
237+
if (err)
238+
return err;
239+
240+
err = whal_Timer_Start(&g_whalTimer);
241+
if (err)
242+
return err;
243+
244+
err = Peripheral_Init();
245+
if (err)
246+
return err;
247+
248+
return WHAL_SUCCESS;
249+
}
250+
251+
whal_Error Board_Deinit(void)
252+
{
253+
whal_Error err;
254+
255+
err = Peripheral_Deinit();
256+
if (err)
257+
return err;
258+
259+
err = whal_Timer_Stop(&g_whalTimer);
260+
if (err)
261+
return err;
262+
263+
err = whal_Timer_Deinit(&g_whalTimer);
264+
if (err)
265+
return err;
266+
267+
err = whal_Spi_Deinit(&g_whalSpi);
268+
if (err)
269+
return err;
270+
271+
err = whal_I2c_Deinit(&g_whalI2c);
272+
if (err)
273+
return err;
274+
275+
err = whal_Uart_Deinit(&g_whalUart);
276+
if (err)
277+
return err;
278+
279+
err = whal_Gpio_Deinit(&g_whalGpio);
280+
if (err)
281+
return err;
282+
283+
for (size_t i = 0; i < CLOCK_COUNT; i++) {
284+
err = whal_Clock_Disable(&g_whalClock, &g_clocks[i]);
285+
if (err)
286+
return err;
287+
}
288+
289+
err = whal_Clock_Deinit(&g_whalClock);
290+
if (err)
291+
return err;
292+
293+
return WHAL_SUCCESS;
294+
}

0 commit comments

Comments
 (0)