Write / read the internal flash

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

Write / read the internal flash

Jump to solution
29,779 Views
pascalschröer
Contributor V

Hi at all,

does anyone have got an initialisation code to use the internal flash as value memory? The read and write functions itselfes aren't a problem. I tried to read the datasheet and

used PEX but that doens't help me. I don't undestand which register I have to set and what I need to do that it works. By the way I havn't got understood where are the differences between

using the flash and the EEE (EEPROM)?!

I'm using the FRDM-MK20-D50 board and would like to program without the PEX. Can anyone help me?^^

Thanks

Pascal

1 Solution
8,577 Views
mjbcswitzerland
Specialist V

Pascal

You can only write to flash between 0x00000000 ... 0x0001ffff and between 0x00800000 ... 0x00807fff.

You can read back using pointers from 0x00000000 ... 0x0001ffff and 0x10000000 ... 0x10007fff

0x14000000..0x140007ff is the 2k RAM, which has nothing to do with Flash when not in EEPROM mode.

Don't write at 0x00000000 otherwise you will overwrite your program. Chose a Flash area that is not being used from anything (such as the last sector(s) of the program flash.

Regards

Mark

View solution in original post

0 Kudos
33 Replies
8,216 Views
santiago_gonzal
NXP Employee
NXP Employee

Hello Pascal,

You have more info regarding the FlexMemory (EEPROM enhanced Flash of the Kinetis devices) in this Application Note: http://cache.freescale.com/files/32bit/doc/app_note/AN4282.pdf

In resume, in both cases (Using the flash by code, or use the FlexMemory peripheral) you are using the same physical Flash memory, but the number of times you can write to a same address of flash is limited by the technology and the fabrication process of the Flash memory.

The FlexMemory peripheral reserves more Flash memory than you need to emulate a EEPROM memory (Which can be written much more times). The peripheral takes care of the number of times you write to an address and to check the consistency of the data.

Advantages of using the FlexMemory:

     - You can write much more times to the same address and the peripheral will take care of your data integrity.

     - The write and read times are much faster than in standard EEPROM memories.

Regarding the use of Flash routines, you have the C90TFS driver here:http://cache.freescale.com/files/32bit/software/C90TFS_FLASH_DRIVER.exe?&Parent_nodeId=&Parent_pageT...

It has examples to write and read data to flash memory.

Regards,

Santiago

0 Kudos
8,216 Views
pascalschröer
Contributor V

Thanks, but I only search for the "registers" I have to set, to use the internal EEPROM like a normal external EEPROM... I have found a lot of examples and I have read the reference manual but I don't know what to do now?! I have never found a "normal" initialization function... even when I try to init the internal EEPROM with the help of the PEX.

My aim is to configure:

- an EEPROM sector as big as possible where I can save some coefficients or data (is it right that these are max. 2048Bytes / MK20DX128?)

The function to write or read the data at a position in the space with the help of a pointer isn't the problem.

Do I have to use the FTFL Module described in the reference manual? because there are some flash commands ... but I have got the same questions, where and how can I set these commands? Which registers do I have to set instead of theses commands?

Thanks for your help!

Pascal

0 Kudos
8,216 Views
mjbcswitzerland
Specialist V

Pascal

Remember that the EEPROM in the device is not an internal EEPROM but an emulated EEPROM based on the FlexRAM. The maximum size is 2k in your device.

The question is whether you really need to use EEPROM. As the user's manual states, the EEPROM partition in FlexRAM us useful for storing smaller amounts if data that will be changed often.

If you don't need to change the data often (> 100'000 times) there is probably no need to use it and then there is much more space available for normal data flash usage.

See the following thread for how to simply write internal flash: Serial number programming in production - Kinetis K10

The code is suitable for any Kinetis parts (KL or K)

Regards

Mark

8,216 Views
pascalschröer
Contributor V

Thanks, that seems very nice! I will check it out and tell you if it works :smileyhappy:

regards

Pascal

0 Kudos
8,215 Views
mjbcswitzerland
Specialist V

Pascal

1) There is no flash initialisation required and the routines can modify any flash in the device (as long as they are not protected). The linker doesn't need to know what areas the application is working with.

2) There are various rules to be observer when writing to Flash. All flash command pass by the FTFL_FCCOB registers and an attempted write to the Flash memory directly will result in a hardware fault. Also it is necessary to write long words to the device that you use - it is not possible to write bytes. For full detaisl see the Flash Command Operationin your user's manual (Chapter 28.4.9)

The routine that you have used from the other thread is a low-level routine. If you download the uTasker project from KINETIS Project Code you will also have all higher level interfaces as described in chapter 6 of http://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF

