一. 为什么要实施BSP瘦身计划
当前RT-Thread仓库中BSP和.git内容占比约90%,而RT-Thread核心代码及文档仅占约100MB,约为3%。为进一步优化用户体验,我们计划了对现有BSP结构进行改进。过去,为了实现开箱即用的快速开发,HAL库被集成到BSP中,但随着支持的芯片和BSP数量增加,包体体积显著增长,且部分HAL内容可能未被充分利用。
为此,我们提出优化方案:将厂商SDK以软件包形式提供,保留RT-Thread的适配接口,用户可根据需求灵活选择所需芯片的SDK并集成到BSP中。这样既保持了快速开发的便利性,又显著减小了包体体积,让RT-Thread更轻量、高效,满足多样化的芯片应用场景。
本指南以stm32为例。
二. 操作流程
操作流程大致可以分为三步。以 stm32f4 为例。
(一). 软件包索引仓库更新
软件包目前统一放到下面的目录中,bsp中默认选中即可。
https://github.com/RT-Thread/packages/tree/master/peripherals/hal-sdk
1.fork一份软件包索引仓库
仓库地址:RT-Thread/packages: packages index repository for rt-thread.

2.将fork的仓库克隆到本地
git clone https://github.com/fengmuyou/packages.git

3. 打开本地仓库进行修改
在本地打开克隆的索引仓库,创建一个新的分支,在packages\peripherals\hal-sdk路径下创建stm32文件夹
git checkout -b "f4_hal" //创建一个新分支

4. 添加stm32f4索引文件夹
在stm32下添加stm32f4_cmsis_driver文件夹和stm32f4_hal_driver文件夹,在两个文件夹下分别添加Kconfig、package.json这两个文件
stm32f4_cmsis_drivers
1.Kconfig
# Kconfig file for package stm32f4_cmsis_drivermenuconfig PKG_USING_STM32F4_CMSIS_DRIVER bool "STM32 F4 CMSIS driver package" select PKG_USING_CMSIS_CORE default nif PKG_USING_STM32F4_CMSIS_DRIVER config PKG_STM32F4_CMSIS_DRIVER_PATH string default "/packages/peripherals/hal-sdk/stm32/stm32f4_cmsis_driver" choice prompt "Version" help Select the package version config PKG_USING_STM32F4_CMSIS_DRIVER_LATEST_VERSION bool "latest" endchoice config PKG_STM32F4_CMSIS_DRIVER_VER string default "latest" if PKG_USING_STM32F4_CMSIS_DRIVER_LATEST_VERSIONendif
2.package.json
{ "name": "stm32f4_cmsis_driver", "description": "STM32 F4 CMSIS driver package", "description_zh": "STM32 F4 CMSIS 驱动包", "enable": "PKG_USING_STM32F4_CMSIS_DRIVER", "keywords": [ "stm32f4_cmsis_driver", "STM32" ], "category": "peripherals", "author": { "name": "RT-Thread-packages", "email": "package_team@rt-thread.com", "github": "RT-Thread-packages" }, "license": "Apache-2.0", "repository": "https://github.com/RT-Thread-packages/stm32f4_cmsis_driver", "icon": "unknown", "homepage": "https://github.com/RT-Thread-packages/stm32f4_cmsis_driver#readme", "doc": "unknown", "site": [ { "version": "latest", "URL": "https://github.com/RT-Thread-packages/stm32f4_cmsis_driver.git", "filename": "", "VER_SHA": "master" } ]}
stm32f4_hal_driver
1.Kconfig
# Kconfig file for package stm32f4_hal_drivermenuconfig PKG_USING_STM32F4_HAL_DRIVER bool "STM32 F4 HAL driver package" select PKG_USING_STM32F4_CMSIS_DRIVER default nif PKG_USING_STM32F4_HAL_DRIVER config PKG_STM32F4_HAL_DRIVER_PATH string default "/packages/peripherals/hal-sdk/stm32/stm32f4_hal_driver" choice prompt "Version" help Select the package version config PKG_USING_STM32F4_HAL_DRIVER_LATEST_VERSION bool "latest" endchoice config PKG_STM32F4_HAL_DRIVER_VER string default "latest" if PKG_USING_STM32F4_HAL_DRIVER_LATEST_VERSIONendif
2.package.json
{ "name": "stm32f4_hal_driver", "description": "STM32 F4 HAL driver package", "description_zh": "STM32 F4 HAL 驱动包", "enable": "PKG_USING_STM32F4_HAL_DRIVER", "keywords": [ "stm32f4_hal_driver", "STM32" ], "category": "peripherals", "author": { "name": "RT-Thread-packages", "email": "package_team@rt-thread.com", "github": "RT-Thread-packages" }, "license": "BSD-3-Clause", "repository": "https://github.com/RT-Thread-packages/stm32f4_hal_driver", "icon": "unknown", "homepage": "https://github.com/RT-Thread-packages/stm32f4_hal_driver#readme", "doc": "unknown", "site": [ { "version": "latest", "URL": "https://github.com/RT-Thread-packages/stm32f4_hal_driver.git", "filename": "", "VER_SHA": "master" } ]}
注意!!!:仓库地址要保证正确,软件包才能正确地被拉下来。

