【问题标题】:Reading in 16 bits from a 32 bit register从 32 位寄存器中读取 16 位
【发布时间】:2012-04-11 08:41:11
【问题描述】:

我正在尝试从特定寄存器中读取某些值。手册指定我必须先访问 16 位 LSB 访问,然后再访问 16 位 MSB 访问。我是否一次读取所有 32 位,然后根据需要分别屏蔽剩余的 16 msb/lsb?或者有没有办法只读取 16 位拳头。

谢谢, 内科

【问题讨论】:

  • 如果您指定您正在谈论的处理器,这将对我们有所帮助。
  • 你在做什么架构?哪个寄存器?
  • 有问题的寄存器是 SoC 上的“时间计数器”
  • 您应该指定 SOC 部分 - 通常寄存器特定于控制器,而不是处理器。要了解如何正确访问硬件寄存器,需要精确的细节。没有这些,一切都是猜测。

标签: c assembly embedded arm


【解决方案1】:

如果手册说要先访问 16 位 LSB,然后再访问 16 位 MSB,请按照手册中的说明进行操作。

例如(小端):

#define REG (*(volatile uint32_t *) 0x1234)

uint16_t val_hi, val_lo;

val_lo = *((volatile uint16_t *) &REG);
val_hi = *((volatile uint16_t *) &REG + 1);

请注意,编译器有时还提供 HI 和 LO 标识符来访问 LSB 或 MSB,例如除了示例中的 REG

#define REGL (*(volatile uint16_t *) 0x1234)
#define REGH (*(volatile uint16_t *) 0x1236)

【讨论】:

  • 但是,这并不能保证“原子性”,因为寄存器可能会在读取 lo 和 hi 之间发生变化。
  • @OliCharlesworth 手册要求对 32 位寄存器的访问是非原子的:首先是 16 位 LSB,然后是 16 位 MSB。这不是一个不寻常的要求。这段代码不保证两个 16 位读取的原子访问。嵌入式编译器通常对易失性对象的访问非常保守,但如果有任何疑问,可以使用汇编代码。
  • 读取低 16 位可能会将高 16 位传输到寄存器。也许医生告诉它或不告诉它;-)
  • @ouah:啊,是的,我错过了那个规范。然后 +1!
【解决方案2】:

目前尚不清楚您使用什么语言来执行此操作。我假设您在 C 中使用内联汇编。

我最熟悉 NASM。对 i386 使用 NASM 语法:

mov eax, 0x12345678 ; load whatever value
mov bx, ax          ; put LSW in bx
shr eax, 16         ; shift MSW to ax
                    ; now ax = MSW, bx = LSW

我猜气体 (C) 代码会是这样的:

movl $0x12345678, %eax # load whatever value
movw %ax, %bx          # put LSW in bx
shrl $16, %eax         # shift MSW to ax
                       # now ax = MSW, bx = LSW

【讨论】:

    猜你喜欢
    • 2010-10-13
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 2012-01-11
    • 2018-03-31
    相关资源
    最近更新 更多