Contact me: hankecnc@gmail.com

可移植性实验(ARM M4) #92

推推 grbl 3年前 (2023-01-21) 157次浏览
打开
MechaSteve 打开了这个问题 2017 年 1 月 15 日 · 51 条评论
打开

可移植性实验(ARM M4)#92

MechaSteve 打开了这个问题 2017 年 1 月 15 日 · 51 条评论

注释

可移植性实验(ARM M4) #92

我已经开始考虑将 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 :
这些应该被删除并替换为事件、轮询和中断驱动逻辑。

可移植性实验(ARM M4) #92
贡献者

@MechaSteve: 谢谢。所有好东西都已经得出了相同的结论。过去一个月有很多线下活动。当我们准备就绪时,很快就会有一些有趣的惊喜出现。无论如何,从长远来看,我正忙于重写代码库以消除大部分这些问题,以确保这一切都是长期可持续的。

可移植性实验(ARM M4) #92 添加了 chamnit漏洞 问题 并删除 漏洞 标签 2017 年 1 月 16 日
可移植性实验(ARM M4) #92

很高兴看到你的店里有什么。

大量的代码库确实可以不变地工作。显然,在 32 位与 8 位数据类型方面存在一些潜在的优化。

不久前,我为 Stellaris 发射台制作了一个 CNC 分线板,我主要只是想在上面实现最低限度的功能。

可移植性实验(ARM M4) #92
贡献者

@MechaSteve: 好吧,可以这么说。这是移植到 LPC 处理器又名 SmoothieBoard 的 Grbl v1.1视频。正如预期的那样,性能近乎荒谬。在他们自己的板上比 Smoothieware 好近一个数量级。开发人员(Todd 和 Brett Fleming,又名 LaserWeb 和 JSCut)能够在两周内移植和测试它。代码可在此处获得。

可移植性实验(ARM M4) #92

AVR 上的 floats 和 double 大小相同,可能想在 ARM 上解决它不存在的问题。
即使用 sqrtf() 而不是 sqrt() 并添加诸如:-Wdouble-promotion、-Wfloat-conversion 和可能的 -fsingle-precision-constant 之类的编译器选项

可移植性实验(ARM M4) #92

@langwadt完全同意。

可移植性实验(ARM M4) #92

我刚刚发现的一个问题应该在 master 分支中得到修复:

mc_parking_motion:
motion_control.h/c 中的声明和实现应包含在 ifdef PARKING_ENABLE 指令中。

我猜 AVR 编译器会忽略这段代码,因为没有任何东西调用它,但它应该被选择掉。当我在我的端口上工作时,它抛出了一个小错误。

可移植性实验(ARM M4) #92

这是我对 GRBL 0.9 的 HAL 的看法 – 对于 TI TM4C123GH6PM (Tiva C),我已经在一个单独的项目(驱动程序)中分离出所有依赖硬件的代码,并且我正在使用函数指针将驱动程序代码绑定到 GRBL – 我这样做不像无数#defines。
TM4C123.zip 的 GRBL HAL
并非 100% 完整且未在真机上测试 – 但初步测试看起来很有希望。当以 80 MHz 运行 CPU 时,IIRC 中断延迟下降到 3uS。

可移植性实验(ARM M4) #92

我的初稿在https://github.com/MechaSteve/grbl_tiva

我最终创建了 inputs.h 和 outputs.h 来处理配置、读取和写入。我还尝试在这些函数中保留所有引脚反转。
我还用一个通用轴位掩码替换了所有基于引脚的位掩码。

在我的待办事项列表中有:
设置中断优先级以允许 Step reset 中断 Step 中断,以及 step 中断串行。
重写串行函数以充分利用 FIFO 的深度。
为 Spindle 创建频率调制以支持 PowerFlex525 脉冲序列输入。
测试限位开关和其他 I/O。
用完整的力学测试

可移植性实验(ARM M4) #92
贡献者

@MechaSteve: 惊人的!感谢您这样做。现在有很多端口,包括过去的一些。我计划花一些时间回顾每个人的移植方法,这样我就可以了解制作“Gnea”核心需要什么。因此,每个端口只需要插入核心即可。这将释放我的一些责任,并将移植工作委托给各个端口维护者。

至于我,SAMD21 端口可通过串行、步进定时器和 I/O 引脚操作。接下来是测试原生 USB 串口,看看有多少 CPU 成本和 EEPROM 仿真。集成本机 USB 一直很奇怪,因为每当我启用步进计时器回调时它就会崩溃/断开连接。任何人有任何想法为什么?昨天大部分时间都在试图弄清楚这一点。

可移植性实验(ARM M4) #92

