Arduino Forum

Products => Arduino Due => Topic started by: riddik00 on Mar 19, 2015, 08:24 am

Title: how to write and read arduino due internal flash memory?
Post by: riddik00 on Mar 19, 2015, 08:24 am
hello,
I need to store data in arduino due after the power down.
what i need is, to take an IR code from a remote and store in the arduino DUE internal flash memory.
i can't find any reference anywhere to how to do that, all say to write to EEPROM but on arduino DUE there is not EEPROM.
Title: Re: how to write and read arduino due internal flash memory?
Post by: Palliser on Mar 19, 2015, 10:41 pm
Hello riddik00,
I use the following library:
https://github.com/sebnil/DueFlashStorage (https://github.com/sebnil/DueFlashStorage)

You can save/retrieve data from the internal Flash of Due. You will not lost the data even when power is down. The only way to lost the data is when you reprogram Due.

Caveat: You can 'brick' your Arduino Due if lack of power during writing/retrieving on flash. Regards,

p
Title: Re: how to write and read arduino due internal flash memory?
Post by: acherian on Mar 31, 2015, 05:25 am
Dear Palliser,

I am trying to use the DueFlashStorage. I am fairly new to arduino, so had few questions on this library.
1.  I am using this with ethernet shield and Due. My code is currently 32,120 (6%) of storage space. This will go up. Do you know how to change the offset of the flash page in this lib so it is not conflicting with the program itself?
2. If I use the native usb port to program, after the first time if I reprogram, IDE shows error saying flash is locked. have you come across this issue? it works ok with programming port though.

I would appreciate any inputs on this. kind regards,
Title: Re: how to write and read arduino due internal flash memory?
Post by: MorganS on Mar 31, 2015, 06:22 pm
1. Don't do that. The library already has that offset built in.
2. Then use the port which works.
Title: Re: how to write and read arduino due internal flash memory?
Post by: acherian on Apr 01, 2015, 03:30 am
MorganS,

Thanks for the comment. The library already has an offset: True, but that (according to SebNil, the author) is a fixed offset. It worked for him, and it may work for me, but on his blog page, he has replied to someone that it is user's responsibility to calculate offset based on the code. So I just wanted to know how to do that in case needed.

And yes, I am using the port that works for now. This does require a second processor (for future designs if we go that way). It would be nice to keep the design simple hence I was wondering what causes the flash lock on the native programming port.
Title: Re: how to write and read arduino due internal flash memory?
Post by: exedor on Jul 29, 2015, 02:22 am
There some predefined constants that are already defined.  The Due has two banks of flash memory that I *think* are 256K each.  There are constants defined called IFLASH0_ADDR and IFLASH1_ADDR, and a few others.

Those are the base address of the two banks of flash memory.  To calculate the write address, assuming you want to put your stuff at the very back (opposite end of program memory) of the flash address space, then you would calculate it like this:

Code: [Select]
byte *writeAddr = (byte *)(IFLASH1_ADDR + IFLASH1_SIZE - sizeof(whatever_structure_you_want_store));


However, the best idea is probably to put it at the beginning of the first page that will give you the space you need.  In which case you would do something like this:

Code: [Select]
u_int pages = sizeof(whatever_you_want_stored) / IFLASH1_PAGE_SIZE;
if (sizeof(whatever_you_want_stored) % IFLASH1_PAGE_SIZE > 0) pages++;
byte *writeAddr = (byte *)(IFLASH1_ADDR + IFLASH1_SIZE - IFLASH1_PAGE_SIZE * pages);


These are absolute addresses.  After looking at his library it looks like address 0 is probably the same as IFLASH1_ADDR.  That being the case, you would use this for the writeAddr definition:

Code: [Select]
byte *writeAddr = (byte *)(IFLASH1_SIZE - IFLASH1_PAGE_SIZE * pages);
Title: Re: how to write and read arduino due internal flash memory?
Post by: earx on Jun 24, 2016, 10:07 pm
*bump*

this sounds like a great library. recently did this on the NXP LPC2468 and it works like a charm. however, the brick part scares me. what if the user is a moron and decides to power down while the thing is writing? and how long does the write of, say, 100 bytes, cost anyhow? on the NXP it was done in under 200 ms.. also i'm curious as to how exactly the bricking would work?
Title: Re: how to write and read arduino due internal flash memory?
Post by: pepelevamp on Nov 06, 2018, 04:33 pm
Apologies for reviving the zombie thread.
But the answer to this last question is: use a supercapacitor to hold charge for a moment after power has been pulled. My 3D printer does this. During the unfortunate event of a short power cut, it will store its position/status into eeeprom and resume work as if nothing happened. It can only handle very short power cut periods say 1 second but yeah.

