Helpful ReplyHot!Not understanding the PFM swap...

Page: 12 > Showing page 1 of 2
Author
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
2019/02/17 07:21:14 (permalink)
0

Not understanding the PFM swap...

I'm trying to learn how to properly live update a PIC32MZ2048EFH144. This chip has the dual memory bank live update. I am not using Harmony. I'm using MPLABX v5.1 with XC32 2.1. I'm not sure any of that matters for my question but I figured it couldn't hurt.
 
I found a great example of how to swap the BFM and I have been able to successful program BFM UPPER and LOWER. 
With the BFM lower starting at 0x9FC00000 and the BFM upper start with an offset of +0x20000. I am able to test this swap by using this run count variable.
 
uint32_t __attribute__((persistent)) run_count;

 
I then just..
  • copy the BFM lower to the BFM upper
  • Update the BF1SEQ0 and BF2SEQ0 so that the boot bank swap
 
When I reboot the proper BFM is running and works. Now onto my question. The part that I'm not sure how to get working is the PFM region selection. The datasheet says the following.
The PFM partitions of each bank are mapped into upper and lower regions of the memory map. Start-up code, executing from the BFM, can select the mapping of the two PFM partitions into the two PFM regions.
So based on what I've read it seems that the startup code just needs to set the SWAP (PFSSWAP) bit in the NVMCON register. However I'm not sure if my "main" function is running in the BFM?
int main(int argc, char** argv)

Is this running in BFM? Also I call code that is another CPP class, could this be loading the current PFM which is why my app crashes soon as I try to swap the bit. Well I assume it's crashing because the device just reboots.
 
Here is my goal. My goal is to have my firmware (hex) file be able to initially be program onto our device using a PICkit 3 style programmer. After that I would like to...
  • send a new hex file over Bluetooth
  • that would then be programmed into the not current BFM / PFM 
  • swap the BFM
  • reboot and have the BFM select the PFM that relates
This is what I have done and seems to work.
  • I can send the hex file over Bluetooth and program the correct locations (I think)
  • I can properly swap the BFM
  • Then nothing works
I don't think my code is properly able to set the correct PFM swap bit. What do you think? Am I close or way off base?
#1
aschen0866
Super Member
  • Total Posts : 4402
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/17 09:27:24 (permalink)
0
There is an independent piece of firmware, known as "live update switcher", that resides entirely in the BFM. Upon a reset, it reads certain locations the PFM, from both the lower and upper panels,  to determine which PFM panel should the application run from.
#2
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/17 12:16:40 (permalink)
0
"Upon a reset, it reads certain locations the PFM, from both the lower and upper panels,  to determine which PFM panel should the application run from."
 
If so then where is this "certain location" in the PFM. I've looked and now looking again at the "bootloader" basic sample from harmony to see if I can find the special sauce...
#3
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/18 06:08:05 (permalink)
0
OK, so I think I found that certain location. 
  • 0x9D000000 <- LOWER_FLASH_ID_BASE_ADDRESS
  • 0x9D100000 <- UPPER_FLASH_ID_BASE_ADDRESS
I also found some bootloader code that looks to write these addresses. However I don't seem to be able to write them. I'm using the same Quad Write I used for my other writes so I'm not sure why it would not work.
 
Here is what the output look on first run. This is after a programming via a PICkit3.
Lower Flash ID: 0x275A72B4
  Checksum Start: 0x3C1A9D02
  Checksum End: 0x03400008
Upper Flash ID: 0xFFFFFFFF
  Checksum Start: 0xFFFFFFFF
  Checksum End: 0xFFFFFFFF
Now this is kind of what I would expect, except is the checksum correct? not sure? OK, now the code snippet I found does the following.

 
#define FLASH_ID_CHECKSUM_START 0xDEADBEEF
#define FLASH_ID_CHECKSUM_END 0xBEEFDEAD
#define FLASH_ID_CHECKSUM_CLR 0xFFFFFFFF
 
        /* Program Checksum and initial ID's for both panels*/
        T_FLASH_ID low_flash_id = { 0 };
        T_FLASH_ID up_flash_id = { 0 };
 
        low_flash_id.flash_id = 1;
        low_flash_id.checksum_start = FLASH_ID_CHECKSUM_START;
        low_flash_id.checksum_end = FLASH_ID_CHECKSUM_END;

        up_flash_id.flash_id = 0;
        up_flash_id.checksum_start = FLASH_ID_CHECKSUM_START;
        up_flash_id.checksum_end = FLASH_ID_CHECKSUM_END;
        
        APP_NVMQuadWordWrite((void *)LOWER_FLASH_ID_BASE_ADDRESS, (uint32_t *)&low_flash_id);
        APP_NVMQuadWordWrite((void *)UPPER_FLASH_ID_BASE_ADDRESS, (uint32_t *)&up_flash_id);

 
