开源Marlin2.x源代码架构学习笔记

简介: 开源Marlin2.x源代码架构学习笔记

最近两个月MBA美帝在职研的课程即将结束,经过个人的努力,目前两门课:全球商务、定量决策均分绩点如下,基本上逼近满分(凡尔赛了,哈哈哈),光鲜亮丽的背后,带领小组始终冲在了班级的最前面,同时也付出了不少精力和汗水,通宵了不知道多少个夜晚,交完学期项目以后就结课啦,开始进入下一门课的学习!所以开始有时间可以折腾新东西啦:(不少同学应该知道我开了个知识星球,专门分享这些内容,这里就不好放出来啦,有兴趣和我说即可)

640.png

640.png

Marlin相当庞大,自2.x版本开始,陆陆续续开始集成了32位机,主流的STM32、LPC等高性能MCU逐渐取代了以Arduino2560等8位机的3D打印机方案。Marlin,庞大到让每个初学者开始学习看代码都会觉得闻风丧胆,当然我刚开始接触的时候也不例外,但是不管是学什么东西,只要把大方向掌握了,那么细节的东西用到了再慢慢研究也不迟,同时,Marlin的文档非常少,对于初学者来说,是非常不友好的!以下这些介绍也是Marlin刚开放不久的说明文档,笔者英语水平有限,如有翻译失误,尽情纠正与谅解!

1、Marlin代码工程架构

以下是原版的Marlin固件解压下来的显示情况:

640.png

当使用 PlatformIO 构建Marlin时,它会在.pio此处创建一个文件夹,并且在shell中使用git的时候,这 是当前的工作目录,如下图所示:

640.png

1.2、 buildroot 文件夹

该目录包含开发人员的帮助脚本、字体工具、CI测试工具、Marlin图标和其它数据

1.3、 buildroot/share/PlatformIO 文件夹

电路板定义、环境变量、链接脚本和构建脚本会存放在这个地方,这个文件夹内的构建环境会经常引用 ini文件夹

1.4、 ini 文件夹

包含按 MCU 类型组织的所有 PlatformIO 环境设置, platformio.ini 文件将这些引入为 PlatformIO 提供构建/上传/调试设置,有一个文件特别有用:即是Marlin自定义构建脚本 features.ini 在构建开 始时用于根据启用的功能过滤源文件,因此构建能够完成得更快。

640.png

1.5、 Marlin 文件夹

构建Marlin时,配置文件就放在这个位置:

640.png

1.6、 Marlin/src 文件夹

包含Marlin应用程序,Marlin基于 Arduino 框架进行开发,所以它含有 Arduino 框架的setup()loop() 功能。

2、Marlin应用源代码Marlin/src 文件夹

640.png

Marlin应用源代码主要由以上文件夹组成,核心的入口程序文件是 MarlinCore.cppMarlinCore.h 会做一些宏和变量以及函数的声明,在这个文件中可以找到基于 Arduino 框架的 setup()loop() 函 数,其余的文件夹包含的源码主要的作用如下:

  • core文件夹

640.png

包含Marlin源文件需要的类型、宏、使用程序功能等等,大多数源文件只需要包含 inc/MarlinConfig.h 就可以确保这些文件按预期顺序包含在内。

  • feature文件夹

640.png

包含一些可选功能的支持代码,当然这个文件夹下的代码有些功能是非常简单的,只需要添加一个 G代码或者在公共代码中插入更改即可完成。如果一个特性需要定义一个类或者一组函数,这些附 加的文件将放在这个位置。

  • gcode 文件夹

640.png

包含GCodeParser 类的定义以及所有G代码命令的实现(有一些不在这里实现,但大部分是的),这 些功能都被包装在一个名为 GcodeSuite 的类里,G代码实现的文件被捆绑在多个类别的子文件夹 中,这些文件被命令为具体的G代码,因此可以使用 IDE 的查找功能找到它们。

  • HAL文件夹

640.png

每个控制器系列都提供控制硬件的功能,但并非所有控制器系列都使用相同的接口, Marlin2.x 版本实现了硬件抽象层,更好的屏蔽了平台的差异性,使其它的平台更好的兼容 Arduino 框架。

  • inc文件夹

640.png

包含了Marlin版本、配置条件等等的基本内容,请注意,每个HAL还包含自己的 Conditionals*.hSanityCheck.h文件 。

  • lcd 文件夹

640.png

所有与 LCDTFTOLED、编码器、按钮和串行控制器的相关代码都放在这里,语言翻译通常仅 适用于外部控制器,因此语言翻译也放在这里。

  • libs文件夹

640.png

