GithubHelp home page GithubHelp logo

flashstorage's Introduction

FlashStorage library for Arduino

The FlashStorage library aims to provide a convenient way to store and retrieve user's data using the non-volatile flash memory of microcontrollers.

The flash memory, due to it's properties, is generally used to store the firmware code, but it can also be used to store user data.

Supported hardware

Currently, ATSAMD21 and ATSAMD51 cpu are supported (and consequently every board based on this cpu like the Arduino Zero or Aduino MKR1000).

Limited number of writes

Flash memory has a limited amount of write cycles. Typical flash memory can perform about 10000 writes cycles to the same flash block before starting to "wear out" and begin to lose the ability to retain data.

So BEWARE: IMPROPER USE OF THIS LIBRARY CAN QUICKLY AND PERMANENTLY DESTROY THE FLASH MEMORY OF YOUR MICRO, in particular you should avoid to call the write() function too often and make sure that in the entire life of the micro the number of calls to write stay well below the above limit of 10000 (it's a good rule-of-thumb to keep that number in mind even if the manufacturer of the micro guarantees a bigger number of cycles).

The same caution must be taken if you're using the EEPROM API emulation (see below) with the EEPROM.commit() function.

Usage

First of all you must declare a global FlashStorage object for each piece of data you intend to store in the flash memory. For example if you want to store the age of a person you must declare an age_storage like this:

FlashStorage(age_storage, int);

this instruction means "create a FlashStorage to store an int variable and call it age_storage". Now you can use age_storage as a place to safely store an integer:

void readAndStoreUserAge() {
  Serial.println("Please enter your age:");
  String age = Serial.readStringUntil('\n');

  age_storage.write(age.toInt());  // <-- save the age
}

after a reset of the microcontroller you can retrieve the stored age by using:

int user_age = age_storage.read();

Using the alternative EEPROM-like API

If you include FlashAsEEPROM.h you'll get an EEPROM emulation with the internal flash memory. See EmulateEEPROM sketch for an example.

The API is very similar to the well known Arduino EEPROM.h API but with two additional functions:

  • EEPROM.isValid() returns true if data in the EEPROM is valid or, in other words, if the data has been written at least once, otherwise EEPROM data is "undefined" and the function returns false.
  • EEPROM.commit() store the EEPROM data in flash. Use this with care: Every call writes the complete EEPROM data to flash. This will reduce the remaining flash-write-cycles. Don't call this method in a loop or you will kill your flash soon.

License

This library is released under LGPL-2.1.

FAQ

Can I use a single FlashStorage object to store more stuff?

Yes, you can declare a struct with more fields and create a FlashStorage object to store the entire structure. See the StoreNameAndSurname sketch for an example on how to do it.

The content of the FlashStorage is erased each time a new sketch is uploaded?

Yes, every time you upload a new sketch, the previous content of the FlashStorage is erased and filled with 0's. The FlashStorage library does not allow to set another default value.

Do you recommend to use FLASH instead of EEPROM?

No. If your micro provides an EEPROM it's almost always better to use that because it's a kind of memory designed with the specific purpose to store user data (it has a longer lifetime, number of write cycles, etc...).

In the absence of an EEPROM you can use this library to use a piece of the flash memory as an alternative to EEPROM. However, you must always keep in mind of it's limits.

flashstorage's People

Contributors

cbolgiano avatar cmaglie avatar dhalbert avatar eduardog26 avatar mitchellpontague avatar obra avatar oxullo avatar tuxedo0801 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flashstorage's Issues

Question: Data Types

Hi, does this library work with all Data Types? I tried with "String" and "char" and didn't work.

Thanks

Persist data when uploading new sketch

Is there a way to persist data when uploading new sketch?

The README says:

The content of the FlashStorage is erased each time a new sketch is uploaded?

Yes, every time you upload a new sketch, the previous content of the FlashStorage is erased.

There are use cases where you want e.g., configuration data to survive the upload of a new sketch version.

If this is absolutely not possible, is there at least a way to read out the old data, then merging it with the compiled new sketch prior to uploading the new sketch?

flash endurance > 10k

Hi,
first off, thanks for the library. This is more of a comment than an issue, but perhaps it would be good to update the README.

You're giving the number 10k, which I was slightly worried about in my application - so I checked the datasheet: 36.10 NVM characteristics. Flash as EEPROM emulation is minimum 100k typical 600k cycles.

I'm now running a burn test on a SAMD21J, and it is at 500k cycles so far with no errors (which is why I checked the datasheet). I'll edit this comment to add when I start seeing errors.

16 bit ?

Write read 16 bit ?
Not 8 bit as AVR.
EEPROM.write(i, 100+i);
EEPROM.read(i)

Is there a way to store a struct of struct array?

I need to store a struct made of an array of other struct, something like this:

typedef struct {
  boolean valid;
  char label[20];
  char name[20];
} A;

typedef struct {
  A arrayOfAs[50];
} B;

....

FlashStorage(flash_B_store, B);

Is there a way to do it using this library?

EEPROM::Update doesn't look right...

The function needs to set _dirty if, and only if, the new data doesn't equal the existing data. It currently doesn't set the _dirty flag for any reason.

Any chance to port to nRF52840?

@cmaglie would it be possible to use this as a basis for a library to read/write internal flash on the new Nano 33 BLE boards?

I've got a project where I'd like to set a non-volatile 'dirty' bit in flash to check for clean shutdowns.

FlashAsEEROM weird issues

We have some issues with the EEPROM lib ...

The effects we see in a more complex program:

We write >1,5k of data and finally do a commit(). This gives no error, but it seems that after next device startup not all the data is there.

I tried to narrow down the issue to a small testable example:

#define EEPROM_EMULATION_SIZE 2048
#include <FlashAsEEPROM.h>

void setup() {
  SerialUSB.begin(115200);

  while (!SerialUSB) {
  }

  byte firstByte = EEPROM.read(0x0000);

  // if EEPROM is "empty" ...
  if (firstByte == 0xFF) {

    
    // write repeatedly 0x00...0xFF to "EEPROM"
    SerialUSB.println("write to EEPROM ...");

    byte v = 0x00;


    for (int i = 0; i < EEPROM_EMULATION_SIZE; i++) {
      
      SerialUSB.print("Writing: #");
      SerialUSB.print(i);
      SerialUSB.print(" -> ");
      SerialUSB.println(v);
      EEPROM.write(i, v);
      
      v++;
      
    }
    
    SerialUSB.println("  Doing commit ...");
    EEPROM.commit();
    SerialUSB.println("  Doing commit ...*DONE*");
    
    SerialUSB.println("Writing *DONE*");
    SerialUSB.println("Do manual reboot now ...");
    
  }
  else
  {

    // Verify that EEPROM contains repeatedly 0x00...0xFF 
    SerialUSB.println("Read from EEPROM ...");
    byte v = 0x00;
    for (int i = 0; i < EEPROM_EMULATION_SIZE; i++) {

      
      
      byte b = EEPROM.read(i);
      SerialUSB.print("Read: #");
      SerialUSB.print(i);
      SerialUSB.print(" -> ");
      SerialUSB.print(b);
      SerialUSB.print(" vs. ");
      SerialUSB.println(v);
      
      
      if (b!=v) {
        SerialUSB.println("WRONG!!!!");  
        while(true);
      }

      v++;
            
    }
    SerialUSB.println("All fine!!!");  

  }
}

void loop() {
  // nothing to do here
}

The idea: On the first startup, fill the entire EEPROM with sequences of 0x00...0xFF
Then you need to restart the device. Now it will compare the EEPROM content with the required 0x00..0xFF sequences.

Interestignly, I get a different, but also weird behavior:

If I set the EEROM emulation size to 1024, it works quite well.Writing and reading works as expected. All the data can be written und reading out return the same data.

On 2048 the "commit" after writing all the data is hanging forever.

And on 4096 or 8192 it struggles with writing to EEPROM (the for-loop is not finished): Somewhere around EEPROM index ~2200 it just stops writing.

Any ideas on what's wrong?
I'm using a custom SAMD21 board...

best regards,
Alex

Wrong default values?

A fresh and unused eeprom has usually 0xff on each byte... The FlashAsEEPROM gives you 0x00....

Maybe this should be changed? What do you think?

Updating value inside struct.

Is there a way to update only one value inside the struct object instead of updating them all?

I've tried something like:

settings.saved = true;
flashStore.write(settings.saved);

Getting error:

exit status 1
no matching function for call to 'FlashStorageClass<Settings>::write(boolean&)'

trying to write/read a string (variable length) to persistent storage on Nano 33 IOT

i am trying to the the eeprom emulation (I guess?)
https://github.com/cmaglie/FlashStorage/blob/master/examples/EmulateEEPROM/EmulateEEPROM.ino

EEProm.read/write/isValid()

compiles ok, just always reports isValid = false

is this the right function to use?

I REALLY don't CARE HOW its done... name, address, location,, whatever
flash, eeprom, stones in a cup.

the example doesn't say it wont work on this board.. and the lib says it supports samd21 and 51

String fileName="something";
          int i=0;
          for(;i<fileName.length();i++){
            EEPROM.write(i, fileName.charAt(i));  // write out 1 char of data at a time
          }
          EEPROM.write(i,'\0');  // add on a string terminator
          EEPROM.commit();   // flush 

this is a json string with variable length elements, I can imagine a max length..

Data Types for millis()

We should use unsigned long for all millis variables, or uint32_t

I dont understand the distinction

erase() fails if FlashClass::flash_size > ROW_SIZE

Hi Cristian. Very useful library. I was doing some testing with an instance of FlashClass larger than 8192 bytes (ROW_SIZE), and I found an issue. My store was 65536 bytes, and I found that if I called store.erase(), only the first row (8192 bytes) was erased. The issue is the use of INTFLAG.bit.DONE, which does become true when a command completes, but needs to be cleared before doing another command. What you have in erase(ptr) now is:

NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr);
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
while (NVMCTRL->INTFLAG.bit.DONE == 0) { }

