Skip to content

Commit d7d2e19

Browse files
committed
ports/stm32: Add Zephyr BLE HCI driver and IPCC integration.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 9a8ad56 commit d7d2e19

37 files changed

Lines changed: 1341 additions & 80 deletions

ports/stm32/FreeRTOSConfig.h

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2025 MicroPython Contributors
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
/*
28+
* FreeRTOS Configuration for STM32 MicroPython port
29+
*/
30+
31+
#ifndef FREERTOS_CONFIG_H
32+
#define FREERTOS_CONFIG_H
33+
34+
#include <stdint.h>
35+
36+
// Most STM32 have 4 NVIC priority bits
37+
// This will be overridden by CMSIS if included later
38+
#ifndef __NVIC_PRIO_BITS
39+
#define __NVIC_PRIO_BITS 4
40+
#endif
41+
42+
// Get clock frequency from HAL
43+
extern uint32_t SystemCoreClock;
44+
#define configCPU_CLOCK_HZ (SystemCoreClock)
45+
46+
// Cortex-M interrupt priorities
47+
// STM32F4/F7 have 4 priority bits (0-15), lower number = higher priority
48+
// SysTick and PendSV should be at lowest priority for FreeRTOS
49+
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY (15)
50+
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY (5)
51+
52+
// Derived values (shifted for NVIC registers)
53+
#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - __NVIC_PRIO_BITS))
54+
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - __NVIC_PRIO_BITS))
55+
56+
// ============================================================================
57+
// MANDATORY for MicroPython threading backend
58+
// ============================================================================
59+
60+
#define configSUPPORT_STATIC_ALLOCATION (1)
61+
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS (1)
62+
#define configUSE_MUTEXES (1)
63+
#define configUSE_RECURSIVE_MUTEXES (1)
64+
#define INCLUDE_vTaskDelete (1)
65+
#define INCLUDE_xTaskGetCurrentTaskHandle (1)
66+
67+
// ============================================================================
68+
// Scheduler configuration
69+
// ============================================================================
70+
71+
#define configTICK_RATE_HZ (1000)
72+
#define configUSE_PREEMPTION (1)
73+
#define configUSE_16_BIT_TICKS (0)
74+
#define configMAX_PRIORITIES (8)
75+
#define configMINIMAL_STACK_SIZE (128)
76+
#define configMAX_TASK_NAME_LEN (16)
77+
#define configUSE_TICK_HOOK (1)
78+
#define configUSE_IDLE_HOOK (0)
79+
#define configUSE_TIME_SLICING (1)
80+
81+
// ============================================================================
82+
// Memory configuration
83+
// ============================================================================
84+
85+
// Dynamic allocation enabled for idle/timer tasks
86+
// Python threads use static allocation with GC memory
87+
#define configSUPPORT_DYNAMIC_ALLOCATION (1)
88+
#define configTOTAL_HEAP_SIZE (4096)
89+
90+
// ============================================================================
91+
// Optional features
92+
// ============================================================================
93+
94+
#define configCHECK_FOR_STACK_OVERFLOW (2)
95+
#define INCLUDE_uxTaskGetStackHighWaterMark (1)
96+
#define configUSE_TASK_NOTIFICATIONS (1)
97+
#define configUSE_COUNTING_SEMAPHORES (1)
98+
#define configUSE_QUEUE_SETS (0)
99+
100+
// Timers disabled to save space (enable if needed)
101+
#define configUSE_TIMERS (0)
102+
103+
// ============================================================================
104+
// Include optional function APIs
105+
// ============================================================================
106+
107+
#define INCLUDE_vTaskPrioritySet (1)
108+
#define INCLUDE_uxTaskPriorityGet (1)
109+
#define INCLUDE_vTaskDelay (1)
110+
#define INCLUDE_vTaskDelayUntil (1)
111+
#define INCLUDE_vTaskSuspend (1)
112+
#define INCLUDE_xTaskGetSchedulerState (1)
113+
#define INCLUDE_xTaskResumeFromISR (1)
114+
#define INCLUDE_eTaskGetState (1)
115+
116+
// ============================================================================
117+
// Assert configuration
118+
// ============================================================================
119+
120+
#define configASSERT(x) do { if (!(x)) { __asm volatile ("cpsid i"); for (;;) {} } } while (0)
121+
122+
// ============================================================================
123+
// Cortex-M specific
124+
// ============================================================================
125+
126+
#define configUSE_PORT_OPTIMISED_TASK_SELECTION (1)
127+
128+
// Disable handler installation check - our SVC/PendSV handlers wrap the
129+
// FreeRTOS handlers, so the vector table addresses won't match exactly.
130+
// The wrappers correctly forward to vPortSVCHandler/xPortPendSVHandler.
131+
#define configCHECK_HANDLER_INSTALLATION (0)
132+
133+
// Handler integration note:
134+
// DO NOT define xPortPendSVHandler, xPortSysTickHandler, vPortSVCHandler here.
135+
// The STM32 port keeps its own handlers and calls FreeRTOS functions as needed.
136+
// This preserves existing port functionality (pendsv_dispatch, systick_dispatch, etc).
137+
138+
#endif // FREERTOS_CONFIG_H

