写这篇文章之前默认各位的VSCode+PlatfromIO以及Marlin的开发环境都已搭建成功,如果不懂怎么搭建开发环境的,请移步Marlin官方,查看官方文档讲解:
marlinfw.org
3D 打印进入国内算是比较晚的,所以在百度上学习和参考的资料都比较少,并且大部分的技术文章基本上都只是讲怎么配置,其它的内容其实非常少,包括对源代码的分析等等。以下是我自己学习爬坑总结的将一个全新的开发板适配到Marlin固件经验:
1、下载最新的Marlin官方固件
然后对固件进行解压:
2、移植Marlin2.x到野火STM32F103ZET6开发板
2.1、导入该工程到Visual Studio Code
2.2、添加硬件平台编号
要让Marlin能够识别到硬件平台,我们需要在 boards.h 中定义相应的板级编号,如下所示:
/Marlin/src/core/boards.h
2.3、为新板创建新的引脚分配文件
/Marlin/src/pins/stm32f1/
由于野火的这款开发板是 STM32F1 系列,Marlin已经做了相应的支持,所以我们直接在这个上面这个路径下创建一个文件 pins_WildFire_V1.h ,然后找到这个目录下另外一个相同芯片相似的引脚配置文件复制过来即可,接下来的工作就是修改管脚:
在前面我们看到,Marlin固件支持的一款MKS_ROBIN的主控芯片就是 STM32F103ZET6 ,所以我们找到这款芯片的引脚分配文件,然后将这个文件里的所有代码复制到 pins_WildFire_V1.h 中去:
#define BOARD_MKS_ROBIN 4011 // MKS Robin (STM32F103ZET6)
将这个文件里的所有代码复制到 pins_WildFire_V1.h 中去:
2.4、配置板级编译环境并绑定硬件平台
2.4.1、绑定编号与管脚的关系
/Marlin/pins/pins.h
2.4.2、python脚本编写
这部分主要是为了让 buildroot 构建环境的时候能够准确的匹配到具体的硬件平台,指定固件名称并告诉固件上传的时候要链接到MCU上的哪个地址。
/buildroot/share/PlatformIO/scripts/
新建一个python脚本 wildfire_v1.py ,把链接地址、链接脚本名称、最终生成的文件按以下格式写入:
#
# buildroot/share/PlatformIO/scripts/wildfire_v1.py
#
import marlin
marlin.prepare_robin("0x08007000", "wildfire_v1.ld","wildfire.bin")
2.4.3、链接脚本编写
链接脚本在2.4.2中已经在python脚本中指定,当系统进行编译时,会找到这个链接文件。
/buildroot/share/PlatformIO/ldscripts/
新建一个链接脚本 wildfire_v1.ld ,按链接脚本的格式编写各个段:
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、新板环境适配
由于 Marlin2.0 已经支持 STM32F1 系列,也为 STM32F1 系列编写了相应的 ini 配置文件,我们只需要参考这个文件里的配置脚本,然后照葫芦画瓢即可。
/ini/stm32f1.ini
添加新板环境适配,以下的section以及ini配置属于platformio的部分,感兴趣可以去了解,后续会写一篇文章专门来讲解:
#
# 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 #指定用哪个python脚本进行构建
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、修改串口号
STM32 没有串口0,我们需要改下串口号为1,否则Marlin编译的时候会报错,当然也可以修改为其它的串口号,只要硬件平台支持就可以。
3.2、修改串口波特率
通常,把串口波特率修改为115200就可以了。
3.3、设置主板
将主板改为我们在 2.1 章节里的那个宏
3.4、将移植好的Marlin固件进行编译
关掉Visual Studio Code,重新打开进行编译,可以看到,编译成功!
编译好的固件的位置在这里:
然后点击Upload,上传到 STM32 开发板成功:
然后打开串口调试助手,发现没有任何信息输出:
这是因为没有 bootloader 的原因,因为 app 的地址是从 0x8007000 开始运行的,而 MCU 是从0x8000000 开始运行的,所以我们需要一个启动程序,启动的直接将地址指向 0x8007000 ,这样Marlin固件就可以跑起来了。
4、编写bootloader 启动程序
由于在链接地址中,我们已经指定了地址:
所以直接将编译好的 Marlin 固件上传到 STM32 开发板是无法执行成功的,所以我们需要编写一个bootloader ,用于启动并跳转地址到 0x8007000 这个地址,这样 Marlin 固件才能跑起来。
思考一下,为什么Marlin要这么做?
这是是为了后期 3D 打印机的 IAP 固件升级功能,可以实现线下更新固件。
接下来我们就来实现这个 bootloader 。
4.1、 STM32CubeMX 配置
4.1.1、时钟配置
4.1.2、指定 SWD 为调试端口
4.1.3、定义一个LED提示灯
4.1.4、生成基础工程
然后打开这个工程进行代码编写
4.1.5、编写 bootloader 代码
定义公共变量和宏
typedef void (*pFunction)(void);
//APP在内部FLASH的起始地址
#define APP_RUNING_ADDRESS 0x8007000
main函数编写如下:
/**
* @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区域有没有APP,如果有则跳转到APP代码区
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 */
//如果没有APP,则会进入死循环,LED灯以300ms交替闪烁
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(300);
}
/* USER CODE END 3 */
}
4.1.6、编译并下载bootloader
编写完毕以后进行编译:
直接点击下载按钮,将程序下载到已经上传好Marlin固件的 MCU 里:(注意,Marlin已经在3小节中上传成功了)
5、移植成功
打开串口调试助手,可以看到有Marlin固件的信息输出了:
接下来我们发送一个 gcode 代码测试一下:
测试成功,至此, Marlin2.x 固件移植到野火 STM32F103ZET6 开发板成功,野火的开发板也可以作为3D 打印机的主板了。
6、项目开源地址
本节代码已同步到码云的代码仓库中,获取方法如下:
码云仓库:
https://gitee.com/morixinguan/marlin2.0.x-support-wildfire-board.git
获取项目方法:
git clone https://gitee.com/morixinguan/marlin2.0.x-support-wildfire-board.git
我还将之前做的一些项目以及练习例程在近期内全部上传完毕,与大家一起分享交流,如果有任何问题或者对该项目感兴趣,欢迎加我微信:morixinguan一起交流学习。