OpenNuvoton / M031BSP

BSP for M031 Series MCU
Apache License 2.0
15 stars 16 forks source link

Reset type for complete restart #6

Open jeromeDms opened 2 years ago

jeromeDms commented 2 years ago

HI I developed a bootloader and app located both in APROM. Bootloader reads a flag from LDRom and decides to jump to App or stay in bootloader. This works fine.

When the app decides to invalidate itself, it resets the flag stored in LDRom and reboot so IC will reboot and restart in bootloader mode.

When the app resets the flag in LDRom, resetting the CPU from code does not restart in bootloader mode, I can see the flag was properly reseted when reading LDRom from ICP tool, anyway the app does not restart in bootloader mode, unless I press the reset button on the eval board.

So it seems there is a difference between a push button reset and SYS_ResetChip(). I also tried with SYS_ResetCPU(); and NVIC_SystemReset(); but the behavior is similar.

Thanks

My code is as follow :

#define BOOTLOADER_BASE_ADDRESS             0
#define LDROM_VALID_FLAG_ADDRESS            FMC_LDROM_BASE
#define VALID_FLAG_APP                      0x55AA66BB

// -----------------------------------------------------------------------------------
void invalidateAppAndRebootBootloader(void)
{
      // Invalidate app
      setAppFlagValidInLDRom(FALSE);

      // reboot from bootloader      
      SYS_UnlockReg();
      /* Enable FMC ISP function */
      FMC_Open();
      /*Disable all interrupts*/
      NVIC->ICER[0] = 0xFFFFFFFF;

      FMC_SetVectorPageAddr(BOOTLOADER_BASE_ADDRESS);

      SYS_ResetChip();  <-- **I SUSPECT THIS RESET METHOD IS NOT APPROPRIATE**
}  

// -----------------------------------------------------------------------------------
uint32_t    readValidAppFlagFromLDRom(void)
{
      uint32_t flag;

      // Enable FMC ISP function 
      SYS_UnlockReg();
      FMC_Open();

      flag = FMC_Read(LDROM_VALID_FLAG_ADDRESS);

      FMC_Close();
      SYS_LockReg();    

      return flag;
}

// -----------------------------------------------------------------------------------
void    setAppFlagValidInLDRom(uint8_t setValid)
{
      uint32_t currentFlag;

      currentFlag = readValidAppFlagFromLDRom();

      // We must validate the app
      if(setValid == TRUE)
      {
            // It is already valid
            if(currentFlag == VALID_FLAG_APP)
            {
                    return;
            }
      }
      else
      // We must INvalidate the app
      {
            // It is already INvalid
            if(currentFlag != VALID_FLAG_APP)
            {
                    return;
            }
      }

      SYS_UnlockReg();
      FMC_Open();

      // Enable FMC ISP function 
      FMC_ENABLE_LD_UPDATE();

      // erase first page in LDRom
      FMC_Erase(LDROM_VALID_FLAG_ADDRESS);

      // Validate the app if required
      if(setValid == TRUE)
      {
           FMC_Write(LDROM_VALID_FLAG_ADDRESS, VALID_FLAG_APP);
      }

      FMC_DISABLE_LD_UPDATE();

      FMC_Close();
      SYS_LockReg();
}
kchuang1 commented 2 years ago

Hi, Please use SYS_SystemReset(...) instead of SYS_ResetChip(...) and the BOOTLOADER_BASE_ADDRESS is equal to 0x00100000 or not.

You can refer the FMC_IAP sample in BSP for the LDROM and APROM switch.

jeromeDms commented 2 years ago

BOOTLOADER_BASE_ADDRESS is 0x00

My bootloader is stored at address 0 of the APROM. My app starts at 0x2800 in APROM. I'm using LDROM only to store the flag.

SYS_SystemReset(...) does not work, as mentioned in my previous post. I'm then always booting from APROM at address 0 (bootloader). Bootloader reads flag from LDRom and if the flag is valid, it jumps to App at address 0x2800 as follow :

// Read the valid flag from LDROM
validAppCheckFlag = readValidAppFlagFromLDRom();
if(validAppCheckFlag == VALID_FLAG_APP)
{
      // Jump to app
      rebootFromAddress(APP_BASE_ADDRESS); // 0x2800
}   

