注释
AFAICT 唯一可能成为问题的地方是 report.c,因为其他位置在没有运动时访问数组。在 report.c 中制作了一个副本,当然是为了最大限度地减少报告中使用的数据不一致的风险。作为旁注,在 32 位处理器上运行时风险微不足道 – 很可能报告的位置在到达发件人时已经过时。 |
谢谢。我知道这个潜在的问题。在过去的几年里,我一直在关注位置变量的这个 int32 读取。似乎没有不良影响,因为访问变量的大部分时间都是受控的。它要么在停止处,要么在改变它的中断内。作为@terjeio唯一一次不是在生成状态报告时,这是非关键的。 也就是说,我不完全记得为什么我最终省略了原子读取。可能是懒惰或不想关闭全局中断以减少抖动或可能丢失一些传入数据(不要以为我曾经测试过这个)。 |
我要礼貌地反对这一点,因为根据该数据报告回位置的垃圾数据可能会导致任何应用程序出现任何数量的问题。无论如何,Grbl 的输出应该总是正确的。 我不认为用 cli 包装 memcpy 引入的延迟将是一个重大问题,因为几乎所有与 Grbl 一起使用的驱动程序都是微步进的(或者很少是实际的伺服系统)……也许是这样的150 个时钟周期?如果我算对了,也许是 10 微秒? 我要试一试,看看我的 O-scope 上关于时序和抖动影响的结果。 |
@bdurbrow:尚未报告与潜在竞争条件相关的报告生成问题。但是,不要让它阻止您对其进行测试。我自己很好奇。 至于非关键报告,还有其他同步位置的方法,比如来自通信协议本身。报告位置旨在用于 DRO 目的,而不是用于关键过程,主要是因为它是伪实时的。当 Grbl 有时间发送消息时,消息会被发回,并且可以以最大 10Hz 左右的速率生成一条消息。comm 协议要快得多。 |
IMO 尝试隔离由使 memcpy 原子化引起的时序问题/抖动是浪费时间 – 为此,您需要找到任何时序中断被相对罕见的状态报告延迟的位置。它肯定会被更频繁发生的其他中断淹没。 我有时会查看编译器生成的汇编代码,例如。对于 ARM,memcpy 是这样实现的:
这里它甚至不是一个函数调用,但是 LDMIA 指令是可中断的——但我相信不是在单个寄存器加载的中间——可能导致报告最多减少一步(这可能会四舍五入)。虽然这是针对 32 位处理器的,但 8 位 Atmel 代码将大不相同。 因此,如果您可以使编译生成一个汇编程序列表,您将能够评估由于使其成为原子而引起的最坏情况抖动,这是通过将 memcpy 加上中断禁用/启用所需的时钟周期相加来进行的。 |
在 32 位处理器上使用 32 位变量这不是问题,在 8 位处理器上它而不是禁用中断我认为更有意义的是进行“安全”读取以检查读取后 msb 是否已更改并且重试 |
嗯…无论如何我需要做一些其他相关的时间测量,所以检查这个并没有超出我的范围…
实际上,不……你只需要诱导类似的行为。 我还在玩它,但我今晚所做的是将 sys_position 的原子副本放入 protocol_execute_realtime(),并将一些端口引脚翻转到原子副本和主步进器 ISR 的顶部。所以,我在 o-scope 上看到的是 a) 当原子复制开始时(我的 o-scope 通道 1 上引脚输出脉冲的上升沿)和结束(下降沿);当 ISR 触发时(我的 o-scope 的通道 2 上的脉冲)。 原子副本在进行长距离快速移动时以大约 25khz 左右的频率发射(基本上,我告诉它在小行星带中寻找某个地方 |
@bdurbrow:不要忘记处理器周期是一种有限的资源。
以 10Hz 与 25Khz 运行 memcpy 是完全不同的,后者消耗了大量的可用周期(增加 CPU 负载)。在 10Hz 时,原子复制增加抖动的风险很小 – 例如。与将报告字符串移出到 UART 引入的抖动相比。但是你的测试并没有触发报告,所以这也可能会影响结果,通过相对减少 CPU 负载…… 如果您担心抖动,也许值得考虑切换到 32 位平台,我上面列出的 memcpy 运行 15 个周期,如果我正确地添加它们的话 – 小于 200nS @ 80MHz。或许 ESP32 将成为生成无抖动步进脉冲的最终处理器,如果优先考虑的话——如果 RMT 外设可用于脉冲生成。 |
10hz 与 25khz 是完全不同的——但我只是在寻找最坏的情况;并试图引起延迟,因此它会出现在示波器上以进行测量。我在猜测,但我认为真实世界的结果可能是每秒或每两秒发生一次额外的 10 微秒抖动事件……如果是这样的话。我不认为它会成为 Grbl 用于的机器种类的一个有意义的因素…… @chamnit– 是的,还有一个设备驱动程序使用的额外的(1khz 计时器 – 这是在我的 Mega2560 端口的修改版本上测试的;所以它有用于 lcd、SD 卡和集成矩阵键盘的驱动程序)。FWIW,然而,我昨晚在没有串行数据输入的情况下测量了明显的抖动,所以串行中断不是该测试的一个因素…… |
@bdurbrow:忘了还有串行写中断。它很小,但是全局中断开销是固定的。如果您有串行输出,它可能是一个促成因素。 |
@britt,如果您担心坐标错误,为什么不修复它而不是运行模拟?我在这封电子邮件的末尾提供了一个修复程序。存在潜在的错误,但它被击中的可能性真的很小。其他中断对于可能触发此错误的事实没有任何重要意义。这里承诺的修复:在 report_realtime_status 里面有一个 memcopy memcpy(current_position,sys.position,sizeof(sys.position)); 将此行更改为此 redo_memcpy:memcpy(current_position,sys.position,sizeof(sys.position)); 对于 (idx=0; idx< N_AXIS; idx++) if(((uint8_t*)&sys.position[idx])[1]!=((uint8_t*)¤t_position[idx])[1]) goto redo_memcpy; 克里斯。2018-10-16 19:47 GMT+02:00,Sonny Jeon <notifications@github.com>:
|
我想你是想标记@bdurbrow ? |
@cri-s:你的代码片段中的 uint8_t 数组索引不应该是 3 吗?(对于小端 32 位变量)。 |
不,小端系统需要 1,大端系统需要 2。如果你有 union { uint32_t 变量;uint8_t 变量[4];}; little endian 是 32bit 变量 0xabcde8ff 读入如下: // var[0]==0xff // var[1]==0xe8 // var[2]==0xcd // var[3]==0xab 代码检查第二个字节是否与复制的相同或者是否同时发生了变化。这不一定意味着复制的位置数据是错误的,它只是意味着存在损坏数据的最小可能性。具体在上面的例子中,如果 memcpy 期间的步进中断代码增加了该值,则它变为 0xabcde900 并且在这种情况下会重复 memcopy。相反,步进代码简单地减少了变量,新值是 0xabcde8fe,在这种情况下,不可能得到错误的值。 @布里特 ,感谢指正,给您带来的不便,敬请谅解。2018-10-17 3:07 GMT+02:00,Terje Io <notifications@github.com>:
|
或者… |
@shooter64738这如何与归位、偏移和工作坐标系一起工作? |
如果你设置一个工作坐标偏移量,它只是从已知的机器位置中减去它,然后将 G54、G55 等发送到 grbl。从那时起,工作位置可能与机器位置不同。 |
如果我没看错,我认为存在访问 sys_position 数组的竞争条件。
sys_position 在中断时由 stepper.c 中的 ISR 更新;但是可以在整个代码库的多个位置访问,而不会在访问期间禁用中断。
这也会影响 Grbl 的 mega2560 端口。