ports/stm32/Makefile

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,35 @@ MBOOT_TEXT0_ADDR ?= 0x08000000
5858
include $(TOP)/py/py.mk
5959
include $(TOP)/extmod/extmod.mk
6060

61+
# FreeRTOS threading backend integration
62+
ifeq ($(MICROPY_PY_THREAD),1)
63+
FREERTOS_DIR = $(TOP)/lib/FreeRTOS-Kernel
64+
include $(TOP)/extmod/freertos/freertos.mk
65+
66+
# Architecture-specific FreeRTOS port
67+
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 g4 l4 wb wl))
68+
FREERTOS_PORT_DIR = $(FREERTOS_DIR)/portable/GCC/ARM_CM4F
69+
else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f7 h7 n6))
70+
FREERTOS_PORT_DIR = $(FREERTOS_DIR)/portable/GCC/ARM_CM7/r0p1
71+
else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0))
72+
FREERTOS_PORT_DIR = $(FREERTOS_DIR)/portable/GCC/ARM_CM0
73+
else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f1 f2 l1))
74+
FREERTOS_PORT_DIR = $(FREERTOS_DIR)/portable/GCC/ARM_CM3
75+
else
76+
$(error Unsupported MCU_SERIES for FreeRTOS: $(MCU_SERIES))
77+
endif
78+
79+
SRC_C += $(FREERTOS_PORT_DIR)/port.c
80+
SRC_C += freertos_hooks.c
81+
INC += -I$(FREERTOS_PORT_DIR)
82+
INC += -I$(FREERTOS_DIR)/include
83+
CFLAGS += -DMICROPY_PY_THREAD=1
84+
endif
85+
6186
GIT_SUBMODULES += lib/libhydrogen lib/stm32lib lib/tinyusb
87+
ifeq ($(MICROPY_PY_THREAD),1)
88+
GIT_SUBMODULES += lib/FreeRTOS-Kernel
89+
endif
6290

6391
CROSS_COMPILE ?= arm-none-eabi-
6492
LD_DIR=boards
@@ -114,7 +142,7 @@ INC += -I$(TOP)/lib/tinyusb/src
114142
INC += -I$(TOP)/shared/tinyusb/
115143
INC += -Ilwip_inc
116144

