无刷电机小车开发记录01——制作RTT内GD32E503器件的BSP

前情提要
最近计划开始做一个无刷电机的小车玩玩,不用网上的现有方案,一切从零开始自己做方案。硬件方案打算用gd32e503和eg2134栅极驱动ic等一系列国产器件去做,这样就面临一个问题,不太好用arduino跑simplefoc快速出原型。所以软件方案想基于rtt开发,这样只需移植一些硬件驱动和foc以及卡尔曼滤波等算法,其它的很多功能还是可以用rthread组件实现的,总不能所有轮子都自己造,毕竟玩这个小车的目的也只是想深入玩玩这些控制算法。这个小车的整个开发周期可能会很长,至少是以年为度量单位的,第一是因为工作比较忙,只能用一些零散时间搞,第二是因为计划用到什么学什么,有意思的地方都深入的研究研究,不以速成为目的。整个开发过程也都记录一下,图文形式的记录可能会在rtthread论坛进行记录,视频形式的记录就发布在b站上,希望有兴趣的小伙伴也可以一起玩一玩哈。
前期工作
前段时间,大概花了一周的时间已经把第一版测试用的硬件电路和机械结构设计完毕,如下是硬件电路的3d视图。
如下是三轮小车形态的车底盘3d渲染图:
下图是平衡车形态的车底盘3d渲染图:
下图为二阶平衡车形态的车底盘3d渲染图:
目前第一版的硬件测试电路已焊接完毕,第一版测试小车也完成了组装,下图是刚组装起来的平衡车形态的无刷电机小车,就计划先拿它开刀了,其它形态后面再慢慢玩。小车还算小巧,等测试通过后计划再做一版集成度更高更小巧的玩玩。
千里之行始于创建bsp
一切就绪,准备开始撸程序了,那遇到的第一个问题就是目前rtthread的bsp内并没有我想用的这款gd32e503的处理器(用这款处理器是想玩一玩它的三角函数加速器,有硬件计算电路,就不用查询法去计算三角函数了,感觉跑foc会舒服很多)。所以第一步就是要学习一下添加自己的bsp了。
下载gd32e503固件库和rtt源码包
做bsp的第一步,自然是下载rtthread源码和gd32e503的固件库了。目前rtthread的稳定发行版应该是4.1.0,但我这里只是玩玩,对稳定度要求不高,果断去码云上下载了最新的master版本,目前的版本是5.0.1:
1/* rt-thread version information */ 2#define rt_version_major                5               /**< major version number (x.x.x) */ 3#define rt_version_minor                0               /**< minor version number (x.x.x) */ 4#define rt_version_patch                1               /**< patch version number (x.x.x) */ gd32e503的固件库包含在开发板demo资料里,最新版本是v1.2.2:
添加gd32e503器件到mdk
gd32e50x的addon资源包,目前最新版本是1.3.3,如果还没有安装mdk需要先安装一下mdk,这里不做过多表述,然后再安装addon资源包内的两个”.pack”文件(也可以只安装e50x版本的):
如下图所示,mdk内的devicedatabase内能找到gd32e50x系列的器件列表,证明资源包安装成功。
添加libraries
拷贝固件库到bsp的libraries目录内
解压rtt源码包和固件库压缩包,先拷贝固件库的”gd32e50x_firmware_library”文件夹到rtt源码包的”bsp/gd32/arm/libraries/“路径下:
修改libraries目录内的配置文件
这里可以看到libraries目录下还有两个配置文件“kconfig”和“.ignore_format.yml”,kconfig文件后面用menuconfig或rtthreadstudio ide去配置肯定会用到,另外一个文件暂时不知道什么用途,但不妨一起修改了,kconfig文件修改如下(文档末尾添加gd32e5的配置信息):
1config soc_family_gd32 2    bool 3config soc_series_gd32f1 4    bool 5    select arch_arm_cortex_m3 6    select soc_family_gd32 7config soc_series_gd32f2 8    bool 9    select arch_arm_cortex_m3 10    select soc_family_gd32 11config soc_series_gd32f3 12    bool 13    select arch_arm_cortex_m4 14    select soc_family_gd32 15config soc_series_gd32f4 16    bool 17    select arch_arm_cortex_m4 18    select soc_family_gd32 19config soc_series_gd32e5    #add by cjl 20    bool 21    select arch_arm_cortex_m33 22    select soc_family_gd32
“.yml”文件把gd32e50x的固件库路径名添加到数组末尾:
1dir_path: 2- gd32f10x_firmware_library 3- gd32f20x_firmware_library 4- gd32f30x_firmware_library 5- gd32f4xx_firmware_library 6- gd32e50x_firmware_library
给固件库添加sconscript构建配置文件
从其它固件库文件内(我用的f4xx)拷贝一份”sconscript”文件到新加入的固件库路径内:
1import rtconfig 2from building import * 3# get current directory 4cwd = getcurrentdir() 5# the set of source files associated with this sconscript file. 6src = split(''' 7cmsis/gd/gd32e50x/source/system_gd32e50x.c 8gd32e50x_standard_peripheral/source/gd32e50x_gpio.c 9gd32e50x_standard_peripheral/source/gd32e50x_rcu.c 10gd32e50x_standard_peripheral/source/gd32e50x_exti.c 11gd32e50x_standard_peripheral/source/gd32e50x_misc.c 12''') 13# remove: gd32e50x_standard_peripheral/source/gd32e50x_syscfg.c 14if getdepend(['rt_using_serial']): 15    src += ['gd32e50x_standard_peripheral/source/gd32e50x_usart.c'] 16if getdepend(['rt_using_i2c']): 17    src += ['gd32e50x_standard_peripheral/source/gd32e50x_i2c.c'] 18if getdepend(['rt_using_spi']): 19    src += ['gd32e50x_standard_peripheral/source/gd32e50x_spi.c'] 20if getdepend(['rt_using_can']): 21    src += ['gd32e50x_standard_peripheral/source/gd32e50x_can.c'] 22if getdepend(['bsp_using_eth']): 23    src += ['gd32e50x_standard_peripheral/source/gd32e50x_enet.c'] 24if getdepend(['rt_using_adc']): 25    src += ['gd32e50x_standard_peripheral/source/gd32e50x_adc.c'] 26if getdepend(['rt_using_dac']): 27    src += ['gd32e50x_standard_peripheral/source/gd32e50x_dac.c'] 28if getdepend(['rt_using_rtc']): 29    src += ['gd32e50x_standard_peripheral/source/gd32e50x_rtc.c'] 30    src += ['gd32e50x_standard_peripheral/source/gd32e50x_pmu.c'] 31if getdepend(['rt_using_wdt']): 32    src += ['gd32e50x_standard_peripheral/source/gd32e50x_wwdgt.c'] 33    src += ['gd32e50x_standard_peripheral/source/gd32e50x_fwdgt.c'] 34if getdepend(['rt_using_sdio']): 35    src += ['gd32e50x_standard_peripheral/source/gd32e50x_sdio.c'] 36    src += ['gd32e50x_standard_peripheral/source/gd32e50x_dma.c'] 37path = [ 38    cwd + '/cmsis/gd/gd32e50x/include', 39    cwd + '/cmsis', 40    cwd + '/gd32e50x_standard_peripheral/include',] 41cppdefines = ['use_stdperiph_driver'] 42group = definegroup('libraries', src, depend = [''], cpppath = path, cppdefines = cppdefines) 43return('group')
创建bsp
拷贝bsp模板
任意拷贝一份bsp文件夹(我同样也是用的407)重命名为e503:
修改board.h头文件
其中主要需要修改的内容都在board路径下。先看board.h文件,我这里没有做外部sdram,所以注释掉相关定义,我板子实际焊的是gd32e503rct6,所以sram大小改为96kb,再把相关头文件名修改一下:
1#ifndef __board_h__ 2#define __board_h__ 3#include gd32e50x.h 4#include drv_usart.h 5#include drv_gpio.h 6#include gd32e50x_exti.h 7//#define ext_sdram_begin    (0xc0000000u) /* the begining address of external sdram */ 8//#define ext_sdram_end      (ext_sdram_begin + (32u * 1024 * 1024)) /* the end address of external sdram */ 9//  internal sram memory size[kbytes]  10//  default: 64 11#ifdef __iccarm__ 12// use *.icf ram symbal, to avoid hardcode. 13extern char __icfedit_region_ram_end__; 14#define gd32_sram_end          &__icfedit_region_ram_end__ 15#else 16#define gd32_sram_size         96      //96 for gd32e503xc         128 for gd32e503xe  ... 17#define gd32_sram_end          (0x20000000 + gd32_sram_size * 1024) 18#endif 19#ifdef __armcc_version 20extern int image$$rw_iram1$$zi$$limit; 21#define heap_begin    (&image$$rw_iram1$$zi$$limit) 22#elif __iccarm__ 23#pragma section=heap 24#define heap_begin    (__segment_end(heap)) 25#else 26extern int __bss_end; 27#define heap_begin    (&__bss_end) 28#endif 29#define heap_end          gd32_sram_end 30#endif
添加gd32e50x_libopt.h
在固件库内的随便一个例程路径内拷贝一份”gd32e50x_libopt.h”到当前bsp的board路径内,替换掉原有的“gd32f4xx_libopt.h”
修改board目录下的kconfig和sconscript配置文件
而对于board目录下的“kconfig”和“sconscript”配置文件也要稍作修改,基本都是把f4xx的字符串改成e50x的。稍需注意的是“sconscript”文件内对于启动文件相关的配置,e50x有高密度(hd)和互联(cl)两个版本。我这里用的e503rc或者是re都是高密度版本,所以选择hd的汇编启动文件。而且还需要说明的是,虽然我这里没有注释掉gcc编译器下的启动文件,但其实e503的固件库内并没有提供gcc版本的启动文件,也就是说后面不能用rtt的ide去开发了。等什么时候有了再加进来吧。或者后面看需要,不行就自己改一版gcc编译器的启动文件。目前这两个文件就暂且修改这么多,后面再看情况,如有问题再进行修改。
“sconscript”文件修改如下:
1import os 2import rtconfig 3from building import * 4import('sdk_lib') 5cwd = getcurrentdir() 6# add general drivers 7src = split(''' 8board.c 9''') 10path =  [cwd] 11startup_path_prefix = sdk_lib 12if rtconfig.platform in ['gcc']: 13    src += [startup_path_prefix + '/gd32e50x_firmware_library/cmsis/gd/gd32e50x/source/gcc/startup_gd32e50x_hd.s'] 14elif rtconfig.platform in ['armcc', 'armclang']: 15    src += [startup_path_prefix + '/gd32e50x_firmware_library/cmsis/gd/gd32e50x/source/arm/startup_gd32e50x_hd.s'] 16elif rtconfig.platform in ['iccarm']: 17    src += [startup_path_prefix + '/gd32e50x_firmware_library/cmsis/gd/gd32e50x/source/iar/startup_gd32e50x_hd.s'] 18cppdefines = ['gd32e50x','gd32e50x_hd'] 19group = definegroup('drivers', src, depend = [''], cpppath = path, cppdefines = cppdefines) 20return('group')
修改三种编译器用的链接脚本
修改”board/linker_scripts”目录下的连接文件,如无特殊要求可不对连接脚本做太多修改,只需要修改ram和rom地址和大小即可,以“link.sct”为例:
1lr_irom1 0x08000000 0x00040000  {    ; load region size_region  256kb 2  er_irom1 0x08000000 0x00040000  {  ; load address = execution address 3   *.o (reset, +first) 4   *(inroot$$sections) 5   .any (+ro) 6  } 7  rw_iram1 0x20000000 0x00018000  {  ; rw data  96kb 8   .any (+rw +zi) 9  } 10}
修改bsp顶层sconstruct和rtconfig.py文件
修改新建bsp目录下的sconstruct文件和rtconfig.py文件:
sconstruct文件只需要修改“gd32_library”的值:
1gd32_library = 'gd32e50x_firmware_library'
修改工程模板
接下来修改工程模板文件,我这边只修改mdk5版本的工程模板:
修改device为实际使用的gd32e503rc:
调试工具改成dap:
利用env工具配置rtthread并生成mdk工程
在新键的bsp目录下运行env工具(env工具的安装与使用请参考rtt官方文档),对rtt做初步配置:
最后根据提示,输入命令生成mdk5的工程,(如果想要提交自己制作的bsp,请参照官方bsp制作规范):
下载验证
最后打开工程,稍微修改一下main.c内的内容,加一条调试语句,修改对应的led引脚。编译一下,如果能编译通过说明上面修改的内容没问题,如果有错误请仔细检查上面格配置文件修改的内容是否正确或者自行根据错误提示进行修改。烧录程序就可以看到运行效果了。
1#include  2#include  3#include  4#include  5/* defined the led2 pin: pc6 */ 6#define led_pin get_pin(b, 11) 7#define buzzer_pin get_pin(b, 12) 8int main(void) 9{ 10    int count = 1; 11    /* set led2 pin mode to output */ 12    rt_pin_mode(led_pin, pin_mode_output); 13    rt_pin_write(buzzer_pin, pin_low); 14    rt_pin_mode(buzzer_pin, pin_mode_output); 15    rt_kprintf(无刷电机小车测试程序! ); 16    while (count++) 17    { 18        rt_pin_write(led_pin, pin_high); 19        rt_thread_mdelay(500); 20        rt_pin_write(led_pin, pin_low); 21        rt_thread_mdelay(500); 22    } 23    return rt_eok; 24}
今天就先玩到这里,后面再使用一段时间这个bsp,需要优化的地方优化一下,然后再往码云上提交一份。
其它链接
视频方面目前只有一个前期的开题视频,简单讲了一下想做一些什么,过了一遍硬件电路的设计方案,想了解详情的可以观看下面的视频哦!更多的阶段性功能展示以及调试视频后续再慢慢更新。
【无刷电机小车——搞起来!-哔哩哔哩】 https://b23.tv/zmvhbs7
无刷电机小车开发记录02——bsp导入rtthreadstudio:https://club.rt-thread.org/ask/article/4c90d45831ce0722.html
无刷电机小车开发记录03——pwm信号输入捕获驱动:https://club.rt-thread.org/ask/article/dc39eb608f1eba75.html
无刷电机小车开发记录04——互补pwm驱动移植:https://club.rt-thread.org/ask/article/004229252f06d18d.html
———————end———————
   点击阅读原文进入官网