5. 修改Kconfig文件
在stm32文件夹下的 Kconfig 文件里添加配置,确保能找到对应的Kconfig文件

6. 工作流文件修改
在workflows/aciont_tool.yml 文件里添加 pkgs --update,这个修改一次即可,后续添加其他软件包索引不用再修改。

7. 修改完之后进行提交
git add . git commit -m "add stm32_f4 软件包仓库索引"git push origin f4_hal
8. 创建pr,等待审核合并。
(二). 软件包仓库更新
1. 软件包分为cmsis与drivers
首先就是分别 fork cmsis 与 drivers 两个软件包仓库,并克隆仓库到本地,在本地创建一个新分支再进行修改。
2. 适配stm32f4_cmsis_driver
创建一个新的分支
git checkout -b f4_cmsis //创建一个新分支
添加 SConscript 文件
添加启动文件选择以及system_stm32f4xx.c文件,芯片型号宏定义在 stm32f4xx.h 文件下可以找到。
from building import *import os# Import environment variablesImport('env')# Get the current working directorycwd = GetCurrentDir()# Initialize include paths and source files listpath = [os.path.join(cwd, 'Include')]src = [os.path.join(cwd, 'Source', 'Templates', 'system_stm32f4xx.c')]# Map microcontroller units (MCUs) to their corresponding startup filesmcu_startup_files = { 'STM32F401xC': 'startup_stm32f401xc.s', 'STM32F401xE': 'startup_stm32f401xe.s', 'STM32F405xx': 'startup_stm32f405xx.s', 'STM32F407xx': 'startup_stm32f407xx.s', 'STM32F410Cx': 'startup_stm32f410cx.s', 'STM32F410Rx': 'startup_stm32f410rx.s', 'STM32F410Tx': 'startup_stm32f410tx.s', 'STM32F411xE': 'startup_stm32f411xe.s', 'STM32F412Cx': 'startup_stm32f412cx.s', 'STM32F412Rx': 'startup_stm32f412rx.s', 'STM32F412Vx': 'startup_stm32f412vx.s', 'STM32F412Zx': 'startup_stm32f412zx.s', 'STM32F413xx': 'startup_stm32f413xx.s', 'STM32F415xx': 'startup_stm32f415xx.s', 'STM32F417xx': 'startup_stm32f417xx.s', 'STM32F423xx': 'startup_stm32f423xx.s', 'STM32F427xx': 'startup_stm32f427xx.s', 'STM32F429xx': 'startup_stm32f429xx.s', 'STM32F437xx': 'startup_stm32f437xx.s', 'STM32F439xx': 'startup_stm32f439xx.s', 'STM32F446xx': 'startup_stm32f446xx.s', 'STM32F469xx': 'startup_stm32f469xx.s', 'STM32F479xx': 'startup_stm32f479xx.s',}# Check each defined MCU, match the platform and append the appropriate startup filefor mcu, startup_file in mcu_startup_files.items(): if mcu in env.get('CPPDEFINES', []): if rtconfig.PLATFORM in ['gcc', 'llvm-arm']: src += [os.path.join(cwd, 'Source', 'Templates', 'gcc', startup_file)] elif rtconfig.PLATFORM in ['armcc', 'armclang']: src += [os.path.join(cwd, 'Source', 'Templates', 'arm', startup_file)] elif rtconfig.PLATFORM in ['iccarm']: src += [os.path.join(cwd, 'Source', 'Templates', 'iar', startup_file)] break# Define the build groupgroup = DefineGroup('STM32F4-CMSIS', src, depend=['PKG_USING_STM32F4_CMSIS_DRIVER'], CPPPATH=path)# Return the build groupReturn('group')
添加stm32_update.py文件,并运行,对启动文件进行修改
python stm32_update.py //运行stm32_update.py
# Copyright (c) 2006-2022, RT-Thread Development Team## SPDX-License-Identifier: Apache-2.0## Change Logs:# Date Author Notes# 2021-10-11 Meco Man First version# This file is suggested to use under Linux environment.# > python stm32_update.py# update STM32 startup assembly language file:# 1.replace main to entry (GCC)# 2.reduce the heap size as 0x000 (Keil IAR)# 3.extend the GCC stack size as 0x400, which is the same as Keil and IAR startup files.import osimport re# replace 'bl main' to 'bl entry'def stm32update_main2entry(path): oldline = '' newline = '' for root, dirs, files in os.walk(path): for file in files: if os.path.splitext(file)[1] == '.s': # find .s files (Keil MDK) file_path = os.path.join(root,file) flag_need_replace = False with open(file_path,'r+',) as f: while True: line = f.readline() if line == '': break elif ('bl' in line) and ('main' in line): # find 'bl main' oldline = line # bl main newline = line.replace('main', 'entry') # use 'entry' to replace 'main' flag_need_replace = True # mark that need to be replaced break if (flag_need_replace == True): # use 'entry' to replace 'main' f.seek(0) content = f.read() f.seek(0) f.truncate() newcontent = content.replace(oldline, newline) f.write(newcontent)#reduce the heap size as 0x000def stm32update_heap2zero(path): oldline = '' newline = '' for root, dirs, files in os.walk(path): for file in files: file_path = os.path.join(root,file) if os.path.splitext(file)[1] == '.s': # find .s files (Keil MDK) with open(file_path,'r+',) as f: flag_need_replace = False while True: line = f.readline() if line == '': break re_result = re.match('\\s*Heap_Size\\s+EQU\\s+0[xX][0-9a-fA-F]+', line) if re_result != None: oldline = line newline = re.sub('0[xX][0-9a-fA-F]+','0x00000000', oldline) flag_need_replace = True break if flag_need_replace == True: f.seek(0) content = f.read() f.seek(0) f.truncate() newcontent = content.replace(oldline, newline) f.write(newcontent) elif os.path.splitext(file)[1] == '.icf': # find .icf files (IAR) with open(file_path,'r+',) as f: flag_need_replace = False while True: line = f.readline() if line == '': break re_result = re.match('\\s*define\\s+symbol\\s+__ICFEDIT_size_heap__\\s*=\\s*0[xX][0-9a-fA-F]+', line) if re_result != None: oldline = line newline = re.sub('0[xX][0-9a-fA-F]+','0x000', oldline) flag_need_replace = True break if flag_need_replace == True: f.seek(0) content = f.read() f.seek(0) f.truncate() newcontent = content.replace(oldline, newline) f.write(newcontent) elif os.path.splitext(file)[1] == '.lds': # find .lds files (GCC) with open(file_path,'r+',) as f: flag_need_replace = False while True: line = f.readline() if line == '': break re_result = re.match('\\s*_system_stack_size\\s*=\\s*0[xX][0-9a-fA-F]+', line) if re_result != None: oldline = line newline = re.sub('0[xX][0-9a-fA-F]+','0x400', oldline) flag_need_replace = True break if flag_need_replace == True: f.seek(0) content = f.read() f.seek(0) f.truncate() newcontent = content.replace(oldline, newline) f.write(newcontent)def stm32_update(path): stm32update_main2entry(path) stm32update_heap2zero(path)if __name__ == "__main__": stm32_update(os.getcwd()) print("STM32 startup assembly language file update successfully!")
ps:对启动文件修改主要是将gcc下启动文件的入口函数由 main 改成 entry。

