To store data in flash

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable
        Dear professionals, I would like to store some small data in the flash of my CY8C4247LQL-BL483. I have found the API which is CySysFlashWriteRow(uint32 rowNum, const uint8 rowData[]). However, I cannot specify the row number. Could you give me some suggestion for which row should I use? To confirm if the row is available, where I could check the usage of the flash?   
0 Likes
13 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I would suggest you to use the emEEProm (emulated EEProm) component which is easier to handle than handling flash rows.

   

Keep in mind that there will be a change in the system clocks while writing to flash, so best will be to have ble disabled during that time.

   

There is a C_language extension (I'm not quite satisfied with that way) using the "const" keyword to have a variable (structure or array) in flash:

   

const int32 MyVar = 123456;

   

The "const" keyword is needed AND the initialization is required for the compiler to put this var into flash. Within a function you will have to declare that variable as "static" or it would be allocated on stack.

   

Do not use AnotherVar = MyVar; // This wil set AnoterVar to 123456; regardless of a re-programming of MyVar!!

   

Instead use a memcpy() to transfer the emEEProm area to an sram area.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Currently the emulated eeprom is not supported for the BLE devices. You can use the API CySysFlashWriteRow itself to write to flash. First,you need to identify how much flash is currently consumed by the project. Each flash row is 128 bytes wide. Based on the address of the final flash byte (afterwards you may see full zeros (you can see from debugger)), you can divide that address by 128 to find the row number. 

   

Another option is to force the compiler to store the flash data at some fixed locations. For e.g., if you want to place the flash data at address 0x1000,  first  Open Build Settings -> Linker -> Command Line -> Custom Flags and add:  -Wl,--section-start=.MY_SECTION1=0x00001000

   

    

   

This places the data in Flash address 1000.

   

Now in your project, globally use: uint8 my_flash_data __attribute__ ((section(".MY_SECTION1")))={0xAA,0xBB,0xCC,0xDD};

   

Now the data AA, BB, CC and DD would be placed at addresses 1000-1003.

   

Hope this helps!

   

     

0 Likes
Anonymous
Not applicable

I used to write flash using method mentioned above with PICs & ST micros. But I was unable to write flash of PSoC BLE kit. It goes to exception handler every-time I try to write anything in the section. Even the variable above is uint8 and we are using it as array.
Queries:
1. Variable is uint8 type, but we are using it as array.
2. I used variable as an array, but I was unable to write using My_Flash_Data[0] = 12;. Whenever I do this code goes into exception handler.
3. I am not sure about Cypress flash, but in other micros flash 0xFF is written after a flash/sector erase. Technically it converts 1's to 0's based on modified values, but can never convert 0 to 1. For example - If you wrote 0x00 into flash after a erase you just can not write anything after this you need to erase that sector again. My question is, does Cypress flash behaves like this. If yes, then what are steps by which I can store data in a particular section of FLASH and read/write / store it as much as I want.
4. I also tried CyWriteRow method, going into exception there also.

0 Likes

Anish, post your complete project to write to BLE flash so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hello Bob, I was not calculating used flash correctly and was providing already used row in case of CySysFlashWriteRow function. Now I can read write data on Flash successfully.

   

But new issue that I am facing is whenever I try to connect with any BLE device, PSoC resets immediately. And if I comment flash read/write lines in my code, everything works smooth. Is there some issue with FLASH.

   

I am using BLE pioneer kit.

0 Likes

When writing to flash there will be a change to the internal clocks (which is reverted when finished) and interrupts are not handled during the write. This will interfere with BLE.

   

Try to shut down BLE, prepare for no interrupt handling (and many when finished) and write to flash.

   

The BLE Pioneer kit has got some FRam on board which is connected via I2C and will be easier to handle in case of a power loss. Consider to use the FRam to store information which survive a power-down.

   

 

   

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Oops, I was not aware that the emEEProm component was not yet released for PSoC4BLEs.

   

Writing into flash or EEProm has a critical point: When there is a power-loss during the write (which takes time in the ms-range) you will have corrupted data. When you have got a CY8CKIT-042-BLE you will find some FRam on the board that you can address via I2C. Writing to the FRam is in the µs range which can be easily bridged afterr a power-loss detection. Additionaly the number of FRam write-cycles  is far larger than flash or EEProm.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Do you know if the EEProm component has been released yet?

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

You can design your power supply to 'hold up" long enough to handle

   

an internal FLASH write operation(s). Ie you can eliminate need for an

   

external memory. Goes something like this -

   

 

   

   
    Power Supply (PSOC 1, but general PSOC applicability)   
   
        
   
                    If you are in a critical loop, whether it be controlling machinery, or writing internal EEPROM, power supply and UP have to handle detection and orderly termination of processing threads upon loss of power. Some points –   
   
        
   
     1)      Use LVD to alert UP there is an imminent loss of power about to occur. Process that interrupt to create an orderly shutdown. Point of pickoff for LVD is also of consideration, closer to the energy source generally better control and maximization over power loss. If external LVD is desired then use A/D converter as LVD device. But also potentially presents circuit design problems associated with pin injection current limitations, eg. when power is absent on PSOC, but coming up on LVD sense node. A simple resistor in series with input may resolve   
   
    that issue.   
   
        
   
     2)      LVD alone is not enough, some processes need time during a loss of power to complete. That’s where short term energy storage is critical, eg. electrolytics, bulk caps, battery…..   
   
        
   
     3)      Circuit design, make sure energy cap does not supply energy back to line or regulator by diode isolation. Schottky preferred (switched power MOSFET best) where possible due to lower Vf, less wasted Pdiss, and allows greater V compliance range in design.   
   
        
   
        
   
     4)      To compute cap size needed     ( this is an approximation, assuming load looks like a constant current source, in reality load typically resistive so one would use exponentials to calculate. UP looks like a constant I load due to CV**2 x f Pdiss, whereas loads, like LEDs with I limiting resistors, look more resistive ) -   
   
        
   
    Q = C x V, I = C x dV / dT, C = ( I x dT ) / dV, dT = ( C x dV ) / I   
   
        
   
    I is max current needed   
   
        
   
    dT is time needed to complete processor thread completion, like EEPROM write as an example   
   
        
   
    dV is allowed voltage drop to insure UP stays within operation specs, basically ( Vloss_of_power_detect – Vupmin )   
   
        
   
    All computations have to take worst case values to insure C min is computed, over V and T. Stated another way as C and dV go up, I down, we maximize time UP allowed to continue running on loss of power. So we can use LVD to shut down processes using power, like LED display driving as an example, shut off high speed clks to modules like PWM, counters, etc. to lower I needed. Then finish orderly shutdown. Obviously you shutdown critical processes, like ones controlling safety for humans, ticks, bugs,etc.. first……     J   
   
        
   
     5)      A typical calculation (29466, nominal values, you would need to worst case the example values) –   
   
        
   
     a.       Assume 12 Mhz clock, this allows PSOC to operate over 3.0 V to 5.25 V, assume Vdd nominal Is 5V, +/- 5%. You could use LVD to switch clock down from 24 Mhz to 12 Mhz to take advantage of wider operating Vdd range while optimizing speed when normal power in effect. Choose LVDlow_trip = 4.64 V, this is a warning power is about to fail, so dV = 4.64 – 3.00 = 1.64V.   
   
        
   
    Sum total current required, note PSOC specs show UP core current separate from modules current, so you need to sum all the currents. Also PSOC currents speced as tytpicals, so you will need to use a “fudge” factor scale them up. Or characterize design at temp extremes to get a value with confidence.   
   
        
   
    So I = ( Iup + Imodules ) xFfudge, lets choose 50 mA as an example, fudge factor 2 x, so I = 100 mA,. Again you will have to worst case this as best as you can.   
   
        
   
    Lastly assume our main problem is writing EEPROM, we want to write one block with confidence just as power is failing. 200 mS is max needed. Also we need to add some code execution time for rest of orderly shutdown, say 50 mS. Then dT = .25 secs   
   
        
   
    Equation is Amps, Volts, Farads   
   
        
   
    So we have (nominals) C = ( .1 x .25 ) / 1.64 = ~ .015 Farads, or 15,000 uF. Electrolytic tolerances quite poor, very temp dependant, so factor this in to value needed.   
   
        
       
        
   
    Lastly this capacitor has to be charged on power recovery, so use defining equations and estimates of available current to restore capacitance charge, in consideration of startup power supply slew rates. Also protect regulator outputs from discharging this capacitance with a diode or switched MOSFET in series with regulator output. Note its voltage drop factors into calculations. Spice useful to get a handle on overall supply design. The capacitor can be on the input or output side of your regulator, certain advantages and considerations for either topology.   
   
        
   
    Additionally more energy may be available stored in transformer fields. Spice good for estimating this behavior.   
   
        
   
    Reminder you have to worst case all values over T and V for a successful/reliable design. And don’t forget component aging effects.   
   
        
