本文由 RT-Thread 论坛用户 @happycode999 原创公布:https://club.rt-thread.org/as…
一、引言
有幸加入国产 MCU 的移植流动,本次须要移植的是珠海泰为的 TAE32F5300, 是一颗带硬件加速器(ERPU)的用于电力产品的 32 位 MCU,为满足电力行业的要求内置了 4 路独立的 IIR 滤波器用于工业滤波算法,内置一个电能计量模块 ECU。之所以抉择这款芯片,是因为珠海泰为提供的开发板板载了许多外设,是一块非常适合学习的国产 MCU 的开发板,我也很看到其余小伙伴移植到了其余国产 mcu 上,大家都有各自的理由吧。
一开始也感觉移植工作是比拟艰难的,于是在 rtthread 的论坛搜寻国产 MCU 移植,发现了两篇,看到一篇移植华大的,看到移植流程比较简单,于是本人就依照他的办法来移植,心愿这篇文章对移植国产 MCU 的过程有个比拟具体的记录,帮忙各位想移植 RT-Thread 到国产 MCU 的小伙伴解决纳闷。到目前为止,我也仅是实现了 keil 的移植和实现了 pin 和 uart 驱动。发个贴记录一下。
二、BSP 制作前筹备:理解 bsp 构造、理解 scons 的应用、理解 kconfig 的应用
2.1、RT-Thread 中的 BSP 构造
applications:次要为 main.c 文件,用户利用的源码放在该文件。
build:寄存编译出的指标文件
drivers:寄存外设驱动,如后文说的 pin 驱动和 uart 驱动
figures:寄存 readme.md 应用的图片文件
Libraries:芯片的固件库,包含 CMSIS 和规范外设库。
两个规范工程:一个是 iar 的规范工程、一个是 keil 的规范工程,工程里没有任何源文件,次要指明了芯片型号、编译的配置,在应用 scons –target=mdk5 命令时,将依照 sconscript 脚本的要求将源码和头文件放到 keil 工程中。
scons 构建脚本 sconscript:根目录下的该脚本为顶层的脚本,由上面的代码能够看到通过 os.path.isfile 来判断子目录下是否有 sconscript 文件,有的话就将执行子目录下的构建脚本,构建脚本次要指明了源码和头文件的门路。
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
rtconfig.h:rtthread 的配置文件,在应用 menuconfig 命令配置实现后该文件的配置会被批改,通过宏的形式使能或者失能 rtthread 的组件。
kconfig:用于展现 menuconfig 的菜单。
2.2、scons 构建工具的应用
参考 https://www.jianshu.com/p/e4b…,理解 scons 的根本语法,本次移植次要是复制一个与移植芯片相近的工程,本次我参考的是 bsp 下的 mm32f327x,移植须要批改三个 sconscript,一个是 application 文件夹里的、一个是 drivers 文件夹里的、一个是 libraries 文件夹里的。依据本人的 sdk 去批改相应的脚本文件,前面都是展现源码,能够跳过,间接达到 2.3 节 kconfig 的应用,如果须要参考能够持续看上面的内容,多看几个 bsp 就明确了。
application:关注 Split 那局部的代码,是默认须要蕴含的源码,不受配置的影响,前面两个 sconscript 的 Split 同理。
import rtconfig
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd, str(Dir('#'))]
src = Split("""
main.c
tae32f53xx_it.c
tae32f53xx_ll_msp.c
""")
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
drivers:
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
# add the general drivers.
src = Split("""board.c""")
# add serial driver code
if GetDepend('BSP_USING_UART') or GetDepend('BSP_USING_UART1'):
src += ['drv_uart.c']
# add gpio driver code
if GetDepend(['BSP_USING_GPIO']):
src += ['drv_gpio.c']
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
libraries
# RT-Thread building script for bridge
import rtconfig
Import('RTT_ROOT')
from building import *
# get current directory
cwd = GetCurrentDir()
#TAE32F53xx_StdPeriph_Driver/src/hc32f4a0_interrupts.c
#TAE32F53xx_StdPeriph_Driver/src/hc32f4a0_sram.c
# The set of source files associated with this SConscript file.
src = Split("""
CMSIS/Device/Tai_action/TAE32F53xx/Source/system_tae32f53xx.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_cortex.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_sysctrl.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_fpll.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_gpio.c
TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_dma.c
""")
#src += Glob('TAE32F53xx_StdPeriph_Driver/src/*.c')
if GetDepend(['RT_USING_SERIAL']):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_uart.c']
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_tmr.c']
if GetDepend(['RT_USING_I2C']):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_i2c.c']
#if GetDepend(['RT_USING_SPI']):
# src += ['TAE32F53xx_StdPeriph_Driver/src/hc32f4a0_spi.c']
# src += ['TAE32F53xx_StdPeriph_Driver/src/hc32f4a0_qspi.c']
if GetDepend(['RT_USING_CAN']):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_can.c']
if GetDepend(['RT_USING_ADC']):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_adc.c']
#if GetDepend(['RT_USING_RTC']):
# src += ['HC32F4A0_StdPeriph_Driver/src/hc32f4a0_rtc.c']
if GetDepend(['RT_USING_WDT']):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_wwdg.c']
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_iwdg.c']
if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM'] or GetDepend(['RT_USING_PULSE_ENCODER'])):
src += ['TAE32F53xx_StdPeriph_Driver/src/tae32f53xx_ll_tmr.c']
#add for startup script
if rtconfig.CROSS_TOOL == 'gcc':
src = src + ['CMSIS/Device/Tai_action/TAE32F53xx/Source/GCC/startup_ARMCM3.S']
elif rtconfig.CROSS_TOOL == 'keil':
#src = src + ['CMSIS/Device/Tai_action/TAE32F53xx/Source/ARM/startup_ARMCM3.s']
src = src + ['CMSIS/Device/Tai_action/TAE32F53xx/Source/startup_tae32f53xx.c']
elif rtconfig.CROSS_TOOL == 'iar':
src = src + ['CMSIS/Device/Tai_action/TAE32F53xx/Source/IAR/startup_ARMCM3.s']
#add headfile script
path = [cwd + '/CMSIS/Include',
cwd + '/CMSIS/Device/Tai_action/TAE32F53xx/Include',
cwd + '/TAE32F53xx_StdPeriph_Driver/inc']
CPPDEFINES = ['USE_DDL_DRIVER', rtconfig.MCU_TYPE, '__DEBUG']
group = DefineGroup('TAE32_StdPeriph', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')
2.3、kconfig 文件语法
kconfig 次要是用于 menuconfig 的菜单显示内容的文件,参照着他人的写法本人减少或者删除 menuconfig 的配置选项。
三、基于 TAE32F5300 的制作示例
3.1 筹备(git clone rtt 源码、下载 env 工具)
源码和 env 工具都能够在这里下载:https://cn.bing.com/search?q=…
3.2 复制相近的国产 mcu 的 bsp
我复制的是 mm32f327x,理由是都是 cortex-m3 内核,将 bsp 重命名为 tae32f5300
3.3 批改规范工程
关上规范工程,依据原厂的规范工程批改芯片型号、keil 的各种选项:例如是否使能 microlib、链接脚本、默认的调试器、flash 下载算法。
3.4 批改 applications、drivers、libraries 文件夹下的 sconscript 脚本
libraries 文件夹的脚本麻烦点,次要就是指明源码和头文件的门路,一开始就是在这里放弃的,起初看到论坛里的大佬的文章后耐着性子仔仔细细的把这个脚本文件给改完了。
3.5 批改顶层和 drivers 文件夹下的 kconfig
这个改起来不便,如果参考的 bsp 太简略,没有涵盖 kconfig 的所有语法,倡议找一个较完整的,这样改起来就简略了。
3.6 减少 pin 驱动和 uart 驱动
3.6.1 pin 驱动
关上三个 drv_gpio.c 看就明确怎么改了,我参考的是中科蓝讯的 bluetrum、联盛德的 w60x、灵动的 mm32f327x,参考这么多,谁叫我菜呢,不菜就本人写了。
3.6.2 uart 驱动
同 pin 驱动。
总结
本次移植流动是我第一次应用 scons 脚本,目前实现的只有 keil 局部,gcc 的编译报错目前还没解决,心愿借这篇文章让移植 rt-thread 到国产 MCU 变得简略,移植 nano 不能充分发挥 rtthread 的劣势,制作 bsp 就能应用 rtthread 的所有资源。最初,心愿小伙伴的移植之旅顺利。
近来芯片缺货大幕拉开,掀起新一轮国产代替浪潮。RT-Thread 发动一场国产 MCU 移植奉献流动,邀请开发者们加入!
流动详情:国潮崛起!RT-Thread 国产 MCU 移植奉献流动开启!