Write / read the internal flash

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Write / read the internal flash

ソリューションへジャンプ
39,830件の閲覧回数
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 解決策
18,628件の閲覧回数
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 件の賞賛
返信
33 返答(返信)
1,287件の閲覧回数
pascalschröer
Contributor V

Okay thanks!

Regards

0 件の賞賛
返信
1,287件の閲覧回数
pascalschröer
Contributor V

Hi Mark,

I'm sorry to steel your time but I have got another question... First I thought that the "normal" flash function is enough for my application but I'm writing my bachelor thesis and my prof wants to see the EEPROM emulation for some specific cases. For example he would like to see an error code saved in the flash. So to rewrite or erase the error code because of an exception I have to erase a whole sector of 1024 bytes -.- that's too much when I only have to change a few bytes... However, he would like to see the emulation... although I know that the byte write operation is possible with your uTasker code too :smileywink:

So I would like to implement a little sector using the EEPROM emulation. That should only be about 1 kByte or less. The rest I would like to use as "normal" flash like it works :smileyhappy:

Well, I have tried to implement it but I get some hardware faults... Could you tell me the initialization for the EEPROM emulation? I don't know how to partition the data flash space. Do I have to set some setting in the code warrior?

The next point is, that I'm not sure where the EEPROM space and the data flash sector begins, when I have configured it. When I look at the picture below, I think that the start address of the "normal" flash begins at 0x10000000. But is it right that the first EEPROM address is at 0x14000000 ?

Thank you!

Pascal

Bildschirmfoto 2014-05-12 um 20.19.34.png

0 件の賞賛
返信
1,285件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

As you probably already know, 1k EEPROM will require 16k FlexNVM (leaving 16k for use as data Flash if required). This means that writing a few bytes in EEPROM will require 16k to be used. The emulation will also be erasing 1k sectors each time that values are modified. This means that in most cases data flash is not less efficient than EEPROM but quite a lot more efficient (in terms of storage requirements). Therefore I am assuming that use of EEPROM is an academic exercise and not an application requirement  becasue its main interest is when large amounts of small changes are to be made - > 50'000 for example where its reliability then has an advantage.

You should find the details in section 28.4.2.1 of the user's manual. As it informs there, the partition is written using a flash command 0x80. This is not in the flash interface that you have but can be added easily with a new switch case and then passing a buffer with the data size and partition code. The exact data to be sent is given in chapter 28.4.11.14. There si then a second command for the FlexRAM function (0x81), also described there.

Since I haven't used the EEPROM I don't know all details but I expect that the FlexRAM address area from 0x14000000 is used as EEPROM, with the EEPROm emulation taking place automatically between the FlexRAM buffer and the partitioned area of FlexNVM. I also expect that, if partitioned for 1k EEPROm the remaining FlexNVM in data mode will be accessible from 0x10004000 (after the area used by EEPROM). The best way to find out is to command the partition and the experimet with what happens.

Athough not for the EEPROM mode, I have attached a binary file that can be programmed to your board (FRDM-K20D50M). I have now added FlexNVM as data flash support to the uTasker project which makes its use simpler. Rather than need to know where the FleNVM is located, the flash interface routines make it look like it is extended to the end of program Flash. If you connect via Virtual COM to the UART at 115kBaud there is a new set of commands in the "Input/Output" menu as follows:

md       Memory Display [address] [<l>|<w>|<b>] [num]
mm       Memory Modify [address] [<l>|<w>|<b>] [val]
mf       Memory Fill [address] [<l>|<w>|<b>] [val] [num]
sd       Storage Display {as md}
sm       Storage Modify {as mm}
sf       Storage Fill {as mf}
se      

Storage Erase [address] [length]

The first part is not new but allows displaying and writing memory mapped memory (SRAM, Flash, peripheral registers etc.). An attempt to write to Flash would cause an exception in this case.

The Storage commands are different in that they use the Flash interface so they work like the memory commands but add additional capabilities that are very useful when testing.

1. The FlexNVM is mapped to storage space after the internal program Flash (0x00000000..0x0001ffff) so the FlexNVM is 'virtually' mapped to 0x20000..0x27fff).
"sd 1fff0 l 10" commands a read of 10 long words from 0x1fff0 and returns (when the flash is empty)

Memory Display

0x0001fff0    ffffffff ffffffff ffffffff ffffffff  ................

