some updates
it is very likely that the Flash Config registers are overwritten by bootloader bin own set-up.
/platform/devices/MKW30Z4/linker/iar/MKW30Z160xxx4_connectivity.icf
if (gUseBootloaderLink_d)
{
define symbol m_bootloader_start = __region_ROM_start__;
define symbol m_bootloader_end = ((__region_ROM_end__ + 1) / 32) - 1;define symbol m_interrupts_start = m_bootloader_end + 1;
define symbol m_interrupts_end = m_interrupts_start + __vector_table_size__ - 1;define symbol m_bootFlags_start = m_interrupts_end + 1;
define symbol m_bootFlags_end = m_bootFlags_start + 7;define exported symbol __BootFlags_Start__ = m_bootFlags_start;
}
else
{
define symbol m_interrupts_start = __region_ROM_start__;
define symbol m_interrupts_end = m_interrupts_start + __vector_table_size__ - 1;
define symbol m_flash_config_start = 0x00000400;
define symbol m_flash_config_end = 0x0000040F;
}
\platform\devices\MKW30Z4\startup\iar\startup_MKW30Z4.s
SECTION FlashConfig:CODE
__FlashConfig
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFBFE ;0xFFFFFFFE
__FlashConfig_End
....
NMI_Handler
B .
PUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
the booloader has a build-in set of flash config's:
\framework\Bootloader\Bootloader_OTAP_Serial\Linker_cfg\BootloaderOTAP.icf
/*-Sizes-*/
define symbol __size_cstack__ = 0x1000;
define symbol __IntVectTable_start__ = __region_BOOT_ROM_start__;
define symbol __IntVectTable_end__ = __region_BOOT_ROM_start__ + 0x3F;
define symbol __FlashConfig_start__ = 0x00000400;
define symbol __FlashConfig_end__ = 0x0000040f;
define exported symbol __BOOT_STACK_ADDRESS = __region_RAM_end__ - 7; //0x20007FF8;
define symbol __code_start__ = __IntVectTable_end__+1;
from Linker set-up: gRomSize_c=0x28000
Bootloader ROM map seems to be:
(a strange thing is that bootloader table vectors are less than main application 63 vs 192)
\framework\Bootloader\Bootloader_OTAP_Serial\src\OtapSerialBootloader\OtapBootloader.c
/*
* Name: gFlashProtection_c
* Description: The value for FPROT register. By default the Flash is not Protected
*/
#define gFlashProtection_c 0xFFFFFFFF /* Flash is not write protected */
// #define gFlashProtection_c 0xFFFFFFFE /* The first Flash region is write protected */
.......
#if defined(__IAR_SYSTEMS_ICC__)
#pragma location = "FlashConfig"
__root const FlashConfig_t gFlashConfig @ "FlashConfig" ={
{0xFFFFFFFF,
0xFFFFFFFF,
gFlashProtection_c,
0xFFFFFFFE}
};
MKW40Z/30Z/20Z Reference Manual, Rev. 1.2, 10/2015
6.3.2 FOPT boot options
The Flash Option (FOPT) register in the Flash Memory module (FTFA_FOPT) allows the user to customize the operation of the MCU at boot time.
The register contains readonly bits that are loaded from the NVM's option byte in the flash configuration field. The default setting for all values in the FTFA_FOPT register is logic 1 since it is copied from the option byte residing in flash, which has all bits as logic 1 in the flash erased state. To
configure for alternate settings, program the appropriate bits in the NVM option byte. The new settings will take effect on subsequent POR, VLLSx recoveries, and any system reset.
6.3.3 Boot sequence
...
When the system exits reset, the processor sets up the stack, program counter (PC), and link register (LR). The processor reads the start SP (SP_main) from vector-table offset 0. The core reads the start PC from vector-table offset 4. LR is set to 0xFFFF_FFFF. The next sequence of events depends on the NMI input and FTFA_FOPT[NMI_DIS] (See Table 6-2) :
• If the NMI input is high or the NMI function is disabled in FTFA_FOPT, the CPU begins execution at the PC location.
• If the NMI input is low and the NMI function is enabled in FTFA_FOPT, this results in an NMI interrupt. The processor executes an Exception Entry and
reads the NMI interrupt handler address from vector-table offset 8. The CPU begins execution at the NMI interrupt handler.
....
27.3.1 Flash Configuration Field Description
The program flash memory contains a 16-byte flash configuration field that stores default protection settings (loaded on reset) and security information that allows the MCU to restrict access to the flash memory module.
As in main application you wold like to disable the NMI interrupt by setting NMI_DIS to 0 the bootloader must be rebuild with the flash zone updated corresponding to application. Or the linker application mechanism updated to not permit the change of flash config.
second issue is that the new srec image must have a compliant format, it must contain at least a special flash zone between 0x000014C0 to 0x000014C7 used to interact between app and bootloader
(bootloader struct gpBootInfo points as same address as app gBootFlags and has same format)
framework\Bootloader\Bootloader_OTAP_Serial\src\OtapSerialBootloader\OtapBootloader.c
/*! ********************************************************************************** \brief This function will copy the User Application from the external memory
* into the program Flash
*
********************************************************************************** */
void Boot_LoadImage (void)
{....
/* Keep the boot flags set until the all image is downloaded */
for( i=0; i<gEepromParams_WriteAlignment_c; i++ )
{
flags.newBootImageAvailable[i] = gBootValueForFALSE_c;
flags.bootProcessCompleted[i] = gBootValueForTRUE_c;
}....
/* Set the bBootProcessCompleted Flag */
if( FLASH_OK != FLASH_Program((uint32_t)gBootImageFlagsAddress_c, (uint32_t)&flags, sizeof(flags)) )
gHandleBootError_d();...
}
.....
int main(int argc, char **argv)
{...
gpBootInfo = (bootInfo_t*)gBootImageFlagsAddress_c;
if ((gpBootInfo->newBootImageAvailable[0] != gBootValueForTRUE_c) &&
(gpBootInfo->bootProcessCompleted[0] == gBootValueForTRUE_c))
{
/* Set the start address of the interrupt vector*/
SCB_VTOR = gUserFlashStart_d;
JumpToApplication(gUserFlashStart_d);
}
else
{
/* Write the new image */
Boot_LoadImage();
}.......
Also some concerns my raise:
- if new image have not the expected structure it can be spoiled by Boot_LoadImage in this ROM zone 0x000014C0 to 0x000014C7 (same as for bootloader zone)
- actual only one flag is absolute necessary flags.newBootImageAvailable ( the other one bootProcessCompleted can be used for debug)
- as the flash erase process starts, it should first erase these particular flag zones in case of accidental reset occurs.