BSP Slimming Guide | Technical Assembly
1. Why We Implement the BSP Slimming Plan
Currently, in the RT-Thread repository, BSPs and the .git content account for approximately 90%, while the RT-Thread core code and documentation only occupy about 100MB, roughly 3%. To further improve user experience, we plan to optimize the existing BSP structure. In the past, to enable quick development out of the box, the HAL library was integrated into the BSP. However, as the supported chips and BSPs increased, the package size grew significantly, and some HAL content might not be fully utilized.
Therefore, we propose an optimization: providing vendor SDKs as software packages while retaining RT-Thread’s adaptation interfaces. Users can select and integrate only the SDKs needed for their chips, making the BSP more lightweight and efficient. This approach maintains the convenience of rapid development while significantly reducing package size, enabling RT-Thread to better support diverse chip application scenarios. This guide uses STM32 as an example.
2. Operational Process
The process can be divided into three main steps. Using stm32f4 as an example:
(1) Update the Software Package Index Repository
The software packages are currently stored in the following directory, which is selected by default in the BSP:
https://github.com/RT-Thread/packages/tree/master/peripherals/hal-sdk
I. Fork a copy of the software package index repository
Repository address: RT-Thread/packages: packages index repository for RT-Thread.
II. Clone the forked repository to your local machine
git clone https://github.com/fengmuyou/packages.git
III. Open the local repository for modifications
git checkout -b "f4_hal" //创建一个新分支
Open the cloned index repository locally, create a new branch, and navigate to `packages/peripherals/`.
IV. Add the stm32f4 index folder
Under the STM32 directory, add the `stm32f4_cmsis_driver` and `stm32f4_hal_driver` folders. In each of these folders, add the `Kconfig` and `package.json` files.
● stm32f4_cmsis_drivers
a. Kconfig
# Kconfig file for package stm32f4_cmsis_driver
menuconfig PKG_USING_STM32F4_CMSIS_DRIVER
bool "STM32 F4 CMSIS driver package"
select PKG_USING_CMSIS_CORE
default n
if 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_VERSION
endif
b. 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
a. Kconfig
# Kconfig file for package stm32f4_hal_driver
menuconfig PKG_USING_STM32F4_HAL_DRIVER
bool "STM32 F4 HAL driver package"
select PKG_USING_STM32F4_CMSIS_DRIVER
default n
if 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_VERSION
endif
b. 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"
}
]
}
Note!!!: The repository URL must be correct to ensure the software package can be downloaded properly.
V. Modify the Kconfig file
Add the configuration in the Kconfig file located under the STM32 folder to ensure the corresponding Kconfig files can be found.
VI. Modify the workflow file
In the `workflows/action_tool.yml` file, add `pkgs — update`. This change only needs to be made once. Subsequent additions of other software package indexes do not require further modifications.
VII. After modifications, commit the changes.
git add .
git commit -m "add stm32_f4 软件包仓库索引"
git push origin f4_hal
VIII. Create a pull request and wait for review and merging.
(2) Updating the Software Package Repository
1. The software packages are divided into CMSIS and drivers.
● First, fork the CMSIS and drivers repositories separately, clone them locally, create a new branch on your local machine, and make your modifications.
2. Adapting the stm32f4_cmsis_driver
● Create a new branch.
git checkout -b f4_cmsis //创建一个新分支
● Add the SConscript file.
Add startup files selection and the `system_stm32f4xx.c` file. The chip model macros can be found in the `stm32f4xx.h` file.
from building import *
import os
# Import environment variables
Import('env')
# Get the current working directory
cwd = GetCurrentDir()
# Initialize include paths and source files list
path = [os.path.join(cwd, 'Include')]
src = [os.path.join(cwd, 'Source', 'Templates', 'system_stm32f4xx.c')]
# Map microcontroller units (MCUs) to their corresponding startup files
mcu_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 file
for 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 group
group = DefineGroup('STM32F4-CMSIS', src, depend=['PKG_USING_STM32F4_CMSIS_DRIVER'], CPPPATH=path)
# Return the build group
Return('group')
● Add the `stm32_update.py` file and run it to modify the startup files.
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 os
import 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 0x000
def 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!")
Note: The main modification to the startup files is to change the entry function from `main` to `entry` for GCC.
● After making these modifications, commit the changes.
git add .
git commit -m "adapt stm32f4 cmsis for rtt"
git push origin f4_cmsis
● Create a pull request and wait for review and merging.
3. Adapting the stm32f4_hal_driver
● Create a new branch
git checkout -b f4_drivers //创建一个新分支
● Add the SConscript file, which should be modified according to the existing `SConscript` in the `rt-thread\bsp\stm32\libraries\STM32F4xx_HAL` folder. The modification involves changing the file reference paths as needed.
from building import *
import os
cwd = 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')
● After completing the modifications, commit the changes.
git add .
git commit -m "adapt stm32f4 drivers for rtt"
git push origin f4_drivers
● Create a pull request and wait for review and merging.
(3) Updating the Mainline Repository
Using `stm32f407-rt-spark` as an example, all BSPs for the F4 series need to be modified. After successful compilation and testing, submit the changes.
1. Preparation
Fork the latest mainline repository, clone it locally, and create a new branch based on the `master` branch.
● Create a new branch.
git checkout -b f4_sdk
2. In the mainline repository directory (`bsp\stm32\libraries\Kconfig`), select `PKG_USING_STM32xx_HAL_DRIVER`.
3. Modify the `SConstruct` file.
4. Modify the `SConscript` file in the board folder.
5. Add an `SConscript` file in the port folder.
Note:
● The `port` folder under `stm32f407-rt-spark` already contains an `SConscript` file; we just need to modify it slightly.
● Some BSPs may not have an `SConscript` in their port folder; in that case, you need to add one yourself, referring to the existing examples.
6. Add instructions to the `README.md` file:
In the quick start section, add explanations
● Chinese Version
**请注意!!!**
在执行编译工作前请先打开ENV执行以下指令(该指令用于拉取必要的HAL库及CMSIS库,否则无法通过编译):
```bash
pkgs --update
```
● English Version
**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):
```bash
pkgs --update
```
7. Compilation Result
Include the compilation result to ensure that the `f4_hal` package under `packages` can be successfully built.
8. Flashing and Testing
Flash the `rt-thread.elf` file onto the board and observe whether it runs normally.
Note: Some peripherals supported by the board also need to be enabled in the environment (`env`) for compilation and testing.
9. Remove the STM32F4_HAL Driver from the Mainline
Note:
● Please modify all BSPs of the F4 series.
● After successful testing, delete the STM32F4_HAL driver from the mainline repository.
10. Modify the Workflow File
Add `pkgs — update` in the `workflows/action_tool.yml` file.
Note: This change only needs to be made once. For subsequent modifications to other BSPs, no further changes are needed.
11. Push to the Remote Repository
After all tests pass without issues, push the changes to the remote repository.
git add .
git commit -m "bsp:Separate STM32F4 HAL drivers"
git push origin f4_sdk