任何通用数据函数实现或者与硬件库代码都放在这里,如蜂鸣器代码、 CRC16 校验和实现、 3X3 矩阵、数字到字符串的转换功能、用于二进制传输的 HeatShrink ,甚至还有几个 EEPROM 。

  • module文件夹

640.png

这里定义了机器的所有典型功能,包括 3D 打印机拥有的所有的组件,例如:加热器和传感器、热 床探测、路径规划算法、将命令转换为分段运动的高级运动功能、将毫米分段快速转换为步进块的 运动路径规划,以及将块段转换为中断时序和STEP信号的步进器 ISR 。

  • pins文件夹

640.png

Marlin所有的板定义都在这个文件夹中,这里有不同的硬件架构,每个架构下的每块板都有自己独 特的引脚文件, pins.h 根据 MOTHERBOARD 设置进行包含,由于 pins.hMarlinConfig.h 的包 含文件注意,因此它不会包含在其它的地方。

  • sd 目录

640.png

在这里您可以找到所有实现实际文件和文件夹的高级文件系统代码。 CardReader 类是Marlin用 于导航目录、打开G-code文件和从SD卡(或其他媒体)打印的主界面。自从Marlin 2.0.8以来,所有 的媒体类型都派生自 DiskIODriver 抽象类。

3、Marlin的配置

马林是高度可配置的。您将在源代码的许多地方发现应用配置选项来打开和关闭代码、更改行为和提供 值。

  • Marlin源文件如何获得它需要的所有配置值?


首先,当您构建一个c++程序时,第一阶段是分别构建所有的. C和 .cpp 文件。这些文件中的每一个都 必须是完整的,并且每个文件都负责包含它需要的头文件。在大型项目中,这可能会很乏味,所以很多 编译器都允许您创建“预编译头文件”( .PCH 文件),包括所有公共头文件。Marlin不使用 PCH 文件,而是 使用以类似方式工作的常规头文件。


在inc、core、HAL和pins文件夹中头文件的包含顺序很重要,因为每个头文件都是建立在其前身文件之 上的。为了确保始终遵循正确的包含顺序,任何需要配置和条件文件(直到conditionals_ad.h)的代码都 必须包含 inc/ marlinconfigpreh ,而任何需要完全实现的硬件配置的代码都必须包含 inc/MarlinConfig.h


让我们仔细看看每个文件包含的头文件。

3.1、 MarlinConfigPre.h

640.png

3.2、 MarlinConfig.h

640.png

4、一个典型的源文件

将这些内容放在一起,典型的源文件至少将包含 marlinconfigpreh ,以便它可以预先检查一些配置 值。只有在需要时,才会包含其他头文件。有些源文件包含一些特性的头文件是很常见的。

/**
* (c) 2021 Marlin Firmware
* A typical Marlin source.cpp file.
*/
#include "inc/MarlinConfigPre.h"
#if ENABLED(MY_COOL_FEATURE)
#if ENABLED(EXTENSIBLE_UI)
 #include "lcd/extui/ui_api.h"
#endif
#endif // MY_COOL_FEATURE

5、典型的头文件

Marlin头文件不会像源文件一样使用 #if…#endif 来包装。相反,如果不需要头文件,那么它就不会被 包含。Marlin还避免使用c风格的 #ifdef 包装器,并且只在自己的头文件上使用 #pragma 一次。

/**
* (c) 2021 Marlin Firmware
* A typical Marlin header.h file.
*/
#pragma once
extern int my_feature_var;
void do_feature_stuff();

当该特性被禁用时,一些头文件将提供空函数。这使得在单个点关闭东西更容易,并且可以使其他地方 的代码更整洁。

/**
* (c) 2021 Marlin Firmware
* A typical Marlin header.h file.
*/
#pragma once
#include "inc/MarlinConfigPre.h"
#if ENABLED(MY_COOL_FEATURE)
 extern int my_feature_var;
 void do_feature_stuff();
#else
 inline void do_feature_stuff() {}
#endif

6、Marlin的构建过程

一个Marlin式的结构可能需要一段时间,但它像其他任何草图一样工作。Marlin中的所有 .cpp 文件及 其依赖项都将被编译,以及它们包含的任何内容。使用 PlatformIO 的Marlin构建将使用 ini 文件夹中 的文件以及 buildroot/share/PlatformIO 中的脚本,根据您的配置过滤掉未使用的源文件,从而使 其更快。

7、程序和命令流程

Marlin程序的执行从 MarlinCore.cpp 开始,setup()函数初始化,loop()函数主循环,就像 Arduino 草 图一样。loop()函数非常小,主要负责调用idle(),然后在队列前面运行下一个G-code命令。