Title: Re: how to write and read arduino due internal flash memory?
Post by: trev_vb on Apr 20, 2019, 10:04 am
I'll keep up this 'new trend' of replying to a 'zombie thread' by asking another (probably inane and insane?) question... <Grins>
Firstly, some quick background for y'all. (which you MIGHT want to bypass... If so, skip to "<QUESTION>"
I'm using a Due in a truly 'bare-iron' mode
i.e. There's absolutely NO Arduino code in there at all...  I take control right from Reset_Handler () exception and bring it up from 'cold' (and before anyone asks... Yes, I _AM_ switching it over to a PLL derived 84MHz clock!)
Furthermore, during startup, I 'relocate' all of the code from Flash into the 32kB SRAM1 bank (less wait states = slightly faster? LOL)
The application is mildly automotive in nature (specifically drag racing)
During any given 'race', the Due will be logging a bunch of data into the 64kB SRAM0 bank... (And it _COULD_ consume the whole 64kB bank in 'abnormal' circumstances!)
I need to make sure this log info gets stored into non-volatile memory (a.k.a. Flash Bank 1) before some idiot (a.k.a. the teenage driver) turns the thing off.
My 'gut instinct' is a simple 5.5V 1.5Farad supercap (as mentioned above) on the Due +5V rail (since it's 'quasi-safe' to backfeed a Due through the +5V rail - That's how they work when powered by USB!).
The supercap would charge from this same rail (through a 'low-ish' value resistor), and then backfeed the Due through a Schottky diode when the Due loses the Vin supply.  (The Due will KNOW that it's lost Vin within 0.01-0.02 seconds by way of the ADC and the SysTick timer which I've set for 100Hz operation).
<QUESTION>
I cannot find anything in the SAM3X8E datasheet telling me how much time it needs to write data out to flash using the EEFC peripheral.  Given that I might need to write up to 64kB, I'm unsure if a 1.5F supercap is going to give me enough time.  (There's also 16 digital inputs with internal pullups enabled which doesn't exactly help my cause... LOL).
Has anybody here got any 'timing' knowledge of writing to the SAM3X8E FLASH
Title: Re: how to write and read arduino due internal flash memory?
Post by: westfw on Apr 20, 2019, 10:43 am
2.3 ms per page, without auto-erase.

See the data sheet section on "ac characteristics" (46.10.10 in my relatively old copy.)
Title: Re: how to write and read arduino due internal flash memory?
Post by: ard_newbie on Apr 20, 2019, 11:01 am
Furthermore, during startup, I 'relocate' all of the code from Flash into the 32kB SRAM1 bank (less wait states = slightly faster? LOL)
The DUE is optimized for reading from Flash, reading code from SRAM is a bit slower. You want to locate your code in SRAM only when this is mandatory (read Unique ID for example), or if you want to reduce wear in Flash….

Why not power the DUE with a battery pack (from 7V to 12V is OK)?

There is the DueFlashStorage library to store data in Flash. However, you should know that some users have had issues with this library : after writing data to the Flash, they can't upload a new sketch (Flash page is lock message) with the regular arduino IDE. Search in recent threads in the DUE sub forum for some "possible" ways to unlock Flash regions. Note that for some users, even these workarounds do not clear definitely the Flash lock bit.

I think, but this is only a guess, that there is some mismatch during a write in Flash if an interrupt occurs at the same time (e.g. Systick fires an interrupt 1000 times per second), and this could be a workaround:

Just before writing into the Flash with this library, write: __set_FAULTMASK(1); // 1 = Disable all interrupts, except NMI; 0=Enable previous interrupts

Just after writing into the Flash, write: __set_FAULTMASK(0);  So that you can Serial print, use micros(), millis() and delay() again.


Title: Re: how to write and read arduino due internal flash memory?
Post by: trev_vb on Apr 20, 2019, 04:04 pm
I _thought_ I had scanned my eyes through the ENTIRE 1450+ page datasheet looking for that info, but there it is!!!
As for the SAM3XiE running faster in FLASH than in RAM, I'm somewhat surprised.
However, I've now got to PROVE that to myself so that it 'sticks' in my ancient old cranium.