0x00020000    ffffffff ffffffff ffffffff ffffffff  ................

0x00020010    ffffffff ffffffff  ........

That is, it puts the program flash and data flash together as if it were contiguous. The same command using "md" would exception after the 0x1ffff boundary is passed!

2. "sf 1fff0 12345678 10" fills the area with 10 x 0x12345678. This means that these commands can be used to write to Flash (which would not be possible with memory modify or memory fill).

3. "se 20000" erases a sector from 0x20000 (from the start of the FlexNVM area), whereas "se 1fff0 20" would erase the last sector in program flash and the first in FlexNVM since it needs to erase two sectors to clear the requested area.

This means that file systems or parameter systems can use a contiguous area of flash made up of the end of program Flash and the FlexNVM to manage, say 64k of parameter data without complications posed by the fact that these areas are in fact not together in physical memory. Write and erase operatiosn in FlexNVM space don't block interrupts since this is not neccessary when running code at the same time in program Flash, but the accesses that are in program Flash still block interrupts.

The "memory display" command can still be used to see the physical FlexNVM space at "0x10000000" whereas the storage commands make its use simpler.

Flash restrictions still apply with the storage commands since it is still not possible to erase less that a sector at a time, etc., although 4 byte writes to 0x20000, 0x20001, 0x20002 and 0x20003 are possible as the final write commits the 4 buffered bytes of a long word after they are all available. A byte fill is possible as long as the length is a multiple of 4 bytes, etc...

In case external Flash were connected via SPI the SPI Flash occupies the virtual address space "after" the FlexNVM so that the application can simply use an even larger contiguous address area for file system/parameter storage. (eg. a "sf" command could be used to fill a pattern from a starting address in internal program flash, thorugh the FlexNVM area and ending somewhere in the SPI Flash area).

Regards

Mark

1,285件の閲覧回数
pascalschröer
Contributor V

Hey Mark,

The EEPROM emulation works! :smileyhappy: but I have got two questions:

1.

For the very first time I have to patition the EEPROM size and the normal flash size like you know.

After that the device partition mustn't be changed anymore, because of device damage. But how can

I figure that the flash is already partitioned? I tried to trigger at the FTFL_FCNFG_EEERDY bit but this bit

isn't set after partitioning....

2.

When I flash the device with code warrior the IDE does a MassErase so all saved data in the EEPROM

partition are deleted... is there any setting to fix that? To fix that problem for the normal flash use I have

selected a "not erased" sector in the advanced CW settings.

Thanks

Pascal

0 件の賞賛
返信
1,285件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

1. FTFL_FCNFG is a status register and resets to 0x00 therefore it is not intended to show the state of the partition (it is used to verify that operations have completed).

I believe that you need to read back the "partition code" and "data set size" from Data Flash IFR (see section 28.3.3) - command 0x03 in table 28-42,

2. Check that you don't have the debug connection set to perform a mass erase on connection (see in the connection characteristics) since I would expect CW to only erase the area that it needs to program code to. I always work with parameters in program flash and haven't had difficulties, even without setting any advanced settings.

In the worst case, you can load a boot loader to the board which then accepts new applications but doesn't delete more internal program code than set up to do, thus protecting stored data in program flash or elsewhere.

I noticed that when using the OpenSDA's USB-MSD loader it performs a mass erase and thus deletes all data in program and also data flash (EEPROM). I suppose that the mass erase makes the operation fast but such details can be a nuisance to real developments and thus make the tools useless in some situations.

Personally I load the uTasker USB-MSD loader to the board instead since this only deletes the area in program flash reserved for application code and loading programs to be board is much faster than using CW - an "attach" target can then be used for debugging if needed.

Regards

Mark

0 件の賞賛
返信
1,285件の閲覧回数
pascalschröer
Contributor V

Hey Mark

Now, the program works like it should! Thanks for that!

But if I work like the datasheet says, I have to do a FCMD_ERASE_ALL_BLOCKS (0x44) command

before set the partition command. So I can be sure that the device is erased. The Erase command doesn't work...

Because of the mass_erase after flashing the device, that doesn't matter. However, do you have an idea

why the command doesn't work? I thought it would be very easy to implement this command because it hasn't

got any parameters to set... I have set FTFL_FCCOB0 = 0x44 and add it to your uTasker code example like the other

commands for partitioning. Is there a fault?

Thanks

