I am making a flash library for an external SPI flash chip attached to my Arduino Due.
I want to be able to store information on it like with the EEPROMWriteAnything
http://playground.arduino.cc/Code/EEPROMWriteAnythingI am trying to store a struct on the Flash chip, below I have my sketch and library files. After trying to read back the data it gives me different values.
It has taken me a while just to get the library to compile with the templates as I have never used them before.
Sketch
#include <SPI.h>
#include <flashMemory.h>
flashMemory exFlash(7,4);
struct trackSettings
{
long monkeys;
int dogs;
double cats;
String mice;
} configuration;
void setup() {
exFlash.begin();
Serial.begin(115200);
configuration.monkeys = 215623;
configuration.dogs = 123;
configuration.cats = 123.123;
}
void loop() {
Serial.print("Saving amount: ");
Serial.println(exFlash.writeAnything(0,configuration));
Serial.println(configuration.monkeys);
Serial.println(configuration.dogs);
Serial.println(configuration.cats);
Serial.println("Saved!");
configuration.monkeys = 0;
configuration.dogs = 0;
configuration.cats = 0;
Serial.println("Local Set to 0");
Serial.print("Reading back: ");
Serial.println(exFlash.readAnything(0,configuration));
Serial.println("After reading");
Serial.println(configuration.monkeys);
Serial.println(configuration.dogs);
Serial.println(configuration.cats);
while(1){}
}
Serial Monitor Output
Saving amount: 32
215623
123
123.12
Saved!
Local Set to 0
Reading back: 32
After reading
-51457
-1
nan
flashMemory.h file
#ifndef flashMemory_h
#define flashMemory_h
#if defined(__AVR__)
#include "Arduino.h"
#include "SPI.h"
#include "hardware/avr/HW_AVR_defines.h"
#elif defined(__arm__)
#include "Arduino.h"
#include "SPI.h"
#include "hardware/arm/HW_ARM_defines.h"
#endif
class flashMemory
{
public:
flashMemory(uint8_t CE);
flashMemory(uint8_t CE,uint8_t SPIClock);
void begin();
boolean bulkErase();
boolean writeEnable();
boolean writeDisable();
boolean verifySR(uint8_t sRegister, uint8_t value);
void timeOut(uint16_t timeOut);
uint16_t timeOut();
void write(uint32_t address, uint16_t value);
byte read(uint32_t address);
template <class T> uint16_t writeAnything(uint16_t ee, const T& value);
template <class T> uint16_t readAnything(uint16_t ee, T& value);
protected:
uint8_t _pinCE, _SPIClock;
uint16_t _timeOut;
boolean _SPIClockSelect;
void _SPIstart(uint8_t rate);
void _writeFlash(uint32_t address, uint16_t value);
};
template <class T> uint16_t flashMemory::writeAnything(uint16_t ee, const T& value)
{
const byte* p = (const byte*)(const void*)&value;
uint16_t i;
for(i = 0; i < sizeof(value);i++)
{
write(ee++,*p++);
}
return i;
}
template <class T> uint16_t flashMemory::readAnything(uint16_t ee, T& value)
{
byte* p = (byte*)(void*)&value;
uint16_t i;
for(i = 0;i<sizeof(value);i++)
{
*p++ = read(ee++);
}
return i;
}
#endif
flashMemory.cpp file
boolean flashMemory::bulkErase()
{
writeEnable();
digitalWrite(_pinCE,LOW);
SPI.transfer(0xC7);
digitalWrite(_pinCE,HIGH);
uint32_t start = millis();
boolean error = false;
while(error == true && millis() - start < _timeOut){
error = verifySR(0,1);
}
return error;
}
void flashMemory::timeOut(uint16_t timeOut)
{
_timeOut = timeOut;
}
uint16_t flashMemory::timeOut()
{
return _timeOut;
}
//Write Enable
//This enables data to be send to the Flash chip to write data.
boolean flashMemory::writeEnable(void){
uint32_t time = millis();
boolean error = false;
do{
digitalWrite(_pinCE,LOW); //Select the Flash chip on the SPI bus
SPI.transfer(0x06); //WREN (Write Enable)
digitalWrite(_pinCE,HIGH); //deselect the Flash chip on the SPI bus
error = verifySR(1,1);
}while(error == false && millis() - time < _timeOut); //Retry until the change was made
return error;
}
//Write Disable
//This disables data to be send to the Flash chip to write data.
boolean flashMemory::writeDisable(){
uint32_t time = millis();
boolean error = false;
do{
digitalWrite(_pinCE,LOW); //Select the Flash chip on the SPI bus
SPI.transfer(0x04); ///WRDI (Write Disable)
digitalWrite(_pinCE,HIGH); //deselect the Flash chip on the SPI bus
error = verifySR(1,1);
}while(error == false && millis() - time < _timeOut); //Retry until the change was made
return error;
}
//Verify Status Register
//Send the register location and the value you are expecting.
//This will return a boolean for the result
boolean flashMemory::verifySR(byte sRegister, byte value){
uint32_t time = millis();
byte error = 0; //Hold the returned value from the status register.
do{
digitalWrite(_pinCE,LOW); //Select the Flash chip on the SPI bus
SPI.transfer(0x05); //Send the status register read instruction
error = SPI.transfer(0xff); //Read the returned data from the chip
if(error == 255){ //If error code is 255 then show user in serial monitor
}
digitalWrite(_pinCE,HIGH); //deselect the Flash chip on the SPI bus
}while(error == 255 && millis() - time < _timeOut); //do it once and if error do it until no error.
byte _value = 0; //The value collected in the required register position
_value = bitRead(error,sRegister); //get the value returned in that position
if(_value != value){ //return if it was the correct response or not.
return false;
}else if(_value == value){
return true;
}
}