寫(xiě)這篇文章之前默認(rèn)各位的VSCode+PlatfromIO以及Marlin的開(kāi)發(fā)環(huán)境都已搭建成功,如果不懂怎么搭建開(kāi)發(fā)環(huán)境的,請(qǐng)移步Marlin官方,查看官方文檔講解:
marlinfw.org
3D 打印進(jìn)入國(guó)內(nèi)算是比較晚的,所以在百度上學(xué)習(xí)和參考的資料都比較少,并且大部分的技術(shù)文章基本上都只是講怎么配置,其它的內(nèi)容其實(shí)非常少,包括對(duì)源代碼的分析等等。以下是我自己學(xué)習(xí)爬坑總結(jié)的將一個(gè)全新的開(kāi)發(fā)板適配到Marlin固件經(jīng)驗(yàn):
1、下載最新的Marlin官方固件
然后對(duì)固件進(jìn)行解壓:
2、移植Marlin2.x到野火STM32F103ZET6開(kāi)發(fā)板
2.1、導(dǎo)入該工程到Visual Studio Code
2.2、添加硬件平臺(tái)編號(hào)
要讓Marlin能夠識(shí)別到硬件平臺(tái),我們需要在 boards.h 中定義相應(yīng)的板級(jí)編號(hào),如下所示:
/Marlin/src/core/boards.h
2.3、為新板創(chuàng)建新的引腳分配文件
/Marlin/src/pins/stm32f1/
由于野火的這款開(kāi)發(fā)板是 STM32F1 系列,Marlin已經(jīng)做了相應(yīng)的支持,所以我們直接在這個(gè)上面這個(gè)路徑下創(chuàng)建一個(gè)文件 pins_WildFire_V1.h ,然后找到這個(gè)目錄下另外一個(gè)相同芯片相似的引腳配置文件復(fù)制過(guò)來(lái)即可,接下來(lái)的工作就是修改管腳:
在前面我們看到,Marlin固件支持的一款MKS_ROBIN的主控芯片就是 STM32F103ZET6 ,所以我們找到這款芯片的引腳分配文件,然后將這個(gè)文件里的所有代碼復(fù)制到 pins_WildFire_V1.h 中去:
#define BOARD_MKS_ROBIN 4011 // MKS Robin (STM32F103ZET6)
將這個(gè)文件里的所有代碼復(fù)制到 pins_WildFire_V1.h 中去:
2.4、配置板級(jí)編譯環(huán)境并綁定硬件平臺(tái)
2.4.1、綁定編號(hào)與管腳的關(guān)系
/Marlin/pins/pins.h
2.4.2、python腳本編寫(xiě)
這部分主要是為了讓 buildroot 構(gòu)建環(huán)境的時(shí)候能夠準(zhǔn)確的匹配到具體的硬件平臺(tái),指定固件名稱并告訴固件上傳的時(shí)候要鏈接到MCU上的哪個(gè)地址。
/buildroot/share/PlatformIO/scripts/
新建一個(gè)python腳本 wildfire_v1.py ,把鏈接地址、鏈接腳本名稱、最終生成的文件按以下格式寫(xiě)入:
#
# buildroot/share/PlatformIO/scripts/wildfire_v1.py
#
import marlin
marlin.prepare_robin("0x08007000", "wildfire_v1.ld","wildfire.bin")
2.4.3、鏈接腳本編寫(xiě)
鏈接腳本在2.4.2中已經(jīng)在python腳本中指定,當(dāng)系統(tǒng)進(jìn)行編譯時(shí),會(huì)找到這個(gè)鏈接文件。
/buildroot/share/PlatformIO/ldscripts/
新建一個(gè)鏈接腳本 wildfire_v1.ld ,按鏈接腳本的格式編寫(xiě)各個(gè)段:
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K - 40
rom (rx) : ORIGIN = 0x08007000, LENGTH = 512K - 28K
}
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc
2.4.4、新板環(huán)境適配
由于 Marlin2.0 已經(jīng)支持 STM32F1 系列,也為 STM32F1 系列編寫(xiě)了相應(yīng)的 ini 配置文件,我們只需要參考這個(gè)文件里的配置腳本,然后照葫蘆畫(huà)瓢即可。
/ini/stm32f1.ini
添加新板環(huán)境適配,以下的section以及ini配置屬于platformio的部分,感興趣可以去了解,后續(xù)會(huì)寫(xiě)一篇文章專門(mén)來(lái)講解:
#
# wildfire_v1 (STM32F103ZET6)
#
[env:wildfire_v1]
platform = ${common_stm32f1.platform}
extends = common_stm32f1
board = genericSTM32F103ZE
extra_scripts = ${common_stm32f1.extra_scripts}
buildroot/share/PlatformIO/scripts/wildfire_v1.py #指定用哪個(gè)python腳本進(jìn)行構(gòu)建
build_flags = ${common_stm32f1.build_flags}
-DSS_TIMER=4 -DSTM32_XL_DENSITY
debug_tool = stlink
upload_protocol = stlink
3、配置并下載Marlin 2. x 固件
/Marlin/Configuration.h
3.1、修改串口號(hào)
STM32 沒(méi)有串口0,我們需要改下串口號(hào)為1,否則Marlin編譯的時(shí)候會(huì)報(bào)錯(cuò),當(dāng)然也可以修改為其它的串口號(hào),只要硬件平臺(tái)支持就可以。
3.2、修改串口波特率
通常,把串口波特率修改為115200就可以了。
3.3、設(shè)置主板
將主板改為我們?cè)?2.1 章節(jié)里的那個(gè)宏
3.4、將移植好的Marlin固件進(jìn)行編譯
關(guān)掉Visual Studio Code,重新打開(kāi)進(jìn)行編譯,可以看到,編譯成功!
編譯好的固件的位置在這里:
然后點(diǎn)擊Upload,上傳到 STM32 開(kāi)發(fā)板成功:
然后打開(kāi)串口調(diào)試助手,發(fā)現(xiàn)沒(méi)有任何信息輸出:
這是因?yàn)闆](méi)有 bootloader 的原因,因?yàn)?app 的地址是從 0x8007000 開(kāi)始運(yùn)行的,而 MCU 是從0x8000000 開(kāi)始運(yùn)行的,所以我們需要一個(gè)啟動(dòng)程序,啟動(dòng)的直接將地址指向 0x8007000 ,這樣Marlin固件就可以跑起來(lái)了。
4、編寫(xiě)bootloader 啟動(dòng)程序
由于在鏈接地址中,我們已經(jīng)指定了地址:
所以直接將編譯好的 Marlin 固件上傳到 STM32 開(kāi)發(fā)板是無(wú)法執(zhí)行成功的,所以我們需要編寫(xiě)一個(gè)bootloader ,用于啟動(dòng)并跳轉(zhuǎn)地址到 0x8007000 這個(gè)地址,這樣 Marlin 固件才能跑起來(lái)。
思考一下,為什么Marlin要這么做?
這是是為了后期 3D 打印機(jī)的 IAP 固件升級(jí)功能,可以實(shí)現(xiàn)線下更新固件。
接下來(lái)我們就來(lái)實(shí)現(xiàn)這個(gè) bootloader 。
4.1、 STM32CubeMX 配置
4.1.1、時(shí)鐘配置
4.1.2、指定 SWD 為調(diào)試端口
4.1.3、定義一個(gè)LED提示燈
4.1.4、生成基礎(chǔ)工程
然后打開(kāi)這個(gè)工程進(jìn)行代碼編寫(xiě)
4.1.5、編寫(xiě) bootloader 代碼
定義公共變量和宏
typedef void (*pFunction)(void);
//APP在內(nèi)部FLASH的起始地址
#define APP_RUNING_ADDRESS 0x8007000
main函數(shù)編寫(xiě)如下:
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
//uint8_t timeout = 3 ;
uint32_t JumpAddress;
pFunction Jump_To_Application;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
//判斷在0x8007000區(qū)域有沒(méi)有APP,如果有則跳轉(zhuǎn)到APP代碼區(qū)
if (((*(__IO uint32_t*)APP_RUNING_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
__disable_irq();
HAL_DeInit();
HAL_RCC_DeInit();
JumpAddress = *(__IO uint32_t*) (APP_RUNING_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) APP_RUNING_ADDRESS);
Jump_To_Application();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//如果沒(méi)有APP,則會(huì)進(jìn)入死循環(huán),LED燈以300ms交替閃爍
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(300);
}
/* USER CODE END 3 */
}
4.1.6、編譯并下載bootloader
編寫(xiě)完畢以后進(jìn)行編譯:
直接點(diǎn)擊下載按鈕,將程序下載到已經(jīng)上傳好Marlin固件的 MCU 里:(注意,Marlin已經(jīng)在3小節(jié)中上傳成功了)
5、移植成功
打開(kāi)串口調(diào)試助手,可以看到有Marlin固件的信息輸出了:
接下來(lái)我們發(fā)送一個(gè) gcode 代碼測(cè)試一下:
測(cè)試成功,至此, Marlin2.x 固件移植到野火 STM32F103ZET6 開(kāi)發(fā)板成功,野火的開(kāi)發(fā)板也可以作為3D 打印機(jī)的主板了。
6、項(xiàng)目開(kāi)源地址
本節(jié)代碼已同步到碼云的代碼倉(cāng)庫(kù)中,獲取方法如下:
碼云倉(cāng)庫(kù):
https://gitee.com/morixinguan/marlin2.0.x-support-wildfire-board.git
獲取項(xiàng)目方法:
git clone https://gitee.com/morixinguan/marlin2.0.x-support-wildfire-board.git
我還將之前做的一些項(xiàng)目以及練習(xí)例程在近期內(nèi)全部上傳完畢,與大家一起分享交流,如果有任何問(wèn)題或者對(duì)該項(xiàng)目感興趣,歡迎加我微信:morixinguan一起交流學(xué)習(xí)。