前情提要
最近計(jì)劃開始做一個(gè)無(wú)刷電機(jī)的小車玩玩,不用網(wǎng)上的現(xiàn)有方案,一切從零開始自己做方案。硬件方案打算用GD32E503和EG2134柵極驅(qū)動(dòng)IC等一系列國(guó)產(chǎn)器件去做,這樣就面臨一個(gè)問(wèn)題,不太好用Arduino跑SimpleFOC快速出原型。所以軟件方案想基于RTT開發(fā),這樣只需移植一些硬件驅(qū)動(dòng)和FOC以及卡爾曼濾波等算法,其它的很多功能還是可以用RThread組件實(shí)現(xiàn)的,總不能所有輪子都自己造??,畢竟玩這個(gè)小車的目的也只是想深入玩玩這些控制算法。這個(gè)小車的整個(gè)開發(fā)周期可能會(huì)很長(zhǎng),至少是以年為度量單位的,第一是因?yàn)楣ぷ鞅容^忙,只能用一些零散時(shí)間搞,第二是因?yàn)橛?jì)劃用到什么學(xué)什么,有意思的地方都深入的研究研究,不以速成為目的。整個(gè)開發(fā)過(guò)程也都記錄一下,圖文形式的記錄可能會(huì)在RTThread論壇進(jìn)行記錄,視頻形式的記錄就發(fā)布在B站上,希望有興趣的小伙伴也可以一起玩一玩哈。
前期工作
前段時(shí)間,大概花了一周的時(shí)間已經(jīng)把第一版測(cè)試用的硬件電路和機(jī)械結(jié)構(gòu)設(shè)計(jì)完畢,如下是硬件電路的3D視圖。

如下是三輪小車形態(tài)的車底盤3D渲染圖:

下圖是平衡車形態(tài)的車底盤3D渲染圖:

下圖為二階平衡車形態(tài)的車底盤3D渲染圖:

目前第一版的硬件測(cè)試電路已焊接完畢,第一版測(cè)試小車也完成了組裝,下圖是剛組裝起來(lái)的平衡車形態(tài)的無(wú)刷電機(jī)小車,就計(jì)劃先拿它開刀了,其它形態(tài)后面再慢慢玩。小車還算小巧,等測(cè)試通過(guò)后計(jì)劃再做一版集成度更高更小巧的玩玩。

千里之行始于創(chuàng)建BSP
一切就緒,準(zhǔn)備開始擼程序了,那遇到的第一個(gè)問(wèn)題就是目前RTThread的BSP內(nèi)并沒(méi)有我想用的這款GD32E503的處理器(用這款處理器是想玩一玩它的三角函數(shù)加速器,有硬件計(jì)算電路,就不用查詢法去計(jì)算三角函數(shù)了,感覺跑FOC會(huì)舒服很多)。所以第一步就是要學(xué)習(xí)一下添加自己的BSP了。
下載GD32E503固件庫(kù)和RTT源碼包
做BSP的第一步,自然是下載RTThread源碼和GD32E503的固件庫(kù)了。目前RTThread的穩(wěn)定發(fā)行版應(yīng)該是4.1.0,但我這里只是玩玩,對(duì)穩(wěn)定度要求不高,果斷去碼云上下載了最新的master版本,目前的版本是5.0.1:

1/*?RT-Thread?version?information?*/
2#define?RT_VERSION_MAJOR????????????????5???????????????/**
3#define?RT_VERSION_MINOR????????????????0???????????????/**
4#define?RT_VERSION_PATCH????????????????1???????????????/**
GD32E503的固件庫(kù)包含在開發(fā)板Demo資料里,最新版本是V1.2.2:

添加GD32E503器件到MDK
GD32E50x的AddOn資源包,目前最新版本是1.3.3,如果還沒(méi)有安裝MDK需要先安裝一下MDK,這里不做過(guò)多表述,然后再安裝AddOn資源包內(nèi)的兩個(gè)”.pack”文件(也可以只安裝E50x版本的):

如下圖所示,MDK內(nèi)的DeviceDatabase內(nèi)能找到GD32E50x系列的器件列表,證明資源包安裝成功。

添加libraries
拷貝固件庫(kù)到BSP的libraries目錄內(nèi)
解壓RTT源碼包和固件庫(kù)壓縮包,先拷貝固件庫(kù)的”GD32E50x_Firmware_Library”文件夾到RTT源碼包的”bsp/gd32/arm/libraries/“路徑下:

修改libraries目錄內(nèi)的配置文件
這里可以看到libraries目錄下還有兩個(gè)配置文件“Kconfig”和“.ignore_format.yml”,Kconfig文件后面用menuconfig或RTthreadStudio IDE去配置肯定會(huì)用到,另外一個(gè)文件暫時(shí)不知道什么用途,但不妨一起修改了,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的固件庫(kù)路徑名添加到數(shù)組末尾:
1dir_path:
2-?GD32F10x_Firmware_Library
3-?GD32F20x_Firmware_Library
4-?GD32F30x_Firmware_Library
5-?GD32F4xx_Firmware_Library
6-?GD32E50x_Firmware_Library
給固件庫(kù)添加SConscript構(gòu)建配置文件
從其它固件庫(kù)文件內(nèi)(我用的F4xx)拷貝一份”SConscript”文件到新加入的固件庫(kù)路徑內(nèi):

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')
創(chuàng)建BSP
拷貝BSP模板
任意拷貝一份BSP文件夾(我同樣也是用的407)重命名為E503:

