LPC546xx iap write returns undocumented error code 21

cancel
Showing results for 
Search instead for 
Did you mean: 

LPC546xx iap write returns undocumented error code 21

Jump to solution
557 Views
Contributor II

When writing to sector 0x0 starting at location 0x0 iap write returns error code 21 which is not defined in the user guide or fsl_flashiap.h. I'm using the same code to write to sector 7 without any issues. I'm using a dual enhanced image to boot from sector 7, and then attempt to write to sector 0.  If I boot from sector 0 and write to sector 7, the same logic works perfectly.

Is error 21 defined?

/*@}*/

/*!
* @brief Flashiap status codes.
*/
enum _flashiap_status
{
kStatus_FLASHIAP_Success = kStatus_Success, /*!< Api is executed successfully */
kStatus_FLASHIAP_InvalidCommand = MAKE_STATUS(kStatusGroup_FLASHIAP, 1U), /*!< Invalid command */
kStatus_FLASHIAP_SrcAddrError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 2U), /*!< Source address is not on word boundary */
kStatus_FLASHIAP_DstAddrError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 3U), /*!< Destination address is not on a correct boundary */
kStatus_FLASHIAP_SrcAddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 4U), /*!< Source address is not mapped in the memory map */
kStatus_FLASHIAP_DstAddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 5U), /*!< Destination address is not mapped in the memory map */
kStatus_FLASHIAP_CountError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 6U), /*!< Byte count is not multiple of 4 or is not a permitted value */
kStatus_FLASHIAP_InvalidSector =
MAKE_STATUS(kStatusGroup_FLASHIAP,
7), /*!< Sector number is invalid or end sector number is greater than start sector number */
kStatus_FLASHIAP_SectorNotblank = MAKE_STATUS(kStatusGroup_FLASHIAP, 8U), /*!< One or more sectors are not blank */
kStatus_FLASHIAP_NotPrepared =
MAKE_STATUS(kStatusGroup_FLASHIAP, 9U), /*!< Command to prepare sector for write operation was not executed */
kStatus_FLASHIAP_CompareError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 10U), /*!< Destination and source memory contents do not match */
kStatus_FLASHIAP_Busy =
MAKE_STATUS(kStatusGroup_FLASHIAP, 11U), /*!< Flash programming hardware interface is busy */
kStatus_FLASHIAP_ParamError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 12U), /*!< Insufficient number of parameters or invalid parameter */
kStatus_FLASHIAP_AddrError = MAKE_STATUS(kStatusGroup_FLASHIAP, 13U), /*!< Address is not on word boundary */
kStatus_FLASHIAP_AddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 14U), /*!< Address is not mapped in the memory map */
kStatus_FLASHIAP_NoPower = MAKE_STATUS(kStatusGroup_FLASHIAP, 24U), /*!< Flash memory block is powered down */
kStatus_FLASHIAP_NoClock =
MAKE_STATUS(kStatusGroup_FLASHIAP, 27U), /*!< Flash memory block or controller is not clocked */
};

1 Solution
6 Views
Senior Contributor III

Bernhardt is saying that the IAP call is preventing you from writing invalid code to sector 0. If it allowed you to do this, your application would never boot. To fix it, you must calculate the correct checksum and put it into the image before flashing.

View solution in original post

11 Replies
6 Views
Contributor II

Interesting, I didn't realize it had a check at programming time, I figured it would just let me write an invalid image if I tried. That did the trick, thank you.

0 Kudos
7 Views
Senior Contributor III

Bernhardt is saying that the IAP call is preventing you from writing invalid code to sector 0. If it allowed you to do this, your application would never boot. To fix it, you must calculate the correct checksum and put it into the image before flashing.

View solution in original post

6 Views
Contributor III

If you compare with the error codes for ISP, you see that there 0x15 is USER_CODE_CHECKSUM, while for IAP it is listed with error code decimal 15. Since the other codes agree, this should most likely be decimal 21.

0 Kudos
6 Views
Contributor II

Here is the output from GB, stepping through FLASHIAP_CopyRamToFLash()