These next level routines are:

Eg.

extern int  fnEraseFlashSector(MEMORY_RANGE_POINTER ptrSector, MAX_FILE_LENGTH Length);

extern int  fnWriteBytesFlash(MEMORY_RANGE_POINTER ucDestination, unsigned char *ucData, MAX_FILE_LENGTH Length);

extern int fnMassEraseFlash(void);

which allow simple use.

Eg. if you want to write 100 bytes at the address 0x20000 you can prepare a buffer with the required data content and write it as follows:

static unsigned char myData[100];

int i;

for (i = 0; i < sizeof(myData); i++) {

    myData[i] = i;

}

fnWriteBytesFlash((MEMORY_RANGE_POINTER)0x20000, myData, sizeof(myData));

The routine handles the Flash details and allows programming on a byte basis (with some possible restrictions imposed by the HW) from the point-of-view of the application.

To delete this again

fnEraseFlashSector(((MEMORY_RANGE_POINTER)0x20000, sizeof(myData));

Note however the smallest delete size depends on the Flash sector size of the flash.

For more ease, the next level routines are file system routine so you can write data to files at a higher layer (uFileSystem) or the uParameterSystem (also discussed in the document) contains an interface that is designed specifically to handle parameter storage, retrieval and parameter modifications. It allows the user to work with a pure byte interface and also make single byte changes to the parameters (sort of EEPROM emulation) with a fail safe swap block method so that no parameters are lost in case of resets or power loss during programming.

Note also that the lower level routines also automatically handle writing to devices outside of internal Flash.

For example, if you have a 256k Flash device any writes to the range 0..256k will be written to internal flash. If you have a 1Meg serial SPI Flash connected via SPI it can be defined to be memory mapped to the range 256k..1280k so writes to this area are automatically written it it instead. It also handles writing over flash medium boundaries and the file system layer doesn't need to know the physical medium actually used. The same is true for SPI flash connected via I2C or external parallel Flash.

Finally note that if you use the uTasker project it allows the flash use to be simulated (in the VisualStudio project) so you can also step into the flash programming routines to see how it works - see the Flash interface emulation in operation (to understand how the FTFL operates). The emulation interface also check that no rules are broken when programming flash and will inform you of usage errors.

Regards

Mark

0 Kudos
8,215 Views
pascalschröer
Contributor V

Hey Mark,

I think it works with the help of uTasker :smileyhappy: but what do I have to include in my project to use it there? I would like to include the header hardware.h because there are the used prototypes of theses functions. If I do so, there are many of erros which says "UNKNOWEN TYPE NAME" 'QUEUE_HANDLE' or 'QUEUE_TRANSFER' and so on...

Thanks :smileyhappy:

Pascal

0 Kudos
8,216 Views
mjbcswitzerland
Specialist V

Pascal

You can find typedefs in the file types.h.

Either copy these or replace the ones used with your own, or remove them if not needed.

Since the uTasker project is an integrated environment including all resources like OS, drivers, TCP/IP, USB stacks, FAT etc. it is designed to be usable 'out-of-the-box' when used as entity, but taking snippets of code from it and using them in different environments may require adapting to suit.

If you need only the flash drivers I would just copy the corresponding prototypes and then you also don't need to worry about the rest.

The usual method is however to use the complete uTasker project and put your application into it because then you have pretty much all Kinetis interfaces supported with simple API interfaces (rather than having to develop each from scratch) and you can also run your project in the simulator so that further development and debugging is more effcient. It is still possible to study the HW interfaces if that is your main interest since these are emulated in the simulator, which helps experimenting with them, and the HW API are both flexible and expandable. Projects can be moved between Kinetis and Coldfire processors very easily due to the HW abstraction layer which is highly compatible between the two projects. On top of that your application can simply use various USB and TCP/IP services, as well as other interfaces (FAT, SD-card, SLCD, GLCD) which are available as standard in the project. Furthermore if you change the Kinetis that you are working with you need to only change the processor define in the project to move to whichever one you want without any need to modify any driver code.
For example consider the new FRDM-K64F (costs $29) since it would eat your little FRDM-MK20-D50 for breakfast ;-)

Regards

Mark

0 Kudos
8,216 Views
pascalschröer
Contributor V

Hey :smileywink:

Now I have compiled and debuted it!!! It seems that it works, but is there also a function to read the data? I hope it will work^^ :smileyhappy:

And I have got a question to your function call:

<< fnWriteBytesFlash((MEMORY_RANGE_POINTER)0x20000, myData, sizeof(myData)); >>

