I am looking to write a firmware that writes a structure to and reads it back from EEPROM memory. Converting the structure into a byte stream is working, however when I abstract the problem by putting the structure into a namespace, or call functions that pass pointers to the structure, the byte offsets seem to change by multiples of 2.
To create the memory map of the structure I am using the methods:
template <typename U>
void StoreStruct(U *structure, unsigned int location) {
byte values[sizeof(U)];
memcpy(values, structure, sizeof(U));
...
}
template <typename U>
void RetrieveStruct(U *result, unsigned int location) {
byte readValues[sizeof(U)];
...
memcpy(result, readValues, sizeof(U));
}
When calling these from a common namespace, they function as expected. When called from an architected set of namespaces, the byte offsets appear to move around. Is this expected?
Update:
Test Code:
eeprom.h:
#include <Wire.h>
#include <Arduino.h>
#ifndef EEPROM_H
#define EEPROM_H
struct ExampleStructure {
const byte magic[4] = {192,43,67,181};
byte settingsVersion[4] = {0, 0, 0, 1};
};
namespace EEPROM {
const int memoryI2CAddress = 0x50;
bool CompareArrays(byte *array1, byte *array2, unsigned int count) {
bool result = true;
for (unsigned int i = 0; i < count; i++) { result = result && (array1[i] == array2[i]); }
return result;
}
void ReadBytes(byte *result, unsigned int count, unsigned int baseAddress) {
while (Wire.available()) { Wire.read(); } //Clear buffer
Wire.beginTransmission(memoryI2CAddress);
Wire.write((byte)(baseAddress >> 8));
Wire.write((byte)(baseAddress & 0xFF));
Wire.endTransmission();
unsigned int returnCount = Wire.requestFrom(memoryI2CAddress, count);
for (unsigned int i = 0; i < returnCount; i++) { result[i] = Wire.read(); }
}
void WriteBytes(byte *values, unsigned int count, unsigned int address) {
Wire.beginTransmission(memoryI2CAddress);
Wire.write((byte)(address >> 8));
Wire.write((byte)(address & 0xFF));
Wire.write(values, count);
Wire.endTransmission();
delay(5);
byte checkBytes[count];
ReadBytes(checkBytes, count, address);
if (!CompareArrays(values, checkBytes, count)) { Serial.println("Written bytes not written correctly."); }
else { Serial.println("Everything went fine"); }
}
template <typename U>
void StoreStruct(U *structure, unsigned int location) {
byte values[sizeof(U)];
memcpy(values, structure, sizeof(U));
WriteBytes(values, sizeof(U), location);
}
void Initialise() {
Wire.begin();
ExampleStructure a;
a.settingsVersion[0] = 0;
a.settingsVersion[1] = 0;
a.settingsVersion[2] = 0;
a.settingsVersion[3] = 1;
StoreStruct(&a, 896);
}
}
#endif
settings.h
#include "eeprom.h"
#ifndef SETTINGS_H
#define SETTINGS_H
namespace Settings {
void Initialise() {
ExampleStructure a;
a.settingsVersion[0] = 0;
a.settingsVersion[1] = 0;
a.settingsVersion[2] = 0;
a.settingsVersion[3] = 1;
EEPROM::StoreStruct(&a, 896);
}
}
#endif
Main file:
#include "eeprom.h"
#include "settings.h"
void setup() {
Serial.begin(115200);
Settings::Initialise();
EEPROM::Initialise();
}
void loop() {}
Output:
Writing:
Written bytes not written correctly.
Writing:
Everything went fine