Flash Page is Locked

I was happily going along downloading program updates when I get "Flash page is locked".

I tried the push Erase and Reset with no luck.

How do I recover from this?

I did see another thread on this topic with no resolution.

Thanks,
-j

Hello johnf95037,

I also started to experience this with my last batch of Dues.
So far, the only way to make them work is as follows:

With the board powered, press the erase button and after a second, while keeping pressed the erase button, press the reset button. Then, keep them pressed for another second and release them. Now try to upload a sketch. This have worked 100% of the time with my new Dues but I still do not know why this happens. It is a pain when you have stacked other shield with Due and need to do a new upload.

Regards,

p

Hey Palliser,

I did try that, but I'll do it again and see what happens. I curious how the lock bits get set.

Thanks,
-j

I found this statement in the SAM3X datasheet: Asserting the ERASE pin clears the lock bits, thus unlocking the entire Flash.

It should work. Hmmm.

Hmm, again. I did see a post where a guy had the same problem I'm experiencing. He pressed the erase button then started the upload. When the upload started, he released the erase button and the load was successful.

I tried this and it worked. Why, I don't know just yet. I have an Atmel ICE for debugging it's time to learn to use so I can get in and see what's actually happening. Are lock bits actually set or is it something else?

A work-around is ok, but a fix is best.

Well the press the erase and release at the proper time really doesn't work. The IDE is fooled, but the program doesn't load.

ICE is next.

-j

johnf95037,

Have you tried using the .bin with bossac via CMD?

Regards,

p

I haven't tried Bossac yet. I do have Atmel Studio 6.2 and an Atmel ICE debugger. I can see that there is a lock bit set, but I still can't unlock it even with the current tool chain. I've opened up a case with Atmel tech support to get this resolved.

I'll update.

-j

I'm puzzled on two counts, AFAIK, bossa doesn't set lock bits. Generally that sort of thing DIY users don't need. So I don't know what is setting the bit.

The second is that the ERASE is an erase all/unbrick type operation. It's ok to clear lock bits when doing a bulk erase, because after the erase the code you want protected is wiped. (There are some manufacturers who have a one time only lock which can never be erased, but I don't think Atmel do this).

I guess that something weird is happening that sets a lock bit in a way that also means erase can't clear it, so hopefully Atmel can shed some light on how that can happen.

Good afternoon. I use in my project Arduino Due. When programming, I get the error: Flash page is locked. I am a beginner to the Arduino. Tell me, what is this error and how to fix it. Thanks.

There are several of these "Flash page is locked" Due posts but none seem to be resolved.

I've tried installing BOSSA and it fails installation for some unexplained reason. I've even tried SAMs apps but they don't show any application for Windows 64 bit. And of course none of the button pushing has worked either. Also reloading IDE drivers for 32 bit Due.

Like others I was pretty much minding my own business when this occurred. A minor change to my code and now this expensive POS is locked. Way too easy to brick this thing.

Is there any direction I can be pointed too?

Thank you,

Ed

Arduino IDE only uses BOSSAC which is a software solution buts this flash lock issue can be solved only by using a hardware probe like SAM-ICE together with Atmel Studio tools.

Some times SAM-BA works but it will depends of how the issue was created (ie. sudden lack of power while writing, messing with RAM memory registers, etc.)

-p

As I understand the datasheet, all Flash pages can be locked with the GPNVM bit 0 set to 1 (called security bit), or one or more Flash pages can be locked using specific commands: "Write page and lock" or "Erase page and write page then lock" or " Set Lock Bit" commands with EEFC0/EEFC1.

Although I didn't encountered this issue, if I couldn't upload a sketch and get a "Flash page is locked" error message, and if an manual erase (more than 200 ms) and reset would fail to recover a normal situation, I would try to upload a minimal sketch in SRAM to set GPNVM bit 0 to 0 to unlock all pages. The IAP function in ROM can be used for all these commands.

Apart from using according official hardware (SAM-ICE) and software (Atmel Studio 6 or 7) tools to solve this 'Flash page locked' issue, I could not find another consistent way to do it. In my opinion, the real problem here is that there is no easy way for someone inexperienced with ARM to restore a Due after this crash.

Anyway, here a snapshot of AS6 and device programming showing the 31 regions to lock or unlock.

-p

Thanks for this information Palliser. Does this "manip" work for you when you get a "Flash page is locked" error message ?

I did this snippet to unlock all 32 lock bits in Flash bank 0 and Flash bank 1 whatever their previous state (Not tested since I never have the above error message):

#define RAMFUNC __attribute__ ((long_call, section (".ramfunc")))
#define IROM_ADDR (0x00100000u)
#define CHIP_FLASH_IAP_ADDRESS (IROM_ADDR + 8)
#define EEFC_FKEY 0x5A

