AceTime  1.1.2
Date and time classes for Arduino that support timezones from the TZ Database, and a system clock that can synchronize from an NTP server or an RTC chip.
CrcEeprom.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_HW_CRC_EEPROM_H
7 #define ACE_TIME_HW_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 ace_time {
24 namespace hw {
25 
42 class CrcEeprom {
43  public:
44 
49 #if defined(ESP8266) || defined(ESP32)
50  void begin(uint16_t size) {
51  EEPROM.begin(size);
52  }
53 #else
54  void begin(uint16_t /*size*/) {
55  }
56 #endif
57 
61  uint16_t writeWithCrc(int address, const void* const data,
62  const uint16_t dataSize) const {
63  uint16_t byteCount = dataSize;
64  const uint8_t* d = (const uint8_t*) data;
65 
66  // write data blcok
67  while (byteCount-- > 0) {
68  write(address++, *d++);
69  }
70 
71  // write CRC at the end of the data block
72  uint32_t crc = FastCRC32().crc32((const uint8_t*) data, dataSize);
73  uint8_t buf[4];
74  memcpy(buf, &crc, 4);
75  write(address++, buf[0]);
76  write(address++, buf[1]);
77  write(address++, buf[2]);
78  write(address++, buf[3]);
79 
80  bool success = commit();
81  return (success) ? dataSize + sizeof(crc) : 0;
82  }
83 
88  bool readWithCrc(int address, void* const data,
89  const uint16_t dataSize) const {
90  uint16_t byteCount = dataSize;
91  uint8_t* d = (uint8_t*) data;
92 
93  // read data block
94  while (byteCount-- > 0) {
95  *d++ = read(address++);
96  }
97 
98  // read CRC at the end of the data block
99  uint8_t buf[4];
100  buf[0] = read(address++);
101  buf[1] = read(address++);
102  buf[2] = read(address++);
103  buf[3] = read(address++);
104  uint32_t crc;
105  memcpy(&crc, buf, 4);
106 
107  uint32_t dataCrc = FastCRC32().crc32((const uint8_t*) data, dataSize);
108  return crc == dataCrc;
109  }
110 
111  private:
112  void write(int address, uint8_t val) const {
113 #if defined(ESP8266) || defined(ESP32)
114  EEPROM.write(address, val);
115 #else
116  EEPROM.update(address, val);
117 #endif
118  }
119 
120  uint8_t read(int address) const {
121  return EEPROM.read(address);
122  }
123 
124  bool commit() const {
125 #if defined(ESP8266) || defined(ESP32)
126  return EEPROM.commit();
127 #else
128  return true;
129 #endif
130  }
131 };
132 
133 }
134 }
135 
136 #endif
137 
138 #endif
ace_time::hw::CrcEeprom
Thin wrapper around the EEPROM object (from the the built-in EEPROM library) to read and write a give...
Definition: CrcEeprom.h:42
ace_time::hw::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:88
ace_time::hw::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:61
ace_time::hw::CrcEeprom::begin
void begin(uint16_t size)
Call from global setup() function.
Definition: CrcEeprom.h:50