【问题标题】:Embedded ARM/Raspberry Pi Assembly in CC 中的嵌入式 ARM/Raspberry Pi 程序集
【发布时间】:2019-02-28 18:55:07
【问题描述】:

我正在将一个库从 Arduino 移植到 Raspbian。有一部分嵌入式程序集我无法弄清楚,我希望有人可以提供帮助或将我指向不同的资源。有帮助的是,代码注释很好,所以祈祷。非常感谢。

Arduino 代码是:

// The macro below uses 3 instructions per pin to generate the byte to transfer with SPI
// Retreive duty cycle setting from memory (ldd, 2 clockcycles)
// Compare with the counter (cp, 1 clockcycle) --> result is stored in carry
// Use the rotate over carry right to shift the compare result into the byte. (1 clockcycle).
#define add_one_pin_to_byte(sendbyte, counter, ledPtr) \
{ \
    unsigned char pwmval=*ledPtr; \
    asm volatile ("cp %0, %1" : /* No outputs */ : "r" (counter), "r" (pwmval): ); \
    asm volatile ("ror %0" : "+r" (sendbyte) : "r" (sendbyte) : );  \
}

unsigned char sendbyte;
add_one_pin_to_byte(sendbyte, counter, --ledPtr);

我相信在 ARM/Raspberry Pi 上,“比较”是“CMP”而不是“CP”,但问题在于“ROR”语句。我在构建时收到一条错误消息:

/tmp/ccZN1jmK.s: Assembler messages:
/tmp/ccZN1jmK.s:138: Error: bad arguments to instruction -- `ror r3'

我知道“ROR”是 Rotate Over Right,我希望编译器将“r3”放入其中,并且“r3”可能是第四个寄存器(如果你使用第零个我想是第三个寄存器)。

虽然此代码设计得非常紧凑,允许低功耗处理器完成大量工作,但我可以将其转换为 C 并在必要时消除程序集。

【问题讨论】:

  • 快速浏览一下类似sendbyte = (sendbyte >> 1) | (counter == *ledPtr) ? 0x80 : 0x00;
  • 看不到汇编代码但我认为你只能在累加器寄存器上做ROR,所以把R3移到A再试一次?
  • 顺便说一句,即使是原始代码也被破坏/不安全。不能保证两个 asm 块之间会保留进位标志。它应该写成一个块。

标签: c assembly arduino raspberry-pi


【解决方案1】:

我正在将一个库从 Arduino 移植到 Raspbian。

这是行不通的。

The library you're trying to port 专为 Arduino 上使用的 AVR 微控制器的硬件而设计。这取决于内存映射端口 I/O 的可用性并使用特定的硬件计时器。

Raspberry Pi 是一个完全不同的系统。该库所依赖的许多功能在 Pi 上使用的 BCM283x 处理器上不可用。此外,BCM283x 以更高的时钟速度运行,这使得该库使用的大部分优化都是不必要的(甚至是不合适的)。

我不确定您究竟想在这里完成什么,但您需要在更高的层次上解决这个问题。尝试对该代码执行逐行“翻译”不会产生有用的结果。

【讨论】:

  • 虽然我很欣赏这些反馈,但“这行不通”既无用也不准确。我了解这两个平台之间的架构和功能差异。保持积极的态度。
  • 我可以粉饰答案的数量是有限度的!如果您知道这些差异,那么:您打算如何替换该库对计时器中断的使用?
  • setitimer(ITMER_REAL, ...) 模拟了 SIGALRM 上的中断。
【解决方案2】:

我的问题是,在 ARM/Raspberry Pi 上,ROR 指令需要两个参数,即目标寄存器和要旋转的寄存器。在 Arduino 上,处理器只需要一个参数。将构建的语句是:

asm volatile ("ROR %0, %1" : "=r" (sendbyte) : "r" (sendbyte) : );

但是,我决定使用接近@Jester 的 C 代码的东西。

【讨论】:

  • 您现在使用 sendbyte 作为旋转计数,以及要旋转的值。 请参阅 Best practices for circular shift (rotate) operations in C++ 使用内部或纯 C(因为编译器知道如何优化旋转指令);对于ROR 可以应用于除mov 之外的指令的操作数的ARM 特别有用。 (ror 助记符只是mov dst, src ror count 的别名。但还要注意,AVR ROR 通过进位循环;这就是它首先进行比较的原因。源中的 cmets 甚至对此进行了解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 2021-04-01
  • 2021-05-19
相关资源
最近更新 更多