// During this sequence, the software cannot run out of Flash so needs to run out of ROM with the IAP function.
RAMFUNC
void ClearAllLockRegions()
{
  boolean Bank_nb;
  uint32_t priMask = __get_PRIMASK ();
  __disable_irq();
 
  /************************************************************************************/
  // FWS (Flash Wait States) register should be set to 6 (look at the errata at the end of the datasheet)
  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
  /*****************************************************************************/

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

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

  Bank_nb = 0;    // select flash Bank 0
  while (!(EFC0->EEFC_FSR & EEFC_FSR_FRDY));     // Wait for EEFC0 Ready
  // Clear all 16 regions lock bits of Flash Bank 0
  IAP_function(Bank_nb, EEFC_FCR_FKEY(EEFC_FKEY) |  EEFC_FCR_FCMD(EFC_FCMD_CLB) | EEFC_FCR_FARG(0xFFFF));
  while (!(EFC0->EEFC_FSR & EEFC_FSR_FRDY));

  Bank_nb = 1;    // select flash Bank 1
  while (!(EFC1->EEFC_FSR & EEFC_FSR_FRDY));     // Wait for EEFC1 Ready
  // Clear all 16 regions lock bits of Flash Bank 1
  IAP_function(Bank_nb, EEFC_FCR_FKEY(EEFC_FKEY) |  EEFC_FCR_FCMD(EFC_FCMD_CLB) | EEFC_FCR_FARG(0xFFFF));
  while (!(EFC1->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);
  /**************************************************************************************/
  __set_PRIMASK (priMask);
}

RAMFUNC
int main (void)
{

  WDT_Disable(WDT) ;
  init();      // initialize hardware
  ClearAllLockRegions();
  while(true);
 
}

ard_newbie:
Thanks for this information Palliser. Does this "manip" work for you when you get a "Flash page is locked" error message ?

I did this snippet to unlock all 32 lock bits in Flash bank 0 and Flash bank 1 whatever their previous state (Not tested since I never have the above error message):

I have the same error as described in this thread. The code did not work, it can't be uploaded since the Arduino Due is locked.

Have anyone found a solution to this problem or is this game over for my Due?

What was the last code you successfully uploaded ?

ard_newbie:
What was the last code you successfully uploaded ?

The following is the code. It does use the "DueFlashStorage.h" lib. I wonder if the lock bit was set when I started uploading a new program to the Due while it was in the process of saving to the flash. As you can see the code uses a couple of libs, I'll supply them to you shortly.
This is the code I uploaded when the error first occurred. But the last functioning program I uploaded was very similar to this as I only changed a line or two. I don't remember exactly what I changed.

// UNFINISHED::
//          CONTROL:  ctrlReset:  filename needs to be saved with DueFlashStorage.h to make it recoverable after restart
//          READ:     getPar:     add code for retrieving data from sensors 
//          correct ip for setTX in this file
#include <CONTROL.h>
#include <MODE.h>
#include <TXRX.h>
//#include <MONITOR.h>
#include <READ.h>
#include <TEST.h>

#define TRUE 1
#define FALSE 0
#define STARTUP 1
#define IDLE 2
#define ACTIVE 3
#define SHUTDOWN 4
#define BYTES_PER_TX 28
#define TXS_PER_SAVE 28
#define HEATER_PIN_1 40
#define HEATER_PIN_2 42
#define SAVE_PIN 4
#define Tmin 10         // Min temperature of temperature measurment unit before heater is turned ON
#define Tmax 15         // Max temperature of temperature measurment unit before heater is turned OFF
#define SAMPLES_PER_EVENT_CHECK 10
#define TIMER_LIFTOFF 20000
#define TIMER_IDLE_CUTOFF 50000
#define TIMER_IDLE_LANDING 50000
#define TIMER_ACTIVE_AFTER_LANDING 45000
#define LANDING_ALTITUDE_LIMIT 100

TEST testClass;   // OBS! Remove before flight
MODE modeClass;
TXRX txrxClass;
//MONITOR monClass;
READ readClass;
CTRL ctrlClass(BYTES_PER_TX, TXS_PER_SAVE, HEATER_PIN_1, HEATER_PIN_2,
                SAVE_PIN, LANDING_ALTITUDE_LIMIT, TIMER_LIFTOFF,
                TIMER_IDLE_CUTOFF, TIMER_IDLE_LANDING,
                TIMER_ACTIVE_AFTER_LANDING);

File root;
long interval = 25;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
uint8_t oldcomMode = 0;
uint8_t comByte;
int heatStatus = 0;
int mode = ACTIVE;  // OBS! Change before flight
int count = 0;
int vaiai;
char sensData1[45] = {'1','3','3','7','4','0','0','5','d','0','0','0','0','8'}; // ={info, t, heat1, heat2, infr1, cover, posx, posy, posz, wind, accx, accy, accz, press} 
char sensData2[45] = {'l','e','e','t','0','0','0','0','0','0','0','0','9'};
char bufferDataRX;
char bufferComRX;
int overview = 0b10000000; // Indicates which sensor box the data was recorded 


// TXRX   **********************
  // the media access control (ethernet hardware) address for the shield:
  byte mac[] = { 0x90, 0xA2, 0xDA, 0x10, 0xF8, 0x5C };  
  byte ip[] = { 130, 240, 92, 1 };
  byte DNS[] = { 130, 240, 19, 2 };
  byte gateway[] = { 130, 240, 92, 1};
  byte subnet[] = {255, 255, 0, 0};
  unsigned int localPort = 1900; 

  //static ip for PC
  byte remoteip2[] = { 192, 168, 42, 154 };
  byte remoteport2[] = { 112, 23, 0, 0 };

  // TCP
  byte server[] = { 130, 240, 95, 19 };
  unsigned int serverPort = 139;
//        **********************

void setup() {
  Serial.begin(9600);
  Serial.println("********************** I   A M   I N   S E T U P **********************");
  ctrlClass.initSave(SAVE_PIN);
  testClass.init(9600,SAVE_PIN);
  readClass.initREAD();
  //WDT_Restart(WDT); // Reset watchdog timer
  txrxClass.initTXRX(mac, ip, DNS, gateway, subnet, localPort, server, serverPort);
  //WDT_Restart(WDT); // Reset watchdog timer
  mode = ACTIVE;
  root = SD.open("/");
  ctrlClass.clearSD2();
  
}

void loop() {

 //       currentMillis = millis();
  
  //if(currentMillis - previousMillis >= interval) {
    
//      previousMillis = currentMillis;
//      comByte = txrxClass.getComRX();      
//      txrxClass.getDataRX(&sensData2[0], sizeof(sensData1)/sizeof(char));
//        if(comByte & 0b00011000 == 0b00011000) // if reset bit is set
    //    {
  //          ctrlClass.ctrlReset();
    //    }
      //  if((comByte >> 5) != oldcomMode) // if comMode =! oldcomMode
        //{
//          modeClass.setMode((comByte >> 5));  // set the commanded mode
          //  oldcomMode = (comByte >> 5);          
        //}

      // mode = modeClass.getMode();
      //WDT_Restart(WDT); // Reset watchdog timer
//        if(mode != STARTUP)
//        {
            readClass.getParam(sensData1);
//            txrxClass.setTX(&sensData1[0], remoteip2, remoteport2);      // send to GC
//          txrxClass.setTX(sensData1);      // send to other sensor box
//          heatStatus = ctrlClass.ctrlHeat( 30, 30, 15, 20);
 //         sensData1[1] = overview | heatStatus;
     //       if(mode == ACTIVE)
     //       {
               ctrlClass.ctrlSave(sensData1, sizeof(sensData1)/sizeof(char));
//              ctrlClass.ctrlSave(sensData2, sizeof(sensData2)/sizeof(char));
     //       }
//        }
//        if(count >= SAMPLES_PER_EVENT_CHECK){
//        //  ctrlClass.ctrlEvents(overview, 1000); // OBS! Change 2nd parameter!
//            count = 0;
//        }
//        else{
//            count = count + 1;
//        }

    testClass.dispEXISTdata(sensData1, 44);
    testClass.printDirectory2();
    testClass.dispCharFile("DATA0024.TXT");
}

Edit: You can download all the files I used here: Dropbox - File Deleted - Simplify your life

I don't see in your code the #include <DueFlashStorage.h>.

  • Did you try the workaround proposed by Palliser (this thread, #reply 13) ?

  • If you push the Erase button for 3 seconds then the Reset button for 3 seconds, then select a correct programming port, can you upload this empty sketch ?:

#define LONGCALL __attribute__((long_call))
#define NOINLINE __attribute__((noinline))
#define RAMCODE __attribute__((section(".ramfunc")))

#define RAMFUNC NOINLINE LONGCALL RAMCODE

RAMFUNC
int main(void) {

}

ard_newbie:
I don't see in your code the #include <DueFlashStorage.h>.

  • Did you try the workaround proposed by Palliser (this thread, #reply 13) ?

  • If you push the Erase button for 3 seconds then the Reset button for 3 seconds, then select a correct programming port, can you upload this empty sketch ?:

The DueFlashStorage.h is included inside another lib; CONTROL.h. You can find it in the .zip file I shared in my last post(#17).

  • I haven't tried what Palliser proposed. I don't know how. I have no experience with SAM-ICE but I'm looking into it. If you know a guide of other useful info I'm happy to look into it.

  • I still get the same error when trying your erase method.