Now does that mean my checksum should equal the define if I read it back? confusing...
OK, now on reboot my boot alias properly swaps to BF2 from BF1. So woot, all good there. However, my flash IDs are confusing...
Lower Flash ID: 0x275A0000
  Checksum Start: 0x1C089C02
  Checksum End: 0x02400008
Upper Flash ID: 0x00000000
  Checksum Start: 0x10800007
  Checksum End: 0x8C87DEA8
I'm not sure why they are not setting correctly?
#4
NorthGuy
Super Member
  • Total Posts : 5267
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: online
Re: Not understanding the PFM swap... 2019/02/18 06:53:20 (permalink) ☄ Helpfulby BobbyCannon 2019/02/18 07:54:08
4 (1)
You need to erase before write.
#5
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/18 07:54:00 (permalink)
0
OK, now we are getting somewhere. I was not clearing that page which was also affecting my other writes, I'm sure!
 
Now, it seems I can only write to the non-running application, so how would I erase and set the initial lower ID without having to erase a whole page of data? and I'm not sure I could erase into the application memory space, correct?

Hum...
#6
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/18 07:55:21 (permalink)
0
Oh or maybe there is a way to setup MPLabs to set the initial FLASH_ID to 0? is there a way to do that?
 
#7
NorthGuy
Super Member
  • Total Posts : 5267
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: online
Re: Not understanding the PFM swap... 2019/02/18 09:10:27 (permalink)
4 (1)
BobbyCannon
Now, it seems I can only write to the non-running application, so how would I erase and set the initial lower ID without having to erase a whole page of data? and I'm not sure I could erase into the application memory space, correct?



Typically you write into inactive partition. You bump the inactive BFxSEQ just one above of the active BFxSEQ. This will make sure the next boot will be from the other partition. Of course, it'll only work until BFxSEQ becomes 0xffff, but if you start from 0 then you have 65535 possible updates, which is plenty.
#8
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/18 09:52:19 (permalink)
0
NorthGuy
Typically you write into inactive partition. You bump the inactive BFxSEQ just one above of the active BFxSEQ. This will make sure the next boot will be from the other partition. Of course, it'll only work until BFxSEQ becomes 0xffff, but if you start from 0 then you have 65535 possible updates, which is plenty.



But the BFxSEQ is only for the bootloader, correct? My bootloader swapping works just fine, and I can always just reset both bootloader values when it gets to 65535. Which I'm already restarting those values and it works fine.
 
The problem I'm having is writing the FLASH_ID for FLASH PAGE swapping, correct?
 
#9
NorthGuy
Super Member
  • Total Posts : 5267
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: online
Re: Not understanding the PFM swap... 2019/02/18 10:49:34 (permalink)
0
You can just read BFSWAP bit then switch the PFM accordingly.
#10
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 06:57:19 (permalink)
0
NorthGuy
You can just read BFSWAP bit then switch the PFM accordingly.




First off thank you so much for taking your time to help me.
 
Is there anyway I can simply make my "main" run in the boot loader section and let it select the correct flash panel? This way I could program one firmware in bootloader bank 1 and flash bank 1 and the other firmware in bootloader bank 2 and flash bank 2.
 
Basically I want to be able to manage one project without having a separate bootloader application. If I have to have a separate bootloader application then I guess I could do that also...
 
<edit>
so far everytime I switch the PFM it just reboots or locks up
</edit>
#11
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 07:27:30 (permalink)
0
Here is what I came up with for my initial main... not sure why the bank won't swap?
 