Marlin中的大多数任务都是通过空闲函数执行的,该函数调用 manage_inactivitythermalManager.manage_heater 。您将看到许多对空闲的调用,因为所有等待循环都使用它来保持 机器运行。如果Marlin太长时间没有呼叫空闲,看门狗就会被触发,为了安全重新启动机器。


这个程序架构需要一些注意,因为我们不希望某个函数被idle本身调用,直到堆栈爆炸为止。在Marlin 只有少数的再入守卫,所以在实践中它工作得很好。


从空闲状态跟踪函数调用,可以很直观地看到Marlin是如何使所有设备和特性在程序上下文中运行的。一些特性一直在进行活动,但是Marlin所做的大部分工作都是由G-code命令发起的。

8、中断服务例程

Marlin定义了一些中断服务例程( ISRs ):


  • 步进 ISR 反复运行,通过向步进电机的STEP和DIR引脚发送脉冲以高速移动规划队列和步进电机。这种中断的频率与移动速度有关。
  • 温度 ISR 以接近 1KHz 的频率读取温度传感器,并在读数准备好时向主程序发送信号。它还管理不 需要非常高基频的加热器和风扇配置的软件/慢 PWM 。
  • 终止 ISR 可以被激活,如果终止引脚是中断能力的。它只在结束引脚的输入状态改变时触发。
  • Tone Timer由 Arduino 为某些平台定义,由Marlin为其他平台定义。它处理脉冲压电蜂鸣器来创 建音调,它运行的频率是当前音调的两倍。
  • 伺服定时器提供了用于伺服系统的 PWM 信号。


平台还将为Serial UART和其他设备定义中断,所以Marlin必须小心选择它使用的中断和计时器。

9、G代码的处理

接下来,让我们看看如何处理 G 代码并遵循程序流程。


  • 0.紧急解析器


当命令队列被阻塞,但是机器需要用户以某种形式输入时,您可以做什么?紧急解析器是一个简单的状态机,它在串行代码的低级别上运行,监视某些命令。当它看到 M108、M112 等时,它立即采取行动来处理代码。


  • 1.从Serial和SD读取


manage_inactivity函数调用queue.get_available_commands(),该函数检查即时缓冲区,查询串行 端口,并读取活动的SD打印文件,将行复制到命令队列中,目的是使其充满。


  • 2.弹出G代码


