This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

problems with secondary bootloader on LPC1768 with MCP1700

I'm using µVision 4.50.0.0 with Keil MCB1700 with LPC1768.

I wrote a secondary boot-loader, that reads srecord file from usb and writes that into flash starting 0x20000.
The AN10866.pdf from NXP helped a lot.

The application itself is built with following changes:
Target Options IROM1 Start 0x20000 Size 0x60000
Asm options Define NO_CRP.

The following code should start my application after
successful update/validating the present firmware:

#define APPL_RUN_ADDR           0x00020000

__asm void boot_jump(U32 address)
{
    LDR SP, [R0]
    LDR PC, [R0, #4]
}


void run_appl()
{
     SCB->VTOR = APPL_RUN_ADDR & 0x1FFFF80;

    boot_jump(APPL_RUN_ADDR);
}


This code snippet is copied from nxp's AN10866.pdf, too.

But the firmware doesn't start reliable. Where do I stuck?

APPL_RUN_ADDR is defined to 0x20000

at 0x20004 there's 00020229 (this is the Reset_Handler fro my application, which I checked in the map file).

Unfortunately I don't find the AN10866.zip example files, to see how nxp's bootloader was built exactly.

What else have I forgotten to do?

Thanks in advance
Hubert

Parents
  • You should check a CRC or equivalent prior to loading and attempting to run ANY code downloaded. Insofaras the code to re-startup the processor, this works on 1768:

    
    void __SWI_0(void *(fp)())
    {
            UINT32 RegTemp;
    
            // Reset PCONP to RESET conditions
            PCONP = 0x001817BE;
    
            // Restore VIC slots to RESET conditions
            UninstallIrq(SPI1_INT);
    
            __asm
            {
                    MRS RegTemp, CPSR
                    ORR RegTemp, RegTemp, #0xC0       // Only in supv mode - disable interrupts
                    MSR CPSR_c, RegTemp
                    MRS RegTemp, SPSR
                    AND RegTemp, RegTemp, #0x1F       // Only in supv mode - set to RESET conditions
                    MSR SPSR_cxsf, RegTemp
            }
    
            (*fp)();
    }
    

    Disable interrupts and jump to the start of program code. This sequence MUST be accomplished while the processor is in the 'Supervisory Mode' of operation so that the program stacks and restricted registers can all be accessed and properly initialized by the main program startup code when it executes. HTH.

Reply
  • You should check a CRC or equivalent prior to loading and attempting to run ANY code downloaded. Insofaras the code to re-startup the processor, this works on 1768:

    
    void __SWI_0(void *(fp)())
    {
            UINT32 RegTemp;
    
            // Reset PCONP to RESET conditions
            PCONP = 0x001817BE;
    
            // Restore VIC slots to RESET conditions
            UninstallIrq(SPI1_INT);
    
            __asm
            {
                    MRS RegTemp, CPSR
                    ORR RegTemp, RegTemp, #0xC0       // Only in supv mode - disable interrupts
                    MSR CPSR_c, RegTemp
                    MRS RegTemp, SPSR
                    AND RegTemp, RegTemp, #0x1F       // Only in supv mode - set to RESET conditions
                    MSR SPSR_cxsf, RegTemp
            }
    
            (*fp)();
    }
    

    Disable interrupts and jump to the start of program code. This sequence MUST be accomplished while the processor is in the 'Supervisory Mode' of operation so that the program stacks and restricted registers can all be accessed and properly initialized by the main program startup code when it executes. HTH.

Children
  • Q S, Thanks for your quick answer.

    As I'm transferring the application as S-record file, where every line has its own check-sum, as well as at the end there's an record where I can compare the count of received records with the ones contained in that s-record file.

    I took from your code the PCONP reset, as I'm not using SPI/SSP interfaces I omitted the accesses to CPSR/SPSR.

    It doesn't change very much. Very seldom the application starts, but most of the time not.

    Now I took a deeper look what the processor does when jumping from bootloader into application.
    Single-stepping (F11) in Disassembly beginning at my boot_jump function I observe the following:

    After

    LDR PC, [R0, #4]
    

    the PC is at the Reset_Handler of the application, with single steps I walk through the SystemInit as well as the __main (_main_scatterload) from there I reach my normal main function. But the following free run (F5) results in a Hard_Fault (HARD_FAULT_STAT = 0x40000000)

    I've already checked bit0 of the Interrupt vectors, they're all set (Thumb Mode).

    What else am I missing?

    Thanks Hubert

  • Digging even deeper into the assembly showed after reaching my main function

    0x00021110 F7FEFFE9  BL.W     0x000200E6
    0x00021114 2200      MOVS     r2,#0x00
    0x00021114 2200      MOVS     r2,#0x00
    0x00021116 4611      MOV      r1,r2
    0x00021118 F2AF0057  ADR.W    r0,{pc}-0x53  ; @0x000210C5
    0x0002111C F8DFC0C4  LDR.W    r12,[pc,#196]  ; @0x000211E4
    0x00021120 DF00      SVC      0x00
    

    executing the SVC 0x00 call results in the HardFaultHandler.

    The C-code of that main look like

    
    int main (void)
    {
      os_sys_init(init);
      while(1);
    }
    

    I hope this gives some more hints about what I'm missing.

    Thanks Hubert

  • Where do you remap your interrupt vectors for your new code into the proper interrupt offset prior to executing the os_sys_init(init) call? You need to go back and review how a system functions, I believe.

  • O.K.

    Now I found the solution to start the application located at APPL_RUN_ADDR = 0x20000 reliably.

    before changing the vector table the irq's have to be disabled in the bootloader.

    
    __asm void boot_jump(U32 address)
    {
        LDR SP, [R0]
        LDR PC, [R0, #4]
    }
    
    void run_appl()
    {
    
    //   void (*user_code_entry)(void);
    
       /* Change the Vector Table to the USER_FLASH_START
       in case the user application uses interrupts */
    
         __disable_irq();
         LPC_SC->PCONP = 0x001817BE;
         SCB->VTOR = APPL_RUN_ADDR & 0x1FFFF80;
         boot_jump(APPL_RUN_ADDR);
    }
    

    and in the application the irq's have to be enabled again before calling os_sys_init()!!!

    int main (void)
    {
      __enable_irq();
      os_sys_init(init);                        /* Initialize RTX and start init */
    }
    

    The bootloader is compiled with IROM1 Start=0x0 Size = 0x20000

    The application is compiled with IROM1 Start=0x20000 Size = 0x60000 and Asm Define = NO_CRP

    Hubert

  • Note that this works _only_ because your specific controller starts up in privileged mode. This might not be the case using other controllers.