Error erasing flash memory

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

Error erasing flash memory

Jump to solution
1,123 Views
biafra
Senior Contributor I
I have a custom board with Kinetis K82P121M150. I use MCUXpresso 25.06, SDK 2.8 and PEMicro Multilink Universal.
In the microcontroller there is a bootloader running in internal flash memory starting from address 0.
When it starts, the bootloader check if a valid application is present in the memory area starting from address 0x10000.
If the application is valid, the bootloader jumps to the application's entry point and it runs it.
If the application is not valid, the bootloader waits for an application from the USB port: the application will be stored in the memory area starting from address 0x10000.
When the user starts sending the application, the bootloader first erases the destination memory area and it stores the application in that area.
This whole flow works fine.
 
I've found a problem in the bootloader: the bootloader doesn't erase the last memory sector. As the application has grown and started to occupy the last sector, it's not possible to update it in the field.
So I'd need to upgrade the bootloader. In the production phase the bootloader is programmed using the standard tools.
But the devices already installed can't be updated in the field: they'd need to be replaced.
 
So I thought I'd make an updater application that updates the bootloader.
The bootloader updater is stored in the memory area starting from address 0x10000 (like the device application) and successfully launched from the bootloader.
The bootloader updater must update the bootloader and it works the same way: the bootloader updater waits for a new bootloader from the USB port.
The new bootloader will be stored in the memory area starting from address 0, overwriting the actual bootloader.
When the user starts sending the new bootloader, the bootloader updater need to erase the first 64 kB of the memory starting from address 0, but the erase command exits with an error.
The erase function is FLASH_Erase() and the returned error is kStatus_FTFx_AccessError.
The strange thing is that when I'm debugging the bootloader updater with MCUXpresso, everything works fine. But when the device works stand alone, the kStatus_FTFx_AccessError error is returned.
 
What can the reason of this behaviour?
 
Some informations:
The bootloader updater runs from address 0x10200 and erases the memory range from 0 to 0xFFFF: the memory area to be erased is different from the one where the bootloader updater is executed from.
When the bootloader erases the memory where the application will be stored (0x10000÷0x3FFFF), it runs from flash memory too.
 
Bootloader area: 0÷0xFFFF
Bootloader updater area: 0x10000÷0x3FFFF
The bootloader runs from bootloader area and it erases the bootloader updater area.
The bootloader updater runs from bootloader updater area and it erases the bootloader area.
 
Important:
The bootloader and the bootloader updater are essentially the same: the differences are only the excution area and the erasing area.
The bootloader updater code has been copied from the bootloader code and only the macros specifying the execution and erasing areas have been modified.
 
These are the protection registers content:
FPROT0 = 0xFF
FPROT1 = 0xFF
FPROT2 = 0xFF
FPROT3 = 0xFF
 
These are the first instructions of the reset vector of the bootloader updater:
__asm volatile ("cpsid i");
__asm volatile
(
"ldr r0, =0xE000ED08\n"
"ldr r1, =g_pfnVectors\n"
"str r1, [r0]\n"
"ldr r2, [r1]\n"
"msr msp, r2\n"
);
 
g_pfnVectors is located at the address 0x10200 (it must be aligned to 512 bytes and at the address 0x10000 there are some informations needed by the bootloader to check if the application to run is valid)
 
The actual bootloader updater application ends at the address 0x1CC7C, so I tried to erase the memory area starting from address 0x20000 or 0x30000, but the same error is returned
 
The FLASH_Erase() function is mapped in flash memory, both for the bootloader and the bootloader updater.
There are no .ramfunc sections, both for the bootloader and the bootloader updater.
The USB stack is the same, both for the bootloader and the bootloader updater.
There is no RTOS, neither for the bootloader nor the bootloader updater.
SysTick isn't intialized, neither for the bootloader nor the bootloader updater.
The clock is initialized with BOARD_BootClockRUN() that sets it to 120 MHz, both for the bootloader and the bootloader updater.
The __disable_irq() function is called immediately before the FLASH_Erase() function.
 
