Продолжаем разговор (с) Карлсон, про С++ http://www.caxapa.ru/mcu/wwwboard.html?id=25595
все примерно правильно и на уровне перегрузки операторов я сделал уже давно. Но возможно сделал неправильно, ибо уперся в тупик. Пока раскритикуйте то, что есть, а я попытаюсь красиво сформулировать дальнейшие вопросы.
class TExtBusBase { // примитивы доступа к шине
protected:
TExtBusBase() {};
static void SetAddress (uint16_t Address); // выставляет адрес в порты
static void WriteByte (uint16_t Address, uint8_t Data); // пишет байт
static uint8_t ReadByte (uint16_t Address); // читает байт
};
Поскольку перегрузка операторов не распространяется на члены класса или структуры, а мне нужно "снаружи" хранить самые разные данные, то мне нужно создать шаблон для "любого типа во внешней памяти".
Кроме того, надо как то указывать адрес, по которому размещать эти данные во внешней памяти. Я не придумал ничего лучше, чем неявно использовать для адреса this:
template < class T > class TExtBus : protected TExtBusBase { // переменная произвольного размера
public:
T operator=(T x);
operator T();
protected:
TExtBus() {}
T data; // reserve sizeof(T) bytes
};
/****************************************************************************/
template < class T >
T TExtBus < T > ::operator=(T x) {
for(int i = 0; i < sizeof(T); i++)
WriteByte(uint16_t(this) + i, ((uint8_t *)&x)[sizeof(T)-1-i]);
return x;
}
Теперь могу описывать структуры:
#pragma pack(push,1)
struct TW3100ASocket {
TExtBus < uint8_t > Status;
TExtBus < uint8_t > Options;
TExtBus < uint8_t > dummy[6];
TExtBus < uint32_t > DestinationIP;
TExtBus < uint16_t > DestinationPort, SourcePort;
TExtBus < uint8_t > IPProtocol, TypeOfService;
TExtBus < uint16_t > MaxSegmentSize;
};
struct TW3100A {
TExtBus < uint8_t > Command[4]; // C0_CR...C3_CR
TExtBus < uint8_t > IntStatus[4]; // C0_ISR...C3_ISR
TExtBus < uint8_t > IntFlags, IntMask; // IF, IMR
...........
TW3100ASocket Socket[4];
TExtBus < uint8_t > dummy4[0xE0];
};
тепрь все вроде красиво:
TW3100A *const W3100A_core = 0; //относительно этого рассчитывается this
void foo() {
W3100A_core->Command[0] = RESET; // SW reset
W3100A_core->SourceIP = Config->Ethernet.IP_ADDR;
W3100A_core->Netmask = Config->Ethernet.NETMASK;
W3100A_core->Gateway = Config->Ethernet.GATEWAY;
....
W3100A_core->RxPointers[SocketNo].RxReadPointer = RxReadPtr + RxSize; // Update rx_rd_ptr
....
W3100A_core->Command[SocketNo] = RECEIVE;
}
Какие потециальные грабли могут быть? обращения W3100A_core->member компилятор прекрасно оптимизирует и подставляет константу указатель+смещение члена.