software:firmware
MakAir Firmware
eeprom.cpp
Go to the documentation of this file.
1 
25 #ifdef EEPROM_ENABLED // EEPROM support is not finished yet (remove cppcheck-suppress on functions
26  // when feature is stable)
27 
28 // INCLUDES ===================================================================
29 
30 // Associated header
31 #include "../includes/eeprom.h"
32 
33 #include <math.h>
34 
35 // Internal
36 #include "../includes/config.h"
37 #include "../includes/mass_flow_meter.h"
38 #include "../includes/parameters.h"
39 
40 // External
41 #include "CRC32.h"
42 #include <Arduino.h>
43 #include <HardwareSerial.h>
44 #include <IWatchdog.h>
45 #include <OneButton.h>
46 #include <Wire.h>
47 
48 #define EEPROM_I2C_ADDRESS 0x51
49 
50 unsigned char EEPROM_Buffer[256];
51 
52 // cppcheck-suppress misra-c2012-19.2 ; union correctly used
53 union {
54  uint32_t crc;
55  unsigned char c[4];
56  // cppcheck-suppress misra-c2012-19.2 ; union correctly used
57 } eeprom_crc32;
58 
59 #define EEPROM_VIRGIN_NOTINITIALIZED 0xFA
60 #define EEPROM_VIRGIN_TRUE 0xFF
61 #define EEPROM_VIRGIN_FALSE 0xAB
62 uint8_t eeprom_virgin = EEPROM_VIRGIN_NOTINITIALIZED;
63 
64 inline void eeprom_wire_begin(void) {
65  // pause massflowmeter interrupt before opening I2C bus.
67  Wire.begin();
68 }
69 
70 inline void eeprom_wire_end(void) {
71  // resume mass flow meter after releasing I2C bus.
72  Wire.end();
74 }
75 
76 // cppcheck-suppress unusedFunction
77 int32_t eeprom_read(void) {
78  int32_t totalReadCount = 0;
79  uint8_t readCount;
80 
81  // read last 5 bytes (status bytes), check for virgin status. early exit.
82  eeprom_wire_begin();
83  readCount = Wire.requestFrom(EEPROM_I2C_ADDRESS, 5, 0XFB, 1, true);
84  eeprom_crc32.c[0] = Wire.read();
85  eeprom_crc32.c[1] = Wire.read();
86  eeprom_crc32.c[2] = Wire.read();
87  eeprom_crc32.c[3] = Wire.read();
88  eeprom_virgin = Wire.read();
89  eeprom_wire_end();
90 
91  if (readCount != 5u) {
92  // cppcheck-suppress misra-c2012-15.5
93  return EEPROM_ERROR_UNABLE_TO_RW;
94  }
95 
96  if (static_cast<uint8_t>(EEPROM_VIRGIN_TRUE) == eeprom_virgin) {
97  // cppcheck-suppress misra-c2012-15.5
98  return EEPROM_ERROR_READ_VIRGIN;
99  }
100 
101  // read bytes 16 by 16.
102  for (unsigned int page = 0; page < ((sizeof(EEProm_Content) / 16u) + 1u); page++) {
103  eeprom_wire_begin();
104  // requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t
105  // sendStop)
106  readCount = Wire.requestFrom(EEPROM_I2C_ADDRESS, 16, page * 16u, 1, true);
107  totalReadCount += static_cast<int16_t>(readCount);
108  for (unsigned int i = 0; i < 16u; i++) {
109  EEPROM_Buffer[(page * 16u) + i] = Wire.read();
110  }
111  eeprom_wire_end();
112  delay(7);
113  }
114 
115  int32_t returnVal = 0;
116  if (static_cast<uint64_t>(totalReadCount) >= sizeof(EEProm_Content)) {
117  // read was successfull, copy from intermediate buffer to the real EEProm_Content
118  memcpy(&EEProm_Content, &EEPROM_Buffer, sizeof(EEProm_Content));
119  } else {
120  returnVal = EEPROM_ERROR_UNABLE_TO_RW;
121  }
122 
123  // compute CRC32, compare to the one in eeprom
124  uint32_t crc = CRC32::calculate((unsigned char*)&EEProm_Content, sizeof(EEProm_Content));
125  if (crc != eeprom_crc32.crc) {
126  // cppcheck-suppress misra-c2012-15.5
127  return EEPROM_ERROR_CORRUPTED;
128  }
129 
130  return returnVal;
131 }
132 
133 // cppcheck-suppress unusedFunction
134 int32_t eeprom_write(void) {
135  int32_t totalWriteErrors = 0;
136 
137  // write 16 bytes by 16.
138  for (unsigned int page = 0; page < ((sizeof(EEProm_Content) / 16u) + 1u); page++) {
139  eeprom_wire_begin();
140  Wire.beginTransmission(EEPROM_I2C_ADDRESS);
141  Wire.write(page * 16u); // address
142  // don't ask me why "min" function is so clunky...
143  int remainingBytesInPage = ((sizeof(EEProm_Content) - (page * 16u)) >= 16u)
144  ? 16u
145  : sizeof(EEProm_Content) - (page * 16u);
146  Wire.write(&((reinterpret_cast<uint8_t*>(&EEProm_Content))[page * 16u]),
147  remainingBytesInPage);
148  totalWriteErrors += Wire.endTransmission();
149  eeprom_wire_end();
150  delay(7);
151  }
152 
153  // also write CRC
154  eeprom_crc32.crc = CRC32::calculate((unsigned char*)&EEProm_Content, sizeof(EEProm_Content));
155  eeprom_wire_begin();
156  Wire.beginTransmission(EEPROM_I2C_ADDRESS);
157  Wire.write(0xFB);
158  Wire.write(eeprom_crc32.c[0]);
159  Wire.write(eeprom_crc32.c[1]);
160  Wire.write(eeprom_crc32.c[2]);
161  Wire.write(eeprom_crc32.c[3]);
162  totalWriteErrors += Wire.endTransmission();
163  eeprom_wire_end();
164  delay(7);
165 
166  // also write virgin status, if needed
167  if ((static_cast<uint8_t>(EEPROM_VIRGIN_NOTINITIALIZED) == eeprom_virgin)
168  || (static_cast<uint8_t>(EEPROM_VIRGIN_TRUE) == eeprom_virgin)) {
169  eeprom_wire_begin();
170  Wire.beginTransmission(EEPROM_I2C_ADDRESS);
171  Wire.write(0xFF);
172  Wire.write(EEPROM_VIRGIN_FALSE);
173  totalWriteErrors += Wire.endTransmission();
174  delay(7);
175  eeprom_wire_end();
176  }
177 
178  return ((totalWriteErrors == 0) ? 0 : EEPROM_ERROR_UNABLE_TO_RW);
179 }
180 
181 #if MODE == MODE_EEPROM_TESTS
182 // use for tests only
183 // write 0xFF everywhere.
184 void eeprom_virginize(void) {
185  // write 16 bytes by 16.
186  for (int page = 0; page < 16; page++) {
187  eeprom_wire_begin();
188  Wire.beginTransmission(EEPROM_I2C_ADDRESS);
189  Wire.write(page * 16); // address
190  for (int j = 0; j < 16; j++) {
191  Wire.write(0xFF);
192  }
193  Wire.endTransmission();
194  eeprom_wire_end();
195  delay(7);
196  }
197 }
198 
199 void setup(void) {
200  Serial.begin(115200);
201  Serial.print("EEprom test program. size of struct =");
202  Serial.println(sizeof(EEProm_Content));
203  Serial.println("commands available :");
204  Serial.println("r - Read eeprom");
205  Serial.println("w - Write eeprom");
206  Serial.println("d - Dump eeprom (I2C read)");
207  Serial.println("v - Virginize eeprom");
208  Serial.println("b - dump EEProm_Content buffer");
209 
210  MFM_init();
211 }
212 
213 void loop(void) {
214  char inChar;
215  char buffer[100];
216  if (Serial.available()) {
217  inChar = static_cast<char>(Serial.read());
218  // dump and print eeprom content
219  if (inChar == 'd') {
220  Serial.println("dump EEPROM");
221  for (int page = 0; page < 16; page++) {
222  eeprom_wire_begin();
223  int readCount = Wire.requestFrom(EEPROM_I2C_ADDRESS, 16, page * 16, 1, true);
224  (void)snprintf(buffer, sizeof(buffer), "@%02X | ", page * 16);
225  Serial.print(buffer);
226  for (int i = 0; i < 16; i++) {
227  (void)snprintf(buffer, sizeof(buffer), "%02X ", Wire.read());
228  Serial.print(buffer);
229  }
230  Serial.println("");
231  eeprom_wire_end();
232  }
233  Serial.println("====");
234  }
235  // dump and print EEPROM buffer
236  if (inChar == 'b') {
237  Serial.println("dump EEProm_Content");
238  for (int page = 0; page < 16; page++) {
239  (void)snprintf(buffer, sizeof(buffer), "@%02X | ", page * 16);
240  Serial.print(buffer);
241  for (int i = 0; i < 16; i++) {
242  (void)snprintf(buffer, sizeof(buffer), "%02X ",
243  ((unsigned char*)(&EEProm_Content))[page * 16 + i]);
244  Serial.print(buffer);
245  }
246  Serial.println("");
247  }
248  Serial.println("====");
249  }
250  // virginize eeprom
251  if (inChar == 'v') {
252  Serial.println("VIRGINIZING EEPROM ...");
253  eeprom_virginize();
254  }
255  // write eeprom
256  if (inChar == 'w') {
257  Serial.print("writing eeprom... ");
258  int r = eeprom_write();
259  if (EEPROM_ERROR_UNABLE_TO_RW == r) {
260  Serial.println("ERROR, unable to write in EEPROM");
261  } else {
262  Serial.println("EEPROM written");
263  }
264  }
265  // read eeprom
266  if (inChar == 'r') {
267  Serial.print("reading eeprom... ");
268  int r = eeprom_read();
269  if (EEPROM_ERROR_CORRUPTED == r) {
270  Serial.println("ERROR, eeprom corrupted");
271  } else if (EEPROM_ERROR_READ_VIRGIN == r) {
272  Serial.println("ERROR, eeprom vierge");
273  } else if (EEPROM_ERROR_UNABLE_TO_RW == r) {
274  Serial.println("ERROR, unable to read in EEPROM");
275  } else if (0 == r) {
276  Serial.println("OK");
277  }
278  }
279  // update some bytes
280  if (inChar == 'u') {
281  Serial.println("update bytes in the EEProm_Content ");
282  // increment the first byte.
283  (*((unsigned char*)&EEProm_Content))++;
284  }
285  }
286 }
287 #endif
288 
289 #endif
unsigned char c[2]
uint16_t i
volatile uint16_t MFM_force_release_I2C
bool MFM_init(void)
Initialize Mass Flow Meter.
#define MFM_FORCE_RELEASE_I2C_TRUE
#define MFM_FORCE_RELEASE_I2C_FALSE
void loop(void)
Definition: respirator.cpp:161
void setup(void)
Definition: respirator.cpp:49