[英]How to assign to a C++ volatile struct?
對於硬件驅動程序,我需要一種將 8 x uint32_t 的 C++ 結構寫入 8 個連續 32 位硬件寄存器塊的方法。 這是我的代碼:
#include "stdint.h"
typedef struct
{
uint32_t a[8];
} TCmd;
class MyClass {
public:
void writeCommandBlock( TCmd* ap_src)
{
TCmd * p_dest = reinterpret_cast< TCmd*>(0x40080000); // base register address
*p_dest = *ap_src;
}
};
int main()
{
MyClass m;
TCmd cmd;
cmd.a[0] = 12;
m.writeCommandBlock(&cmd);
}
(實際的結構將具有位域,並且寄存器地址將由常量定義)。
我想使用一個簡單的賦值運算符(如上所示):
*p_dest = *ap_src;
因為我正在使用 ARM Cortex M4 處理器並希望使用 ldm/stm 指令,從而產生如下內容:
ldr r1, [sp, #4]
ldr r0, [sp]
ldm r1!, {r2, r3, r12, lr}
stm r0!, {r2, r3, r12, lr}
ldm r1, {r2, r3, r12, lr}
stm r0, {r2, r3, r12, lr}
這應該比 memcpy 等更快。
當我啟用優化時問題就來了 - 分配被優化了。 所以我將 p_dest 聲明為 volatile:
volatile TCmd * p_dest = reinterpret_cast< TCmd*>(0x40080000);
但賦值行隨后給出錯誤:
<source>:16:21: error: no viable overloaded '='
*p_dest = *ap_src;
~~~~~~~ ^ ~~~~~~~
<source>:3:9: note: candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'volatile TCmd', but method is not marked volatile
typedef struct
^
<source>:3:9: note: candidate function (the implicit move assignment operator) not viable: 'this' argument has type 'volatile TCmd', but method is not marked volatile
1 error generated.
Compiler returned: 1
請問我該如何解決這個問題?
我假設您不希望 TCmd 易失,因此構建它的速度很快,並且只有對硬件寄存器的最終提交應該是易失的。
這個怎么樣:
#include <cstdint>
#include <array>
#include <algorithm>
using TCmd = std::array<uint32_t, 8>;
class MyClass {
public:
void writeCommandBlock(const TCmd & ap_src)
{
volatile uint32_t * p_dest = reinterpret_cast<volatile uint32_t *>(0x40080000); // base register address
std::copy(&ap_src[0], &ap_src[ap_src.size()], p_dest);
}
};
int main()
{
MyClass m;
TCmd cmd;
cmd[0] = 12;
m.writeCommandBlock(cmd);
}
注意:使用 gcc 和 -O2 這會變成一個循環,使用 -O3 會展開為 8 個加載和存儲。 但循環似乎是更可取的代碼。
雖然ldm
操作碼可能更可取,但我相信stm
寄存器上的 stm 是未定義的。 至少在 RaspberryPI 之類的設備上,設備接口非常脆弱,可能會做錯事。
您可能還應該在寫入之后添加一個內存屏障,以確保它確實發生並完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.