FLASHIAP_CopyRamToFlash (dstAddr=0, srcAddr=0x20003f04 <ucHeap+12968>, numOfBytes=256,
systemCoreClock=537034752)
at /Users/caseykelso/dev/mutex.io.firmware/firmware/drivers/fsl_flashiap.c:78
78 command[0] = kIapCmd_FLASHIAP_CopyRamToFlash;
(gdb) n
79 command[1] = dstAddr;
(gdb) n
80 command[2] = (uint32_t)srcAddr;
(gdb) n
81 command[3] = numOfBytes;
(gdb) n
82 command[4] = systemCoreClock / HZ_TO_KHZ_DIV;
(gdb) n
83 iap_entry(command, result);
(gdb) n
85 return translate_iap_status(result[0]);
(gdb) p result
$1 = {21, 536887368, 536872380, 536887000}
(gdb) p/x result
$2 = {0x15, 0x20004048, 0x200005bc, 0x20003ed8}
(gdb)

You can see here that the result is 21 decimal, 0x15 Hex.

The fsl_flashiap.h file from the SDK_2.5.0_LPC54628J512defines these status codes

/*!
* @brief Flashiap status codes.
*/
enum _flashiap_status
{
kStatus_FLASHIAP_Success = kStatus_Success, /*!< Api is executed successfully */
kStatus_FLASHIAP_InvalidCommand = MAKE_STATUS(kStatusGroup_FLASHIAP, 1U), /*!< Invalid command */
kStatus_FLASHIAP_SrcAddrError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 2U), /*!< Source address is not on word boundary */
kStatus_FLASHIAP_DstAddrError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 3U), /*!< Destination address is not on a correct boundary */
kStatus_FLASHIAP_SrcAddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 4U), /*!< Source address is not mapped in the memory map */
kStatus_FLASHIAP_DstAddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 5U), /*!< Destination address is not mapped in the memory map */
kStatus_FLASHIAP_CountError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 6U), /*!< Byte count is not multiple of 4 or is not a permitted value */
kStatus_FLASHIAP_InvalidSector =
MAKE_STATUS(kStatusGroup_FLASHIAP,
7), /*!< Sector number is invalid or end sector number is greater than start sector number */
kStatus_FLASHIAP_SectorNotblank = MAKE_STATUS(kStatusGroup_FLASHIAP, 8U), /*!< One or more sectors are not blank */
kStatus_FLASHIAP_NotPrepared =
MAKE_STATUS(kStatusGroup_FLASHIAP, 9U), /*!< Command to prepare sector for write operation was not executed */
kStatus_FLASHIAP_CompareError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 10U), /*!< Destination and source memory contents do not match */
kStatus_FLASHIAP_Busy =
MAKE_STATUS(kStatusGroup_FLASHIAP, 11U), /*!< Flash programming hardware interface is busy */
kStatus_FLASHIAP_ParamError =
MAKE_STATUS(kStatusGroup_FLASHIAP, 12U), /*!< Insufficient number of parameters or invalid parameter */
kStatus_FLASHIAP_AddrError = MAKE_STATUS(kStatusGroup_FLASHIAP, 13U), /*!< Address is not on word boundary */
kStatus_FLASHIAP_AddrNotMapped =
MAKE_STATUS(kStatusGroup_FLASHIAP, 14U), /*!< Address is not mapped in the memory map */
kStatus_FLASHIAP_NoPower = MAKE_STATUS(kStatusGroup_FLASHIAP, 24U), /*!< Flash memory block is powered down */
kStatus_FLASHIAP_NoClock =
MAKE_STATUS(kStatusGroup_FLASHIAP, 27U), /*!< Flash memory block or controller is not clocked */
};

---

0 Kudos
6 Views
NXP Employee
NXP Employee

Sector 0 is special because the Cortex-M4 will try to start from there. To make sure that there is valid code, the boot ROM checks the first memory locations for the flash signature. IAP seems to do something here as well, maybe a pre-check, if there is a valid signature.

This would be in line with the meaning of 0x15 = USER_CODE_CHECKSUM.

Regards,

Bernhard.

0 Kudos
6 Views
Contributor II

Hi Bernhard,

ISP/Boot ROM would throw the USER_CODE_CHECKSUM  at boot time after scanning for a valid image (legacy, single enhanced, or dual enhanced) and it finds an image with an invalid checksum, right? Please advise.

In this scenario I'm programming sector 0, address 0x0 from firmware that is booted, and the firmware does not reboot during the iap process. I also see that the result has a functional group code that is returned, it shows that of IAP. 

