开源改变世界

精简中断 #1047

推推 grbl 3年前 (2022-10-30) 371次浏览 0个评论
关闭
J-Dunn 打开了这个问题 on 29 Jul 2016 · 18 条评论
关闭

精简中断#1047

J-Dunn 打开了这个问题 on 29 Jul 2016 · 18 条评论

注释

精简中断 #1047

当前的计时器设置工作正常并且经过了很好的测试,但我想知道它是否可以简化并因此加快速度。

是否存在需要固定持续时间的 STEP 脉冲的受支持的驱动程序硬件上下文,或者这是否可以减少到更灵活的条件,即断言 STEP 的最短时间?

谢谢。

精简中断 #1047

我不明白为什么任何硬件都需要最少的时间,但是随着中断中花费的时间接近步进周期,您将用完“关闭”时间。
同样,中断提供了从设置方向到某些硬件可能需要的阶跃脉冲添加延迟的选项

可以在步进中断结束时设置方向,但随后又回到用完“关闭”时间

精简中断 #1047

是否有特定的理由来改变有效的方法?任何变更都存在风险。

精简中断 #1047
作者

J-邓恩 评论 on 30 Jul 2016  

“有什么特别的理由要改变有效的方法吗?”

这是移植到 STM32 的一部分,其中不同的中断结构意味着它无论如何都会被改变。我在这里发布的问题是数百种不同机器硬件配置的相关知识所在的地方。

我的猜测与 langwadt 所说的相同,但这可能只是我对某些可能的排列和要求缺乏了解。

精简中断 #1047

usbcnc 评论 on 30 Jul 2016  

@J-Dunn,如果你想实验定时器,你可以试试Windows仿真项目。这将帮助您了解它的工作原理。我现在正在使用它来分析计时器,看看是否可以优化计时器,甚至将 s 曲线放入 GRBL。Windows 模拟可以帮助您在没有硬件的情况下运行和调试代码。
我首先要做的是看看是否可以为每个计算的计时器删除 srqt 函数。稍后我可能想只使用整数来计算圆。无需使用浮点和 sin cos 函数,不仅节省时间,还节省大量代码空间。

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

What I am trying to do first to see if it is possible to remove the srqt function for each timer calculated.
很难看出在这种计算中如何避免对 sqrt 的需要。我认为可能值得考虑在 AVR 上使用泰勒级数扩展来达到所需的精度,但我怀疑在带有 FPU 的 32b 硬件上是否需要它。

sqrt() 是一个相当复杂的计算,你在STM32F4上计时了吗?

3.10.26
VSQRT
浮点平方根。

我无法找到所需的时钟周期数,但我认为在具有特定指令的硬件上运行时,担心从 GRBL 中消除 sqrt 没有多大意义。

精简中断 #1047

我在 100MHz STM32M4 上大致计时了一个 sqrt(float),大约需要 10us,数学库不使用 FPU 指令可能是为了严格符合 IEEE 标准?

asm 指令 vsqrt.f32 需要 14 个周期,所以 140ns

将 sqrt() 重新定义为使用 vsqrt.f32 的函数似乎不会在快速测试中破坏任何内容

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

哇,快了两个数量级。我假设如果 FPU 有 sqrt 指令,它将被使用。最好将其定义为内联宏,而不是添加 fn 调用的开销。

它主要用于计划阶段,它不太重要,但如果它在那里似乎值得使用。

如果它在 STM32 上占用 10us,那么它在 AVR 上必须至少为 60us。

限制.c:
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.

看起来 sqrt 是 200us 的重要组成部分。这可能值得用 AVR 上的四项泰勒级数展开来代替。这可能会将 sqrt 减少到几个我们。

精简中断 #1047

数学库不使用 FPU 指令可能是为了严格符合 IEEE?

我发现 ST 的勘误表说如果在 14 个周期完成之前返回的 ISR 中使用 VSQRT 会出现问题。这可能是不在 IEEE 环境中使用它的原因。

精简中断 #1047

认为我找到了原因,AVR-GCC 有一个怪癖,即浮点数和双精度数是相同的,所以使用 sqrt(double) 而不是 sqrtf(float) 它们调用相同的函数并不重要

在 ARM 上,浮点数是 32 位,双精度是 64 位,所以当使用 sqrt() 时,使用了可以处理 64 位的冗长库函数,sqrtf() 编译为带有除 -O0 之外的任何内容的单个 vsqrt.f32 指令

对于移植代码,可能应该更改为显式使用浮点函数的浮点版本,即 sinf、cosf、fabsf 等。

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

感谢 langwadt,只是为了完整性 CMSIS 似乎没有使用 sqrtf() 但有自己的带有 arm_sqrt_q15() 等的 fastmath 库。切。

