1
\$\begingroup\$

PSoC4 chips have only between 2 and 4KB of RAM. That's not much, especially if I want to do some data processing. Between 16 and 32KB of Flash seems much more promising, even if I need to share it with the code. Thanks to the "Flash Accelerator" it seems one can use Flash the same way as one would use SRAM, only at cost of a minor performance drop. There's a document that describes how to do it, and it seems quite trivial:

in Project > Build Settings > Linker > Command Line > Custom Flags add:

     -Wl,--section-start=.MY_SECTION=0x00001000

then declare your variable as:

     uint8 variable1 __attribute__ ((section(“.MY_SECTION”)));

(that is using GCC, as PSoC Creator does "out of the box").

Now if I understand correctly, the first thing to consider is the standard 100k write cycles that standard PSoC4 chips have. Performing 100k writes to a variable can take a very short time; does the "accelerator" protect the cell or do I risk damage to the chip with a simple for(uint32 flash_var __attribute__ ((section(“.FLASH”)))=0 ;flash_var<100000;flash_var++){...}?

Next - can I expect the variable to persist its value across power loss, or do I need some extra wizardry to obtain this functionality?

Does that play nice with bootloader in bootloadable applications, or do I risk overwriting the bootloader or something like that?

What other considerations concerning that kind of variables should I have in mind, that I haven't thought of - and which I'd likely learn only "the hard way" if I don't ask?

\$\endgroup\$
6
  • 2
    \$\begingroup\$ I'm not familiar with this chip, but I did some searching and I believe the "flash accelerator" only provides fast read access to flash. There is no way you are going to get 85% of RAM speed while writing flash, not to mention how easily this would destroy the flash (as you noted). To use flash for read/write variables, you will need to use the correct operations to first erase a page of flash and then write to it. In flash, writing can only change "1" bits to "0". To changes "0" to "1", you must erase an entire page. \$\endgroup\$ – DoxyLover Sep 1 '14 at 16:38
  • \$\begingroup\$ @DoxyLover: It appears you are mostly right. The variables can't be trivially written, but the situation isn't nearly as bad. PSoC provides Emulated EEPROM functionality, meaning you declare the variables as volatile static const (or just volatile const in global scope) for reading, and modify them easily through Em_EEPROM_Write(&variable,&value,sizeof(variable)). The write operation takes 15ms typically, so yes, a far cry from 85% RAM speed; it's good for config data but not buffers and the like. \$\endgroup\$ – SF. Sep 1 '14 at 18:34
  • \$\begingroup\$ If you're scrapping for RAM, you need to move up a series. \$\endgroup\$ – Matt Young Oct 15 '14 at 16:39
  • \$\begingroup\$ @MattYoung: The tiny problem with that is that the price jumps up an order of magnitude. \$\endgroup\$ – SF. Oct 15 '14 at 17:41
  • \$\begingroup\$ You wouldn't use a lawn mower to plow a 1000 acre field... \$\endgroup\$ – Matt Young Oct 15 '14 at 17:45
1
\$\begingroup\$

I had very good results using the PSoC3's Emulated EEPROM, and I believe the E_EEPROM component is the same for both PSoC3 and PSoC4. Here are your easy answers first:

  1. Yes, the values will stay persistent across power loss, as long as the power loss doesn't occur during the write cycle.

  2. You shouldn't have any issues with your E_EEPROM variables overwriting anything. If you're using the Cypress macros correctly, the compiler should be locating empty flash locations for you. However, I have no idea what happens if you allocate more flash variables than you have room for. I would hope the compiler would throw an error for you, but I haven't tried it.

  3. I would check your documentation again for how to actually use the E_EEPROM. The PSoC3 used the Keil compiler because the core is actually an Intel 8051, unlike PSoC4's ARM core, so it's possible that you're correct. But it seems more complicated than it needs to be. I didn't have to use any compiler flags, and the Emulated EEPROM component provided a much easier to use API. Also, take a look at the example projects that come with PSoC Creator.

Here's the downside: As far as I know, you do need to worry about flash wear levelling. I was unable to find any references to an automated wear-levelling scheme in the PSoC3 docs, so I assume there is none. You can definitely wear out your Flash cells with repeated writes, though the compiler may be smart enough to optimize out the Flash writes in your loop example.

Keep in mind that you also don't need to write to the same variable to wear things out. In the PSoC3, flash rows are 256 bytes wide. If you have an array of 32 uint8's and that array happens to align perfectly with a Flash row, writing to any element of the array is going to put the entire array through a Read-Erase-Write cycle. The PSoC4 row size might be different, but you're going to face the same situation.

The E_EEPROM was a perfect solution for me when I needed data to stay persistent across resets, and didn't have nearly enough real EEPROM. It's a good option as long as you have the space and take care to avoid wearing out your Flash cells.

\$\endgroup\$
1
\$\begingroup\$

The Emulated EEPROM component is handy, and I've used it for a couple of projects where I needed to store some fairly large data arrays between power cycles. 2 pitfalls to watch out for: Bootloading and wear-levelling.

At power-up (by default), the PSOC bootloader will check the entire application flash checksum to test the whether the application image is valid or not. By saving to flash, you are affecting the data that is summed and have a 255 in 256 chance of "corrupting" your flash image from the bootloader's perspective. Cypress proposes a solution where the bootloader is goosed into calculating the checksum only during a bootloadable image update. Which is fine if you don't plan to update the PSOC in the field.

This will compromise the bootloader's ability to throw an exception if the image has actually been corrupted. Not a common event, but a better alternative to running rogue instructions from flash. My particular projects involved a PSOC5LP working as a peripheral module to a larger (ARM Cortex-A) control system. So my specs allowed the system, as a whole, to handle an invalid image exception should it happen.

The workaround that I used was to buffer the Emulated EEPROM contents in RAM at boot, use and modify the data during runtime, and finally flush the arrays back to flash at power down.

When I loaded the Em_EEPROM data into RAM at boot, the application calculated the checksum. The data would then be used and occasionally modified by the application code during runtime. When writing back to the Em_EEPROM at shutdown, I would calculate the checksum again, and then write a value to balance the delta back into a set of flash registers that I had reserved for this check-and-balance mechanism.

As with any code that can write to flash, be very, very conscious of wear levelling. Due diligence is strongly advised to develop a mechanism to limit unnecessary writes. Also, there is no 100% bulletproof method for protecting your image data when using self-writing flash. At some point, there will be a power loss event that will cause a write or series of writes to fail. Application code should take this into consideration and handle exceptions accordingly.

As always, design within the confines of your system specs, goals and capabilities. If the projects that I have worked on were stand-alone MCU designs, then I would probably not have used the methods that I described above. In the context of the projects as they were designed, it worked rather elegantly. For a standalone PSOC system, I would have likely used an external persistent medium (flash, EEPROM, SD card, etc..) to keep the design more robust by avoiding self-writing flash.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.