KL26Z How can my app write/read to a reserved FLASH segment?

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

KL26Z How can my app write/read to a reserved FLASH segment?

1,160 Views
bgraham
Contributor IV

MCUXpresso IDE v11.0.1 [Build 2563] [2019-09-01]
MCU: MKL26Z256VLH4

I would like to store run-time configuration information in the MCU's internal FLASH.

The FLASH will be written to less then 10 times for the life of the product.

In other MCUs, I could define a section in the FLASH that the linker and compiler would then reserve.

Can I set up a FLASH area in MCUXpresso, or do I have to bit bang this all out?

Thanks,

Bruce Graham

Labels (1)
Tags (2)
0 Kudos
5 Replies

1,012 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hello, Bruce

In the MCUxpresso you could add and split flash areas by doing a right-click on the project, then click on properties. 

Capture_flash_split.PNG

After doing a split for example you could  specify the amount of space and then apply and close

split_mem.PNG

I hope this information helps you. If you need more assistance please let us know! 

Best regards, Charles

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,012 Views
bgraham
Contributor IV

Diego,

You created a FLASH "area" that is named "Flash2".

How do the SDK FLASH APIs use the new FLASH "area" that is named "Flash2"?

Thanks,

Bruce

On Tue, Feb 11, 2020 at 6:49 PM diego.charles <admin@community.nxp.com>

0 Kudos

1,012 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hello Bruce, 

Thanks for your detailed previous response, I believe that is a useful reference for other users of the community. 

 In order to use the SDK flash drivers in a the specific sector you will need to specify the destination address, that you will use to erase or write.

 

Since the flash memory of your device has 256KB of and has sectors (pages) of 1KB of size, it has 256 sectors, and the last sectors are located in the higher addresses. 

If you import the  SDK example p-flash.  You will notice that the example erases in the last sector of the flash memory because implements the following sentence to calculate the destination address of the sector that is going to be erased. 

destAdrss = pflashBlockBase + (pflashTotalSize - (SECTOR_INDEX_FROM_END * pflashSectorSize));

Since   pflashBlockBase =0 , pFlashTotalSize 256Kb ,  SECTOR_INDEX_FROM_END =1 and pFlashSectorSize is 1kB.  

destAdrss = 0x0000 + (0x4_0000 - (1 * 0x400));

destAdrss is 0x3fc00.

The sentence could be used to erase the desired flash sector, that is going to be used to write. If you modify the macro SECTOR_INDEX_FROM_END you could refer to another sector from the end,  

Have a great day,
Diego

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,012 Views
bgraham
Contributor IV

Thanks Diego,

but the FLASH can't be written to from code running from FLASH, so must run from SRAM. 

I am using the KL26 SDK with my KL16 MCU.

I defined a APP_FLASH_1KB in Properties | C/C++ Build | MCU settings.

address=0x0003FC00, size=0x400

In the debugger's memory window, I can see the top of FLASH at 0x0003FC00.

0x0003FC00 to 0x00040000 is filled with 0xFF.

I used the debugger's memory window to set 0x01020304 at 0x0003FC00.

0x0003FC00 01020304 FFFFFFFF FFFFFFFF FFFFFFFF ....ÿÿÿÿÿÿÿÿÿÿÿÿ
0x0003FC10 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

memcpy() from 0x0003FC00 returns 0x01020304, so the memcpy() worked.

memcpy() to 0x0003FC00, generates a Hard Fault, IPSR = 0x3.

The buffer used by memcpy() is aligned on the 32-bit address 0x1ffffc40, so I doubt the Hard Fault was caused by an alignment fault.

I read

KL16 Sub-Family Reference Manual, Rev. 3.2, October 2013, and

Production Flash Programming Best Practices for Kinetis K- and L-series MCUs, Rev 1, 05/2014, and

Avoiding Read While Write Errors When Developing In-Software Flash Programming Applications for Kinetis and ColdFire+ MCUs, Rev. 0, 04/2013, and 

Kinetis SDK v.2.0 API Reference Manual

I got it to work using the SDK APIs.

main()

  init()

  read()

init()

FLASH_Init(&m_flashDriver);

FLASH_GetProperty(&m_flashDriver, kFLASH_PropertyPflash0BlockBaseAddr, &iflashBlockBase);
FLASH_GetProperty(&m_flashDriver, kFLASH_PropertyPflash0TotalSize, &iflashTotalSize);
FLASH_GetProperty(&m_flashDriver, kFLASH_PropertyPflash0SectorSize, &m_iflashSectorSize);

 m_destAdrss = iflashBlockBase + (iflashTotalSize - m_iflashSectorSize);

read()

memcpy((void *)&m_AppSettingsInFLASH, (const void *)m_destAdrss, sizeof(T_APP_SETTING_IN_FLASH));

write()

FLASH_GetSecurityState(&m_flashDriver, &securityStatus);

FLASH_Erase(&m_flashDriver, m_destAdrss, m_iflashSectorSize, kFLASH_ApiEraseKey);

FLASH_VerifyErase(&m_flashDriver, m_destAdrss, m_iflashSectorSize, kFTFx_MarginValueUser);

FLASH_Program(&m_flashDriver, m_destAdrss, (uint8_t*)&m_AppSettingsInFLASH, sizeof(T_APP_SETTING_IN_FLASH));

FLASH_VerifyProgram(&m_flashDriver, m_destAdrss, sizeof(T_APP_SETTING_IN_FLASH), (uint8_t*)&m_AppSettingsInFLASH, kFTFx_MarginValueUser,&failAddr, &failDat);

0 Kudos

1,012 Views
mjbcswitzerland
Specialist V

Hi Bruce

You don't usually need to reserve anything in the linker script. If your program is not using all the sectors simply using the top one or two for parameters already means that they are not used by the program. [If your program were to be using all sectors it wouldn't be possible anyway....]
To read them you can simply use a pointer to the memory:

#define PARAMETER_LOCATION  (SIZE_OF_FLASH - SIZE_OF_FLASH_SECTOR)

unsigned char local_parameters[SIZE_OF_PARAMETERS]; // local copy
memcpy(local_parameters, (const void *)PARAMETER_LOCATION, sizeof(local_parameters)); // retrieve parameters

The linker needs to know nothing of this and it is then fully portable in case you change compiler etc. To make the area larger at some point #define PARAMETER_LOCATION  (SIZE_OF_FLASH - (2 * SIZE_OF_FLASH_SECTOR)) would already do it.

To write you can do the same (in the opposite direction) if you have a flashing function that accepts the flash destination location, although you will need to first delete the sector to make changes.

In the uTasker project we have a fail safe parameter system as standard (using a swap block to avoid loss of config data in case there were a power fail during the save) which you can compare if you need a truly robust solution; it also allows extending to a file system:
https://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF

KL26 binary including the operation at https://www.utasker.com/kinetis/FRDM-KL26Z.html

Source on GITHUB and allows flashing operation to be fully emulated in Visual Studio in case you want to copy the ideas and reference code.

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

0 Kudos