Hello, I am trying to implement a 'firmware switch' feature by setting the fuses for Flash remapping (0x6E0) and calling the firmware switch using the ROM API. I've been using AN12255SW as a guide, however I've been unable to get the 'firmware_swap' example working in MCUXpresso.
I set the fuses using the following code in my main function:
#define EXAMPLE_OCOTP_FUSE_MAP_ADDRESS 0x6E0
#define EXAMPLE_OCOTP_FUSE_WRITE_VALUE 0x001C7000 // 7 MB image size, 7 MB offset
Is this approach where the fuses are set, then the ROM API call to 0x0020001C able to work? Or is there a more preferred method for bootloading on the RT1062?
Also, is this able to work if the boot mode is set to Internal boot? I would think so since the GPIO does not seem to affect anything related to the flash remap config, but it's the only unknown I can think of on this.
Hi @schafbo
Please see my comments in blue.
Is this approach where the fuses are set, then the ROM API call to 0x0020001C able to work?
Or is there a more preferred method for bootloading on the RT1062? Also, is this able to work if the boot mode is set to Internal boot? I would think so since the GPIO does not seem to affect anything related to the flash remap config, but it's the only unknown I can think of on this.
The boot ROM uses the state of the BOOT_MODE and eFuses to determine the boot
device. For development purposes, the eFuses(mostly for MP) used to determine the boot device may be
overridden using the GPIO pin inputs. More details, please see IMXRT1060RM.pdf section 9.2, page 195.
The device has four boot modes (one is reserved for NXP use, Internal Boot: 10). The boot mode is selected based on the binary value stored in the internal BOOT_MODE register, value of 00b in the BOOT_MODE[1:0] register selects the Boot From Fuses mode.
- A value of 00b in the BOOT_MODE[1:0] register selects the Boot From Fuses mode.
- A value of 10b in the BOOT_MODE[1:0] register selects the Internal Boot mode.
If BT_FUSE_SEL = 1, all boot options are controlled by the eFuses described in
Boot eFuse descriptions
If BT_FUSE_SEL = 0, the specific boot configuration parameters may be set using
the GPIO pins rather than eFuses.
Please see the high-level boot sequence which show high-level boot ROM code flow as below.
About second stage bootloader, plesae refer to ota_examples/mcuboot_opensource project. https://github.com/nxp-mcuxpresso/mcux-sdk-examples/tree/main/evkbmimxrt1170/ota_examples/mcuboot_op...
B.R,
Sam
Sam,
I set the boot mode to 'Boot from fuses' and set the value for BT_FUSE_SEL to 1. However, I'm still unable to use the ROM API to jump to the application stored at the other location in memory.
Thank you for linking the 'mcuboot_opensource' second stage bootloader. However I'm wondering if the OCOTP fuses also need to be set for this example, or the fuses are only needed when working with the ROM API/first stage bootloader such as in AN12255?
If you want to do second stage or OTA featue, it is recommended to use 'mcuboot_opensource' project. I do not recommend you to use fuse in the development stage, because it is a one-time.
This AN12255 is only an example to remap flash address based on FlexSPI interface, it has many dependence.
Thank you Sam, I was wondering earlier if using the Internal boot mode ignored the fuse settings I wrote to 0x6E0, but I think after looking at the manual and this diagram that is not the case and this should work fine.
From your diagram it's not clear this is a first stage bootloader problem? The only step I see where it possibly could get hung up on is Authenticate Image, however using the default 'Open' security setting should ignore the authentication and try to use the image regardless.
There are two partitions in flash. The first is the application where the program is currently running, the other is where the binary is written to and then we would jump later. The binary that is written to the second partition is literally the same application converted .axf -> .bin, but with another version number.
I am still not sure if this API call to 0x0020001C using this function is correct:
void bl_firmware_switch(uint32_t index){
run_bootloader_ctx_t boot_para;boot_para.B.imageIndex = index;
boot_para.B.serialBootInterface = kEnterBootloader_SerialInterface_USB;
boot_para.B.bootMode = kEnterBootloader_Mode_Default;
boot_para.B.tag = kEnterBootloader_Tag;
g_bootloaderTree->runBootloader( (void *)&boot_para );
}void bl_api_init(void){
g_bootloaderTree = (bootloader_api_entry_t *)*(uint32_t *)0x0020001c;
}bl_firmware_switch has argument 1 or 0 depending on the current index.
I am still not sure if this API call to 0x0020001C using this function is correct
--> You need to enable fuse setting and follow section 3.2.2 to use MFGtool to program multipe firmware.
Sam,
I used MFGTool from the Flashloader_RT106x_1.0 tools, following the process outlined in AN12108 and AN12255. I'm able to combine two of the firmware_swap programs into an unsigned bootable image.
However MFGTool is not able to connect to the processor to program it and displays "No Device Connected". I've put the processor into Serial Download mode/ISP mode to connect, I can verify this using the Secure Provisioning Tool. I'm not sure why this isn't able to connect... I also tried putting MFGTool in Windows 7 compatibility mode but this didn't help.
Hi @schafbo
There is a long history here. The conclusion is that if you encounter compatibility issues, please use Secure Provisioning SDK (SPSDK) instead.
MFGTool(Manufacturing tool) applications supports the Kinetis or RT105x bootloader, there are some outdated documentations:
- https://www.nxp.com/webapp/Download?colCode=KBLMFGTOOLUG&location=null
- MCU Bootloader Manufacturing Tool User's Guide
The MfgTool for MCU devices is bundled together with the MCU bootloader in <sdk_package>/middleware/mcu-bootloader/bin." It means that you can find the MfgTool under the RT1060 SDKs, and following the paths that are mentioned on Chapter 2 of this document.
Hi @schafbo
There seems be some issues on flash remapping, please kindly check these comments from my side, pelease correct me if something wrong.
1. checking OCOTP setting is correct or not.
// Reload the current register values
OCOTP_ReloadShadowRegister(OCOTP);
// Read the current fuse value
uint32_t fuse_value;
OCOTP_ReadFuseShadowRegister(OCOTP, EXAMPLE_OCOTP_FUSE_MAP_ADDRESS, &fuse_value);
printf("Current Fuse Value: 0x%08X\n", fuse_value);
// Write the new fuse values
OCOTP_WriteFuseShadowRegister(OCOTP, EXAMPLE_OCOTP_FUSE_MAP_ADDRESS, EXAMPLE_OCOTP_FUSE_WRITE_VALUE);
// Verify the fuse value
OCOTP_ReadFuseShadowRegister(OCOTP, EXAMPLE_OCOTP_FUSE_MAP_ADDRESS, &fuse_value);
printf("New Fuse Value: 0x%08X\n", fuse_value);
2. checking the function with log.
typedef void (*bootloader_api_entry_t)(void);
bootloader_api_entry_t g_bootloaderTree;
void bl_api_init(void) {
g_bootloaderTree = (bootloader_api_entry_t *)*(uint32_t *)0x0020001C;
if (g_bootloaderTree == NULL) {
printf("Bootloader API entry point is NULL\n");
}
}
void bl_firmware_switch(uint32_t index) {
run_bootloader_ctx_t boot_para;
boot_para.B.imageIndex = index;
boot_para.B.serialBootInterface = kEnterBootloader_SerialInterface_USB;
boot_para.B.bootMode = kEnterBootloader_Mode_Default;
boot_para.B.tag = kEnterBootloader_Tag;
if (g_bootloaderTree != NULL) {
g_bootloaderTree->runBootloader((void *)&boot_para);
} else {
printf("Bootloader API not initialized\n");
}
}
3. Please check binary firmware address when you flash them into board.
B.R,
Sam
Sam, thank you for your response.
I believe the fuse setting of 0x1C7000 is correct for two 7 MB sections offset by 7MB.
I verified that g_bootloaderTree is not set to NULL in both cases.
Also, wanted to check that the image is written to the intended spot and is not corrupted....
In this case I verify that I erase the flash from 0x700000 - 0xE00000 and then write the image to this spot. 0x700000 - 0xE00000 is memory mapped to 0x60700000 - 0x60E00000 and I can see the data written there in MCUXpresso.
However after the firmware switch call the PC is set to 0x202090.
I'm wondering if my Boot Mode setting of "internal boot" will still allow me to set the fuses and jump, or if the fuse settings are ignored in this mode?
Thanks
It looks like I'm getting stuck in the first stage ROM bootloader (ROMCP). I'm using the 'Internal Boot' boot mode and would like to keep using the GPIO pins to set the boot config. Will this cause a problem if I want to set the fuse bits so that the firmware can switch between images (using the ROM API)?
Attached is the definition for the fuse bits, I believe this config is correct. After jump to image 1, the debugger shows the PC is 0x202090.