Is it possible to write at the address 0x20000? because  the data sheet says, that the FLEX RAM addresses begins at 0x14000000...

If it is possible, in which borders can I work?

btw: did you write the uTaskers code? I have seen your name in the header file. NICE job!

Thank you!!!

Pascal

0 Kudos
8,216 Views
mjbcswitzerland
Specialist V

Pascal

To read from internal Flash you can simply use a pointer to the data, or read into a local buffer using memcpy(). If using uTasker code you can use uMemcpy() which will perform the copy using DMA, which is about 4x faster than a SW copy.

The generic storage reading function is otherwise

extern void fnGetParsFile(unsigned char *ParLocation, unsigned char *ptrValue, MAX_FILE_LENGTH Size);

which will retrieve data from whatever storage medium the address corresponds to but this will simply translate to

uMemcpy(ptrValue, ParLocation, Size);

when there is only internal Flash involved.

In the case of the Kinetis K20 on your board, it has 128k of Program Flash (0x00000000.. 0x0001ffff) so the example with 0x20000 is in fact not possible with this chip. When using the lowest level functions you need to be sure that the writes stay within the Flash boundaries otherwise there may be a hardware fault; the higher level functions will tend to handle additional details to keep within valid ranges.

The program flash has a sector size of 1k (the smallest block of Flash that can be erased at a time) and supports long word, aligned writes.

The FlexRAM is at 0x14000000 and 0x14000fff, which is used as either 2k traditional RAM or is used together with EEPROM emulation. This can be used as normal RAM if the FlexNVM is used as simple data flash (that is, in the same way as the main program Flash).

This function (fnWriteBytesFlash()) is not intended for the 32k of FlexNVM (between 0x10000000 and 0x10007fff), which has also a 1k sector size. However it can still be used with it by doing the following:

- writing writing/erasing write to the address range 0x00800000..0x00807fff. When reading, read from the address range 0x10000000..0x10007fff.

Then it is 'also' possible to save 32k of data in the FlexNVM area as well as in the 128k program Flash area.

The reason for this 'strange' addressing is because these command use the address bit 23 (0x00800000) to distinguish between writes/erases in program or NVM memory. When reading, it is memory mapped as normal for direct accessing.

Until now I have never used FlexNVM in a project because the non-Flex devices tend to be cheaper (as far as I remember) and unless there is a need for very high endurance EEPROM emulation (where a larger amount of Flash is used to create a smaller amount of EEPROM) the standard program Flash works very well. The 1k Flash granularity (up to 4k for the bigger parts) is a strength of the Freescale parts which make the program Flash very flexible anyway.

Regards

Mark

0 Kudos
8,216 Views
pascalschröer
Contributor V

Hey Mark

Yesterday, I tried to read the flash only with the help of a simple pointer, like you said.

<< To read from internal Flash you can simply use a pointer to the data, >>

But that didn't work how I expected...In this case I chose the start address 0x14000000 to write the array into the flash.

Should that work? I haven't understood the right meaning at the end of this paragraph :smileywink:

<< The FlexRAM is at 0x14000000 and 0x14000fff, which is used as either 2k traditional RAM or is used together with EEPROM emulation. This can be used as normal RAM if the FlexNVM is used as simple data flash (that is, in the same way as the main program Flash). >>

When I'm back at home I will try to set the start adress to 0x00000000 and tell you if that works.

Thanks

Pascal

0 Kudos
8,578 Views
mjbcswitzerland
Specialist V

Pascal

You can only write to flash between 0x00000000 ... 0x0001ffff and between 0x00800000 ... 0x00807fff.

You can read back using pointers from 0x00000000 ... 0x0001ffff and 0x10000000 ... 0x10007fff

0x14000000..0x140007ff is the 2k RAM, which has nothing to do with Flash when not in EEPROM mode.

Don't write at 0x00000000 otherwise you will overwrite your program. Chose a Flash area that is not being used from anything (such as the last sector(s) of the program flash.

Regards

Mark

0 Kudos
8,216 Views
pascalschröer
Contributor V

Thank you very much for your help Mark!

My problem is solved. It works how it should. :smileyhappy:

I have got only a little question to the data flash. Is it secured, that the program flash never reaches the data flash? In other words, can I be sure that the addresses from                0x00800000 to 0x00807fff are "reserved" for my data?! Or do I have to configure something?

Thanks!

Pascal

0 Kudos
8,216 Views
mjbcswitzerland
Specialist V

Pascal

If you don't put program content there it will not be used by anything apart from your application.

That is, if this area if not defined in the linker script for (possible) program code use you can be sure that it is 'reserved' for your application.