以及将arm下启动文件的堆的大小改为0。

修改完成后提交
git add . git commit -m "adapt stm32f4 cmsis for rtt"git push origin f4_cmsis
创建pr,等待审核合并。
3. 适配stm32f4_hal_driver
创建一个新的分支
git checkout -b f4_drivers //创建一个新分支
添加 SConscript 文件,可根据 rt-thread\bsp\stm32\libraries\STM32F4xx_HAL 文件夹下的 SConscript 对应着修改,改变文件引用的路径。
from building import *import oscwd = GetCurrentDir()path = [os.path.join(cwd, 'Inc')]src_path = os.path.join(cwd, 'Src')path += [os.path.join(cwd, 'Inc/Legacy')]CPPDEFINES = ['USE_HAL_DRIVER']src = [os.path.join(src_path, 'stm32f4xx_hal.c'),os.path.join(src_path, 'stm32f4xx_hal_cec.c'),os.path.join(src_path, 'stm32f4xx_hal_cortex.c'),os.path.join(src_path, 'stm32f4xx_hal_crc.c'),os.path.join(src_path, 'stm32f4xx_hal_cryp.c'),os.path.join(src_path, 'stm32f4xx_hal_cryp_ex.c'),os.path.join(src_path, 'stm32f4xx_hal_dma.c'),os.path.join(src_path, 'stm32f4xx_hal_dma_ex.c'),os.path.join(src_path, 'stm32f4xx_hal_pwr.c'),os.path.join(src_path, 'stm32f4xx_hal_pwr_ex.c'),os.path.join(src_path, 'stm32f4xx_hal_rcc.c'),os.path.join(src_path, 'stm32f4xx_hal_rcc_ex.c'),os.path.join(src_path, 'stm32f4xx_hal_rng.c'),os.path.join(src_path, 'stm32f4xx_hal_gpio.c'),]if GetDepend(['RT_USING_SERIAL']) or GetDepend(['RT_USING_NANO', 'RT_USING_CONSOLE']): src += [os.path.join(src_path, 'stm32f4xx_hal_uart.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_usart.c')]if GetDepend(['RT_USING_I2C']): src += [os.path.join(src_path, 'stm32f4xx_hal_i2c.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_i2c_ex.c')]if GetDepend(['RT_USING_SPI']): src += [os.path.join(src_path, 'stm32f4xx_hal_spi.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_qspi.c')]if GetDepend(['RT_USING_USB']): src += [os.path.join(src_path, 'stm32f4xx_hal_pccard.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_pcd.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_pcd_ex.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_hcd.c')] src += [os.path.join(src_path, 'stm32f4xx_ll_usb.c')]if GetDepend(['RT_USING_CAN']): src += [os.path.join(src_path, 'stm32f4xx_hal_can.c')]if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']) or GetDepend(['RT_USING_PULSE_ENCODER']): src += [os.path.join(src_path, 'stm32f4xx_hal_tim.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_tim_ex.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_lptim.c')]if GetDepend(['BSP_USING_ETH']): if GetDepend(['BSP_ETH_LEGACY_MODULE_ENABLED']): src += [os.path.join(src_path, 'Legacy/stm32f4xx_hal_eth.c')] else: src += [os.path.join(src_path, 'stm32f4xx_hal_eth.c')]if GetDepend(['RT_USING_ADC']): src += [os.path.join(src_path, 'stm32f4xx_hal_adc.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_adc_ex.c')]if GetDepend(['RT_USING_DAC']): src += [os.path.join(src_path, 'stm32f4xx_hal_dac.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_dac_ex.c')]if GetDepend(['RT_USING_RTC']): src += [os.path.join(src_path, 'stm32f4xx_hal_rtc.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_rtc_ex.c')]if GetDepend(['RT_USING_WDT']): src += [os.path.join(src_path, 'stm32f4xx_hal_iwdg.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_wwdg.c')]if GetDepend(['RT_USING_SDIO']): src += [os.path.join(src_path, 'stm32f4xx_ll_sdmmc.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_sd.c')]if GetDepend(['RT_USING_AUDIO']): src += [os.path.join(src_path, 'stm32f4xx_hal_i2s.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_i2s_ex.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_sai.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_sai_ex.c')]if GetDepend(['RT_USING_MTD_NOR']): src += [os.path.join(src_path, 'stm32f4xx_hal_nor.c')]if GetDepend(['RT_USING_MTD_NAND']): src += [os.path.join(src_path, 'stm32f4xx_hal_nand.c')]if GetDepend(['BSP_USING_FMC']): src += [os.path.join(src_path, 'stm32f4xx_ll_fmc.c')] src += [os.path.join(src_path, 'stm32f4xx_ll_fsmc.c')]if GetDepend(['BSP_USING_SDRAM']): src += [os.path.join(src_path, 'stm32f4xx_hal_sdram.c')]if GetDepend(['BSP_USING_EXT_FMC_IO']): src += [os.path.join(src_path, 'stm32f4xx_hal_sram.c')]if GetDepend(['BSP_USING_ON_CHIP_FLASH']): src += [os.path.join(src_path, 'stm32f4xx_hal_flash.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_flash_ex.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_flash_ramfunc.c')]if GetDepend(['BSP_USING_LTDC']): src += [os.path.join(src_path, 'stm32f4xx_hal_ltdc.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_ltdc_ex.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_dma2d.c')] src += [os.path.join(src_path, 'stm32f4xx_ll_dma2d.c')] src += [os.path.join(src_path, 'stm32f4xx_hal_dsi.c')]group = DefineGroup('STM32F4-HAL', src, depend = ['PKG_USING_STM32F4_HAL_DRIVER'], CPPPATH = path, CPPDEFINES = CPPDEFINES)Return('group')
修改完成后提交
git add .git commit -m "adapt stm32f4 drivers for rtt"git push origin f4_drivers
创建pr,等待审核合并。
(三). 主线仓库更新
这里bsp的修改以stm32f407-rt-spark为例,具体的需要把f4系列所有的bsp都进行修改,编译测试通过后再提交。
1. 准备工作
fork 一份最新的主线仓库,克隆到本地,基于master分支创建一个新的分支。
创建一个新的分支
git checkout -b f4_sdk
2. 在主线仓库目录(bsp\stm32\libraries\Kconfig)中 select PKG_USING_STM32xx_HAL_DRIVER