最干净的方法是在头文件中重新定义 sqrt() 而不是编辑所有 sqrt() 调用或使用 #define 并弄乱代码?

#define sqrt sqrtf // 在 Cortex 上使用 FPU vsqrt.f32

??

精简中断 #1047

简单得多,在 grbl.h 中将 math.h 替换为 tgmath.h 它知道类型并调用正确的函数

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

谢谢,我不知道那个标题。用它建造大约 600b 的精灵的大小。

但是,它似乎并没有给我一个 VSQRT :


080170d4 <sqrtf>:
 80170d4: b510        push  {r4, lr}
 80170d6: ed2d 8b02   vpush {d8}
 80170da: 4c29        ldr r4, [pc, #164]  ; (8017180 <sqrtf+0xac>)
 80170dc: b08a        sub sp, #40 ; 0x28
 80170de: eef0 8a40   vmov.f32  s17, s0
 80170e2: f000 fb23   bl  801772c <__ieee754_sqrtf>

sqrtf() 编译为单个 vsqrt.f32 指令

我似乎没有得到那个。在 stepper.c 中使用上面的宏我仍然得到 __ieee754_sqrtf,我错过了什么?

精简中断 #1047

尝试开启一些优化,比如 -OG

精简中断 #1047

@J-Dunn:仅供参考,AVR 上的浮点乘法并没有那么快。每个浮点乘法需要 9-10us(浮点除法更糟)。通过使用泰勒展开,您可能会得到更多的循环,但我担心它的近似值引起的错误以及我如何使相关计算变得不稳定。当你做这样的事情时,你必须非常小心。也就是说,我认为不值得花时间和精力为 328p 收集更多的周期,因为它对大多数人来说运行正常。俗话说,没坏,就不要“修”。

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

尝试开启一些优化,比如 -OG

不,遗憾的是它仍然以 __ieee754_sqrtf 结尾:?

精简中断 #1047

如果您真的很想花时间优化事物,那么您应该使用类似:https ://mcuoneclipse.com/2015/08/23/tutorial-using-gnu-profiling-gprof-with-arm-cortex-m /。其他任何事情都在黑暗中刺伤。过去我曾多次走上这条路,几乎总是发现我认为有问题的地方并不是实际存在的地方。最后,我最好还是把精力花在添加功能上:-(然而,像你一样深入挖掘是一种很好的教育体验。

精简中断 #1047
作者

J-邓恩 评论 2016 年 7 月 31 日  

正如我在上面的#4中指出的那样,这里的重点是移植到 STM32,问题是任何支持的硬件是否都需要一个固定的脉冲周期,而不是一个简单的最小周期,并断言 STEP。

如果下降沿不需要“准时”发生,它会大大简化 ISR。但是可能有一些驱动硬件使用下降沿。也许桑尼可以对此发表评论。

精简中断 #1047
作者

J-邓恩 评论 2016 年 8 月 1 日  

         prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);
 8011fc4: edd3 7a09   vldr  s15, [r3, #36]  ; 0x24
 8011fc8: ee77 7aa7   vadd.f32  s15, s15, s15
 8011fcc: ee67 7a87   vmul.f32  s15, s15, s14
 8011fd0: ee76 7ae7   vsub.f32  s15, s13, s15
 8011fd4: eeb1 0ae7   vsqrt.f32 s0, s15
 8011fd8: eeb4 0a40   vcmp.f32  s0, s0
 8011fdc: eef1 fa10   vmrs  APSR_nzcv, fpscr
 8011fe0: d009        beq.n 8011ff6 <st_prep_buffer+0x186>
 8011fe2: edd3 7a09   vldr  s15, [r3, #36]  ; 0x24
 8011fe6: ee77 7aa7   vadd.f32  s15, s15, s15
 8011fea: ee27 0a87   vmul.f32  s0, s15, s14
 8011fee: ee36 0ac0   vsub.f32  s0, s13, s0
 8011ff2: f001 fd2b   bl  8013a4c <sqrtf>

啊,我想我找到了为什么 sqrtf 还在那里。由于 VSQRT 在错误时返回零(如负数的根)以及非错误的零结果,因此编译器必须依靠 IEEE754 代码周围的 sqrtf() 包装器来进行错误处理。所以它通常是非常快的 FPU 调用,但 sqrtf() 和 __ieee754_sqrtf() 代码仍然被编译进去。

这似乎与严格且一致的错误处理过程有关,该过程符合 IEEE 标准。如果 VSQRT 返回一个有限的结果是所有需要的,它很快,否则它必须重做 calc 很长的路要找出发生了什么。

精简中断 #1047
喜欢 (0)

您必须 登录 才能发表评论!