原文标题:无刷电机小车开发记录01——制作rtt内gd32e503器件的bsp
文章出处:【微信公众号:rtthread物联网操作系统】欢迎添加关注!文章转载请注明出处。

话题:中兴被美国禁购了,为何中国不停售苹果?
意法半导体STSPIN32单Shunt BLDC电机控制器 极具性价比和理想全合一
超薄电池引领电子设备瘦身潮
住建部下发通知:4月起新建住宅须采用光纤入户
红外链路温度传感器允许隔离温度传感器
无刷电机小车开发记录01——制作RTT内GD32E503器件的BSP
减反射膜及镀膜技术简介
74ls154与74hc154能通用吗?有什么区别
工程师教你解决运放问题
浅析手机专用CMOS传感器有哪些
闪存是什么意思?华为p10闪存门背后,三星成最大赢家彰显优势!
Vista生命周期即将完结 Windows手机单份额跌至0.3%几乎绝迹
穷途末路!无法逃脱死亡的第三方ROM!
Si3262 一款低功耗刷卡+触摸+mcu 三合一SOC芯片
泰矽微电子4款产品再获车规认证
什么是手机来电防火墙
2023专精特新中小企业发展大会
新型医疗X光乳腺成像法 辐射低出25倍
新能源汽车电驱动桥的设计开发
毫米波人体扫描仪市场:过去、现在和未来