Исправлено расположение памяти синхронизированных переменных со ссылками - PullRequest
0 голосов
/ 01 июля 2019

Можно ли создать класс / структуру, которая имеет определенный макет памяти, но имеет две переменные, которые необходимо синхронизировать, не прибегая к ручной синхронизации его с функцией?

Пример:

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

regA и regC должны содержать одно и то же значение одновременно (несмотря на последовательную запись данных в регистр).И физически расположены по разным адресам в памяти

В сущности, что-то вроде этого будет wat, то, что я хочу:

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 ]

1 голос
/ 03 июля 2019

Вот несколько ответов,

В строгом случае вашего примера добавьте фиктивный член в структуру

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;
}

Если ваши два регистра не достаточно близки в памяти, чтобы записать единственный собственный целочисленный размер для вашего процессора, то вот план Б.

Что если вместо двух регистров, имеющих точное значение, вы держите их очень близко, записывая новое значение поэтапно. Начиная со старого значения, добавляйте или вычитайте по одному из каждого регистра, чередуя, пока они оба не равняются новому значению.

Если ни один из этих способов не работает, то вашему оборудованию нужно то, что программное обеспечение не может сделать. Решением этой проблемы является замена оборудования. Используйте FPGA, запишите два регистра одновременно. Или другое решение HW, основанное на вашей конкретной ситуации.

1 голос
/ 02 июля 2019

Понятно «одновременно» невозможно. Если вы просто имеете в виду, что всегда поддерживается одно и то же значение, когда к ним можно получить доступ, тогда:

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. Фактические способы сделать это для вашей цели будут отличаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...