0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

 consider saving data in EEPROM:

   

http://www.cypress.com/?app=forum&id=2492&rID=105370

   

 

   

odissey1

0 Likes
Anonymous
Not applicable
        Thanks a lot! These advices are quite helpful! I really appreciate that! Yes I would like to store data in flash in case of battery dead. Our project needs to put the kit to live herself for a long time and recycle her after she finishing the task.   
0 Likes
manusharian
Level 4
Level 4
25 replies posted 10 replies posted 10 questions asked

Hello everybody,

   

I am trying to do the same thing, read and write data from flash. Basically I would like to use the rest of the flash to store values which will be then read and send over a communication protocol.

   

In this way and using the information from PSOC references I created a module presented here. The chip I used is CY8C4248BLQI-BL583 the chip has BLE and 256kB of FLASH arranged in 1024 rows (0-1023 as I observed) of 256 bytes each.  Also do not get confused for me Start and End row are both 450 because I intended to start at 450 row(code is about 415 rows) and go along to 1023 but for testing I only want to fill a row and read it.

   

Also all of you fell free to use this code for your projects it it is ok for you of course. The only rows that you should modify are the first 2 , START and END rows numbers.

   

[UPDATE] Added some comments in the code. Also fell free to suggest improvements/find errors. I think the code can be done also using addresses, but I used rows since in PSOC if you write 3 elements in a row it will automatically delete the entire row.

   