Another information about the clock in the process:
- The bootloader starts and it calls the BOARD_BootClockRUN() function, setting the clock to 120 MHz
- The bootloader checks for the valid application (the bootloader updater), it's valid
- The bootloader BOARD_BootClockHSRUN() function, setting the clock to 148 MHz (the frequency at which the application runs)
- The bootloader jumps to the application (bootloader updater) entry point
- The bootloader updater starts and it calls the BOARD_BootClockRUN() function, setting the clock back to 120 MHz (the maximum frequency for writing the flash memory)
 
Many thanks
 
Biafra

 

1 Solution
995 Views
biafra
Senior Contributor I

Hi everyone and @Alice_Yang,

 

I found the solution.

The problem was related to the transient on the clock/run mode.

Before the bootloader jumps to the bootloader updater, it calls the BOARD_BootClockHSRUN() function. When it starts, the bootloader updater calls the BOARD_BootClockRUN(). This function sets the clock frequency, but doesn't set the power mode.

Before the call BOARD_BootClockRUN() function, there was a need to insert the instructions:

SMC_SetPowerModeRun( SMC );
while( SMC_GetPowerModeState( SMC ) != kSMC_PowerStateRun )
	; //wait

 

This is the begin of the BOARD_BootClockHSRUN() function:

void BOARD_BootClockHSRUN(void)
{
    /* Set HSRUN power mode */
    SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);
    SMC_SetPowerModeHsrun(SMC);
    while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun)
    {
    }
    /* Set the system clock dividers in SIM to safe value. */
    CLOCK_SetSimSafeDivs();
    ...
}

 

This is the begin of the BOARD_BootClockRUN() function:

void BOARD_BootClockRUN(void)
{
    /* Set the system clock dividers in SIM to safe value. */
    CLOCK_SetSimSafeDivs();
    ...
}

 

Many thanks

Biafra

 

View solution in original post

4 Replies
996 Views
biafra
Senior Contributor I

Hi everyone and @Alice_Yang,

 

I found the solution.

The problem was related to the transient on the clock/run mode.

Before the bootloader jumps to the bootloader updater, it calls the BOARD_BootClockHSRUN() function. When it starts, the bootloader updater calls the BOARD_BootClockRUN(). This function sets the clock frequency, but doesn't set the power mode.

Before the call BOARD_BootClockRUN() function, there was a need to insert the instructions:

SMC_SetPowerModeRun( SMC );
while( SMC_GetPowerModeState( SMC ) != kSMC_PowerStateRun )
	; //wait

 

This is the begin of the BOARD_BootClockHSRUN() function:

void BOARD_BootClockHSRUN(void)
{
    /* Set HSRUN power mode */
    SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);
    SMC_SetPowerModeHsrun(SMC);
    while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun)
    {
    }
    /* Set the system clock dividers in SIM to safe value. */
    CLOCK_SetSimSafeDivs();
    ...
}

 

This is the begin of the BOARD_BootClockRUN() function:

void BOARD_BootClockRUN(void)
{
    /* Set the system clock dividers in SIM to safe value. */
    CLOCK_SetSimSafeDivs();
    ...
}

 

Many thanks

Biafra

 

1,062 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello @biafra 

You do not have a .ramfunc configuration,
so the Flash API is still executing from Flash.
When you try to erase the 0x00000 region,
it returns kStatus_FTFx_AccessError.

Therefore, the Flash driver needs to be executed from RAM.

 

BR

Alice

1,054 Views
biafra
Senior Contributor I
Hi @Alice_Yang,

Many thanks for your answer.

To be clear:

There is no explicit .ramfunc configuration, but in the driver the FTFx_DRIVER_IS_FLASH_RESIDENT macro is defined as 1U, so the I think the driver is copied and executed from RAM
The bootloader can erase the region 0x10000÷0x3FFFF (so even the 0x20000÷0x3FFFF). The bootloader updater can't erase neither the region 0x0000÷0xFFFF nor the region 0x20000÷0x3FFFF, but the driver is the same (the bootloader updater project has been copied from the bootloader project)

Many thanks

Biafra
1,020 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello @biafra 

Could you please debug the bootloader updater to check what value it returns when an erase operation fails for a sector in the 0x20000–0x3FFFF range?
 
Thank you.
 
BR
Alice