修改board.h頭文件
其中主要需要修改的內(nèi)容都在board路徑下。先看board.h文件,我這里沒(méi)有做外部SDRAM,所以注釋掉相關(guān)定義,我板子實(shí)際焊的是GD32E503RCT6,所以SRAM大小改為96KB,再把相關(guān)頭文件名修改一下:
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]?<8-64>
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
在固件庫(kù)內(nèi)的隨便一個(gè)例程路徑內(nèi)拷貝一份”gd32e50x_libopt.h”到當(dāng)前bsp的board路徑內(nèi),替換掉原有的“gd32f4xx_libopt.h”

修改board目錄下的Kconfig和SConscript配置文件
而對(duì)于board目錄下的“Kconfig”和“SConscript”配置文件也要稍作修改,基本都是把F4xx的字符串改成E50x的。稍需注意的是“SConscript”文件內(nèi)對(duì)于啟動(dòng)文件相關(guān)的配置,E50x有高密度(hd)和互聯(lián)(cl)兩個(gè)版本。我這里用的E503RC或者是RE都是高密度版本,所以選擇hd的匯編啟動(dòng)文件。而且還需要說(shuō)明的是,雖然我這里沒(méi)有注釋掉gcc編譯器下的啟動(dòng)文件,但其實(shí)E503的固件庫(kù)內(nèi)并沒(méi)有提供gcc版本的啟動(dòng)文件,也就是說(shuō)后面不能用RTT的IDE去開發(fā)了。等什么時(shí)候有了再加進(jìn)來(lái)吧。或者后面看需要,不行就自己改一版gcc編譯器的啟動(dòng)文件。目前這兩個(gè)文件就暫且修改這么多,后面再看情況,如有問(wèn)題再進(jìn)行修改。
“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”目錄下的連接文件,如無(wú)特殊要求可不對(duì)連接腳本做太多修改,只需要修改RAM和ROM地址和大小即可,以“l(fā)ink.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'

修改工程模板
接下來(lái)修改工程模板文件,我這邊只修改MDK5版本的工程模板:

修改Device為實(shí)際使用的GD32E503RC:

調(diào)試工具改成DAP:

利用env工具配置RTthread并生成MDK工程
在新鍵的bsp目錄下運(yùn)行env工具(env工具的安裝與使用請(qǐng)參考RTT官方文檔),對(duì)RTT做初步配置:

最后根據(jù)提示,輸入命令生成mdk5的工程,(如果想要提交自己制作的BSP,請(qǐng)參照官方BSP制作規(guī)范):

下載驗(yàn)證
最后打開工程,稍微修改一下main.c內(nèi)的內(nèi)容,加一條調(diào)試語(yǔ)句,修改對(duì)應(yīng)的LED引腳。編譯一下,如果能編譯通過(guò)說(shuō)明上面修改的內(nèi)容沒(méi)問(wèn)題,如果有錯(cuò)誤請(qǐng)仔細(xì)檢查上面格配置文件修改的內(nèi)容是否正確或者自行根據(jù)錯(cuò)誤提示進(jìn)行修改。燒錄程序就可以看到運(yùn)行效果了。
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("無(wú)刷電機(jī)小車測(cè)試程序!\n");
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}

今天就先玩到這里,后面再使用一段時(shí)間這個(gè)BSP,需要優(yōu)化的地方優(yōu)化一下,然后再往碼云上提交一份。
其它鏈接
視頻方面目前只有一個(gè)前期的開題視頻,簡(jiǎn)單講了一下想做一些什么,過(guò)了一遍硬件電路的設(shè)計(jì)方案,想了解詳情的可以觀看下面的視頻哦!更多的階段性功能展示以及調(diào)試視頻后續(xù)再慢慢更新。
【無(wú)刷電機(jī)小車——搞起來(lái)!-嗶哩嗶哩】 https://b23.tv/ZmvhBS7
無(wú)刷電機(jī)小車開發(fā)記錄02——BSP導(dǎo)入RTThreadStudio:https://club.rt-thread.org/ask/article/4c90d45831ce0722.html
無(wú)刷電機(jī)小車開發(fā)記錄03——PWM信號(hào)輸入捕獲驅(qū)動(dòng):https://club.rt-thread.org/ask/article/dc39eb608f1eba75.html
無(wú)刷電機(jī)小車開發(fā)記錄04——互補(bǔ)PWM驅(qū)動(dòng)移植:https://club.rt-thread.org/ask/article/004229252f06d18d.html
———————End———————