The DONE flag is never cleared, so when erase() is called for a store larger than one row, and the code above gets called more than once with no delay, the DONE flag is already set and the erase does not occur. My fix was to use the READY flag rather than the DONE flag, the same as you do for SAMD21. The READY flag is cleared automatically when you start a command, so it never has to be "manually" cleared, as is required for DONE. The code below fixes the problem, and it's nice that it is the same logic as SAMD21.

NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr);
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
while (NVMCTRL->STATUS.bit.READY == 0) { }

write() must also be modified to use READY instead of DONE in the logic for both PBC (page buffer clear) and WP (write page).

EEPROM flash address

hi @cmaglie,
i tried to understand were the EEPROM-data is stored, but i found an address pointer to an array only:
https://github.com/cmaglie/FlashStorage/blob/master/src/FlashStorage.cpp#L29
is this dynamic and depends on sketch size?
can i define my own const flash-address?

i will try to adapt SDU library to run update within internal flash (yes with about 50% of storage lost).
but i also need EEPROM emulation.
for example:
SDU (or IFU=internal flash update) is placed on 0x2000+
sketch is placed on 0x6000+
EEPROM is on last x flash bytes (lets say 8192 bytes)
1fst half of the available area between 0x6000 and EEPROM is for sketch and a second for new FW.