int main(int argc, char** argv)
{
 uint32_bits temp1, temp2;
    bool valid1, valid2;
 uint8_t bank = 1;

    temp1.Val = BF1SEQ0;
    temp2.Val = BF2SEQ0;

    valid1 = ((temp1.word.LW + temp1.word.HW) == 0xFFFF);
    valid2 = ((temp2.word.LW + temp2.word.HW) == 0xFFFF);

    if (valid1 == true && valid2 == true)
    {
        bank = (temp1.word.LW >= temp2.word.LW) ? 1 : 2;
    }
    else if (valid1 == true)
    {
        bank = 1;
    }
    else if (valid2 == true)
    {
        bank = 2;
    }

 if (bank == 2)
 {
  // need to swap the panels
  NVMKEY = 0;
  NVMKEY = 0xAA996655;
  NVMKEY = 0x556699AA;
  NVMCONSET = _NVMCON_SWAP_MASK;
 }

 return run();
}

 
#12
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 07:53:53 (permalink)
0
A lot of the code I'm seeing has the boot loader jumping to the app base address?
 
/* Address of the Flash from where the application starts executing */
/* Rule: Set APP_FLASH_BASE_ADDRESS to _RESET_ADDR value of application linker script*/
#define APP_RESET_ADDRESS (APP_FLASH_BASE_ADDRESS)
 
/* Set default to APP_RESET_ADDRESS */
fptr = (void (*)(void))APP_RESET_ADDRESS;
...
fptr();

 
Maybe this is what I'm confused about. Wouldn't this already be executing? Maybe I'm thinking that my code is the bootloader but it's not? or I'm not understanding when the code transitions from the "boot loader" to this "app flash base address" location?
 
#13
NorthGuy
Super Member
  • Total Posts : 5267
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: online
Re: Not understanding the PFM swap... 2019/02/19 07:56:35 (permalink)
0
You need to do the swap while the code is running from BFM.
 
The code execution always start in BFM at 0xbfc00000. This is also an NMI vector location. So, the code placed there by the compiler detects whether it is an NMI or the start of the program, then jumps to the C initialization. This is the place where you would do the swap. I just disassembled this to see what it is doing, then replaced with my own code which does what I need instead. Unfortunately, I don't know how to do this in a more conventional way.
 
#14
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 08:23:58 (permalink)
0
When you say "then jumps to the C initialization" is that "main" or is "main" 0xbfc00000?
 
I really appreciate the help and thank you for your patience. What I don't understand is the transition from BFM to PFM. So currently I'm just trying to copy BFM1 to BFM2 and PFM1 to PFM2 then swap to boot the same code just in the other location. Maybe the swap is working but I'm not cloning the memory correctly?
 
I'm having trouble pasting the code here but maybe I'm doing this wrong?
 
I'm copying from 
 
virAddr = (uint32_t *) LBA_START_LOC;
while (virAddr < (uint32_t *)LBA_END_LOC)
{
 if (((uint32_t)virAddr % PFM_PAGE_BSIZE) == 0)
 {
  PIC32::FlashPageErase((void *)((uint32_t)virAddr + UBA_OFFSET));
  PIC32::ToggleStatusLed(1);
 }

 for (i = 0, rowStart = virAddr; i < PFM_ROW_WSIZE; i++)
 {
  /* Ignore the 4 QW that contains the BFSEQ number and replace with all FFs */
  if (rowStart >= (uint32_t *)LBA_BFSEQ_QW_START
   && rowStart <= (uint32_t *)LBA_BFSEQ_QW_END)
  {
   RowBuf[i] = 0xFFFFFFFF;
  }
  else
  {
   RowBuf[i] = *rowStart;
  }

  rowStart++;
 }

 PIC32::FlashRowWrite((void *)((uint32_t)virAddr + UBA_OFFSET), RowBuf, PFM_ROW_BSIZE);

 virAddr += PFM_ROW_WSIZE;
}

 
 and same with flash app panel
 

virAddr = (uint32_t *) LOWER_FLASH_ID_BASE_ADDRESS;
PIC32::FlashPageErase((void *)((uint32_t) virAddr + FLASH_UPPER_OFFSET));
PIC32::ToggleStatusLed(2);
 
virAddr = (uint32_t *) LOWER_FLASH_APP_BASE_ADDRESS;
 while (virAddr < (uint32_t *) LOWER_FLASH_APP_END_ADDRESS)
 {
  if (((uint32_t) virAddr % PFM_PAGE_BSIZE) == 0)
  {
   PIC32::FlashPageErase((void *)((uint32_t) virAddr + FLASH_UPPER_OFFSET));
   PIC32::ToggleStatusLed(2);
  }

  for (i = 0, rowStart = virAddr; i < PFM_ROW_WSIZE; i++)
  {
   RowBuf[i] = *rowStart;
   rowStart++;
  }

  PIC32::FlashRowWrite((void *)((uint32_t)virAddr + FLASH_UPPER_OFFSET), RowBuf, PFM_ROW_BSIZE);
  virAddr += PFM_ROW_WSIZE;
 }

 
