注释
|
@MechaSteve: 谢谢。所有好东西都已经得出了相同的结论。过去一个月有很多线下活动。当我们准备就绪时,很快就会有一些有趣的惊喜出现。无论如何,从长远来看,我正忙于重写代码库以消除大部分这些问题,以确保这一切都是长期可持续的。 |
|
很高兴看到你的店里有什么。 大量的代码库确实可以不变地工作。显然,在 32 位与 8 位数据类型方面存在一些潜在的优化。 不久前,我为 Stellaris 发射台制作了一个 CNC 分线板,我主要只是想在上面实现最低限度的功能。 |
|
@MechaSteve: 好吧,可以这么说。这是移植到 LPC 处理器又名 SmoothieBoard 的 Grbl v1.1视频。正如预期的那样,性能近乎荒谬。在他们自己的板上比 Smoothieware 好近一个数量级。开发人员(Todd 和 Brett Fleming,又名 LaserWeb 和 JSCut)能够在两周内移植和测试它。代码可在此处获得。 |
|
AVR 上的 floats 和 double 大小相同,可能想在 ARM 上解决它不存在的问题。 |
|
@langwadt完全同意。 |
|
我刚刚发现的一个问题应该在 master 分支中得到修复: mc_parking_motion: 我猜 AVR 编译器会忽略这段代码,因为没有任何东西调用它,但它应该被选择掉。当我在我的端口上工作时,它抛出了一个小错误。 |
|
这是我对 GRBL 0.9 的 HAL 的看法 – 对于 TI TM4C123GH6PM (Tiva C),我已经在一个单独的项目(驱动程序)中分离出所有依赖硬件的代码,并且我正在使用函数指针将驱动程序代码绑定到 GRBL – 我这样做不像无数#defines。 |
|
我的初稿在https://github.com/MechaSteve/grbl_tiva 我最终创建了 inputs.h 和 outputs.h 来处理配置、读取和写入。我还尝试在这些函数中保留所有引脚反转。 在我的待办事项列表中有: |
|
@MechaSteve: 惊人的!感谢您这样做。现在有很多端口,包括过去的一些。我计划花一些时间回顾每个人的移植方法,这样我就可以了解制作“Gnea”核心需要什么。因此,每个端口只需要插入核心即可。这将释放我的一些责任,并将移植工作委托给各个端口维护者。 至于我,SAMD21 端口可通过串行、步进定时器和 I/O 引脚操作。接下来是测试原生 USB 串口,看看有多少 CPU 成本和 EEPROM 仿真。集成本机 USB 一直很奇怪,因为每当我启用步进计时器回调时它就会崩溃/断开连接。任何人有任何想法为什么?昨天大部分时间都在试图弄清楚这一点。 |
|
我知道一些控制命令对 USB 有一些响应时间要求。 检查您正在使用的库的文档。我之前使用过的那些 (Microchip PIC18) 包括关于最小化高优先级中断的警告。 |
|
我认为我对移植 grbl 的另一个主要观察是中断需要抽象一点。 我对 GPIO 写入和读取函数的使用从 Step ISR 中删除了很多硬件特定代码。除了 IO 引脚和重置定时器外,几乎不需要对 ISR 进行任何修改。我认为以下函数将允许与平台无关的 OnStepStart() 回调函数。
同样应该有一个 OnStepDelay() 和 OnStepReset() 回调。 移植也很棘手的一个领域是 printString、serial_write、环形缓冲区和串行 FIFO 如何与 serialTX ISR 交互。部分问题在于 TX 中断是边沿触发的,因此在启用中断时不会立即调用(假设 FIFO 为空)。这需要手动调用 OnSerialTX() 回调来启动 TX 周期。 |
|
很容易在 FIFO 中引入竞争条件,尤其是当中断和非中断都从中弹出时。您可能必须从可变切换到原子,并特别注意获取-释放语义。 |
|
@MechaSteve我没用过 tiva,但我用过的定时器很少,你在步进中断中使用定时器的方式对我来说是错误的。如果它像大多数定时器一样,当您禁用定时器时,您基本上已经忘记了时间,即您的周期会随着进入中断和禁用定时器的时间以及重新启用定时器所用的时间而变化。 |
|
@tbfleming是的。 @langwadt正确的。由于我努力调试步进输出未打开的原因,代码有点乱。(简短版本:我没有正确启用 GPIO 端口。>_<) |
|
@MechaSteve也许看看带串行端口 TX 的 DMA?将节省处理中断、TX 启动等的复杂性 |
|
@gerritvAFAIK,grbl 中的所有 TX 字符串都以换行符结尾。这可以与固定双缓冲区一起使用,通过 DMA 将串行消息传输到 UART。 环形缓冲区包含在 serial.h 中,因此即使对传输方法(USB 缓冲区)进行较大更改也只需要修改此区域。到目前为止,这个版本只使用了可用内存的一小部分;因此,创建足够大的缓冲区应该没有问题。 |
|
我会将 DMA 指向消息,无需复制内容。可能需要一个消息 ptrs/lengths 队列,供 DMA 完成处理程序处理。我发现 Tiva(也许还有其他)具有收集/分散 DMA 功能很有趣。在 1970 年代,我们在用于串行通信和打印机的 Univac CS/P 处理器中广泛使用了这种技术。 |
|
这对于在 flash rom 中包含大量错误消息的表来说效果很好,但有点需要在 ram 中动态组装反馈。 |
|
@MechaSteve:原来是 SparkFun SAMD21 开发板导致了 USB 崩溃。不完全确定为什么。Arduino 零完美运行。 |
|
我的 TI TM4C123GH6PM HAL 端口现已更新至 1.1f,并在我的 CO2 激光雕刻机外部进行了部分测试 – 电机正在运行并且 I/O 正在工作。 |
|
@terjeio: 感谢分享!顺便说一句,我无法追踪您的代码。你能把它贴在某个地方吗?我想看看你是如何做你的 HAL 的,因为我现在正在把它正式化,并且想在发布它之前收集更多的想法和概念。 |
|
@terjeio:我很好奇,因为您对离散计时器的使用与我考虑过的解决方案类似。您是否探索过将步进脉冲输出连接到全 32 或半宽定时器/计数器模块的计数器输入? 此外,对于 PPI 模式,您是否考虑过创建一个虚拟的第 3 轴,其中每个运动在 z 轴和 xy 平面上移动相等的距离? 每英寸脉冲模式也可以为我提供一种很好的方法,让我使用我正在使用的 VFD 创建每齿进给。 |
|
@chamnit:在这里 – 驱动程序部分将被视为不完整,因为它依赖于我的雕刻师的代码,我现在不会发布它,因为它只会混淆。我也已经开始转换我的独立库,如果有兴趣可以稍后发布。我的基本想法是核心 GRBL 代码不应包含任何硬件相关代码,该部分被抽象出来并通过函数表 (hal.h) 访问 – main.c 被 grbllib.c 替换为入口点(我是使用 GRBL 作为库)。使用函数表使我可以轻松地在我自己的雕刻例程和 GRBL 之间切换,而无需重复代码。我已经开始对位带进行一些试验,我现在正在使用它来控制电机 – 必须对 GRBL 进行一些更改才能将其用于内部标志。 编辑:拼写错误… |
|
@MechaSteve:我认为不可能通过定时器可靠地计算步进脉冲,你必须确保计数方向遵循方向脉冲。好吧,至少当脉冲/方向信号来自 MPU 之外时,我的卡也被设计为与 Mach3 一起工作。我在 VHDL (CPLD) 中创建了我的(可锁存的)计数器,我正在使用 MSP340G2553 处理器来处理 PPI 生成,处理器不断轮询定时器并计算行进距离(斜边 – “如乌鸦飞翔”)并将其用于只要激光器打开,就会产生激光脉冲。我不确定你所说的涉及 Z 的虚拟第 3 轴是什么意思——我的实现 Z(激光开/关)是 1 或 0,只要它在被送入之前为 1,它就会被 PPI 处理器切碎激光管。 |
|
@terjeio: 太谢谢了!看起来您正在使用函数指针来管理 HAL。我正在用宏和内联函数做一些不同的方法。我假设这样会更有效率。效率有多高,我不确定。无论哪种方式,方法都非常相似。 |
|
@chamnit : I have not checked the cost of inlining versus function calls, the cost for indirecting function calls via pointers versus calling them directly is very little – only a few cycles IIRC. Maybe the biggest advantage of using my approach is maintainability – |