that's like in a datasheet:
grafik

_Dirty is not reset after commit

I've seen #11 and agree with it. When a value is written (EEPROMClass::update), _dirty is set, because a commit is required to make this change persistent.

A commit only writes data to flash memory, if neccessary - equals to if _dirty is set and makes sense as well. But where is the _dirty flag cleared? Otherwise after the first call of EEPROMClass::update the _dirty is always true and makes no sense anymore.

I propose to clear the dirty flag at the end of the commit:

void EEPROMClass::commit()
{
  if (!_initialized) init();
  if (_dirty) {
    _eeprom.valid = true;
    eeprom_storage.write(_eeprom);
    _dirty = false;
  }
}

With this statement you may call commit even within a loop and it does not harm flash memory, because the data is actually only written to flash, if some data was changed with a EEPROMClass::update before.

writting 200kB data to the flash

The way I understand the library, is that the storage is limited to the size of the RAM since one have to first declare the variable in RAM. Is that correct?

I am trying to write a lot of data to the flash (like up to 200kB).

The way I would like it to work is to fill a 256B buffer in RAM and then write it to flash. Then increment the address, refill the buffer and write it again to the new address.
Is there a way to do that?
I looked at the write(flash_address, data, flash_size) function, but between the different class definition and the pointers, I am lost!
Any help (or pointer towards the right direction) would be much welcome.
I think that could also be a useful feature for other data logger projects that will want to store a lot of data.

