AceUtils  0.3
Useful Arduino utilties which are too small as separate libraries, but complex enough to have external dependencies to other libraries.
CrcEeprom.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_UTILS_CRC_EEPROM_H
7 #define ACE_UTILS_CRC_EEPROM_H
8 
9 #if ! defined(UNIX_HOST_DUINO)
10 
11 // EEPROM is supported only on certain Arduino boards. In particular, many
12 // (most?) Arduino Zero compatible boards cannot support EEPROM even on Flash
13 // emulation because the version of the SAMD21 chip on the board doesn't
14 // support RWW (read-while-write).
15 #if !defined(AVR) && !defined(ESP8266) && !defined(ESP32) && \
16  !defined(TEENSYDUINO)
17  #error Unsupported architecture
18 #endif
19 
20 #include <EEPROM.h>
21 #include <FastCRC.h>
22 
23 namespace crc_eeprom {
24 
41 class CrcEeprom {
42  public:
43 
48 #if defined(ESP8266) || defined(ESP32)
49  void begin(uint16_t size) {
50  EEPROM.begin(size);
51  }
52 #else
53  void begin(uint16_t /*size*/) {
54  }
55 #endif
56 
60  uint16_t writeWithCrc(int address, const void* const data,
61  const uint16_t dataSize) const {
62  uint16_t byteCount = dataSize;
63  const uint8_t* d = (const uint8_t*) data;
64 
65  // write data blcok
66  while (byteCount-- > 0) {
67  write(address++, *d++);
68  }
69 
70  // write CRC at the end of the data block
71  uint32_t crc = FastCRC32().crc32((const uint8_t*) data, dataSize);
72  uint8_t buf[4];
73  memcpy(buf, &crc, 4);
74  write(address++, buf[0]);
75  write(address++, buf[1]);
76  write(address++, buf[2]);
77  write(address++, buf[3]);
78 
79  bool success = commit();
80  return (success) ? dataSize + sizeof(crc) : 0;
81  }
82 
87  bool readWithCrc(int address, void* const data,
88  const uint16_t dataSize) const {
89  uint16_t byteCount = dataSize;
90  uint8_t* d = (uint8_t*) data;
91 
92  // read data block
93  while (byteCount-- > 0) {
94  *d++ = read(address++);
95  }
96 
97  // read CRC at the end of the data block
98  uint8_t buf[4];
99  buf[0] = read(address++);
100  buf[1] = read(address++);
101  buf[2] = read(address++);
102  buf[3] = read(address++);
103  uint32_t crc;
104  memcpy(&crc, buf, 4);
105 
106  uint32_t dataCrc = FastCRC32().crc32((const uint8_t*) data, dataSize);
107  return crc == dataCrc;
108  }
109 
110  private:
111  void write(int address, uint8_t val) const {
112 #if defined(ESP8266) || defined(ESP32)
113  EEPROM.write(address, val);
114 #else
115  EEPROM.update(address, val);
116 #endif
117  }
118 
119  uint8_t read(int address) const {
120  return EEPROM.read(address);
121  }
122 
123  bool commit() const {
124 #if defined(ESP8266) || defined(ESP32)
125  return EEPROM.commit();
126 #else
127  return true;
128 #endif
129  }
130 };
131 
132 }
133 
134 #endif
135 
136 #endif
crc_eeprom::CrcEeprom::writeWithCrc
uint16_t writeWithCrc(int address, const void *const data, const uint16_t dataSize) const
Write the data with its CRC.
Definition: CrcEeprom.h:60
crc_eeprom::CrcEeprom::readWithCrc
bool readWithCrc(int address, void *const data, const uint16_t dataSize) const
Read the data from EEPROM along with its CRC.
Definition: CrcEeprom.h:87
crc_eeprom::CrcEeprom
Thin wrapper around the EEPROM object (from the the built-in EEPROM library) to read and write a give...
Definition: CrcEeprom.h:41
crc_eeprom::CrcEeprom::begin
void begin(uint16_t size)
Call from global setup() function.
Definition: CrcEeprom.h:49