<code>

   


   #include "CyFlash.h"

   

/* Starting Row where you want to put data in Flash */
#define FLASH__nStoreStartRow 450

   

/* Last row where you want to put the data in Flash */
#define FLASH__nStoreEndRow 450 //1023
  /* Heads to know the current write row and read row */ 
static uint32 FLASH__u32CurrentWriteRow = FLASH__nStoreStartRow;
static uint32 FLASH__u32CurrentReadRow = FLASH__nStoreStartRow;

   

/* Write to Flash method. The data received at input should ve size of an ROW, in my case 256 in others 128 */
int8 FLASH_i8StoreData(uint8 *pu8Data)
{
 int8 enHALStatus = CY_SYS_FLASH_SUCCESS;
 int8 i8Status = 1;

   

/* Checking to see if there are still rows available for write */
 if(FLASH__u32CurrentWriteRow <= FLASH__nStoreEndRow)
 {
        enHALStatus = CySysFlashWriteRow(FLASH__u32CurrentWriteRow ,pu8Data);
  /* Check status, if success increase Write row head, else return error code */
  if(enHALStatus == CY_SYS_FLASH_SUCCESS)
  {
            FLASH__u32CurrentWriteRow++;
  }
  else
  {
   i8Status = -1;
  }
 }
 else
 {
  i8Status = -1;
 }
 
 return i8Status;
}

   

​/* Read merhod from Flash of an entire row; this method can be made to read less than a row if needed */
int8 FLASH_i8GetData(uint8 *pu8Data)
{
    uint8 au8Data[CY_FLASH_SIZEOF_ROW];
 uint8* pu8AuxPointer;
    uint16 u16Index;
 int8 i8Status = 0;
 
 /* check if there is something in Flash using read and write heads */
 if(FLASH__u32CurrentReadRow < FLASH__u32CurrentWriteRow)
 {
        
   /* Create the pointer address using the size of the row and the read row head */    
  pu8AuxPointer = (uint8 *)(CY_FLASH_BASE + (CY_FLASH_SIZEOF_ROW * FLASH__u32CurrentReadRow));
  /* copy all the data of a row, This can also be done with memcpy but I did not tested yet */
        for(u16Index = 0; u16Index < (uint16)CY_FLASH_SIZEOF_ROW; u16Index++)
        {
            au8Data[u16Index] = *(pu8AuxPointer + u16Index);
        }
       
     memcpy(pu8Data, au8Data,CY_FLASH_SIZEOF_ROW);

   

FLASH__u32CurrentReadRow++;
 }
 else
 {
  i8Status = -1;
 }
 
 return i8Status;
}

   

/* return the number of rows filled using, read and write heads */
uint32 FLASH_u32GetStoredItems(void)
{
 uint32 u32Result;
 
 if(FLASH__u32CurrentReadRow  >= FLASH__u32CurrentWriteRow)
 {
  u32Result = 0;
 }
 else
 {
  u32Result = (FLASH__u32CurrentWriteRow - FLASH__u32CurrentReadRow);
 }
 
 return u32Result;
}

   

/* Reset the write and read heads This should be called after a flash empty operation*/
void FLASH_vResetStoredItems(void)
{
    FLASH__u32CurrentWriteRow = FLASH__nStoreStartRow;
    FLASH__u32CurrentReadRow = FLASH__nStoreStartRow;
}
</code>

0 Likes
manusharian
Level 4
Level 4
25 replies posted 10 replies posted 10 questions asked

Update on this:

   

Hello,

   

It worked for some time but then I had some clock problems even if I used a 256KB FLASH chip and it is stated in data sheets that these chips should not have the clock problems, or any side effect problems. It turns out it have.

   

But good news Thanks to Cypress community using a technical ticket we corrected this in terms of using another function: CyBle_StoreAppData from BLE_StackHostMain.h file. In the header file you can check the description. if you replace the function FLASH_i8StoreData from my previous post with this function you are good to go. I am able to fully write the flash with BLE connection on and until now I did not have any problems at all.

   

 

   

<code>

   

int8 FLASH_i8StoreData(uint8 *pu8Data)
{
 int8 i8Status = 1;
    uint8* pu8AuxPointer;
 if(FLASH__u32CurrentWriteRow <= FLASH__nStoreEndRow)
 {
       
        pu8AuxPointer = (uint8 *)(CY_FLASH_BASE + (CY_FLASH_SIZEOF_ROW * FLASH__u32CurrentWriteRow));
       
        while(CyBle_StoreAppData(pu8Data,pu8AuxPointer,CY_FLASH_SIZEOF_ROW,0) != CYBLE_ERROR_OK)
        {
            ;
        }
       
        FLASH__u32CurrentWriteRow++;
 }
 else
 {
  i8Status = -1;
 }
 
 return i8Status;
}
</code>

0 Likes