Erase function doesn't work

I tried to erase the content of flash but it doesn't work. Is this way to erase ? I use a Feather M0 Adalogger

#include <FlashStorage.h>

FlashStorage(MyFlash, uint8_t *);


void setup(){
    MyFlash.write((uint8_t *) 255); // Write something
    MyFlash.erase(1); // The erase function is unknown
}

void loop(){

}

In the FlashStorage.h file there is an erase function but when I call it in the program, it says that the Erase function doesn't exist...

Thanks!

typo , should be SR but wrote CR

typo on line 56 of FlashStorage.cpp

#if defined(__SAMD51__)
// Invalidate all CMCC cache entries if CMCC cache is enabled.
static void invalidate_CMCC_cache()
{
  if (CMCC->CR.bit.CSTS) {      <--- SR.bit.CSTS
    CMCC->CTRL.bit.CEN = 0;
    while (CMCC->SR.bit.CSTS) {}
    CMCC->MAINT0.bit.INVALL = 1;
    CMCC->CTRL.bit.CEN = 1;
  }
}
#endif

Permanent memory after upload a new sketch,

I need permanent memory, which will not be erased after upload a new sketch. Now I have to use an external EEPROM.
Maybe this is possible with FlashStorage also? There must be a part of the Flash that will not be harmed by the upload, but that requires modification of the bootloader etc. What do you think?

error: 'class EEPROMClass' has no member named 'get' or 'put'

Hi! I try to port some code form an Arduino Nano to an Feather M0 Cortex. I run into a problem with the get and put function. Is it not possible to use?

I run with #include <FlashAsEEPROM.h>

void loadEEPROMSettings() {
  // Load settings from EEPROM to custom struct
  EEPROM.get(0, txSettings);

  bool rewriteSettings = false;

  // Loop through all settings to check if everything is fine
  for (uint8_t i = 0; i < numOfSettings; i++) { 

    // If setting default value is -1, don't check if its valid
    if( rules[i][0] != -1 ){

      short val = getSettingValue(i);
    
      if (! inRange(val, rules[i][1], rules[i][2])) {
        // Setting is damaged or never written. Rewrite default.
        rewriteSettings = true;
        setSettingValue(i, rules[i][0] );
      }
    }
  }

  if(txSettings.firmVersion != VERSION){
    
    setDefaultEEPROMSettings();
    
  }
  else if (rewriteSettings == true) {
    updateEEPROMSettings();
  }
  
  // Calculate constants
  calculateRatios();

}

/* 
 * Write settings to the EEPROM then exiting settings menu.
 */
void updateEEPROMSettings() {
  EEPROM.put(0, txSettings);
  calculateRatios();
}

A lot of errors while compiling FlashStoreAnd Retrieve