我知道一些控制命令对 USB 有一些响应时间要求。

检查您正在使用的库的文档。我之前使用过的那些 (Microchip PIC18) 包括关于最小化高优先级中断的警告。

可移植性实验(ARM M4) #92

我认为我对移植 grbl 的另一个主要观察是中断需要抽象一点。

我对 GPIO 写入和读取函数的使用从 Step ISR 中删除了很多硬件特定代码。除了 IO 引脚和重置定时器外,几乎不需要对 ISR 进行任何修改。我认为以下函数将允许与平台无关的 OnStepStart() 回调函数。

  • StepDirSet(长 lDirectionMask)
  • 步骤目录清除()
  • StepSet(长lStepMask)
  • 步骤清除()
  • StepTimerStart(无符号长 ulTimerPeriod)
  • StepResetTimerStart( unsigned long ulPulseWidth)
    用于延迟 -StepResetTimerStart( unsigned long ulPulseWidth, unsigned long ulDelay)

同样应该有一个 OnStepDelay() 和 OnStepReset() 回调。

移植也很棘手的一个领域是 printString、serial_write、环形缓冲区和串行 FIFO 如何与 serialTX ISR 交互。部分问题在于 TX 中断是边沿触发的,因此在启用中断时不会立即调用(假设 FIFO 为空)。这需要手动调用 OnSerialTX() 回调来启动 TX 周期。
另一个问题是它写入 FIFO 后立即被调用。(如果 TX 空闲,一旦写入字节,它会立即从 FIFO 移到移位寄存器,创建 TX_Empty 中断)环形缓冲区在将数据移动到 FIFO更新,因此第一个字节被加载到TX FIFO 两次。我之前
通过移动尾巴来解决这个问题向 FIFO 写入数据,并在回调开始时检查缓冲区是否为空。这确实意味着回调会在缓冲区结束时再执行一次以停止 TX 周期。
我想我可能仍然有 ISR 可能会丢失数据的边缘情况。它可能需要一个 bSerialTXRunning 标志。

可移植性实验(ARM M4) #92

很容易在 FIFO 中引入竞争条件,尤其是当中断和非中断都从中弹出时。您可能必须从可变切换到原子,并特别注意获取-释放语义。

可移植性实验(ARM M4) #92

@MechaSteve我没用过 tiva,但我用过的定时器很少,你在步进中断中使用定时器的方式对我来说是错误的。如果它像大多数定时器一样,当您禁用定时器时,您基本上已经忘记了时间,即您的周期会随着进入中断和禁用定时器的时间以及重新启用定时器所用的时间而变化。

可移植性实验(ARM M4) #92

@tbfleming是的。
我考虑的另一个解决方案是在 UART 中断处理程序中创建一个额外的 else 分支,该分支也将调用 TX 回调。然后我可以使用 IntPendSet 函数强制对 UART 处理程序进行软件中断。这样回调就不会被中断/抢占。我认为这将避免潜在的问题。

@langwadt正确的。由于我努力调试步进输出未打开的原因,代码有点乱。(简短版本:我没有正确启用 GPIO 端口。>_<)
对于 Timer1A,这并不重要,只是延迟和脉冲宽度。
Timer0A 的操作应该略有不同。TIVA 上的定时器可以选择在写入寄存器时立即加载重新加载值(默认),或者等到下一个超时事件加载值。
正确的方法是通过加载第一个定时器周期来启动定时器,将其配置为立即重新加载,然后启用定时器。然后,将配置更改为仅在每个连续的周期更改超时时重新加载。我需要确保这能正确计算步数。

可移植性实验(ARM M4) #92

@MechaSteve也许看看带串行端口 TX 的 DMA?将节省处理中断、TX 启动等的复杂性
。https://sites.google.com/site/luiselectronicprojects/tutorials/tiva-tutorials/tiva-dma/understanding-the-tiva-dma有一些很好的阅读话题。回到 Z80 SCC 时代,我们更喜欢 DMA 而不是中断驱动。

可移植性实验(ARM M4) #92

@gerritvAFAIK,grbl 中的所有 TX 字符串都以换行符结尾。这可以与固定双缓冲区一起使用,通过 DMA 将串行消息传输到 UART。
– 在位置 A 缓冲数据,直到换行为止。
– 如果 DMA 空闲,则从 A 开始传输,开始缓冲到位置 B

环形缓冲区包含在 serial.h 中,因此即使对传输方法(USB 缓冲区)进行较大更改也只需要修改此区域。到目前为止,这个版本只使用了可用内存的一小部分;因此,创建足够大的缓冲区应该没有问题。

可移植性实验(ARM M4) #92

