熟悉RT-Thread的朋友都知道,RT-Thread提供了许多BSP,但不是所有的板子都能找到相应的BSP,这时就需要移植新的BSP。RT-Thread的所有BSP中,最完善的BSP就是STM32系列,但从2020年下半年开始,国内出现史无前例的芯片缺货潮,我们参考STM32F103系列进行GD32F103系列的BSP制作。
我使用的是GD32F103VET6芯片进行移植,以下是本人的gitee库。
Gitee//gitee.com/zhaodhajhdjahwd/gd32-bsp
1 BSP 框架制作
在具体移植GD32407V-START的BSP之前,先做好GD32的BSP架构。BSP 框架结构如下图所示:在这里插入图片描述
GD32的BSP架构主要分为三个部分:libraries、tools和具体的Boards,其中libraries包含了GD32的通用库,包括每个系列的HAL以及适配RT-Thread的drivers;tools是生成工程的Python脚本工具;另外就是Boards文件,当然这里的Boards有很多,我这里值列举了GD32103C-eval。这里先谈谈libraries和tools的构建,然后在后文单独讨论具体板级BSP的制作。1.1 Libraries构建
Libraries文件夹包含兆易创新提供的HAL库,这个直接在兆易创新的官网就可以下载。
http://www.gd32mcu.com/cn/download/0?kw=GD32F1
然后将HAL库(GD32F10x_Firmware_Library)复制到libraries目录下,重命名为GD32F10x_Firmware_Library,其他的系列类似
GD32F10x_Firmware_Library就是官方的文件,基本是不用动的,只是在文件夹中需要添加构建工程的脚本文件SConscript,其实也就是Python脚本。SConscript文件的内容如下:
1importrtconfig
2frombuildingimport*
3
4#getcurrentdirectory
5cwd=GetCurrentDir()
6
7#ThesetofsourcefilesassociatedwiththisSConscriptfile.
8
9src=Split('''
10CMSIS/GD/GD32F10x/Source/system_gd32f10x.c
11GD32F10x_standard_peripheral/Source/gd32f10x_gpio.c
12GD32F10x_standard_peripheral/Source/gd32f10x_rcu.c
13GD32F10x_standard_peripheral/Source/gd32f10x_exti.c
14GD32F10x_standard_peripheral/Source/gd32f10x_misc.c
15''')
16
17ifGetDepend(['RT_USING_SERIAL']):
18src+=['GD32F10x_standard_peripheral/Source/gd32f10x_usart.c']
19
20ifGetDepend(['RT_USING_I2C']):
21src+=['GD32F10x_standard_peripheral/Source/gd32f10x_i2c.c']
22
23ifGetDepend(['RT_USING_SPI']):
24src+=['GD32F10x_standard_peripheral/Source/gd32f10x_spi.c']
25
26ifGetDepend(['RT_USING_CAN']):
27src+=['GD32F10x_standard_peripheral/Source/gd32f10x_can.c']
28
29ifGetDepend(['BSP_USING_ETH']):
30src+=['GD32F10x_standard_peripheral/Source/gd32f10x_enet.c']
31
32ifGetDepend(['RT_USING_ADC']):
33src+=['GD32F10x_standard_peripheral/Source/gd32f10x_adc.c']
34
35ifGetDepend(['RT_USING_DAC']):
36src+=['GD32F10x_standard_peripheral/Source/gd32f10x_dac.c']
37
38ifGetDepend(['RT_USING_HWTIMER']):
39src+=['GD32F10x_standard_peripheral/Source/gd32f10x_timer.c']
40
41ifGetDepend(['RT_USING_RTC']):
42src+=['GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c']
43src+=['GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c']
44
45ifGetDepend(['RT_USING_WDT']):
46src+=['GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c']
47src+=['GD32F10x_standard_peripheral/Source/gd32f10x_fwdgt.c']
48
49ifGetDepend(['RT_USING_SDIO']):
50src+=['GD32F10x_standard_peripheral/Source/gd32f10x_sdio.c']
51
52path=[
53cwd+'/CMSIS/GD/GD32F10x/Include',
54cwd+'/CMSIS',
55cwd+'/GD32F10x_standard_peripheral/Include',]
56
57CPPDEFINES=['USE_STDPERIPH_DRIVER']
58
59group=DefineGroup('Libraries',src,depend=[''],CPPPATH=path,CPPDEFINES=CPPDEFINES)
60
61Return('group')
该文件主要的作用就是添加库文件和头文件路径,一部分文件是属于基础文件,因此直接调用Python库的Split包含,另外一部分文件是根据实际的应用需求添加的。
接下来说说Kconfig文件,这里是对内核和组件的功能进行配置,对RT-Thread的组件进行自由裁剪。如果使用RT-Thread studio,则通过RT-Thread Setting可以体现Kconfig文件的作用。
如果使用ENV环境,则在使用 menuconfig配置和裁剪 RT-Thread时体现。
后面所有的Kconfig文件都是一样的逻辑。下表列举一些常用的Kconfig句法规则。
Kconfig的语法规则网上资料很多,自行去学习吧。
bsp/gd32/Kconfig内容如下:
1configSOC_FAMILY_GD32
2bool
3
4configSOC_SERIES_GD32F1
5bool
6selectARCH_ARM_CORTEX_M3
7selectSOC_FAMILY_GD32
8
9configSOC_SERIES_GD32F2
10bool
11selectARCH_ARM_CORTEX_M3
12selectSOC_FAMILY_GD32
13
14configSOC_SERIES_GD32F3
15bool
16selectARCH_ARM_CORTEX_M4
17selectSOC_FAMILY_GD32
18
19configSOC_SERIES_GD32F4
20bool
21selectARCH_ARM_CORTEX_M4
22selectSOC_FAMILY_GD32
最后谈谈HAL_Drivers,这个文件夹就是GD32的外设驱动文件夹,为上层应用提供调用接口。
好了,先看
E:RT_ThreadGD32_BSPrt_thread_codebspgd32f103librariesgd32_drivers/SConscript文件。
1Import('RTT_ROOT')
2Import('rtconfig')
3frombuildingimport*
4
5cwd=GetCurrentDir()
6
7#addthegeneraldrivers.
8src=Split("""
9""")
10
11#addpindrivers.
12ifGetDepend('RT_USING_PIN'):
13src+=['drv_gpio.c']
14
15#addusartdrivers.
16ifGetDepend(['RT_USING_SERIAL']):
17src+=['drv_usart.c']
18
19#addi2cdrivers.
20ifGetDepend(['RT_USING_I2C','RT_USING_I2C_BITOPS']):
21ifGetDepend('BSP_USING_I2C0')orGetDepend('BSP_USING_I2C1')orGetDepend('BSP_USING_I2C2')orGetDepend('BSP_USING_I2C3'):
22src+=['drv_soft_i2c.c']
23
24#addspidrivers.
25ifGetDepend('RT_USING_SPI'):
26src+=['drv_spi.c']
27
28#addspiflashdrivers.
29ifGetDepend('RT_USING_SFUD'):
30src+=['drv_spi_flash.c','drv_spi.c']
31
32ifGetDepend('RT_USING_WDT'):
33src+=['drv_wdt.c']
34
35ifGetDepend('RT_USING_RTC'):
36src+=['drv_rtc.c']
37
38ifGetDepend('RT_USING_HWTIMER'):
39src+=['drv_hwtimer.c']
40
41ifGetDepend('RT_USING_ADC'):
42src+=['drv_adc.c']
43
44path=[cwd]
45
46group=DefineGroup('Drivers',src,depend=[''],CPPPATH=path)
47
48Return('group')
E:RT_ThreadGD32_BSPrt_thread_codebspgd32f103librariesgd32_drivers/Kconfig文件结构如下:
1ifBSP_USING_USBD
2configBSP_USBD_TYPE_FS
3bool
4#"USBFullSpeed(FS)Core"
5configBSP_USBD_TYPE_HS
6bool
7#"USBHighSpeed(HS)Core"
8
9configBSP_USBD_SPEED_HS
10bool
11#"USBHighSpeed(HS)Mode"
12configBSP_USBD_SPEED_HSINFS
13bool
14#"USBHighSpeed(HS)CoreinFSmode"
15
16configBSP_USBD_PHY_EMBEDDED
17bool
18#"UsingEmbeddedphyinterface"
19configBSP_USBD_PHY_UTMI
20bool
21#"UTMI:USB2.0TransceiverMacrocellInterace"
22configBSP_USBD_PHY_ULPI
23bool
24#"ULPI:UTMI+LowPinInterface"
25endif
1.2 Tools构建
该文件夹就是工程构建的脚本,
1importos
2importsys
3importshutil
4
5cwd_path=os.getcwd()
6sys.path.append(os.path.join(os.path.dirname(cwd_path),'rt-thread','tools'))
7
8
9#BSPdistfunction
10defdist_do_building(BSP_ROOT,dist_dir):
11frommkdistimportbsp_copy_files
12importrtconfig
13
14print("=>copygd32bsplibrary")
15library_dir=os.path.join(dist_dir,'libraries')
16library_path=os.path.join(os.path.dirname(BSP_ROOT),'libraries')
17bsp_copy_files(os.path.join(library_path,rtconfig.BSP_LIBRARY_TYPE),
18os.path.join(library_dir,rtconfig.BSP_LIBRARY_TYPE))
19
20print("=>copybspdrivers")
21bsp_copy_files(os.path.join(library_path,'HAL_Drivers'),os.path.join(library_dir,'HAL_Drivers'))
22shutil.copyfile(os.path.join(library_path,'Kconfig'),os.path.join(library_dir,'Kconfig'))
以上代码很简单,主要使用了Python的OS模块的join函数,该函数的作用就是连接两个或更多的路径名。最后将BSP依赖的文件复制到指定目录下。在使用scons --dist 命令打包的时候,就是依赖的该脚本,生成的dist 文件夹的工程到任何目录下使用,也就是将BSP相关的库以及内核文件提取出来,可以将该工程任意拷贝。1.3 gd32f103vet6-eval构建
2 BSP移植
2.1 Keil环境准备
接下来我们下载GD32F30x的软件支持包。
下载地址:http://www.gd32mcu.com/cn/download/0?kw=GD32F1
双击安装包,按照操作步骤进行安装。
安装成功后,重新打开Keil,则可以在File->Device Database中出现Gigadevice的下拉选项,点击可以查看到相应的型号。2.2 BSP工程制作
1.构建基础工程
首先看看RT-Thread代码仓库中已有很多BSP,而我要移植的是Cortex-M4内核。这里我找了一个相似的内核,把它复制一份,并修改文件名为:gd32103C-eval。这样就有一个基础的工程。然后就开始增删改查,完成最终的BSP,几乎所有的BSP的制作都是如此。
2.修改BSP构建脚本
E:RT_ThreadGD32_BSPrt_thread_codebspgd32f103gd32f103vet6/Kconfig修改后的内容如下
1mainmenu"RT-ThreadConfiguration"
2
3configBSP_DIR
4string
5optionenv="BSP_ROOT"
6default"."
7
8configRTT_DIR
9string
10optionenv="RTT_ROOT"
11default"../../.."
12
13configPKGS_DIR
14string
15optionenv="PKGS_ROOT"
16default"packages"
17
18source"$RTT_DIR/Kconfig"
19source"$PKGS_DIR/Kconfig"
20source"../libraries/Kconfig"
21source"board/Kconfig"
该文件是获取所有路径下的Kconfig。
E:RT_ThreadGD32_BSPrt_thread_codebspgd32f103gd32f103vet6/SConscript修改后的内容如下:
1#formodulecompiling
2importos
3Import('RTT_ROOT')
4frombuildingimport*
5
6cwd=GetCurrentDir()
7objs=[]
8list=os.listdir(cwd)
9
10fordinlist:
11path=os.path.join(cwd,d)
12ifos.path.isfile(os.path.join(path,'SConscript')):
13objs=objs+SConscript(os.path.join(d,'SConscript'))
14
15Return('objs')
该文件是用于遍历当前目录的所有文件夹。
E:RT_ThreadGD32_BSPrt_thread_codebspgd32f103gd32f103vet6/SConstruct修改后的内容如下:
1importos
2importsys
3importrtconfig
4
5ifos.getenv('RTT_ROOT'):
6RTT_ROOT=os.getenv('RTT_ROOT')
7else:
8RTT_ROOT=os.path.normpath(os.getcwd()+'/../../..')
9
10sys.path=sys.path+[os.path.join(RTT_ROOT,'tools')]
11try:
12frombuildingimport*
13except:
14print('CannotfoundRT-Threadrootdirectory,pleasecheckRTT_ROOT')
15print(RTT_ROOT)
16exit(-1)
17
18TARGET='rtthread.'+rtconfig.TARGET_EXT
19
20DefaultEnvironment(tools=[])
21env=Environment(tools=['mingw'],
22AS=rtconfig.AS,ASFLAGS=rtconfig.AFLAGS,
23CC=rtconfig.CC,CCFLAGS=rtconfig.CFLAGS,
24AR=rtconfig.AR,ARFLAGS='-rc',
25CXX=rtconfig.CXX,CXXFLAGS=rtconfig.CXXFLAGS,
26LINK=rtconfig.LINK,LINKFLAGS=rtconfig.LFLAGS)
27env.PrependENVPath('PATH',rtconfig.EXEC_PATH)
28
29ifrtconfig.PLATFORM=='iar':
30env.Replace(CCCOM=['$CC$CCFLAGS$CPPFLAGS$_CPPDEFFLAGS$_CPPINCFLAGS-o$TARGET$SOURCES'])
31env.Replace(ARFLAGS=[''])
32env.Replace(LINKCOM=env["LINKCOM"]+'--maprtthread.map')
33
34Export('RTT_ROOT')
35Export('rtconfig')
36
37SDK_ROOT=os.path.abspath('./')
38
39ifos.path.exists(SDK_ROOT+'/libraries'):
40libraries_path_prefix=SDK_ROOT+'/libraries'
41else:
42libraries_path_prefix=os.path.dirname(SDK_ROOT)+'/libraries'
43
44SDK_LIB=libraries_path_prefix
45Export('SDK_LIB')
46
47#preparebuildingenvironment
48objs=PrepareBuilding(env,RTT_ROOT,has_libcpu=False)
49
50gd32_library='GD32F10x_Firmware_Library'
51rtconfig.BSP_LIBRARY_TYPE=gd32_library
52
53#includelibraries
54objs.extend(SConscript(os.path.join(libraries_path_prefix,gd32_library,'SConscript')))