I don't see any SDK example to read/write data to non-volatile memory of MKL28Z such as internal ROM and flash during runtime. I need to store CHANGING data measurement statistics & other system pertinent info so in case of power outage or intentional power-down after manufacturing test of the product & shelving in the box, these data will be retained & can retrieved during system initialization and during normal in-service operations.
Basically, I need non-volatile storage for small database structures. I remember reading about a 32-byte "protected" user data area that will persist even at VLLS0, lowest leakage stop mode. But that's too small & I need space for data to persist even at complete power-down.
I know MKL28Z has 32K ROM & 512KB Flash RAM. I missed the point when I selected MKL28Z as MCU for our product that it has "ROM" not "EEPROM", but is there a way to write to the ROM, away from bootloader area? This way I don't have to mix up with bootloader. I understand that ROM is permanent but in today's technology maybe there's a way to read/write to in in MKL28Z?
I saw a 2015 post where "Ma Hui" recommended downloading a "driver" for the KL43Z? I honestly don't understand how this goes... https://community.nxp.com/thread/356524 ... and this may not work for the KL28Z I'm using.
I mean, I'm currently using MCUXpresso IDE to research & develop different operations that I will soon gather all together in 1 big system of operations under RTOS & multitasking, mutex, queuing operations so I don't understand how that driver gets into this picture.
Is it possible to do segmentation during compilation with pre-processor directives like .bss .data . code... through MCUXpresso builds so at run time I know the variable combined in flash with code will RESIDE in flash & not get loaded in RAM which will disappear on power-down?
What I'm asking is a method to save / store realtime-changing data to memory during manufacturing test &/or in-service runtime that will persist even when system is powered-down, either to/from:
2) Flash RAM
Please keep in mind, this is reading/writing data in realtime runtime operation.
Thanks for the help.
P.S. to Erich,
Great info & related post links. I'm devouring all right now. If you see the "Memory details" window screenshot on my recent response this morning posted above, it shows the default memory map of an SDK flash project, how it is in MCUXpresso very similar to your article how you did it in PE. I don't have that "InfFLASH Component" as used in PE so I SKIPPED that section on your old article. Do you think I'll do well in MCUXpresso without having something similar?
This snapshot below is the new memory configuration AFTER I split the flash & made memory range adjustments.. I only took the top 64KB flash memory, subtracted 64KB from 512KB, leaves 448KB for vector table & code. This is just for practice in this project. I'm not sure if I had to specify the same "driver" for both flash areas as shown on the rightmost column but I did anyway. Build did not complain but I have not debugged because I'm still about to change the code. I'm not flash programming as this project is about. I'm writing data into the flash memory 64KB I allocated. My plan in step-by-step... following your post.
Now, I'm about to do the header file & source programming for setter & getter functions similar to what you did.
I'm not sure if changing the "Names" column would affect anything in linker & I wonder whether or not I use these names in the definitions will have any bearing since there I'll be HARDCODING direct memory address definitions like those in your header file example.
Before I do that I have some detail I'd like to ask > Question: Referring back to your Memory Configuration of internal flash inside Processor Expert (PE), did you intentionally "bypass" the details about the memory range between MemoryArea2 and the added MemoryArea4 which is MemoryArea3 because Area3 did not have enough space to take out from? basically 1FC00-1F7F0 = 410h = 1040d (an odd number)? Just curious...
Let me know if you have any further tips, corrections &/or comments on the matter.
(I combined notes to both Erich & Mark on this post.)
I was thinking along those lines as you are advising but I needed an expert like you confirm to me. Linking is good way because the binary result will already make all memory map aligned, wherever you port the FW the process, any flash programmer will put things in the right place. Am I correct?
My concern with "split" is it will take my 512KB flash & split it in half so I will only be left with 256KB for vector & code.
I don't like minimizing my code when I may only need, say, 32KB of data, not 256KB.
I like how PE lets you manually specify address range & size at will but as MCUXpresso is more newer & supposedly more powerful, I'll see if that is also possible to do. Do you know?
I'm thinking for experiment after I "Split" Flash section, I can then modify columns "Location" & "Size". I'm going to try such on a dummy project & trying out the rest of your examples. I'm studying all the links that are embedded in your linker blog post, links within links... so I can know better how these memory mapping & linking works.
All data are embedded & transparent to any user. The system will use all data internally for different calculations, measurements & statistics to indicate "to a user" whenever any part of the product needs to be replaced or for any error reporting.
Let me think about the necessity of an EEPROM emulator, I would like to keep things very simple.
I like both yours & Erich's interface read/write function calls so I'll definitely create those.
There will be RTOS for multitasking so I may be using mutex to ensure data protection integrity on read/write.
So I'm taking both of your great suggestions & pick/choose the best way that will make the system work.
Thank you very much TO BOTH for the help.
(Note to Mark: this post was supposed to be directed to Erich Styger but these follow-up questions can apply to your most recent post too. So you are welcome to respond as I hope Erich would also do. Thanks to both in advance.)
... I posted about my issue on NXP forum community about using MCU MKL28Z's flash memory to read/write data that are needed by my product to be persistent even when powered down, in order to have the data available on power up.
I just found your old blog, https://mcuoneclipse.com/2014/05/31/configuration-data-using-the-internal-flash-instead-of-an-extern..., about reading/writing data from/to flash memory area.
It seems viable for my application but I'm on MCUXpresso IDE. I have not seen you reply to my post on NXP forum maybe because it's under a different category?
For any project in MCUXpresso, under Properties, there's the C/C++Build -> MCU settings -> Default LinkServer Flash Driver Memory Map. Based on your example, I wonder if I need to MODIFY ("Split' button) the Flash Area so the flash program space will separate from the planned data flash space?
Also under Debug Configurations (I use PEmicro Debugger) -> Debugger tab - Advance Options button, on the pop-up window, there is option to "preserve" non-volatile memory by range from & to boxes.
The Flash memory range of MKL28Z is 00000000-0007fffh. Do I just define a memory block within that range that I know should be protected from flash erasure & code programming by using that "advance" options under debug configurations?
Outside of debugging, how will this allocated data memory space pan out when binary code flashing with standalone programmers?
Is the data range now based on what's defined in my firmware in a header .h file, by HARDCODING those addresses to read/write from & creating special function calls in a source .c file like you have done in your example?
Thanks for the help.
There are various possible solutions but from a firmware point of view you need routines for the flash interface:
- writing data (the KL28 can write aligned long words or multiple of)
- reading data (memory mapped reading is possible for just a pointer based copy from the flash location to user data is needed unless the interface should allow multiple media to be used without the higher levels being aware)
- erasing sectors(s) - a Flash sector needs to be erased each time any bit in it needs to be changed from '0' to 1''
Then you need an EEPROM emulation layer that allows the user to read and write data without needing to know exactly where it is located (this allows the flash to be managed with wear level techniques to increase its life time/number or writes/erases) so that the user can effectively change bytes without needing to be aware that it is deleting and moving data around. The EEPROM emulation layer should also ensure that no data can be lost in case of a power outage during the (several ms) time which this takes, unless your product quality doesn't need to ensure users can't lose data in such rare circumstance.
From a system design point of view it is simplest to have all of your working parameters in RAM (eg. a struct) so that the application can access them and change them as desired. You only need to then call the parameter storage calls when the new parameters are actually needed to be saved (a save or commit command) and you can restore after a reset just be reading the block of data back to the struct. If you always need to update parameters in Flash on every change (no test change interval, for example) it just means the save commend is executed after ever change of any parameter (slower since it can take time to erase and rewrite flash each time and causes more Flash wear).
Directly working with parameters in Flash is possible by working with a struct pointer set to their physical Flash location (which can move around) but is not adviced (unless you have very limited RAM) since you will then also need to ensure that parameters (program variables at the end of the day) are also aligned and have sizes that are appropriate for the Flash used (and may need to be redesigned when a different chip is used) so that they can also be changed according to the flash rules.
Where the Flash area is that is used by the EEPROM emulation layer and how large it is should be configurable - either by defines or by editing the linker script (I avoid the second due to portability/environment dependency but if you know that you are writing for a single project that will never be reused or need porting script based customisation is possible if you find it easier).
The article in Configuration Data: Using the Internal FLASH instead of an external EEPROM | MCU on Eclipse describes the principle, but is using Processor Expert. Technically you can use Processor Expert in MCUXpresso IDE, but PEx is a legacy technology by now.
To your questions:
- yes, you should split your FLASH memory so you have a dedicated area for your flash programming, otherwise the linker might place code/data there
- Best if you use a memory block at the end of the FLASH area. Make sure it is aligned to the block size of your flash (e.g. 8K).
- Hardcoding the address is the most simple way to use it. The more elegant (but more complex) way is to define linker symbols (see Accessing GNU Linker Script Symbols from C/C++ | MCU on Eclipse )
I hope this helps,
I guess I need an embedded setup within MCUXpresso for my FW & HW product like some build pre-processor directives of segmenting memory, surrounding specific variables with #ifdef - #endif that will ensure the data will fall within flash memory map (00000000-0007FFF) area for sure, at the correct specific area I allocate within the non-volatile space. Something like setting-up for .bss, .code, .data & such & or setup for build & flashing within MCUXpresso together with variable definitions may be surrounded by #ifdef-#endif pre-processors.
No linker scrip setups are required since the flash memory is memory mapped and code can access it with pointers.
Some solutions do control it via the linker script but these are unnecessarily complicated, compiler dependent and so non-portable (therefore generally poor solutions that should be avoided).
The uTasker parameter system's user setup is simply:
#define PARAMETER_BLOCK_SIZE (2 * FLASH_GRANULARITY)
#define PARAMETER_BLOCK_START (SIZE_OF_FLASH - PAR_BLOCK_SIZE)
to configure a swap block (the safest method with fail safe storage) consisting of two flash sectors at the end of the Flash memory, which is a setup that will generally suit all processors (but can be changed to suit different storage sizes and locations to suit any requirement). This doesn't require any linker script fiddling and so is fully compiler independent and portable to ensure no future maintenance issues when environments are changed or a new developer takes over.
Download the uTasker open source project and copy its parameter system, which works on the KL28:
You can also simulate the KL28 operation (including Flash) whereby any errors in usage will be signaled by the simulator so the developer can't do anything wrong without knowing it (or having to spend time debugging on the HW):
- [parameter- and file system, including low level Flash accessing] http://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF
There is a binary at the link below that allows parameter system testing on the FRDM-KL28Z (the save command allows parameters changes to be saved in a fail-safe manner so that even power loss during execution will not cause invalid data/parameters to persist.
Low level memory commands can be tested as show in the video: https://www.youtube.com/watch?v=Pe9A8qsefzQ (valid also for FRDM-KL28Z in standard Flash memory).
Note that the ROM in the KL28 is used for the boot loader and is not accessible by the user.
Complete Kinetis solutions for professional needs, training and support: http://www.utasker.com/kinetis.html
uTasker: supporting >1'000 registered Kinetis users get products faster and cheaper to market
Request Free emergency remote desk-top consulting at http://www.utasker.com/services.html
Open Source version at https://github.com/uTasker/uTasker-Kinetis