Go Down

Topic: Writing to flash / EEPROM emulation (Read 3233 times) previous topic - next topic

stimmer

Has anyone else got anywhere with trying to write to the flash memory at runtime?

I had a go at this last night and I think I am getting somewhere. It doesn't help that the datasheet is vague and occasionally inaccurate on the subject. This example code increments a variable and writes it to flash every time the reset button is pressed (after a 1.5 second delay the first time) - could people please test this and tell me if it works? If it works reliably then it might be possible for someone to develop it into some kind of EEPROM-emulation library.

Code: [Select]
// flash memory write example by stimmer
// call nv_load() to load data from flash
// modify nv_ram[] array (64 32-bit words)
// then call nv_save() to save back to flash (not too often!)

uint32_t nv_ram[64];
const uint32_t nv_flash[64] __attribute__((aligned(256)))={0};

//taken from ASF
__attribute__ ((section(".ramfunc")))
uint32_t efc_perform_fcr(Efc *p_efc, uint32_t ul_fcr) {
    volatile uint32_t ul_status;
    p_efc->EEFC_FCR = ul_fcr;
    do {
        ul_status = p_efc->EEFC_FSR;
    } while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
    return (ul_status & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE));
}

void nv_load(){ 
  for(int i=0;i<64;i++)nv_ram[i]=nv_flash[i];
}

// This is complete guesswork. The docs are all wrong!
int nv_save(){
  uint32_t * nv_write = const_cast<uint32_t *> (nv_flash); 
  unsigned long FlashSectorNum = ((unsigned long)nv_flash - 0x80000) / 256;
  Efc * efc = FlashSectorNum >= 1024 ? EFC1 : EFC0;
  FlashSectorNum &= 1023;
  unsigned long flash_cmd = 0;
  unsigned long flash_status = 0; 
  flash_cmd = (0x5A << 24) | (FlashSectorNum << 8) | 0x03;
 
  noInterrupts();
  for(int i=0;i<64;i++)nv_write[i]=nv_ram[i];
  flash_status = efc_perform_fcr (efc, flash_cmd);
  interrupts();
 
  return flash_status;
}

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

  nv_load();
 
  if(nv_ram[6]!=9){
    nv_ram[6]=9;
    nv_ram[42]=1;
    delay(1500);
    Serial.println("This is the first time I have been run.");
    // you probably won't see that unless you open the serial monitor quite soon after uploading
  }
  else {
    Serial.print("I have been reset ");
    Serial.print(nv_ram[42]);
    Serial.print(" time");
    Serial.println(nv_ram[42]==1 ? "." : "s.");
    if(nv_ram[42]>10)Serial.println("Please don't reset me any more, as we don't know how many times the flash can be reprogrammed before it breaks.");
    if(nv_ram[42]>100)Serial.println("I said stop pressing the bloody reset button you idiot!");
    nv_ram[42]++;
  }   
  nv_save();
 
}

void loop() {
}
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

cmaglie

I've started something here, if you want to give it a look:

https://github.com/cmaglie/Flash

but honestly I'm not satisfied with the API I come up, I didn't exclude a complete refactoring.
C.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy