I am using the the NXP MK60FN1M0VLQ12 and I have some variables I want to store in the internal Flash, so I declared a separate section in the linker script and a global struct in it to be referenced by the code. Then to program it I use a slightly modified version of Processor Expert's FMC driver to erase the sector then program 8 bytes at a time.
However, whenever the global variable is declared, I fail to erase/program the flash, and otherwise it works fine. Of course the easy workaround in this case is to use a pointer to the section, but I also plan to rewrite a code section, where this wouldn't work. Does this have to do with the C linker/compiler or is it a MK60 or driver thing?
Here are the concerned code slices:
Linker script:
m_status_page (RX) : ORIGIN = 0x00040000, LENGTH = 0x00001000
.status_page : { . = ALIGN(4); KEEP(*(.STATUS_PAGE)) . = ALIGN(4); } > m_status_page
Global variable declaration:
StatusPage _status_page[TOTAL_STATUS_PAGE_NUMBER] __attribute__ ((section (".STATUS_PAGE")));
Then when I do the execute the following command it does nothing and doesn't throw an error:
flashProgram8Bytes(bytes_to_program, _status_page);
But if I don't declare the _status_page variable for example the following command works:
flashProgram8Bytes(bytes_to_program, 0x00040000);
Solved! Go to Solution.
Looking deeper in the RM, it is told that " A write operation to program flash memory or to data flash memory results in a bus error. " [Page 585, K60 Sub-Family Reference Manual, Rev. 6.1, Aug 2012].
The FMC seems to be more of a read acceleration for Program and Data Flash Memory, but does not have the capabilities to write to them.
Seems strange that you can write using FMC, but that could be why they are getting 0 initialized.
As a summary, seems to be more of a MK60 platform related.
Please, let us know if this information is helpful or not
I actually just realized something I should've before.
When I declare a variable in the section it's getting 0 initialized. If I declare an uint32_t I'm getting 4 bytes 0 initialized, if I declare an uint32_t[2] I get 8 bytes, and so on.
However I don't know if this is normal and what's the link to not being able to erase or program the flash...
Not sure what your flashProgram8Bytes() does, but if you have data in it, does it perform an erase first?
What if you do that in your code too (erase first)?
flashProgram8Bytes() is just an interface to call the Flash driver functions:
LDD_TError flashEraseSector(uint8_t sector_number)
{
LDD_TError err;
err = FMC_EraseSector(sector_number);
if (err == ERR_OK)
return flashPerformOperation();
else
return err;
}
LDD_TError flashEraseBlock(uint8_t block_number)
{
LDD_TError err;
err = FMC_EraseBlock(block_number);
if (err == ERR_OK)
return flashPerformOperation();
else
return err;
}
LDD_TError flashProgram8Bytes(uint8_t* source_ptr, LDD_FLASH_TAddress destination_ptr)
{
LDD_TError err;
err = FMC_Write8Bytes(source_ptr, destination_ptr);
if (err == ERR_OK)
return flashPerformOperation();
else
return err;
}
LDD_TError flashPerformOperation(void)
{
LDD_FLASH_TOperationStatus status;
status = FMC_PerformOperation();
if (status == LDD_FLASH_DONE)
{
status = FMC_GetOperationResult();
if (status == LDD_FLASH_IDLE)
return ERR_OK;
else
return ERR_FAILED;
}
else
return ERR_RANGE;
}
I am erasing the Flash first. The real code is more complicated than this, but what I'm doing is basically:
flashEraseSector((uint32_t)_status_page / MK60_FLASH_SECTOR_SIZE);
uint8_t bytes_to_program[8];
for (int i=0; i < data_size; i+=8)
{
initialize_bytes();
flashProgram8Bytes(bytes_to_program, _status_page + i);
}
The flash remains untouched after erases and program commands like this, but it works fine if I remove the _status_page declaration and replace it with 0x00040000 for example.
Hi,
Could be a long shot, but have you tried change the attributes of the section to WX (Read/Write and Executable).
Maybe trying to erase a Section with the Read-Only attribute gives an error.
Again, could be a long shot.
Let us know if this helps with your problem.
Hello, no this is a legitimate try, but I've already tried it without success.
You are telling that when sending the value as a constant (without the label), works.
What if instead of just putting the label, you send it through a function that returns the constant value. That could also help to understand if the linker if taking the label as the 0x00040000 value.
Instead of
flashEraseSector((uint32_t)_status_page / MK60_FLASH_SECTOR_SIZE);
Could be
flashEraseSector((uint32_t) returnAsConstant(_status_page) / MK60_FLASH_SECTOR_SIZE);
Again, could be another long shot.
From I can see the way the parameter is passed to the driver function has no effect in making it work or not.
When I declare a variable in the section, whether I point to the variable or I use the section address directly (0x00040000 in this case), the variable gets 0 initialized and I can't erase or program the flash. And when it isn't declared it works, but of course in this case I use an address since the variable isn't declared.
Looking deeper in the RM, it is told that " A write operation to program flash memory or to data flash memory results in a bus error. " [Page 585, K60 Sub-Family Reference Manual, Rev. 6.1, Aug 2012].
The FMC seems to be more of a read acceleration for Program and Data Flash Memory, but does not have the capabilities to write to them.
Seems strange that you can write using FMC, but that could be why they are getting 0 initialized.
As a summary, seems to be more of a MK60 platform related.
Please, let us know if this information is helpful or not
That's interesting because we've had applications developed that fully rely on the FMC writing to program flash for firmware upgrade purposes (using the workaround to not define variables in the section or to not define sections at all). That seems to be a bug turned into a feature then...