3. 修改SConstruct文件

4. board文件夹下的SConscript

5. 在port文件夹下添加SConscript文件

ps: stm32f407-rt-spark 的 port 文件夹下有SConscript文件,我们只需简单的修改即可。有些bsp的port文件下没有SConscript文件,需要我们自己添加,可以参考这里进行修。
6. 在 README.md 文件添加说明
在快速上手下添加说明
中文版本
**请注意!!!**在执行编译工作前请先打开ENV执行以下指令(该指令用于拉取必要的HAL库及CMSIS库,否则无法通过编译):```bashpkgs --update```
英文版本
**Attention please!!!**Before the compilation work, please open ENV and execute the following command (this command is used to pull the necessary HAL library and CMSIS library, otherwise it cannot be compiled):```bashpkgs --update```
7.编译结果
确保能编译 packages 下的 f4_hal 文件

8. 烧录测试
将rt-thread.elf文件烧录到板子上,观察是否能够正常运行。

ps:板子支持的一些外设也需要在env中开启,进行编译测试。
9. 删除主线上的STM32F4_HAL驱动
ps: 请把f4系列所有的bsp都进行修改,测试通过后在删除主线上的 STM32F4_HAL 驱动。

10.修改工作流文件
在workflows/aciont_tool.yml 文件里添加 pkgs --update,这个修改一次即可,后续添加其他修改其他bsp不用再修改。

11.提交到远程仓库
全部测试没问题后,提交的远程仓库。
git add .git commit -m "bsp:Separate STM32F4 HAL drivers"git push origin f4_sdk
12. 创建pr,等待审核合并。
全部0条评论
快来发表一下你的评论吧 !