Pascal

0 件の賞賛
返信
1,285件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

The erase all blocks command is already supported and used.

See:

// This command is used to erase the complete FLASH contents, including the security area

// Since the complete FLASH will be empty the code will no longer run afterwards

//

extern int fnMassEraseFlash(void)

{

    return (fnFlashNow(FCMD_ERASE_ALL_BLOCKS, 0, 0));

}


Could you send me the code so that I can check it out?

Regards

Mark

0 件の賞賛
返信
1,285件の閲覧回数
pascalschröer
Contributor V

Hey Mark,

here is "my" code :smileywink: I think it's almost the same like yours. But when I try to work with the ERASE_ALL_BLOCKS command

the CW shows me a strange erros message "no source found at ...0xFFFFFF....." and after that the device is secured. So I have to reflash it and work without the

ERASE_ALL_BLOCKS command. Then the code works very well.

Please notice that I set: FTFL_FSTAT |= FTFL_FSTAT_CCIF_MASK;

Behind the Partition command and the flex ram command. Without this, there is no partitioning...

I did that because the data sheet says: After clearing CCIF to launch the Program Section command,...

But this sentence is written behind every command sentence. I'm not sure why I can't find this in your code

behind the PROGRAM_LONG_WORD command...

However, behind the ERASE_ALL_BLOCKS command the CCIF Flag hasn't got an effect.

* FLASH.c

#include "FLASH.h"

// This routine runs from SRAM - the reason why the pointer is passed is to avoid the routine taking it from a const value in FLASH, which is then not code location dependent

static unsigned short fnFlashRoutine[] =                              // to avoid potential compiler in-lining of the routine (removing position independency) the machine code is used directly

{                    

    0x2180,    // MOVS  r1,#0x80                                          load the value 0x80 (command complete interrupt flag) to register r1

    0x7001,    // STRB  r1,[r0,#0x00]                                      write r1 (0x80) to the passed pointer location (r0)

    0x7801,    // LDRB  r1,[r0,#0x00]                                      read back from the same location to r1

    0x0609,    // LSLS  r1,r1,#24                                          shift the register content by 24 bits to the left so that the command complete interrupt flag is at bit 31

    0xd5fc,    // BPL    -4                                                if the command complete interrupt flag bit is '0' (register content is not negative value) branch back to read its value again

    0x4770    // BX    lr                                                return from sub-routine

};

void FLASH(unsigned char ucCommand, unsigned long *ptrWord, unsigned long *ptr_ulWord)

{

    static void (*fnRAM_code)(volatile unsigned char *) = 0;

    if (!fnRAM_code)                                                  // the first time this is used it will load the program to SRAM

    {                                              

        #define PROG_WORD_SIZE 30                                        // adequate space for the small program

        int i = 0;

        unsigned char *ptrThumb2 = (unsigned char *)fnFlashRoutine;

        static unsigned short usProgSpace[PROG_WORD_SIZE];              // make space for the routine on stack (this will have an even boundary)

        ptrThumb2 =  (unsigned char *)(((uint32_t)ptrThumb2) & ~0x1); // thumb 2 address

        while (i < PROG_WORD_SIZE)                                      // copy program to SRAM

        {                              

            usProgSpace[i++] = *(unsigned short *)ptrThumb2;

            ptrThumb2 += sizeof (unsigned short);

        }

        ptrThumb2 = (unsigned char *)usProgSpace;

        ptrThumb2++;                                                    // create a thumb 2 call

        fnRAM_code = (void(*)(volatile unsigned char *))(ptrThumb2);

    }

    while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF_MASK)) {}                            // wait for previous commands to complete

    if (FTFL_FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK))          // check for errors in previous command

    {      

        FTFL_FSTAT = (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK);              // clear old errors

    }

    switch (FTFL_FCCOB0 = ucCommand)        // enter the command sequence

    {

    case FCMD_ERASE_ALL_BLOCKS:

        break;

    case FCMD_PROGRAM_PARTITION:

        FTFL_FCCOB4 = (unsigned char)((uint32_t)0x34);

        FTFL_FCCOB5 = (unsigned char)((uint32_t)0x02);

        FTFL_FSTAT |= FTFL_FSTAT_CCIF_MASK;

        break;

    

    case FCMD_SET_FLEXRAM_FUNCTION:

        FTFL_FCCOB1 = (unsigned char)((uint32_t)0x00);

        FTFL_FSTAT |= FTFL_FSTAT_CCIF_MASK;

        break;

    

    case FCMD_ERASE_FLASH_SECTOR:

        FTFL_FCCOB1 = (unsigned char)(((uint32_t)ptrWord) >> 16); // set address in flash

        FTFL_FCCOB2 = (unsigned char)(((uint32_t)ptrWord) >> 8);

        FTFL_FCCOB3 = (unsigned char)((uint32_t)ptrWord);

        break;

    case FCMD_PROGRAM_LONG_WORD:

        FTFL_FCCOB1 = (unsigned char)(((uint32_t)ptrWord) >> 16); // set address in flash

        FTFL_FCCOB2 = (unsigned char)(((uint32_t)ptrWord) >> 8);

        FTFL_FCCOB3 = (unsigned char)((uint32_t)ptrWord);

        FTFL_FCCOB4 = (unsigned char)(*ptr_ulWord >> 24);            // enter the long word to be programmed

        FTFL_FCCOB5 = (unsigned char)(*ptr_ulWord >> 16);

        FTFL_FCCOB6 = (unsigned char)(*ptr_ulWord >> 8);

        FTFL_FCCOB7 = (unsigned char)(*ptr_ulWord);

        break;

    }

    DisableInterrupts;                                                              // protect this region from interrupts

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

    EnableInterrupts;                                                                  // safe to accept interrupts again

    if(FTFL_FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK | FTFL_FSTAT_MGSTAT0_MASK))

    {

        error_struct.general_error_struct_1.VALUE_ERROR = VALUE_ERROR_FLASH_write;    // if there was an error this will be non-zero

    }

}

