Flash usage for storing Non Volatile data

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Flash usage for storing Non Volatile data

Jump to solution
3,610 Views
santhoshsl
Contributor III

For our project, we have large amount of data which needs to be remembered over Power Cycles (Non Volatile). So we thought of using the Flash itself for this purpose as we have 512Kb of flash.

As we decided to use flash, I started implementing handlers to read/write flash locations. And Attached is the code I used (tweaked out of S12X boot loader).

 

I am trying to Write to the flash locations from 0x7A00. But my system is getting reset continuously when this code is executed.

 

Please someone help me with the code to access Flash locations to store my Non Volatile data.

Original Attachment has been moved to: Flash_Handlers.txt.zip

Labels (1)
0 Kudos
Reply
1 Solution
1,971 Views
kef
Specialist I

1. This part of your code should be moved to and execute from RAM. Flash is not readable while any flash command is in progress, CPU can't read code to execute and runs away.

   FSTAT = FSTAT_CBEIF_MASK;   /* launch the command */

   if ((FSTAT & (FSTAT_ACCERR_MASK + FSTAT_PVIOL_MASK)) != 0)/* problem executing the command? */

    return(FlashProgramError);

  }

while ((FSTAT & FSTAT_CCIF_MASK) == 0)  /* wait here until all commands complete */

  ;

2. Flash errors are triggered when you attempt to write data to flash array, not after launching flash command. So you may move FSTAT checking code away.

Search forums for how to move routine to RAM. I use this approach

https://community.freescale.com/thread/69468

View solution in original post

0 Kudos
Reply
15 Replies
1,972 Views
kef
Specialist I

1. This part of your code should be moved to and execute from RAM. Flash is not readable while any flash command is in progress, CPU can't read code to execute and runs away.

   FSTAT = FSTAT_CBEIF_MASK;   /* launch the command */

   if ((FSTAT & (FSTAT_ACCERR_MASK + FSTAT_PVIOL_MASK)) != 0)/* problem executing the command? */

    return(FlashProgramError);

  }

while ((FSTAT & FSTAT_CCIF_MASK) == 0)  /* wait here until all commands complete */

  ;

2. Flash errors are triggered when you attempt to write data to flash array, not after launching flash command. So you may move FSTAT checking code away.

Search forums for how to move routine to RAM. I use this approach

https://community.freescale.com/thread/69468

0 Kudos
Reply
1,971 Views
santhoshsl
Contributor III

Hello Edward,

Thanks for this input. Sure i will check this RAM moving part and try it again.

0 Kudos
Reply
1,971 Views
santhoshsl
Contributor III

Hello Edward,

I have updated my code as attached. i have updated code to my Flash programs to RAM. But even now, I am seeing that system getting reset after the line

PPAGE = PPAGEVal;

Can you please help me know if I am missing some thing.

0 Kudos
Reply
1,971 Views
kef
Specialist I

I didn't review you code, but you can do PPAGE = x only while code executes from nonbanked flash. Either use Small memory model, or switch PPAGEs only from nonbanked routines, which should be declared and defined between two compiler #pragmas as follows:

#pragma CODE_SEG __NEAR_SEG NON_BANKED

void your_nonbanked_routine()

{

}

#pragma CODE_SEG DEFAULT

Exporting such routines to other C files, you also need to put function prototypes between these two pragmas.

Code for banked routines is read by CPU vie PPAGE - page window. Switching PPAGE while executing banked routine, you are replacing current CPU code with code from different PPAGE and CPU runs away.

You also need to save and restore PPAGE before returning to function in banked flash. Else you will return to wrong PPAGE.

0 Kudos
Reply
1,971 Views
santhoshsl
Contributor III

Hello Edward,

Sorry for disturbing you on this.

But I am quite confused about this PPAGE and Non backed routines thing. Please help me in understanding it.

