修复了带有引用的内存布局同步变量

时间:2019-07-01 13:56:30

标签: c++ embedded language-lawyer

是否有可能创建一个具有定义的内存布局但有两个需要同步的变量的类/结构,而无需诉诸手动将其与函数同步?

一个例子:

struct hardwareLayout{
    uint8_t regA;
    uint8_t regB;
    uint8_t regC;
}

regAregC需要同时包含完全相同的值(尽管将数据顺序写入寄存器)。并且物理上位于内存中的单独地址

实际上,我想要的是这样的东西

struct abstractInterfaceToHardwareLayout{
    uint8_t regA;
    uint8_t regB;
    uint8_t& regC = regA;
}

它将类似于:

abstractInterfaceToHardwareLayout& interface = static_cast<abstractInterfaceToHardwareLayout&>(pointerToBaseOfHardware);
interface.regA = 0x01;
//and as such interface.regC is also the value 0x01

问题在于无法完成此操作,因为编译器会将regC创建为指向uint8_t regA而不是uint8_t值的指针。因此,接口的内存布局将是:

uint8_t regA;
uint8_t regB;
pointer_to_uint8_t_with_value_semantics regC;

regC中的类型宽度和不一致的值可能不同,因为它是指针而不是值。

对于具有memory-mapped-io的嵌入式设备,可能需要单独的存储位置,这要求寄存器具有一定的存储布局。

2 个答案:

答案 0 :(得分:1)

不可能“同时”进行。如果您只是想在每次访问它们时都保持相同的值,那么:

class hardwareLayout
{
public: 
    void setAC( uint8_t r )
    {
        __disable_interrupts() ;
        regA = r ;
        regC = r ;
        __enable_interrupts() ;
    }

    void setB( uint8_t r ) { regB = r ; }

    uint8_t getA( uint8_t r ) const { return regA ; }
    uint8_t getB( uint8_t r ) const { return regB ; }
    uint8_t getC( uint8_t r ) const { return regC ; }

private:
    volatile uint8_t regA;
    volatile uint8_t regB;
    volatile uint8_t regC;
} ;

启用/禁用中断是必要的,以确保在设置A和设置C之间没有其他要中断的执行线程可以抢占。在目标上执行此操作的实际方法将有所不同。

答案 1 :(得分:1)

以下是一些答案,

在您的示例的严格情况下,向结构中添加一个虚拟成员

struct hardwareLayout{
    uint8_t regA;
    uint8_t regB;
    uint8_t regC;
    uint8_t dummy;
}

使用正确的字节位置中的所需值创建一个32位值 并将32位写入寄存器地址。

void SetReg( uint8_t value)
{
    uint8_t tempArray[4];
    hardwareLayout *pHw = YOUR_HW_ADDR;
    uint32_t *pHwu32 = (uint32_t *)YOUR_HW_ADDR;
    uint32_t *pTempU32;

    tempArray[0] = value;
    tempArray[1] = pHw->regB;
    tempArray[2] = value;
    tempArray[3] = 0;

    pTempU32 = (uint32_t *)(&(tempArray[0]));
    *pHwu32 = *pTempU32;
}

如果您的两个寄存器在内存中的距离不足以为您的处理器写入单个本机整数大小,则为计划B。

如果不是通过两个寄存器具有确切的值,而是通过分阶段写入新值来使它们非常接近,该怎么办?从旧值开始,在每个寄存器中加减一,直到它们都等于新值为止。

如果这些都不起作用,则您的硬件需要软件无法执行的操作。解决方案是更改硬件。使用FPGA一次写入两个寄存器。或根据您的具体情况使用其他硬件解决方案。