Board: Wio Terminal
IDE: Arduino 1.8.13
Compiler output:
`FlashStorage.cpp: In member function void FlashClass::write(const volatile void*, const void*, uint32_t)

FlashStorage.cpp: 55:22: error: 'volatile struct NVMCTRL_CTRLB_Type::' has no member named 'MANW
NVMCTRL->CTRLB.bit.MANW = 1
^~~~

FlashStorage.cpp: 60:26: error: 'NVMCTRL_CTRLA_CMDEX_KEY' was not declared in this scope
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC
^~~~~~~~~~~~~~~~~~~~~~~
FlashStorage.cpp:60: note suggested alternative NVMCTRL_CTRLB_CMDEX_KEY
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC
^~~~~~~~~~~~~~~~~~~~~~~
NVMCTRL_CTRLB_CMDEX_KEY

FlashStorage.cpp: 60:52: error: 'NVMCTRL_CTRLA_CMD_PBC' was not declared in this scope
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC
^~~~~~~~~~~~~~~~~~~~~
FlashStorage.cpp:60: note suggested alternative NVMCTRL_CTRLB_CMD_PBC
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC
^~~~~~~~~~~~~~~~~~~~~
NVMCTRL_CTRLB_CMD_PBC

FlashStorage.cpp: 61:33: error: 'volatile struct NVMCTRL_INTFLAG_Type::' has no member named 'READY
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
^~~~~

FlashStorage.cpp: 73:52: error: 'NVMCTRL_CTRLA_CMD_WP' was not declared in this scope
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP
^~~~~~~~~~~~~~~~~~~~
FlashStorage.cpp:73: note suggested alternative NVMCTRL_CTRLB_CMD_WP
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP
^~~~~~~~~~~~~~~~~~~~
NVMCTRL_CTRLB_CMD_WP

FlashStorage.cpp: 74:33: error: 'volatile struct NVMCTRL_INTFLAG_Type::' has no member named 'READY
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
^~~~~
FlashStorage.cpp: In member function void FlashClass::erase(const volatile void*)

FlashStorage.cpp: 92:24: error: 'NVMCTRL_CTRLA_CMDEX_KEY' was not declared in this scope
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER
^~~~~~~~~~~~~~~~~~~~~~~
FlashStorage.cpp:92: note suggested alternative NVMCTRL_CTRLB_CMDEX_KEY
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER
^~~~~~~~~~~~~~~~~~~~~~~
NVMCTRL_CTRLB_CMDEX_KEY

FlashStorage.cpp: 92:50: error: 'NVMCTRL_CTRLA_CMD_ER' was not declared in this scope
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER
^~~~~~~~~~~~~~~~~~~~
FlashStorage.cpp:92: note suggested alternative NVMCTRL_CTRLB_CMD_EP
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER
^~~~~~~~~~~~~~~~~~~~
NVMCTRL_CTRLB_CMD_EP

Error compiling libraries
FlashStorage.cpp: 93:32: error: 'volatile struct NVMCTRL_INTFLAG_Type::' has no member named 'READY
while (!NVMCTRL->INTFLAG.bit.READY) { }
^~~~~`

Either Initilizing, Writing or Reading a String from Flash Storage bricks Seeeduino XIAO.

I cannot quite pinpoint it to either one, but when a string is either initilized, written, or read from a XIAO's flash memory, the next time it is power cycled, there is essentially no communication to the PC it connects to. Not only this, but there is not even an attempt (no Windows 'device connected' sound effect that one normally gets.). The XIAO is bricked to the point to where jumping the reset pins does not even trigger a reset, so that makes me think the processor itself is bricked and can't even initilize/boot anymore.

I used a byte for FlashStorage as well, but I followed plenty of public examples to ensure I did the right steps to utilize it.

Initialization code used (along with some other variables used):

String deviceName = "DAP - 16 Knob Controller";

FlashStorage(d_name, String);
FlashStorage(writeflag, byte);

Reading Code Used:

inline void FetchDeviceName()
{
      char charBoi[32];

      byte nb = writeflag.read();

      if (nb != 69)
        return;


      deviceName = d_name.read();
        
}