我已经开始考虑将 grbl 移植到 ARM M4 平台,并且我发现了一些可以提高整体可移植性的清晰区域。我认为移植到各种平台的一个好方法是对硬件相关模块使用相同的 .h 并限制对 .c 实现的所有更改。(除了 cpu_map.h 文件)
免责声明:这些是我最初的发现,几乎肯定会被修改、修改、附加和/或丢弃。我绝不是这方面的专家。(或任何真的
)
GPIO Init:
当前的代码有很多非常相似的 GPIO 初始化分散在各处。应该有一组通用的 GPIO 初始化函数。这些应该使用以 FUNCTION_PORT, FUNCTION_BIT 形式定义的宏。init 函数不是时间关键的,对于更简单的逻辑可能需要一点时间。应该有 GPIOinitInput(ulPort, ulPin)、GPIOinitOutput(ulPort, ulPin),以及用于写入和读取单个引脚的轻量级 GPIOset、GPIOclear 和 GPIOtest 宏。
操作员面板/控制引脚:
这些实际上应该有自己的 operator.h/operator.c 包含模块。.h 应该定义一个位压缩控制字和一个 getControlWord(void) 函数。
中断:
将所有 ISR 重组为一个包含也可以简化可移植性。.h 应该定义哪些中断事件应该调用其他模块中的哪些函数。即,任何限位开关的引脚变化中断都应调用限位模块中的函数 OnLimitEvent(uint8 limitState),然后清除所有挂起的限位中断。所有引脚更改中断都可以汇集到同一个 ISR,然后 ISR 可以根据引脚映射选择特定的处理程序。
串行:
类似于操作面板,最好将平台相关的外围功能与不可知的缓冲区功能分开。这也将简化未来使用 USB、网络或其他通信接口的修改。
Stepper.c
正如预期的那样,这是最集中的 HW 依赖代码。这个模块的接口越好,就越容易试验不同的算法和其他电机类型。
原子设置/重置:将
它们重构为硬件特定的螺母和螺栓区域。许多 Arm 处理器具有位带内存,允许真正原子设置/清除单个位。
_delay_ms / _delay_us :
这些应该被删除并替换为事件、轮询和中断驱动逻辑。