117-
CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
145+
CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
118146
CFLAGS += -D$(CMSIS_MCU) -DUSE_FULL_LL_DRIVER
119147
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
120148
CFLAGS += $(COPT)
@@ -258,14 +286,12 @@ SRC_C += \
258286
mphalport.c \
259287
msc_disk.c \
260288
mpnetworkport.c \
261-
mpthreadport.c \
262289
irq.c \
263290
pendsv.c \
264291
systick.c \
265292
powerctrl.c \
266293
powerctrlboot.c \
267294
rfcore.c \
268-
pybthread.c \
269295
factoryreset.c \
270296
timer.c \
271297
led.c \
@@ -318,6 +344,11 @@ SRC_C += \
318344
xspi.c \
319345
$(wildcard $(BOARD_DIR)/*.c)
320346

347+
# Threading backend - use pybthread when FreeRTOS not enabled
348+
ifneq ($(MICROPY_PY_THREAD),1)
349+
SRC_C += mpthreadport.c pybthread.c
350+
endif
351+
321352
SRC_O += \
322353
$(STARTUP_FILE) \
323354
$(SYSTEM_FILE)
@@ -494,6 +525,15 @@ SRC_C += mpbtstackport.c
494525
MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
495526
endif
496527

528+
ifeq ($(MICROPY_BLUETOOTH_ZEPHYR),1)
529+
SRC_C += mpzephyrport.c
530+
# Define STM32 port flag for Zephyr BLE CMSIS header selection
531+
CFLAGS += -D__ZEPHYR_BLE_STM32_PORT__
532+
# Enable L2CAP channels (must be passed as CFLAGS for Zephyr sources)
533+
CFLAGS += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1
534+
include $(TOP)/extmod/zephyr_ble/zephyr_ble.mk
535+
endif
536+
497537
endif # MICROPY_PY_BLUETOOTH
498538

499539
# Add stm32-specific implementation of libmetal (and optionally OpenAMP's rproc).
@@ -521,6 +561,16 @@ OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o))
521561
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
522562
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
523563
OBJ += $(GEN_PINS_SRC:.c=.o)
564+
ifeq ($(MICROPY_PY_THREAD),1)
565+
OBJ += $(addprefix $(BUILD)/, $(SRC_FREERTOS_C:.c=.o))
566+
endif
567+
568+
# Zephyr BLE third-party sources are added to SRC_THIRDPARTY_C by zephyr_ble.mk
569+
# after extmod.mk has already processed SRC_THIRDPARTY_C into PY_O.
570+
# Add them explicitly here since they won't be in PY_O.
571+
ifeq ($(MICROPY_BLUETOOTH_ZEPHYR),1)
572+
OBJ += $(addprefix $(BUILD)/, $(SRC_THIRDPARTY_C:.c=.o))
573+
endif
524574

525575
# This file contains performance critical functions so turn up the optimisation
526576
# level. It doesn't add much to the code size and improves performance a bit.
@@ -681,7 +731,7 @@ $(BUILD)/firmware-trusted.bin: $(BUILD)/firmware.bin
681731
$(STM32_CUBE_PROGRAMMER)/bin/STM32_SigningTool_CLI -bin $^ -nk -of 0x80000000 -t fsbl -o $@ -hv $(STM32_N6_HEADER_VERSION)
682732

683733
# List of sources for qstr extraction
684-
SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(GEN_PINS_SRC)
734+
SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(GEN_PINS_SRC) $(SRC_FREERTOS_C)
685735

686736
# Making OBJ use an order-only dependency on the generated pins.h file
687737
# has the side effect of making the pins.h file before we actually compile

ports/stm32/adc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,7 @@
134134
defined(STM32F407xx) || defined(STM32F417xx) || \
135135
defined(STM32F401xC) || defined(STM32F401xE)
136136
#define VBAT_DIV (2)
137-
#elif defined(STM32F411xE) || \
138-
defined(STM32F412Cx) || defined(STM32F412Rx) || \
139-
defined(STM32F412Vx) || defined(STM32F412Zx) || \
137+
#elif defined(STM32F411xE) || defined(STM32F412Zx) || \
140138
defined(STM32F413xx) || defined(STM32F427xx) || \
141139
defined(STM32F429xx) || defined(STM32F437xx) || \
142140
defined(STM32F439xx) || defined(STM32F446xx) || \
@@ -156,7 +154,7 @@
156154
defined(STM32H743xx) || defined(STM32H747xx) || \
157155
defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \
158156
defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || \
159-
defined(STM32H750xx) || defined(STM32H753xx)
157+
defined(STM32H750xx)
160158
#define VBAT_DIV (4)
161159
#elif defined(STM32L432xx) || \
162160
defined(STM32L451xx) || defined(STM32L452xx) || \

ports/stm32/boards/NUCLEO_F412ZG/mpconfigboard.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
MCU_SERIES = f4
22
CMSIS_MCU = STM32F412Zx
33
AF_FILE = boards/stm32f412_af.csv
4-
LD_FILES = boards/stm32f412xg.ld boards/common_ifs.ld
4+
LD_FILES = boards/stm32f412zx.ld boards/common_ifs.ld
55
TEXT0_ADDR = 0x08000000
66
TEXT1_ADDR = 0x08020000
77

ports/stm32/boards/NUCLEO_G474RE/mpconfigboard.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
#define MICROPY_HW_HAS_SWITCH (1)
1010
#define MICROPY_HW_HAS_FLASH (0) // QSPI extflash not mounted
1111

12+
#define MICROPY_PY_ASYNCIO (0)
13+
#define MICROPY_PY_DEFLATE (0)
14+
#define MICROPY_PY_BINASCII (0)
15+
#define MICROPY_PY_HASHLIB (0)
16+
#define MICROPY_PY_JSON (0)
17+
#define MICROPY_PY_RE (0)
18+
#define MICROPY_PY_FRAMEBUF (0)
19+
#define MICROPY_PY_SOCKET (0)
20+
#define MICROPY_PY_NETWORK (0)
21+
1222
// The board has an 24MHz HSE, the following gives 170MHz CPU speed
1323
#define MICROPY_HW_CLK_PLLM (6)
1424
#define MICROPY_HW_CLK_PLLN (85)

ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.mk

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,3 @@ MICROPY_VFS_LFS2 = 1
2424
MICROPY_HW_ENABLE_ISR_UART_FLASH_FUNCS_IN_RAM = 1
2525

2626
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
27-
28-
# Flash tool configuration
29-
OPENOCD_CONFIG = boards/openocd_stm32h7_dual_bank.cfg

ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ void NUCLEO_H743ZI_board_early_init(void);
1717
#define MICROPY_HW_CLK_PLLM (4)
1818
#define MICROPY_HW_CLK_PLLN (400)
1919
#define MICROPY_HW_CLK_PLLP (2)
20-
#define MICROPY_HW_CLK_PLLQ (8)
20+
#define MICROPY_HW_CLK_PLLQ (4)
2121
#define MICROPY_HW_CLK_PLLR (2)
2222
#define MICROPY_HW_CLK_PLLVCI (RCC_PLL1VCIRANGE_1)
2323
#define MICROPY_HW_CLK_PLLVCO (RCC_PLL1VCOWIDE)
@@ -37,16 +37,14 @@ void NUCLEO_H743ZI_board_early_init(void);
3737
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
3838

3939
// UART config
40-
#define MICROPY_HW_UART1_TX (pin_B6)
41-
#define MICROPY_HW_UART1_RX (pin_B15)
4240
#define MICROPY_HW_UART2_TX (pin_D5)
4341
#define MICROPY_HW_UART2_RX (pin_D6)
4442
#define MICROPY_HW_UART2_RTS (pin_D4)
4543
#define MICROPY_HW_UART2_CTS (pin_D3)
4644
#define MICROPY_HW_UART3_TX (pin_D8)
4745
#define MICROPY_HW_UART3_RX (pin_D9)
48-
// #define MICROPY_HW_UART5_TX (pin_B6) // conflict with UART1_TX
49-
// #define MICROPY_HW_UART5_RX (pin_B12) // conflict with Ethernet MII mode
46+
#define MICROPY_HW_UART5_TX (pin_B6)
47+
#define MICROPY_HW_UART5_RX (pin_B12)
5048
#define MICROPY_HW_UART6_TX (pin_C6)
5149
#define MICROPY_HW_UART6_RX (pin_C7)
5250
#define MICROPY_HW_UART7_TX (pin_F7)

ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,3 @@ MICROPY_VFS_LFS2 = 1
2424
MICROPY_HW_ENABLE_ISR_UART_FLASH_FUNCS_IN_RAM = 1
2525

2626
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
27-
28-
# Flash tool configuration
29-
OPENOCD_CONFIG = boards/openocd_stm32h7_dual_bank.cfg

ports/stm32/boards/NUCLEO_H743ZI/pins.csv

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ USB_VBUS,PA9
105105
USB_ID,PA10
106106
USB_DM,PA11
107107
USB_DP,PA12
108-
UART1_TX,PB6
109-
UART1_RX,PB15
110108
UART2_TX,PD5
111109
UART2_RX,PD6
112110
UART2_RTS,PD4

ports/stm32/boards/NUCLEO_H743ZI2/pins.csv

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ USB_VBUS,PA9
105105
USB_ID,PA10
106106
USB_DM,PA11
107107
USB_DP,PA12
108-
UART1_TX,PB6
109-
UART1_RX,PB15
110108
UART2_TX,PD5
111109
UART2_RX,PD6
112110
UART2_RTS,PD4

0 commit comments

Comments
 (0)