post edited by BobbyCannon - 2019/02/19 08:35:32
#15
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 08:25:02 (permalink)
0
oh and the defines
 
#define LBA_START_LOC 0x9FC00000
#define LBA_END_LOC 0x9FC14000
#define FLASH_UPPER_OFFSET 0x100000
#define LOWER_FLASH_BASE_ADDRESS 0x9D000000
#define LOWER_FLASH_ID_BASE_ADDRESS (LOWER_FLASH_BASE_ADDRESS)
#define LOWER_FLASH_ID_END_ADDRESS (LOWER_FLASH_ID_BASE_ADDRESS + FLASH_ID_STRUCT_SIZE)
#define LOWER_FLASH_APP_BASE_ADDRESS (LOWER_FLASH_ID_END_ADDRESS)
#define LOWER_FLASH_APP_END_ADDRESS (LOWER_FLASH_ID_BASE_ADDRESS + FLASH_UPPER_OFFSET - 1)
 
#16
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 08:39:45 (permalink)
0
I think there is a problem when cloning my PFM, I don't think I'm doing the FlashPageErase because my starting address is not allowing it to land on the PFM_PAGE_BSIZE... I'll need to fix that and see if it works.
#17
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 08:44:48 (permalink)
0
I think I just got it working... I think it was just a problem with me incorrectly flashing the PFM... 
 
I'm going to add the code to my production image and see if I can properly upgrade it? I'll report back what I find.
 
#18
aschen0866
Super Member
  • Total Posts : 4402
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/19 11:43:06 (permalink)
0
It looks like you are already looking into the Harmony example LiveUpdate_App and LiveUpdate_Switcher projects. I don't use the live update feature because I can't afford to set aside half of the Flash memory. Assuming you have BOOTLOADER_LIVE_UPDATE_STATE_SAVE set to 1 in the LiveUpdate_App project, and BOOTLOADER_LIVE_UPDATE_SWITCHER set to 1 in the LiveUpdate_Switcher project,  my understanding is that the App will always write the new image to the opposite PFM panel, then bump up the opposite panel's Flash ID by two. On a reset, the Switcher is going to determine which PFM panel to run, and the one with higher Flash ID wins the arbitration. The Switcher also initializes Flash IDs on a freshly programmed device, making the active panel with Flash ID 1 and the non-active panel 0. I am guessing you have already seen the function that does this in LiveUpdate_Switcher project.
 
There is no need to do a page erase before updating Flash ID. The first 16-byte block in the PFM is excluded from the application's build by using a custom linker script. Once the code is programmed, the 16-byte block will always be all 0xFF's to begin with. Therefore you can write new Flash ID and other "markers", i.e., the T_FLASH_ID struct, without erasing the page first.
 
The idea of merging the functionality of the Switcher into the application code can be challenging. This is because the Switcher needs to run before the C run time startup module starts, otherwise the startup module could get initializers from the wrong Flash panel. In the end, you'll be doing exactly what the standalone Switcher is doing in assembly code.
 
Harmony examples don't do the Flash checksum verification. If you need this, you'll have to have a separate tool to post process the hex file. MPLABX has a builtin powerful hex manipulation tool called hexmate. It can merge bootloader and application. It can generate checksum and inject into a location you specify as well.
#19
BobbyCannon
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2019/01/06 16:50:28
  • Location: 0
  • Status: offline
Re: Not understanding the PFM swap... 2019/02/28 13:26:29 (permalink)
0
OK, wanted to drop an update. Here is what is working.
 
1. Enable Flash Write
2. Clear the Upper Boot Flash Area - Erasing boot 0x9FC20000 to 0x9FC34000 with step 0x4000
3. Clear the Upper Program Area - Erasing program 0x9D100000 to 0x9D1FFFFF with step 0x4000
4. Write the data from the hex file
5. Set the proper boot sequence, meaning ensure the new boot sector is higher seq than previous other
6. Reboot
8. Let the boot loader (main) set the proper swap flag based on which boot sector is active.
7. Profit... except...
 
It seems that only my debug enabled hex is working... makes no sense...
 
Anyone have any ideas, the "release" hex works if I program it via a PICkit3 but not if I transfer it OTA (over the air). However the "debug" hex works both ways.
post edited by BobbyCannon - 2019/02/28 13:27:48
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5