I believe that some code will use linker scripts settings to define also data content but I wouldn't do this for two reasons:

1 - it is simple and more understandable form a maintenance point of view to completely control this in the code by defining the start address and the size of the area and the code doesn't need any liker script support to be able to then use this as it wants (based on using address in memeory)

2 - linker scripts are usually not portable and so make moving projects to other environments error prone when application details are cointained there.

Regards

Mark

0 Kudos
8,216 Views
pascalschröer
Contributor V

Hey,

Okay but how can I ensure that the program content occupied only defined space?

Do I have to change the setting in the MK20DX128_flash.Id ? In my opinion the code is very

difficult to understand for the first time :smileywink: Could you tell me what I have to change?

Thanks

Pascal

0 Kudos
8,216 Views
mjbcswitzerland
Specialist V

Pascal

If your MK20DX128_flash.ld is the same as this one here: mcuoneclipse/Examples/FreeRTOS_Ports/CodeWarrior/CW_FreeRTOS_FRDM-K20D50M/Project_Settings/Linker_Fi...

there is no definition for the FlexNVM so the program will also never be located there.

According to that layout the code will occupy only program flash:

m_text (rx) : ORIGIN = 0x00000800, LENGTH = 128K - 0x800

Regards

Mark

0 Kudos
8,216 Views
pascalschröer
Contributor V

Okay :smileyhappy:

Thank you to spend so much time in my problems!

Regards

Pascal

0 Kudos
8,183 Views
pascalschröer
Contributor V

Hey I have got another little question to the flash.

I would like to know, how much time I have to "reserve" to store an int16 variable to the flash?! Without using a ring buffer or something like that... The flash clock is 16MHz... Is there any formula?



Thanks



Pascal

0 Kudos
8,169 Views
mjbcswitzerland
Specialist V

Pascal

The flash programming is self-timed and doesn't depend on the Flash clock speed (read/verify operations will be clock speed dependent).

The smallest unit that can be programmed is a 32 bit value (not 16 bits) and its programming time will depend on various factors such as the exact supply voltage used, temperature, silicon variations (presumably) and also age of the device (how many times it has already been programmed/deleted).

The values are given in the data sheet to your device and it takes typically 65us to program a long word in your K20M50 and a maximum of 145us. I believe that the value is the same for the program Flash and the FlexNVM when used in data flash mode. The maximum time is "probably" the worst case for all valid operating conditions and valid during the life-time of the part (but if this value were to be especially critical I would contact Freescale for confirmation or guidance on a possible safety margin).

Therefore, generally you need to allow >= 145us for a single long word write.

As you probably know, it is not possible to execute program code from the program Flash when data is programmed in the program Flash and it is usual to block interrupts during programming and run the Flashing code in SRAM. This can be critical in systems that need to process data during this time (eg. handle ADC values every 100us and receive UART rx bytes every 20us) and then it is usual to either run some interrupt code in SRAM too (and allow its specific interrupts) or buffer such data using DMA to avoid overruns. When writing data to the FlexNVM it is however possible to execute code in the program Flash, meaning that interrupts don't generally need to be blocked in this instance. When FlexNVM is available in a part this is a possible advantage over a device with a single plane of program Flash.

Regards

Mark

0 Kudos
8,169 Views
pascalschröer
Contributor V

Hi Mark,

Can I say:

I use this range (FlexNVM):

range

0x10000000 to 0x10007FFF 4 ReadWrite// 32KB Data Flash

and set the FlexNVM Partition Code to 1111 = Reserved (defaults to 32 Kbytes of data flash, No EEPROM)

The PFLSH bit of SIM_FCFG2 is 0 // 0 = Physical flash block 1 is used as FlexNVM

Now I will take the FlexNVM as "normal" data flash. And there should be a gap between the program Flash

and the FlexNVM.

Now I don't need to disable the interrupts here:

DisableInterrupts;                                                                //protect this region from interrupts

fnRAM_code((volatile unsigned char *)FTFL_BLOCK);          //execute the command from SRAM

EnableInterrupts;                                                                //safe to accept interrupts again

Is that right?

I'm not sure about the FlexNVM range because the datasheet says that (please see the picture below).

Thank you very much!

Pascal

0 Kudos
8,169 Views
mjbcswitzerland
Specialist V

Pascal

This is correct. The memory range is 0x10000000..0x10007fff according to the physically available FLASH.

The user's manual says that the address range is much larger but the actual content is only read from the correct locations. I think that the wider address range means that accesses won't exception in that range (unused addresses read back 0x00) but obviously there is no point in trying use more address space than is actually physically available.

Regards

Mark

0 Kudos