主循环()调用queue.advance()获取队列前面的命令并立即运行它。在命令完成之前,Marlin不会返回到loop()。注意```queue.advance() ````在队列之前运行内部命令,因此Marlin可以命令自身在常规命令流中 执行一些操作。


  • 3.预扫描G代码


一旦queue.advance()选择了下一个命令,它就调用解析器对G-code行进行预处理。预处理程序验证行号和校验和,如果一切正常,它会在调用特定的G-code处理程序之前对参数进行快速预扫描。


  • 4.处理G代码


所有的G-code处理程序都封装在 GcodeSuite 类中(例如, GcodeSuite::G28() ),尽管有一些在其他地方实现。G-code处理程序是一个简单的没有返回值的void方法。它不是从函数调用中获取参数,而是查询 GCodeParser 类来检查参数并读取它们的值。例如,处理程序使用parser.seen('X')来检查'X'参数是否存在,然后调用parser.value_float()以浮点数的形式获取其数值。请参阅gcode/parser.h获取所有可用的方法。


G-code处理程序几乎可以做任何事情,所以它们被分成单独的文件,每个文件只包含它需要的头文件。所有处理程序必须包括gcode.h,这将包括parser.h


  • 5.命令阻塞


当一个 G1 命令的移动队列被加入时,它就被认为是完成的,所以它可以立即返回。在实践中,特别是 在床水平启用时,每一次线性移动都有可能填满规划队列,并阻塞长时间等待空间打开。


当一个命令需要等待计划器或用户反馈中的空闲空间等内容时,它将调用空闲函数以保持机器的活动和 运行。idle函数甚至会将传入的命令读取到队列中,但是由于idle函数并不会分发g代码或推进队列,所 以在处理程序结束并返回之前,队列不能获得任何空的命令。

往期精彩

步进电机驱动在3D打印应用的学习笔记(一)


光固化3D打印悬空和支撑讲解


3D打印过程与最近的学习成果


两个最常用的3D打印机切片软件


3D打印机marlin固件框架与GCode命令总结


3D打印机Marlin固件串口功能解析和程序移植


让野火F103开发板支持Marlin2.0固件是什么体验?3D打印主控板成员+1


C语言映射表在嵌入式串口解析、UI设计中的应用(值得收藏并实践的精华帖)

目录
相关文章
|
6月前
|
关系型数据库 分布式数据库 数据库
【PolarDB开源】PolarDB与微服务架构的融合:灵活扩展与高效管理
【5月更文挑战第23天】阿里云PolarDB是适用于微服务的高性能分布式数据库,提供数据分片、水平扩展及高可用性解决方案。通过SQL或API实现弹性扩展,内置故障转移保障服务连续性,且兼容MySQL协议,易于集成微服务生态。通过Spring Boot示例展示了PolarDB的配置与集成过程,强调其在现代云原生应用中的重要角色。
161 1
|
13天前
|
存储 SQL Apache
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
Apache Doris 是一个基于 MPP 架构的高性能实时分析数据库,以其极高的速度和易用性著称。它支持高并发点查询和复杂分析场景,适用于报表分析、即席查询、数据仓库和数据湖查询加速等。最新发布的 2.0.2 版本在性能、稳定性和多租户支持方面有显著提升。社区活跃,已广泛应用于电商、广告、用户行为分析等领域。
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
|
18天前
|
编解码 人工智能 开发者
长短大小样样精通!原始分辨率、超长视频输入:更灵活的全开源多模态架构Oryx
【10月更文挑战第23天】Oryx 是一种新型多模态架构,能够灵活处理各种分辨率的图像和视频数据。其核心创新在于能够对图像和视频进行任意分辨率编码,并通过动态压缩器模块提高处理效率。Oryx 在处理长视觉上下文(如视频)时表现出色,同时在图像、视频和3D多模态理解方面也展现了强大能力。该模型的开源性质为多模态研究社区提供了宝贵资源,但同时也面临一些挑战,如选择合适的分辨率和压缩率以及计算资源的需求。
27 3
|
19天前
|
监控 API 调度
开放源代码平台Flynn的架构与实现原理
【10月更文挑战第21天】应用程序的生命周期涉及从开发到运行的复杂过程,包括源代码、构建、部署和运行阶段。
|
1月前
|
分布式计算 大数据 Serverless
云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展
在2024云栖大会开源大数据专场上,阿里云宣布推出实时计算Flink产品的新一代向量化流计算引擎Flash,该引擎100%兼容Apache Flink标准,性能提升5-10倍,助力企业降本增效。此外,EMR Serverless Spark产品启动商业化,提供全托管Serverless服务,性能提升300%,并支持弹性伸缩与按量付费。七猫免费小说也分享了其在云上数据仓库治理的成功实践。其次 Flink Forward Asia 2024 将于11月在上海举行,欢迎报名参加。
178 1
云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展
|
6月前
|
存储 关系型数据库 分布式数据库
【PolarDB开源】深入PolarDB内核:探究存储计算分离架构的设计哲学
【5月更文挑战第20天】PolarDB是阿里巴巴的云原生分布式数据库,以其存储计算分离架构为核心,解决了传统数据库的扩展性和资源灵活性问题。该架构将数据存储和计算处理分开,实现高性能(通过RDMA加速数据传输)、高可用性(多副本冗余保证数据可靠性)和灵活扩展(计算资源独立扩展)。通过动态添加计算节点以应对业务流量变化,PolarDB展示了其在云时代应对复杂业务场景的能力。随着开源项目的进展,PolarDB将持续推动数据库技术发展。
225 6
|
1月前
|
机器学习/深度学习 大数据 PyTorch
行为检测(一):openpose、LSTM、TSN、C3D等架构实现或者开源代码总结
这篇文章总结了包括openpose、LSTM、TSN和C3D在内的几种行为检测架构的实现方法和开源代码资源。
42 0
|
3月前
|
网络协议 Java 物联网
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
766 2
|
6月前
|
存储 关系型数据库 分布式数据库
【PolarDB开源】PolarDB高可用架构解析:确保业务连续性的关键设计
【5月更文挑战第22天】阿里云PolarDB是一款高可用、高性能的云原生数据库,采用分布式共享存储架构实现计算与存储分离。通过主从复制保证数据实时同步,当主节点故障时,从节点能快速接管。此外,PolarDB提供自动故障转移和数据备份恢复功能,确保业务连续性和数据安全性。一个简单的Python SDK使用示例展示了查询数据的过程。总之,PolarDB通过多种机制保障了企业在异常情况下的服务稳定和数据完整性。
268 5
|
6月前
|
人工智能 自然语言处理 开发者
首个基于SSM-Transformer混合架构,开源商业大模型Jamba
【4月更文挑战第13天】AI模型部署与优化迎来新解决方案,ai21labs推出的SSM-Transformer混合架构大模型Jamba结合英伟达NVIDIA NIM服务。Jamba模型在自然语言处理上表现出色,开源特性促进AI技术普及,而NIM提供跨平台、高性能的部署支持。不过,技术门槛、资源需求及优化挑战仍需考虑。
120 6
首个基于SSM-Transformer混合架构,开源商业大模型Jamba