Writing Code Used:

inline void WriteDeviceName(String newName)
{
  if (newName == "")
  return;

  d_name.write(newName);
}

Normally, I would do process of elimination and test each of the three functions seperately, but I do not want to risk keep bricking XIAO's.

Storing structs in flash memory

Hi Cristian,
I'm working on some new prototypes/tutorials with the mkr1000 and I'm using your (super useful) library.
The only problem is that I can't store struct, I tried commenting the "Overloaded version of read" in the .h file, but then everything breaks when I try to write on the flash memory.

Since these tutorials will be published on the 2th of April I have 2 questions :
Do you mind to publish this library on the Arduino Libraries repo?
Do you have time to fix the issue ?

Cheers

Are you sure about the 10K write cycles?

I normally associate EEPROM with 1-10K write cycles and flash with 50-100K. The quoted section in this forum post seems to indicate 50K cycles:

Data Retention of Atmel's dataflash devices is a minimum of 10 years.

Endurance in DataFlash is specified as the number of writes (erase/program
cycles) performed on a page before a bit in that page will fail to read
correctly. For the 0.25um DataFlash family (the parts which are
currently in production ), the endurance is typically 50,000 cycles.

Higher endurance values can be achieved by incorporating error detection and
correction, (ECC), since endurance failures tend to be of a single bit and
random nature. All DataFlash products provide additional bytes within each
page in the memory array. These additional bytes can be used to help perform
the ECC function. The 1Meg through 8Meg densities have 8 additional bytes
per page, the 16Meg and 32Meg have 16 additional bytes per page whilst the 64
Megabit has an additional 32 bytes for each page.

SAMD51 NVM cache disable before write

@mitchellpontague @cmaglie

I didn't have a chance to look at #27 before it was merged. Here is one comment.

This erratum says you need to disable the NVM cache before writing to the Page Buffer, for Rev A EFP and Rev D chips. EDIT: incorrect: it's functional in our code: I had misinterpreted the erratum as applicable to old Rev A chips only and had commented this out in our code. In practice I haven't seen this issue, but better safe than sorry.

image

840 byte struct can crash function ?

Can crash ?

Cpu is ARM SAMD and has 32KB of RAM

#include <FlashStorage.h>
Tbb Timer;
FlashStorage(Tim, Tbb);

Timer = Tim.read();

typedef  struct {
  byte L_on1_H;
  byte L_on1_M;
  byte L_of1_H;
  byte L_of1_M;
  byte L_on2_H;
  byte L_on2_M;
  byte L_of2_H;
  byte L_of2_M;
  
  byte M_on1_H;
  byte M_on1_M;
  byte M_of1_H;
  byte M_of1_M;
  byte M_on2_H;
  byte M_on2_M;
  byte M_of2_H;
  byte M_of2_M;
  
  byte Me_on1_H;
  byte Me_on1_M;
  byte Me_of1_H;
  byte Me_of1_M;
  byte Me_on2_H;
  byte Me_on2_M;
  byte Me_of2_H;
  byte Me_of2_M;
  
  byte G_on1_H;
  byte G_on1_M;
  byte G_of1_H;
  byte G_of1_M;
  byte G_on2_H;
  byte G_on2_M;
  byte G_of2_H;
  byte G_of2_M;
  
  byte V_on1_H;
  byte V_on1_M;
  byte V_of1_H;
  byte V_of1_M;
  byte V_on2_H;
  byte V_on2_M;
  byte V_of2_H;
  byte V_of2_M;
  
  byte S_on1_H;
  byte S_on1_M;
  byte S_of1_H;
  byte S_of1_M;
  byte S_on2_H;
  byte S_on2_M;
  byte S_of2_H;
  byte S_of2_M;
  
  byte D_on1_H;
  byte D_on1_M;
  byte D_of1_H;
  byte D_of1_M;
  byte D_on2_H;
  byte D_on2_M;
  byte D_of2_H;
  byte D_of2_M;
  
} Taa;  // 8x7 = 56 byte.