// -----------------------------------------------------------------------------------
void rebootFromAddress(uint32_t jumpAddress)
{
      SYS_UnlockReg();
      /* Enable FMC ISP function */
      FMC_Open();
      /*Disable all interrupts*/
      NVIC->ICER[0] = 0xFFFFFFFF;

      FMC_SetVectorPageAddr(jumpAddress);

      /* Reset CPU only to reset to new vector page */
      //SYS_ResetCPU();
      /* Reset System to reset to new vector page. */
      NVIC_SystemReset();
}

// -----------------------------------------------------------------------------------
uint32_t    readValidAppFlagFromLDRom(void)
{
      uint32_t flag;

      // Enable FMC ISP function 
      SYS_UnlockReg();
      FMC_Open();

      flag = FMC_Read(LDROM_VALID_FLAG_ADDRESS);

      FMC_Close();
      SYS_LockReg();    

      return flag;
}

From FMC_IAP code, I can see the following comment :

/* NOTE!

FMC_SetVectorPageAddr(FMC_LDROM_BASE);

kchuang1 commented 2 years ago

Hi,

Please check:

  1. ICP tool : Config Bits->Setting --> Chip Booting Selection as "APROM with IAP"
  2. Your APP R/W Base as 0x2800 in project file

I use your similar code to test the Bootloader and APP switch. It can work

jeromeDms commented 2 years ago

Hi 1) It is already set like this, and in addition, my app checks if the configs bits are correctly set as follow :

#define CONFIG_0_BITS_WITH_APROM_IAP    0xFFFFFFBF

// -----------------------------------------------------------------------------------
// Be sure the IC was programmed with APROM+IAP so we 
// can use vector remap for jumping to app
void checkAndUpdateApromWithIAPMode(void)
{
      uint32_t config0Bits[1];

      SYS_UnlockReg();
      FMC_Open();

      // read config 0 bits
      if(FMC_ReadConfig(config0Bits, 1) >= 0)
      {
                if(config0Bits[0] != CONFIG_0_BITS_WITH_APROM_IAP)
        {
                      config0Bits[0] = CONFIG_0_BITS_WITH_APROM_IAP;

                      FMC_ENABLE_CFG_UPDATE();

                      if(FMC_WriteConfig(config0Bits, 1) >= 0)
                      {
                      // reset to restart with new config bits
                      SYS->IPRST0 = SYS_IPRST0_CHIPRST_Msk;

                      }
        }
      }

      FMC_Close();
      SYS_LockReg();
}

2) Yes it is already the case.

Capture d’écran 2021-10-19 à 12 32 55

Again, as I mentioned in the first post, all is working fine, but I need to apply a real hardware reset (using the push button on the eval board). A software reset does not work as the push button reset

kchuang1 commented 2 years ago

FMC_IAP_APP_Switch.zip

Hi, Could you test this code? It works in my test.

jeromeDms commented 2 years ago

Thanks you so much for your time.

We are in a different situation. Both my app and bootloader are located in APROM.

Only a flag is store in LDROM When the flag is set (0x55AA66BB) in LDROM at address 0, that means the app is valid.

So we always boot from Bootloader (APROM address 0). The bootloader reads the flag from LDROM, and :

Once the app has been updated by the bootloader, the bootloader writes the valid flag 0x55AA66BB to LDROM for the next boot.

The problem is only during this next boot, if a software reset is done, it still stays in bootloader rather than jumping to the app at 0x2800. If a hardware reset is done using the push button, the bootloader correctly jumps to the app at 0x2800.

kchuang1 commented 2 years ago

Hi,

My understanding is that your code cannot jump to bootloader from APP without pressing reset button. Is it correct?

Previous code is modified from FMC_IAP sample but its behavior is same as you. One is located at 0x00 as Bootloader and another is located as 0x2800 as APP. From the Uart message, you can see the code switch between these two codes and don't need to press the reset button. It differ with you behavior being not to check the flag store at LDROM.

Another BSP sample, FMC_MultiBoot, is also similar with your requirement except it doesn't read flag in LDROM only. You can also check its behavior.

jeromeDms commented 2 years ago

Your understanding is the opposite :-) The bootloader cannot jump to app without pressing reset button. Anyways, don't understand why but it works now !!

kchuang1 commented 2 years ago

Can you re-produce the bootloader and app switch in my provided code? If yes, you can compare what is different with your code.