My problem(s) with powering it from the existing 12V battery in the vehicle are:
1: Every such race vehicle MUST have a 'battery kill' switch (for safety)
2: The young lass who drives it could easily turn it off at any time
3: As with anything automotive, the 12V rail is kinda 'nominal' and could easily jump around a 100% or so... <Grins>  I don't think the onboard 5V SMPS of a Due would 'appreciate' getting a 24V 'whack' on Vin
I guess another 'option' now that I know the FLASH write speed would be to use an external 'pre-regulator' with its own isolated reservoir capacitor to keep the due running AFTER the battery is switched off.  (I'm already sensing Battery Voltage at the 100Hz data logging rate so I'd know when it's turned off)

As for using the DueFlashStorage library.
There's no fun in that!
Did I mention I'm going 'bare iron'?
I'll roll my own thx <Hehe>
And I'll make sure it's kept isolated from spurious interrupts.... Good tip there on FAULTMASK!
MY SysTick is configured to only fire 100 times a second...  It was all I needed and it keeps one more TC channel 'free' for future use.
As for millis(), Serial.Print() etc, all those 'Arduino' things are WAY outta scope.
If I were coding any lower, I'd have to fire up the assembler!
(There's NO crt0, crtbegin etc code linked into my binary...  Don't want em, don't need em!)

Anyway, I can now safely start writing my FLASH I/O routines....
Thanks a bunch to both of you!

BTW, if anyone starts telling me about the 10k cycle life on the FLASH (@ 85C), I'm not even mildly concerned.
In total, she would do somewhere around 100 races in a season so I'm good for the next 100 years! 1 year was enough for me!
I am not even going to bother 'sharing' the load within the 256kB bank. (Sheer laziness on my part)
Title: Re: how to write and read arduino due internal flash memory?
Post by: trev_vb on May 13, 2019, 02:59 pm
Here's some additional questions for y'all...
Firstly, yes, I have tried to find the answer in the 11057 Atmel datasheet, but perhaps I am BLIND again like I was with the FLASH write timing that Westfw kindly pointed me to (BTW, thanx HEAPS again!)
Secondly, I've also browsed through all the source I have access to in order to answer my own questions, but I found that they kinda 'cheat' by using the IAP code that's resident in the on-chip ROM.  (If I am forced to, I might even have to disassemble that ROM code to be certain)

I'll start with some background:
The datasheet states that there are two instances of the Enhanced Embedded Flash Controller (EFC) inside the SAM3X8E (named EFC0 and EFC1).  It also states that there are two * 256kb flash regions (and within CMSIS these are named IFLASH0 and IFLASH1)
Initially, I had assumed (ugh - what a horrible word... LOL) that EFC0 exclusively controlled IFLASH0 and EFC1 exclusively controlled IFLASH1, but then I realized that I've not been able to see that linkage explicitly mentioned within the datasheet.
1: Does this mean that EFC0 can be used to write to BOTH IFLASH0 and IFLASH1? (and same for EFC1)
2: This raises an implication that there is only a single 256 byte page write buffer that is inherently 'shared' by EFC0 and EFC1.  Is this accurate?  This confuses me as I cannot see why there's a need for a second EEFC controller?  Is it technically possible to use EFC0 and EFC1 simultaneously?  Within the same 256kB of FLASH?  I seriously doubt that is likely!

All of the above become perfectly logical to me if EFC0 is 'solely responsible' for IFLASH0 (the first 256kB) and EFC1 is 'solely responsible' for IFLASH1 (the second 256kB).
- They would each have their own independent 256 byte page write buffer (selected by the actual FLASH address used)
- It would be technically feasible to use BOTH EFC0 and EFC1 simultaneously (assuming code is running from RAM or ROM)
Title: Re: how to write and read arduino due internal flash memory?
Post by: ard_newbie on May 13, 2019, 04:31 pm
You just can't write in Flash from Flash, either from Flash Bank0 or Flash Bank1: You want to write in Flash from SRAM.

You will be using each EFCx to select, e.g. the number of wait states for the corresponding EFCx, not the other one.

There is an interesting Application Note from Atmel: Atmel AT02333: Safe and Secure Bootloader Implementation for SAM3/4.

Read Sam3x datasheet errata section page 1442.

AFAIK, you are free to use IAP function in ROM or EFC registers, except for reading the Unique ID (see the example sketch below):

Code: [Select]

/*********************************************************************/
/*          Read Unique ID and Get Flash Descriptor Functions        */
/*********************************************************************/

#define EEFC0 ((Efc*) 0x400E0A00U)
#define EEFC1 ((Efc*) 0x400E0C00U)
#define GPNVM0    0b1
#define GPNVM1    0b10
#define GPNVM2    0b100
#define EEFC_FKEY 0x5A
#define IFLASH1_ADDR ( IFLASH0_ADDR + IFLASH_SIZE / 2 )
#define CHIP_FLASH_IAP_ADDRESS (IROM_ADDR + 8)
#define EEFC0 EFC1
#define EEFC_FKEY 0x5A
#define EEFC_FMR_SCOD   (0x1ul << 16)
#define IFLASH0_ADDR  0x00080000                               // Flash memory begins at 0x00080000
#define IFLASH1_ADDR ( IFLASH0_ADDR + IFLASH_SIZE / 2 )        // IFLASH1_ADDR  = 0x000C0000


__attribute__ ((section (".ramfunc")))
void ReadUniqueID( uint32_t * latch_buffer )
{
  char __FWS;

  // Set bit 16 of EEFC_FMR : See chap. 49.1.1.2 page 1442
  EFC0->EEFC_FMR |= EEFC_FMR_SCOD;                              // Sequential code optimization disable

  __FWS = (EFC0->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos ; // Save FWS value
  EFC0->EEFC_FMR &= ~ EEFC_FMR_FWS_Msk;
  EFC0->EEFC_FMR |= EEFC_FMR_FWS(6);                            // 6+1 wait states for read and write operations

  //EFC0->EEFC_FMR &= ~EEFC_FMR_FAM;                              // 128-bit access in read Mode only, to enhance access speed.

  while (!(EFC0->EEFC_FSR & EEFC_FSR_FRDY));                    // Send the  STUI command if FRDY bit is high to begin reading in flash
  EFC0->EEFC_FCR = EEFC_FCR_FKEY(EEFC_FKEY) | EFC_FCMD_STUI ;
  //Wait till FRDY falls down
  while (EFC0->EEFC_FSR & EEFC_FSR_FRDY);
  // The Unique Identifier is located in the first 128 bits of
  // the Flash bank 0 in between 0x080000 and 0x08000C (and of the Flash bank 1 in between 0X0C0000 and 0x0C000C ??)
  memcpy(latch_buffer, (void*)IFLASH0_ADDR, 16);                // Read first 128 bits ( 16 first bytes) in one shot beginning at address IFLASHIndex_ADDR

  // Send the SPUI command to stop reading in flash
  EFC0->EEFC_FCR = EEFC_FCR_FKEY(EEFC_FKEY) | EFC_FCMD_SPUI ;
  // Wait till FRDY rises up
  while (!(EFC0->EEFC_FSR & EEFC_FSR_FRDY));

  // Clear bit 16 of EEFC_FMR : See chap. 49.1.1.2 page 1442
  EFC0->EEFC_FMR &= ~EEFC_FMR_SCOD;                             // Sequential code optimization enable

  EFC0->EEFC_FMR &= ~ EEFC_FMR_FWS_Msk;                         // Restore FWS value
  EFC0->EEFC_FMR |= EEFC_FMR_FWS(__FWS);

}
void GetFlashDescriptor( uint32_t * latch_buffer2 )
{
  boolean val;

  //The In Application Programming feature is a function located in ROM that can be called by any software application.
  //When called, this function sends the desired FLASH command to the EEFC and waits for the Flash to be ready
  //The IAP function does NOT work for the Read Unique Identifier commands  !!!

  static uint32_t (* IAP_function) (uint32_t, uint32_t);

  IAP_function = (uint32_t(*)(uint32_t, uint32_t)) * ((uint32_t *) CHIP_FLASH_IAP_ADDRESS);

  //Select reading from Flash Bank 0 or Flash Bank 1
  //val = 0 for EFC0, val = 1 for EFC1
  IAP_function(/*val = */0, EEFC_FCR_FKEY(EEFC_FKEY) | EEFC_FCR_FARG(0) | EEFC_FCR_FCMD(EFC_FCMD_GETD ));

  // If val = 0, select EFC0 else EFC1
  for (byte b = 0; b < 5 ; b++) memcpy(latch_buffer2++, (void*)&EFC0->EEFC_FRR, 4); // Copy 20 bytes from flash to RAM

}
void setup ()
{
  Serial.begin (250000) ;
  /***********   Read Unique ID  ***************************/
  uint32_t latch_buffer[4];
  ReadUniqueID( latch_buffer ) ;

  printf(
    "                                                                  \n"
    "Reading of the 128 bits unique identifier:\n ID = %08X%08X%08X%08X\n",
    latch_buffer[0],
    latch_buffer[1],
    latch_buffer[2],
    latch_buffer[3]
  );

  uint32_t FL_PLANE[2];
  uint32_t FL_ID, FL_SIZE, FL_PAGE_SIZE, FL_NB_PLANE;
  GetFlashDescriptor( latch_buffer ) ;
  Serial.println("Getting Flash Descriptor :");

  for (byte b = 0 ; b < 5 ; b++)
  {
    uint32_t val;
    switch (b) {
      case 0:
        FL_ID = latch_buffer[b];
        val = FL_ID;
        Serial.print("FL_ID = ");
        break;
      case 1:
        FL_SIZE = latch_buffer[b] / 1024;
        val = FL_SIZE;
        Serial.print("FL_SIZE (K bytes)= ");
        break;
      case 2:
        FL_PAGE_SIZE = latch_buffer[b];
        val = FL_PAGE_SIZE;
        Serial.print("FL_PAGE_SIZE (Bytes)= ");
        break;
      case 3:
        FL_NB_PLANE = latch_buffer[b];
        val = FL_NB_PLANE;
        Serial.print("FL_NB_PLANE = ");
        break;
      case 4:
        FL_PLANE[b % 4] = latch_buffer[b] / 1024;
        val = FL_PLANE[b % 4];
        Serial.print("FL_PLANE (K Bytes)["); Serial.print(b % 4); Serial.print("] = ");
        break;
    }
    Serial.println(val, DEC);
  }

}

void loop() {}




Title: Re: how to write and read arduino due internal flash memory?
Post by: trev_vb on May 14, 2019, 01:52 am
Thx Ard_Newbie.
You just can't write in Flash from Flash, either from Flash Bank0 or Flash Bank1: You want to write in Flash from SRAM.
My mistake for not having explicitly declared that all of my code is already RAM-resident.
(FYI, if I was to have used the ROM-Based IAP routine, then it would 'bypass' that issue altogether since the actual update is run from the ROM-based function in that case).

This entire project is partially a 'self-challenge' and part of that challenge is to run the whole thing from RAM.  Therefore I have used a significantly 'customized' linker script rather than the flash.ld version used by the Arduino IDE.
A second part of that self-challenge has been to make sure that every single instruction executed on the Due was written by ME rather than some 'unknown third party'.  My project 'takes control' right at the Reset_Handler() entry point and never relinquishes that control to anything else... Ever!  (And that is why I want to avoid using the ROM-Based IAP function to write data into FLASH).
In my version of Reset_Handler, all of the actual application code is copied from FLASH into RAM.
After that, the interrupt vector table is relocated (using SCB->VTOR) to point to the new table in RAM.
Finally, execution branches over to the newly RAM-resident code.
(It's interesting to note that calling a RAM-based project-mainline from code running in FLASH requires a 'veneer' since the ARM branch-with-link (bl) instruction is unable to encode such a large 'relative' branch from FLASH to RAM.)

In a prior post, you mentioned that execution from RAM is s-l-o-w-e-r than from FLASH which kinda surprised me.  I still intend to confirm that detail for myself in due course.  I readily accept that execution from FLASH can overcome MOST of the inherent slowdown (wait states) due to the wider path employed, but this still leaves the non-sequential code execution (eg: any branch instructions) that will incur the wait-state penalties.

I mentioned in a prior post that this is a truly 'bare-iron' project.  I should have repeated that so mea culpa.
You will be using each EFCx to select, e.g. the number of wait states for the corresponding EFCx, not the other one.
There is an interesting Application Note from Atmel: Atmel AT02333: Safe and Secure Bootloader Implementation for SAM3/4.
Yep, that's all quite logical and is explicitly mentioned in the datasheet. Thx
However, I've not found anything in the datasheet that fully describes the 256 byte page-write buffer.  Is there a single buffer 'shared' by EFC0 and EFC1 as is implied by the fact that it wraps around throughout the 1MB of Flash address space (See 18.4.1)  If true, then applications code CANNOT simultaneously write to FLASH using both EFCs (eg: In alternate execution 'threads')
Nor have I explicitly read whether each EFC can encompass the ENTIRETY of FLASH or just one 256kB half.
It actually gets even MORE confusing when the datasheet seems to imply that EFC0 and EFC1 are actually used during execution for opcode fetch!  (And this implies that system firmware can inadvertently potentially 'corrupt' program execution by setting the number of wait states within EFCn to a value that is too low for reliable operation at the current MCLK speed!)
Lastly, there's even a place in the datasheet that I may need to refer back to Atmel / Microchip.as 'datasheet errata'.  (Take a look at tables 7.2 within 7.2.3.1 Flash overview.  The footnote states:
The Flash contains a 128 byte write buffer, accessible through a 32-bit interface'
Everywhere else in the datasheet, the write buffer is referred to as a 256 byte buffer which corresponds to a single Flash 'page'
Read Sam3x datasheet errata section page 1442.
For others out there, this is a very valid point!
Specifically, the errata advises to set the wait-states to 6 when writing FLASH.to avoid corrupt writes to FLASH.
AFAIK, you are free to use IAP function in ROM or EFC registers, except for reading the Unique ID (see the example sketch below):
I agree that I could simply use the ROM-based IAP function, but that would slightly negate part of my 'self-learning' goal of this project (to write the whole thing as a truly 'bare-iron' project)

In summary, I think that I'm just going to have to 'probe' things myself to conclusively determine the answers I need and that's going to take some time.
If anyone is interested, I guess I can report back to this forum
Title: Re: how to write and read arduino due internal flash memory?
Post by: Tevian on Nov 16, 2019, 02:47 pm
Ok I hope someone is still looking here.

I had a project written on a Nano using the EEPROMAnything.h library for help store multiple array's in the EEPROM. Ultimately I ran out of RAM space so I got a shinny new Due. After some hours I was able to get a working sketch on the Due of my project. Now that there is no EEPROM I needed a way to store some values between power cycles. I tried to use the DueFlashStorage but I'm having trouble. BTW this is the first 'real' coding I've done so my knowledge is limited. I'm kinda learning as I go here. This project is an LED controller that uses a Nextion Display as the control interface.


Here is the structure I'm working with.


Code: [Select]

struct LEDAttributes {
  byte onHour;
  byte onMinute;
   int onTimeMins;
  byte offHour;
  byte offMinute;
   int offTimeMins;
  byte rampMinutes;
  byte lightIntensity;
  byte LEDState;  //0-ON, 1-RAMPING UP, 2-RAMPING DOWN, 3-OFF, 4-Bypass
  byte Lightning;
  byte CurrentPWM;
  byte Debug;
};

LEDAttributes LEDChannel[4] =
{
  {0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0}
};


This reads from an address derived by the structure size as far as I know and writes it to the appropriate structure.


Code: [Select]

for (int i = 0; i <= 3; i++)
  {
    EEPROM_readAnything((i * sizeof LEDChannel[i]), LEDChannel[i]);
   
  }


This pulls the values from the Nextion display and writes them to the correct structure. Then an EEPROM_writeAnything command saves the data.

Code: [Select]

void ESPushCallback(void *ptr)
{
    uint32_t hrON = 0;
    n0.getValue(&hrON);
    uint32_t hrOFF = 0;
    n2.getValue(&hrOFF);
    uint32_t minON = 0;
    n1.getValue(&minON);
    uint32_t minOFF = 0;
    n3.getValue(&minOFF);
    uint32_t LEDramp = 0;
    n4.getValue(&LEDramp);
    uint32_t LEDIntensity = 0;
    h0.getValue(&LEDIntensity);
    uint32_t Lightning = 0;
   

  if(LEDChannel[LEDch - 1].LEDState == 4)
  {
    LEDChannel[LEDch - 1].onHour = hrON;
    LEDChannel[LEDch - 1].onMinute = minON;
    LEDChannel[LEDch - 1].onTimeMins = ((LEDChannel[LEDch - 1].onHour * 60) + LEDChannel[LEDch - 1].onMinute);
    LEDChannel[LEDch - 1].offHour = hrOFF;
    LEDChannel[LEDch - 1].offMinute = minOFF; 
    LEDChannel[LEDch - 1].offTimeMins = ((LEDChannel[LEDch - 1].offHour * 60) + LEDChannel[LEDch - 1].offMinute);
    LEDChannel[LEDch - 1].rampMinutes = LEDramp;
    LEDChannel[LEDch - 1].lightIntensity = LEDIntensity;
    LEDChannel[LEDch - 1].Lightning = Lightning;   
    EEPROM_writeAnything(((LEDch -1) * sizeof LEDChannel[LEDch -1]), LEDChannel[LEDch -1]);
  }
}


This allows me to read a single structure into memory for use in the code.

Code: [Select]

EEPROM_readAnything(((LEDch -1) * sizeof LEDChannel[LEDch -1]), LEDChannel[LEDch -1]);


This was a simple test to see how this thing works but I can't seem to make it work. I can get one structure to write but not two. I'm not sure how to write something that will function similar to the EEPROMeverything library. Also if I change the address in the "dueFlashStorage.write(4, b2, sizeof(LEDChannel[0]));" command from 4 to 5 I get an error on the serial terminal that says "Flash start address must be on four byte boundary". I have no idea what that means and my brains are fried because I'm writing this at about 6am after trying all night to make this work.

Any help is great appreciated! Thx.



Code: [Select]

#include <DueFlashStorage.h>
DueFlashStorage dueFlashStorage;


struct LEDAttributes {
  byte onHour;
  byte onMinute;
   int onTimeMins;
  byte offHour;
  byte offMinute;
   int offTimeMins;
  byte rampMinutes;
  byte lightIntensity;
  byte LEDState;  //0-ON, 1-RAMPING UP, 2-RAMPING DOWN, 3-OFF, 4-Bypass
  byte Lightning;
  byte CurrentPWM;
  byte Debug;
};

LEDAttributes LEDChannel[4] =
{
  {12,0,9999,0,0,0,0,0,0,0,0,0},
  {23,23,23,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,0,0,0}
};

void setup()
{
    Serial.begin(115200);
    delay(500);
   
      byte b2[sizeof(LEDChannel[0])]; // create byte array to store the struct
      memcpy(b2, &LEDChannel[0], sizeof(LEDChannel[0])); // copy the struct to the byte array
      dueFlashStorage.write(4, b2, sizeof(LEDChannel[0])); // write byte array to flash

 
}

void loop() {
  // put your main code here, to run repeatedly:
 
  byte* b = dueFlashStorage.readAddress(4); // byte array which is read from flash at adress 4
  LEDAttributes configurationFromFlash; // create a temporary struct
  memcpy(&configurationFromFlash, b, sizeof(LEDChannel[0])); // copy byte array to temporary struct


 
  Serial.print(configurationFromFlash.onHour);
  Serial.print(",");
  Serial.print(configurationFromFlash.onMinute);
  Serial.print(",");
  Serial.print(configurationFromFlash.onTimeMins);
  Serial.println();
  delay(1000);

}


Title: Re: how to write and read arduino due internal flash memory?
Post by: ard_newbie on Nov 16, 2019, 04:24 pm
Whenever you are using a struct with a DUE (ARM Cortex M3 uc), you have to know that your struct is 4 bytes aligned. Moreover, it is most useful to use uint8_t, uint16_t, uint_32_t, uint64_t, int8_t, int16_t, int32_t, int64_t rather than byte or int (an int is 4 bytes long for a DUE !).

It's easy to see what means "4 bytes aligned" with sizeof() in the example sketch below:

 
Code: [Select]

struct LEDAttributes {
  uint8_t onHour;
  uint8_t onMinute;


  uint32_t onTimeMins;

  uint8_t offHour;
  uint8_t offMinute;


  uint32_t offTimeMins;

  uint8_t rampMinutes;
  uint8_t lightIntensity;
  uint8_t LEDState;  //0-ON, 1-RAMPING UP, 2-RAMPING DOWN, 3-OFF, 4-Bypass
  uint8_t Lightning;

  uint8_t CurrentPWM;
  uint8_t Debug;

};
LEDAttributes LEDChannel;

struct LEDAttributes2 {
  uint8_t onHour;
  uint8_t onMinute;
  uint16_t Padding0;  //***************

  uint32_t onTimeMins;

  uint8_t offHour;
  uint8_t offMinute;
  uint16_t Padding1;  //******************

  uint32_t offTimeMins;

  uint8_t rampMinutes;
  uint8_t lightIntensity;
  uint8_t LEDState;  //0-ON, 1-RAMPING UP, 2-RAMPING DOWN, 3-OFF, 4-Bypass
  uint8_t Lightning;

  uint8_t CurrentPWM;
  uint8_t Debug;
  uint16_t Padding2;  //********************
};
LEDAttributes2 LEDChannel2;

void setup() {

  Serial.begin(250000);

  printf("Size of LEDChannel = %d\n", sizeof(LEDChannel));

  printf("Size of LEDChannel2 = %d\n", sizeof(LEDChannel2));
}


void loop() {

}








Title: Re: how to write and read arduino due internal flash memory?
Post by: MorganS on Nov 16, 2019, 04:46 pm
4-bytes aligned means you should use addresses divisible by 4.

0 4 8 12 16 20...
Title: Re: how to write and read arduino due internal flash memory?
Post by: Tevian on Nov 17, 2019, 04:01 am
Code: [Select]

      byte b2[sizeof(LEDChannel[0])]; // create byte array to store the struct
      memcpy(b2, &LEDChannel[0], sizeof(LEDChannel[0])); // copy the struct to the byte array
      dueFlashStorage.write(4, b2, sizeof(LEDChannel[0])); // write byte array to flash


Ok so in this example "dueFlashStorage.write(4, b2, sizeof(LEDChannel[0]));" the 4 is indead the address to write to? So as the struct gets written it starts at address 4 and fills 4 byte blocks until its done writting? So If I want to write another struct I need to find out the first open block that is a divisor of 4 and put that into the address variable? Sorry if this sounds like a newbie question.

And also if I 'pad' out the variables will the array of structures still work so I can use the for loops to innumerate the struct names? 

Like this..
Code: [Select]

for (int i = 0; i <= 3; i++)
  {
    "flash write"...((i * sizeof LEDChannel[i]), LEDChannel[i]);
  }


Or will I need something more specific dealing with the individual structs. Sorry again if this sounds like a weird question. When I get home i'll try with padding the struct. Thx much everyone!
Title: Re: how to write and read arduino due internal flash memory?
Post by: ard_newbie on Nov 17, 2019, 05:16 am
The padding of structures is done automatically by the DUE compiler (except at the end of a structure).

The object of padding in the example sketch in #16 is only to show you that struct are 4 bytes aligned. IMO adding manualy paddings in struct avoids some misunderstandings.

And yes, the "idea" of your last line of code should work.

Code: [Select]

#include <DueFlashStorage.h>
DueFlashStorage dueFlashStorage;

// I add padding to make sure struct size is a multiple of 4
struct Configuration {
  uint8_t a;
  uint8_t b;
  uint8_t c;
  uint8_t Padding;
};

const uint8_t StructSize = 2;
Configuration configuration[StructSize];
const uint8_t Size = sizeof(Configuration);

void setup() {

  Serial.begin(250000);

  configuration[0].a = 0;
  configuration[0].b = 1;
  configuration[0].c = 2;

  configuration[1].a = 3;
  configuration[1].b = 4;
  configuration[1].c = 5;

  uint8_t MyArray[Size]; // create byte array to store the struct
  for (uint8_t i = 0; i < StructSize; i++)
  {
    memcpy(MyArray, &configuration[i], Size); // copy the struct to the byte array
    dueFlashStorage.write(4 + (i * Size), MyArray, Size); // write byte array to flash
  }

}


void loop() {
  uint8_t* Array;
  Configuration configurationFromFlash; // create a temporary struct

  for (uint8_t i = 0; i < StructSize; i++)
  {
    Array = dueFlashStorage.readAddress(4 + (i * Size));
    memcpy(&configurationFromFlash, Array, Size); // copy byte array to temporary struct

    // print the content
    Serial.print("a:");
    Serial.print(configurationFromFlash.a);

    Serial.print(" b:");
    Serial.print(configurationFromFlash.b);

    Serial.print(" c:");
    Serial.print(configurationFromFlash.c);
    Serial.println();
  }

  Serial.println();
}



BTW, some users have had issues with DueFlashStorage library, after writing in Flash, they can't upload a new sketch. This issue has been solved in several threads in the DUE sub forum in order to unlock lock bits.

Title: Re: how to write and read arduino due internal flash memory?
Post by: Tevian on Nov 17, 2019, 04:30 pm
This has been a big help!! It kinda works now!! LOL

One thing I had to do was to pre-format the space with zeros. When I flash the blocks are all at max value and it messes with the loops I have. Wasn't sure of the best way to do this so I'm checking the first saved value to see if its larger than 23. That being the largest value in hours to be stored there. And if so clear the whole space.

Code: [Select]

  uint8_t test = dueFlashStorage.read(4);
    if (test > 23)
    {
    uint8_t MyArray[LEDStructSize];
   
     for (uint8_t i = 0; i < LEDAttributeCount; i++)
      {
        memcpy(MyArray, &LEDChannel[i], LEDStructSize);
        dueFlashStorage.write(4 + (i * LEDStructSize), MyArray, LEDStructSize);
      }


Also I have another array that has relay attributes. These structures are a different size than the LED ones. I need to store them at the end of the LED attribute space. So would something like this be appropriate for the dueFlashStorage.write command?
Code: [Select]

for (uint8_t i = 0; i < RLYAttributeCount; i++)
  {
    memcpy(MyArray2, &RLYChannel[i], RLYStructSize);
    dueFlashStorage.write(4 + ((i * RLYStructSize) + (LEDAttributeCount * LEDStructSize)), MyArray2, RLYStructSize);
  }


Super helpful guys. Thank you!