本文由RT-Thread论坛用户@happycode999 原创发布:https://club.rt-thread.org/ask/article/3002.html
一、引言
??有幸参加国产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/e4bd3ab9e5d6,了解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=rtthread
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移植贡献活动开启!
|