I've taken the stock SDK_2.5.0_LPC54628J512 iap_flash driver demo and put together a nice turn key project on github. You can pull down my project and follow the build steps on ubuntu 18.04, it pulls down all of the dependencies, toolchain, etc and builds the stock iap_flash demo driver, and also can build a modified iap_flash demo driver that resides in flash at 0x40000. This modified iap_flash demo driver attempts to flash sector 0 0x0 and demonstrates the iap_status return code of 0x15. You'll see that the iap prepare and iap erase function properly, but the write fails.

Please make sure run "make erase", before flashing my modified iap_flash demo with dual enhanced image enabled and at 0x40000 else the chip will see the legacy image at 0x0 and probably won't scan for the dual enhanced image at 0x40000.

Please follow the instructions here to reproduce, and I recommend using a jlink device connected to an LPC54628 OM13094 dev kit for the easiest repro steps. My project pulls down the jlink tools automatically and has scripts for flashing, erasing, downloading flash contents for inspection, and running gdb on the target.

GitHub - caseykelso/lpc54628  (use tag "3" or the head of master branch) Feel free to fork and make a pull request with any suggestions.

Casey

0 Kudos
6 Views
Contributor II

For reference here is gdb console output demonstrating the above issue using the project I've provided

(gdb) b iap_flash.c:72
Breakpoint 2 at 0x42c62: file /mnt/ssd/dev/lpc54628/source/iap_flash.c, line 72.
(gdb) n
67 *(((uint8_t *)(&s_PageBuf[0])) + i) = i;
(gdb) clear
No breakpoint at this line.
(gdb) n
65 for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES; i++)
(gdb) c
Continuing.

Breakpoint 2, main () at /mnt/ssd/dev/lpc54628/source/iap_flash.c:72
72 iap_result = IAP_PrepareSectorForWrite(MYSECTOR, MYSECTOR);
(gdb) n
73 sprintf(outputbuffer,"\r\nPreparing flash sector %d results is %d\r\n",MYSECTOR, iap_result);
(gdb) p/x iap_result
$3 = 0x0
(gdb) n
74 printf(outputbuffer);
(gdb) n
75 iap_result = IAP_CopyRamToFlash((FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES*MYSECTOR) + (i * FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES),
(gdb) s
IAP_CopyRamToFlash (dstAddr=0, srcAddr=0x200000e0 <s_PageBuf>, numOfBytes=256, systemCoreClock=220000000)
at /mnt/ssd/dev/lpc54628/downloads/iap_flash/drivers/fsl_iap.c:222
222 command[0] = kIapCmd_IAP_CopyRamToFlash;
(gdb) n
223 command[1] = dstAddr;
(gdb) n
224 command[2] = (uint32_t)srcAddr;
(gdb) p/x dstAddr
$4 = 0x0
(gdb) n
225 command[3] = numOfBytes;
(gdb) p numOfBytes
$5 = 256
(gdb) n
226 command[4] = systemCoreClock / HZ_TO_KHZ_DIV;
(gdb) n
227 iap_entry(command, result);
(gdb) n
229 return translate_iap_status(result[0]);
(gdb) p result
$6 = {21, 536969216, 0, 276643, 537034616}
(gdb) p/x result
$7 = {0x15, 0x20018000, 0x0, 0x438a3, 0x20027f78}

0 Kudos
6 Views
Contributor II

Some more information:

  • iap prepare returns success
  • iap erase returns success and if I download the flash, you can see that it is erased
  • this problem persists also after a whole chip erase and programming & booting only from sector 7 with a dual enhanced image
  • I've also moved the vector table from the beginning of sector 7 to ram and this has no effect
  • I would like to find out what iap error code 21 is to find a fix, however I'm open to figuring out a work around. 
  • Moving the first dual enhanced image to sector 1 works but if both the sector 1 and sector 7 dual enhanced images, I saw some indeterminate behavior that I've yet to characterize. 
0 Kudos
6 Views
NXP TechSupport
NXP TechSupport

Hello Casey,

Could you please provide your project, that we can reproduce it on our side.

Also tell me which version of IDE you used, and do you use SDK ? which version ?


Have a great day,
TIC

6 Views
Contributor II

Hi Alice, Please see my project github repo at the bottom of this thread.

0 Kudos
6 Views
Contributor II

I'm using the SDK, I'll send over a github repo with a basic project in a bit. Do you have access to an ubuntu 18.04 environment, or I have a docker image that'll build my project, please let me know your preference.


Casey

0 Kudos