我会将 DMA 指向消息,无需复制内容。可能需要一个消息 ptrs/lengths 队列,供 DMA 完成处理程序处理。我发现 Tiva(也许还有其他)具有收集/分散 DMA 功能很有趣。在 1970 年代,我们在用于串行通信和打印机的 Univac CS/P 处理器中广泛使用了这种技术。

可移植性实验(ARM M4) #92

这对于在 flash rom 中包含大量错误消息的表来说效果很好,但有点需要在 ram 中动态组装反馈。
我也更倾向于认为错误消息应该是引用文档的代码。这就是大多数工业硬件所做的,这样 GUI 就可以处理任何本地化(并修复拼写错误)。

可移植性实验(ARM M4) #92
贡献者

@MechaSteve:原来是 SparkFun SAMD21 开发板导致了 USB 崩溃。不完全确定为什么。Arduino 零完美运行。

可移植性实验(ARM M4) #92

我的 TI TM4C123GH6PM HAL 端口现已更新至 1.1f,并在我的 CO2 激光雕刻机外部进行了部分测试 – 电机正在运行并且 I/O 正在工作。
GRBL 与我自己的“像素完美”图像雕刻代码(不涉及 GCode)共存,甚至与之共享基本的驱动程序例程,通过 HAL 函数表路由调用完成。我自己开发的驱动卡有两个 24 位硬件计数器来跟踪 X 和 Y 位置,它们被一个单独的处理器用来提供用于切割的 PPI 模式——不涉及 GRBL 驱动程序代码。PPI 模式是另一种(更好的?)替代方案,用于控制传送到切口的激光功率。接下来 – 真实生活测试。顺便说一句:关于我的激光的更多信息可以在 buildlog.net 上找到

可移植性实验(ARM M4) #92
贡献者

@terjeio: 感谢分享!顺便说一句,我无法追踪您的代码。你能把它贴在某个地方吗?我想看看你是如何做你的 HAL 的,因为我现在正在把它正式化,并且想在发布它之前收集更多的想法和概念。

可移植性实验(ARM M4) #92

@terjeio:我很好奇,因为您对离散计时器的使用与我考虑过的解决方案类似。您是否探索过将步进脉冲输出连接到全 32 或半宽定时器/计数器模块的计数器输入?

此外,对于 PPI 模式,您是否考虑过创建一个虚拟的第 3 轴,其中每个运动在 z 轴和 xy 平面上移动相等的距离?

每英寸脉冲模式也可以为我提供一种很好的方法,让我使用我正在使用的 VFD 创建每齿进给。

可移植性实验(ARM M4) #92
terjeio 评论了 2017 年 2 月 22 日  

@chamnit:在这里 – 驱动程序部分将被视为不完整,因为它依赖于我的雕刻师的代码,我现在不会发布它,因为它只会混淆。我也已经开始转换我的独立库,如果有兴趣可以稍后发布。我的基本想法是核心 GRBL 代码不应包含任何硬件相关代码,该部分被抽象出来并通过函数表 (hal.h) 访问 – main.c 被 grbllib.c 替换为入口点(我是使用 GRBL 作为库)。使用函数表使我可以轻松地在我自己的雕刻例程和 GRBL 之间切换,而无需重复代码。我已经开始对位带进行一些试验,我现在正在使用它来控制电机 – 必须对 GRBL 进行一些更改才能将其用于内部标志。
GRBL Driver.zip GRBL 库
.zip

编辑:拼写错误…

可移植性实验(ARM M4) #92

@MechaSteve:我认为不可能通过定时器可靠地计算步进脉冲,你必须确保计数方向遵循方向脉冲。好吧,至少当脉冲/方向信号来自 MPU 之外时,我的卡也被设计为与 Mach3 一起工作。我在 VHDL (CPLD) 中创建了我的(可锁存的)计数器,我正在使用 MSP340G2553 处理器来处理 PPI 生成,处理器不断轮询定时器并计算行进距离(斜边 – “如乌鸦飞翔”)并将其用于只要激光器打开,就会产生激光脉冲。我不确定你所说的涉及 Z 的虚拟第 3 轴是什么意思——我的实现 Z(激光开/关)是 1 或 0,只要它在被送入之前为 1,它就会被 PPI 处理器切碎激光管。

可移植性实验(ARM M4) #92
贡献者

@terjeio: 太谢谢了!看起来您正在使用函数指针来管理 HAL。我正在用宏和内联函数做一些不同的方法。我假设这样会更有效率。效率有多高,我不确定。无论哪种方式,方法都非常相似。

可移植性实验(ARM M4) #92

@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 –

喜欢 (0)