void FLASH_init(void)

{

      //FLASH(FCMD_ERASE_ALL_BLOCKS,0,0);

      FLASH(FCMD_PROGRAM_PARTITION,0,0);

      FLASH(FCMD_SET_FLEXRAM_FUNCTION,0,0);

}

Thanks

Pascal

0 件の賞賛
返信
1,285件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

I think that the manual suggest that the chip should first be fully erased before changing the partition but a mass erase (erase all blocks) can not be performed as a part of the program sequence since it erases all code (so the program can't continue running). It is not intended that applications change partition use and so this is an operation that is intended to be performed once in the life time of the application/chip.

After a mass erase all Flash content is 0xff and so the secure mode is set. This is normal and the debugger is needed to unsecure it afterwards.

It is probably adequate to replace the mass erase command by a loop that erases each FlexNMV sector instead if this is to be performed automatically by the program and not require subsequent reprogramming with the debugger. This will also ensure that the FlexNVM is clean when setting up the partition. Maybe it won't work when removing a partition since the EEPROM is using half of the content in your case but in this case a post-delete is possible instead of a pre-delete.

Regards

Mark

0 件の賞賛
返信
1,285件の閲覧回数
pascalschröer
Contributor V

Okay :smileyhappy:

Thanks!

Pascal

0 件の賞賛
返信
1,332件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

I am not clear on exactly what you are asking but I suggest looking at the uParameterSystem: http://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF

All code needed for reading/writing internal Flash or external SPI Flash, with safe swap-block methods to avoid potential parameter loss when a reset/power down occurs during the process is included in the package here: http://www.utasker.com/forum/index.php?topic=1721.0

>>By the way I havn't got understood where are the differences between using the flash and the EEE (EEPROM)?!

I think the main difference is that you can modify a single byte in EEPROM but you can't in Flash - you need to delete a complete Flash sector to change a value that has already been written. Also, the Kinetis supports either long word or phrase writes (4 or 8 bytes, depending on processor type) so the smallest write size is this and not a byte. Flash writes are usually faster than EEPROM writes - a write to Flash may take 50..100us but a write to EEPROM may take up to 2ms.

Regards

Mark

1,332件の閲覧回数
pascalschröer
Contributor V

Hi,

first of all, thanks a lot for these long answers in this and the other topic! But although I have spent a lot of time during the easter holiday's I don't understand how to use the utaskersKinetis file... Sry that's my first project and there are so many new aspects I have never thought about.

:smileyconfused:

regards

Pascal

0 件の賞賛
返信
1,332件の閲覧回数
mjbcswitzerland
Specialist V

Pascal

Do you have a specific problem/question?

regards

Mark

0 件の賞賛
返信