Currently in my code I am trying this Flash access from a simple Main function. Before this flash access, I have enabled FCLK and copying my Flash Program and Erase functions to RAM.

After this I am calling ProgramFlash or Erase Flash (These functions I have incorporated from S12X boot loader code).
I was trying to write some data to the location 0x7E00 (while my .s19 says that my image starting record is from 0x7F7F). I selected this location thinking that, my PPage remains same for this.

But when I debugged i got to know that, when my code execution starts from Main(), Ppage value is FE and when I try to write to location 0x7E00, Ppage is getting updated to FD and then it hangs.

So you mentioned that I need to write my flash functions under Non_Banked pragma and take care of PPage. But i am confused that which part of the code I need to write under this Non Banked pragma as I have already moved my Flash routines to RAM.

Can you please help me out in this, if you have some EEprom Emulation on Flash or some other similar implementations with you.

Thanks in Advance.

0 Kudos
Reply
1,971 Views
kef
Specialist I

CPU program pointer is 16 bits wide. To have more than 2^16=64k of code space, banked or paged memory is used. Changing PPAGE different piece of memory is mapped to PPAGE window at 0x8000. So 1) you have to remember that you can't write new value to PPAGE while CPU executes code in PPAGE window.  Routine, which writes to PPAGE had to be placed outside of PPAGE window. 2) when calling such PPAGE manipulating routine, you need to restore PPAGE before or during return back to banked/paged routine. Functions placed in segment with __NEAR_SEG  attribute are called using JSR instruction and return using RTS instruction. JSR and RTS don't manipulate PPAGE, so you need to save and restore PPAGE. By default in banked memory model functions are called with CALL and return using RTC instruction. You may avoid __NEAR_SEG in RAMcode segment definition, and this will make your RAM functions saving/restoring PPAGE automatically.

It is not clear what memory model are you using and what code modifications did you do, also how does your PRM look like, many defines are missing. Could you zip your project and post it here? It would be easier to find real problem.

0 Kudos
Reply
1,971 Views
santhoshsl
Contributor III

Hello Edward,

Thanks for that detailed explanation. Now I understood that Ppage conecpt. Also i could co-relate this info by seeing the linker file data. Based on this understanding, i tried the code as in attached files.

Can you please have a look at that once and let me know the issues.

Flash Access.rar -- these flash access implementation I tweaked out of S12x bootloader

Flash Access_1.rar -- These i implemented seeing the Data sheet and tried the Flash to RAM copy based on the below discussion

https://community.freescale.com/message/100196#100196

I think I might have done blunders but please help me in resolving this issue.

Thanks for reviewing the code.

0 Kudos
Reply
1,972 Views
kef
Specialist I

See attached version, that should work on S12XD with 512k of flash. Smaller derivatives will run away, since your EraseFlash() routine tries to erase most of the flash, including areas that are not available on S12XD256 and lower. You need to review that code. You should find there erase of 3 x 128k flash arrays, followed by erase of last flash array sector by sector.

You copy to RAM routine is removed, instead standard startup routine is used to copy code to RAM.

I did small change in PRM file for P&E multilink. Your version should work, but it is enough to have RAMCode PLACEMENT defined, no need for dedicated RAMCodeSeg SEGMENT. You can place RAMCode to RAM SEGMENT.

Small change in your program and erase routines. Even on error, you shouldn't exit to flash while CCIF bit is cleared.

__PIC_SEG segment attribute is not required.

If you didn't manipulate PPAGE in your program/erase code, I would use __NEAR_SEG attribute to make RAM function called with JSR, which would save few bytes of code and few CPU cycles. But since PPAGE has to be manipulated, __NEAR_SEG is not used and PPAGE is automatically saved and restored in CALL and RTC instructions.

You second version doesn't seem to have program erase routines, only erase verify routine. You should easily fix that. Though erase verify command doesn't erase or program, flash still is not readable while erase verify command is in progress. So you should move that routine to RAM and not exit from RAM to flash while CCIF bit is zero.