typedef  struct {
	Taa Giorno[15];
  byte AutoZero;

} Tbb; // 56 x 15 = 840 bytetypedef  struct {
  byte L_on1_H;
  byte L_on1_M;
  byte L_of1_H;
  byte L_of1_M;
  byte L_on2_H;
  byte L_on2_M;
  byte L_of2_H;
  byte L_of2_M;
  
  byte M_on1_H;
  byte M_on1_M;
  byte M_of1_H;
  byte M_of1_M;
  byte M_on2_H;
  byte M_on2_M;
  byte M_of2_H;
  byte M_of2_M;
  
  byte Me_on1_H;
  byte Me_on1_M;
  byte Me_of1_H;
  byte Me_of1_M;
  byte Me_on2_H;
  byte Me_on2_M;
  byte Me_of2_H;
  byte Me_of2_M;
  
  byte G_on1_H;
  byte G_on1_M;
  byte G_of1_H;
  byte G_of1_M;
  byte G_on2_H;
  byte G_on2_M;
  byte G_of2_H;
  byte G_of2_M;
  
  byte V_on1_H;
  byte V_on1_M;
  byte V_of1_H;
  byte V_of1_M;
  byte V_on2_H;
  byte V_on2_M;
  byte V_of2_H;
  byte V_of2_M;
  
  byte S_on1_H;
  byte S_on1_M;
  byte S_of1_H;
  byte S_of1_M;
  byte S_on2_H;
  byte S_on2_M;
  byte S_of2_H;
  byte S_of2_M;
  
  byte D_on1_H;
  byte D_on1_M;
  byte D_of1_H;
  byte D_of1_M;
  byte D_on2_H;
  byte D_on2_M;
  byte D_of2_H;
  byte D_of2_M;
  
} Taa;  // 8x7 = 56 byte.

typedef  struct {
	Taa Giorno[15];
  byte AutoZero;

} Tbb; // 56 x 15 = 840 byte

There is a warning on 1.6.6 IDE

WARNING: Category '' in library FlashStorage is not valid. Setting to 'Uncategorized'

I can see that for example Wifi101 has a line
category=Communication

on library.properties file, so I guess it can easily be fixed by adding a similar text. What categories are available I do not know, but the ones that I have are
AzureIoT/library.properties:category=Communication
Ethernet/library.properties:category=Communication
FastLED/library.properties:category=Display
Firmata/library.properties:category=Device Control
SoftWire/library.properties:category=Communication
WiFi101/library.properties:category=Communication
arduino_410717/library.properties:category=Communication

Compile error for feather m4

Hello. older version used to work but the newer one does not allow me to upload a sketch. here is what i get as an error:

Documents\Arduino\libraries\FlashStorage\src\FlashStorage.cpp: In function 'void invalidate_CMCC_cache()':

Documents\Arduino\libraries\FlashStorage\src\FlashStorage.cpp:56:13: error: 'struct Cmcc' has no member named 'CR'; did you mean 'SR'?

   if (CMCC->CR.bit.CSTS) {

             ^~

             SR

i modified CR.bit.CSTS to SR.bit.CSTS and it seems to work ok (example sketch works). is that allright or theres something else is going on. thanks

Use this to pass data to bootloader?

Hi,

In the Zero linker script, there are some bytes reserved between the bootloader space and application space. Is it possible to use your code to store data there, and retrieve it in the bootloader? (I think it's the initial utility of those reserved bytes)

Error handling or return value?

Hi, this is nice libary.

But I found if I build a simple struct like:

struct sct_script {
	char content[40][650];
} sct_actionScript;

FlashStorage(script_store, sct_script);

but if read the script_store before the script_store not write anything yet.

It cause arduino freeze and not able keep running until reset manually.

I tracking the code find read using memcpy(data, (const void *)flash_ptr, size);

but I have no idea to handling memcpy return status code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.