Image Selection on JN5169

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

Image Selection on JN5169

Jump to solution
984 Views
mferrari1
Contributor III

I am coding a firmware update utility for the JN5169 and have a question about invalidating a resident code image in flash.

My initial code image is running fine, based at Segment 0 (Flash Address 0x00080000).  I am also able to make a copy of it and base the copy at the beginning of Segment 8 (Flash Address 0x000C0000) - I can see it there in memory via the IDE. So far so good.

Now, I want to invalidate the first image at Flash Address 0x00080000 so that upon restart, the JN5169's bootloader will find the first valid BIR at 0x000C0000 and then remap and use the new image.

Page 7 of JN-AN-1003 says: "One method to achieve this is to program the Status field byte (of the BIR) to 0x00, which will mark the image as invalid".  But since the BIR (the first entry in the Flash Header) is in FLASH, you can't just write to a single byte.  You have to first erase the entire sector, then write in blocks of 16-Byte "pagewords".

JN-UG-3087 Page-127 suggests reading the entire flash sector into RAM, then erasing the flash sector, then change the desired byte in RAM and then write the sector from RAM back into the flash sector.  But the JN5169 Flash Sector is 32k Bytes - there is not enough RAM available to actually do this!

I have tried invalidating the initial image at Sector 0 by simply erasing all of  Sector 0, then looping in a while(1) waiting for the Watchdog to reset, with the hopes that after reset, the bootloader will then find the valid BIR based at flash sector 8 and remap and run ithe code image based there, but this does not work. 

Can anyone advise on how to invalidate the image based at Sector 0 and make the bootloader then find and run the new image which is based at Sector 8?

Thanks,  Matt

0 Kudos
1 Solution
828 Views
mferrari1
Contributor III

The code normally runs based at Sector 0.  The goal is to load an alternate code image based at another Sector and be able to then invalidate the code based at Sector 0 and run the code based at the new Sector instead, and vice versa, thus creating a ping-pong method for loading and running an updated code image while maintaining the prior code image until the new code image is verified.

Assume the following definitions:

#define FLASH_SECTOR_SIZE                         0x8000

#define ALTERNATE_CODE_SECTOR                     8
#define SECTOR_ADDRESS_OF_ALTERNATE_CODE_SECTOR   (ALTERNATE_CODE_SECTOR * FLASH_SECTOR_SIZE)

#define SECTOR_ADDRESS_OF_SECTOR_0                0x00000000
#define FLASH_ADDRESS_OF_SECTOR_0                 0x00080000

#define BOOT_IMAGE_RECORD_STATUS_BYTE_INDEX       13

#define PAGEWORD_SIZE_IN_BYTES                    16

As an example, the following code will copy the code image currently based at Sector 0 and

duplicate it based at the Sector designated for the alternate (new) code image:

uint8   u8i, u8PagewordBytes[PAGEWORD_SIZE_IN_BYTES];

for( u8i = 0; u8i < ALTERNATE_CODE_SECTOR; u8i++ ) {

    bAHI_FlashEraseSector( ALTERNATE_CODE_SECTOR + u8i );

    bAHI_FullFlashProgram( SECTOR_ADDRESS_OF_ALTERNATE_CODE_SECTOR + (u8i * FLASH_SECTOR_SIZE),

                           FLASH_SECTOR_SIZE,

                           (uint8 *)(FLASH_ADDRESS_OF_SECTOR_0 + (u8i * FLASH_SECTOR_SIZE)) );

    // You may want to refresh your Watchdog timer in this loop...

}

Now that you have new code based at the new Sector, you can invalidate the existing code image based at Sector 0, and upon reset, the code image based at the new Sector will run instead of the code which was originally based at Sector 0.  Be aware that because of the remapping that will have occurred (as indicated by the REG_SYS_FLASH_REMAP & REG_SYS_FLASH_REMAP2 registers) the "new" code will still appear to be located at based at Sector 0, even though physically, it's actually based at the new Sector. 

The code below shows how to invalidate the current code image (regardless of whichever Sector it's physically based at):

bAHI_FullFlashRead( SECTOR_ADDRESS_OF_SECTOR_0, PAGEWORD_SIZE_IN_BYTES, u8PagewordBytes );
u8PagewordBytes[BOOT_IMAGE_RECORD_STATUS_BYTE_INDEX] = 0x00;
bAHI_FullFlashProgram( SECTOR_ADDRESS_OF_SECTOR_0, PAGEWORD_SIZE_IN_BYTES, u8PagewordBytes );

Code always appears to be located and running as if it's located at Sector 0 (even if it's not), so if Sectors have become remapped, then accessing "Sector 0" really accesses the remapped Sector. So to invalidate the current image, always write to Sector 0, regardless...