0 Kudos
Reply
1,972 Views
santhoshsl
Contributor III

Hello Edward,,

Thank you very much for those changes and for the detailed explanation(as usual). I tried to execute the code  you attached and could see that values being written to flash locations. I tried to write at different flash banks and pages, and values are successfully written on to those locations. Thanks for helping me in this part.

But have one small issue, that I am not able to read back the values written using the following piece of code

      LogicalAddr = (uchar *)(ProgSRec.LoadAddr + 0x4000); /* for adresses  from 0x4000 till 0x7fff */

      for (j = 0; j < ProgSRec.NumBytes; j++)

      {

         /* check each byte to make sure it programmed properly */

         if (*(LogicalAddr++) == ProgSRec.Data[j])

         {

            k=0;

         }

         else

         {

            k=1;

         }

      }

the value at *(LogicalAddr++) looks to be 0xFF always.

i wrote this snippet of code in my Main function(in Flash) after calling flash program function(in RAM). Also i wrote this cross check in Flash program function(in RAM) also. Both the ways I could not read the value from the flash locations i wrote.

Can you please let me know if there is any issue in the way i am reading.

0 Kudos
Reply
1,972 Views
Dekiru
Contributor IV
1,972 Views
santhoshsl
Contributor III

Hello Dekiru,

Thanks for those links.

Ya I installed them and checked their demo code for this.

But I have space crunch and hence I thought of writing simple functions for this purpose.

0 Kudos
Reply
1,972 Views
kef
Specialist I

It is not clear why do you shift LogicalAddr up by +0x4000. ProgramFlawsh() assumes that ProgSRec.LoadAddr is global address, but after some address range checking it finds that 0x7E00 is not a global address but a CPU local address, which you may read directly using regular C data pointer.

When verifying flash write in flash program function, you need to remember that flash is not readable back until CCIF==1.

0 Kudos
Reply
1,972 Views
santhoshsl
Contributor III

Hello Edward,

I tried that address manipulation to get the exact page location. But understood that I can use the address directly. And based on it I updated my below code. But even after this, I am seeing some random values for *LogicalAddr

   ProgSRec.LoadAddr = 0x7A0000;

   ProgSRec.NumBytes = 2;

   ProgSRec.RecType = DataRec;

   for (i=0;i<ProgSRec.NumBytes; i++)

   {

      d = i;

      ProgSRec.Data[i] = d;

   }

   i=0;

   while(i<4)

   {

      ProgSRec.LoadAddr += 2;

      c = ProgramFlash();

      if (c == 0)

      {

          PORTB_PB0 = CLEAR;

      }

      /* go program the Flash */

      /* OutStr("Error"); / and report an error if there was one */

      i++;

     

      LogicalAddr = (uchar *)(ProgSRec.LoadAddr);

      for (j = 0; j < ProgSRec.NumBytes; j++)

      {

         /* check each byte to make sure it programmed properly */

         if (*(LogicalAddr++) == ProgSRec.Data[j])

         {

            k=0;

         }

         else

         {

            k=1;

         }

      }

0 Kudos
Reply
1,972 Views
kef
Specialist I

I don't know what's wrong. I think you need to debug it somehow yourself.

Do you see changes in flash memory windows in debugger? If not, then in debugger you should go to multilink menu and find and open there memory map dialog, in which you should find piece of flash in question and enable memory refreshing for given piece of memory. Seeing memory contents updated, it should be no problem to track your problems down. Program and erase routines worked fine, only verify should be fixed.

1,972 Views
santhoshsl
Contributor III

Hello Edward,

Thanks for your inputs till now. And sorry for pushing you on this.

yes i debugged the issue and found that it is problem with Far pointer access issue. i declared the pointer as far pointer and now it is working fine. Finally relived with this issue.

Thanks a lot for your support (I was clueless for days before your reply)

0 Kudos
Reply