The documentation indicates that you need to erase the Flash prior to writing to it or an,

exception may result, but Flash can only be erased one whole Sector at a time

(which doesn't work for us here).

Since our goal is only to zero out the Status byte in the BIR and since Flash writes

can only change bits from 1 to 0, this works without having to erase the Sector first.

Flash can only be written using 16-byte Pagewords however, thus the need to read, modify and

write a whole block of 16 bytes, instead of just the one Status byte we're actually interested in.

I hope this helps... What with the remapping and all, it can become a bit confusing...

Matt

View solution in original post

0 Kudos
3 Replies
829 Views
mferrari1
Contributor III

The code normally runs based at Sector 0.  The goal is to load an alternate code image based at another Sector and be able to then invalidate the code based at Sector 0 and run the code based at the new Sector instead, and vice versa, thus creating a ping-pong method for loading and running an updated code image while maintaining the prior code image until the new code image is verified.

Assume the following definitions:

#define FLASH_SECTOR_SIZE                         0x8000

#define ALTERNATE_CODE_SECTOR                     8
#define SECTOR_ADDRESS_OF_ALTERNATE_CODE_SECTOR   (ALTERNATE_CODE_SECTOR * FLASH_SECTOR_SIZE)

#define SECTOR_ADDRESS_OF_SECTOR_0                0x00000000
#define FLASH_ADDRESS_OF_SECTOR_0                 0x00080000

#define BOOT_IMAGE_RECORD_STATUS_BYTE_INDEX       13

#define PAGEWORD_SIZE_IN_BYTES                    16

As an example, the following code will copy the code image currently based at Sector 0 and

duplicate it based at the Sector designated for the alternate (new) code image:

uint8   u8i, u8PagewordBytes[PAGEWORD_SIZE_IN_BYTES];

for( u8i = 0; u8i < ALTERNATE_CODE_SECTOR; u8i++ ) {

    bAHI_FlashEraseSector( ALTERNATE_CODE_SECTOR + u8i );

    bAHI_FullFlashProgram( SECTOR_ADDRESS_OF_ALTERNATE_CODE_SECTOR + (u8i * FLASH_SECTOR_SIZE),

                           FLASH_SECTOR_SIZE,

                           (uint8 *)(FLASH_ADDRESS_OF_SECTOR_0 + (u8i * FLASH_SECTOR_SIZE)) );

    // You may want to refresh your Watchdog timer in this loop...

}

Now that you have new code based at the new Sector, you can invalidate the existing code image based at Sector 0, and upon reset, the code image based at the new Sector will run instead of the code which was originally based at Sector 0.  Be aware that because of the remapping that will have occurred (as indicated by the REG_SYS_FLASH_REMAP & REG_SYS_FLASH_REMAP2 registers) the "new" code will still appear to be located at based at Sector 0, even though physically, it's actually based at the new Sector. 

The code below shows how to invalidate the current code image (regardless of whichever Sector it's physically based at):

bAHI_FullFlashRead( SECTOR_ADDRESS_OF_SECTOR_0, PAGEWORD_SIZE_IN_BYTES, u8PagewordBytes );
u8PagewordBytes[BOOT_IMAGE_RECORD_STATUS_BYTE_INDEX] = 0x00;
bAHI_FullFlashProgram( SECTOR_ADDRESS_OF_SECTOR_0, PAGEWORD_SIZE_IN_BYTES, u8PagewordBytes );

Code always appears to be located and running as if it's located at Sector 0 (even if it's not), so if Sectors have become remapped, then accessing "Sector 0" really accesses the remapped Sector. So to invalidate the current image, always write to Sector 0, regardless...

The documentation indicates that you need to erase the Flash prior to writing to it or an,

exception may result, but Flash can only be erased one whole Sector at a time

(which doesn't work for us here).

Since our goal is only to zero out the Status byte in the BIR and since Flash writes

can only change bits from 1 to 0, this works without having to erase the Sector first.

Flash can only be written using 16-byte Pagewords however, thus the need to read, modify and

write a whole block of 16 bytes, instead of just the one Status byte we're actually interested in.

I hope this helps... What with the remapping and all, it can become a bit confusing...

Matt

0 Kudos
828 Views
mario_castaneda
NXP TechSupport
NXP TechSupport

Hi Matt,

I am checking this and I will get back to you as soon as possible.

Regards,

Mario

0 Kudos
828 Views
mferrari1
Contributor III

Hi Mario –

Please see my updated posting.

I have already solved this problem and have posted an explanation for others in case anyone else needs to understand this also.

Thanks,

Matt