Forums

Invoke bootloader in ISP mode on LPC2368

Started by maximb December 28, 2010
Hi, all.

My custom board has a LPC2368 installed and runs FreeRTOS.
What I am trying to do is to invoke bootloader in ISP mode from my
application - to allow in-field firmware upgrade, when FlashMagic tool
will be used.

I referred the NXP appnote AN10356 to get a clue of how to do it. What
I changed in the example given by the appnote, is the use of GPIO pin
P0.14, since the silicon user's manual declares, that GPIO pin P2.10
is checked by the bootloader.

Also, I tried to use the IAP command 57 - in order to, as declared by
the user's manual, simplify my job. In this case, I care to reset the
PLL and disable the watchdog.

Eventually, none of these options worked for me. What I see is that
when I command my software to invoke the bootloader in ISP mode, the
board resets and goes to bootloader, but the bootloader jumps to
application code instead of staying in the ISP mode and wait for
firmware upgrade.

Please find enclosed below the code:

typedef void ( *TFpIap_t ) ( unsigned long cmd [] , unsigned long stat
[] );

void invoke_isp1( void )
{
    SIapCallData_t call_data;
    static TFpIap_t s_iap_func = ( TFpIap_t )IAP_LOCATION;

    // disconnect PLL
    PLLCON = 0x0;
    PLLFEED = 0xAA;
    PLLFEED= 0x55;

    // set peripheral bus to 1/4th of the system clock
    VPBDIV = 0x0;

    // disable the watchdog
    WDMOD = ~( 0x3 );

    // invoke the IAP call
    call_data.cmd = LPC_IAP_CMD_REINVOKE_ISP; // 57
    s_iap_func( &call_data.cmd, &call_data.stat );
}

void invoke_isp2( void )
{
    void ( *bootloader_entry )( void ) = ( void* )0;

    // reset PINSEL (set all pins to GPIO)
    PINSEL0 = 0x00000000;
    PINSEL1 = 0x00000000;
    PINSEL4 = 0x00000000;

    FIODIR2 = BIT10; // controlled P2.10 is an output
    FIOCLR2 = BIT10; // drive P2.10 low

    // power up all peripherals
    PCONP = 0x03BE;

    // disconnect
    PLLCON = 0x00;
    PLLFEED = 0xAA;
    PLLFEED = 0x55;

    // set peripheral bus to 1/4th of the system clock
    VPBDIV = 0x00;

    // map bootloader vectors
    MEMMAP = 0;

    // set up a watchdog timer to exit ISP mode
    WDTC = 5000 * 1000; // sufficient time to upgrade the firmware
    WDMOD = 0x03;
    WDFEED = 0xAA;
    WDFEED = 0x55;

    // jump to the bootloader address
    bootloader_entry();
}

Any idea why doesn't it work ?

Thanks in advance.
mb
Do you disable interrupts (especially before any feed sequences, and 
entering the bootloader)?

Mike

"maximb" <maxim.bakushin@gmail.com> wrote in message 
news:2c76003f-3e13-4c4a-bed8-9bd5ab8adbcc@l7g2000vbv.googlegroups.com...
> Hi, all. > > My custom board has a LPC2368 installed and runs FreeRTOS. > What I am trying to do is to invoke bootloader in ISP mode from my > application - to allow in-field firmware upgrade, when FlashMagic tool > will be used. > > I referred the NXP appnote AN10356 to get a clue of how to do it. What > I changed in the example given by the appnote, is the use of GPIO pin > P0.14, since the silicon user's manual declares, that GPIO pin P2.10 > is checked by the bootloader. > > Also, I tried to use the IAP command 57 - in order to, as declared by > the user's manual, simplify my job. In this case, I care to reset the > PLL and disable the watchdog. > > Eventually, none of these options worked for me. What I see is that > when I command my software to invoke the bootloader in ISP mode, the > board resets and goes to bootloader, but the bootloader jumps to > application code instead of staying in the ISP mode and wait for > firmware upgrade. > > Please find enclosed below the code: > > typedef void ( *TFpIap_t ) ( unsigned long cmd [] , unsigned long stat > [] ); > > void invoke_isp1( void ) > { > SIapCallData_t call_data; > static TFpIap_t s_iap_func = ( TFpIap_t )IAP_LOCATION; > > // disconnect PLL > PLLCON = 0x0; > PLLFEED = 0xAA; > PLLFEED= 0x55; > > // set peripheral bus to 1/4th of the system clock > VPBDIV = 0x0; > > // disable the watchdog > WDMOD = ~( 0x3 ); > > // invoke the IAP call > call_data.cmd = LPC_IAP_CMD_REINVOKE_ISP; // 57 > s_iap_func( &call_data.cmd, &call_data.stat ); > } > > void invoke_isp2( void ) > { > void ( *bootloader_entry )( void ) = ( void* )0; > > // reset PINSEL (set all pins to GPIO) > PINSEL0 = 0x00000000; > PINSEL1 = 0x00000000; > PINSEL4 = 0x00000000; > > FIODIR2 = BIT10; // controlled P2.10 is an output > FIOCLR2 = BIT10; // drive P2.10 low > > // power up all peripherals > PCONP = 0x03BE; > > // disconnect > PLLCON = 0x00; > PLLFEED = 0xAA; > PLLFEED = 0x55; > > // set peripheral bus to 1/4th of the system clock > VPBDIV = 0x00; > > // map bootloader vectors > MEMMAP = 0; > > // set up a watchdog timer to exit ISP mode > WDTC = 5000 * 1000; // sufficient time to upgrade the firmware > WDMOD = 0x03; > WDFEED = 0xAA; > WDFEED = 0x55; > > // jump to the bootloader address > bootloader_entry(); > } > > Any idea why doesn't it work ? > > Thanks in advance. > mb
On Thu, 30 Dec 2010 13:25:43 -0700, "Michael Anton" <manton@nospamcompusmart.ab.ca> wrote:

>Do you disable interrupts (especially before any feed sequences, and >entering the bootloader)? > >Mike > >"maximb" <maxim.bakushin@gmail.com> wrote in message >news:2c76003f-3e13-4c4a-bed8-9bd5ab8adbcc@l7g2000vbv.googlegroups.com... >> Hi, all. >> >> My custom board has a LPC2368 installed and runs FreeRTOS. >> What I am trying to do is to invoke bootloader in ISP mode from my >> application - to allow in-field firmware upgrade, when FlashMagic tool >> will be used. >> >> I referred the NXP appnote AN10356 to get a clue of how to do it. What >> I changed in the example given by the appnote, is the use of GPIO pin >> P0.14, since the silicon user's manual declares, that GPIO pin P2.10 >> is checked by the bootloader. >> >> Also, I tried to use the IAP command 57 - in order to, as declared by >> the user's manual, simplify my job. In this case, I care to reset the >> PLL and disable the watchdog. >> >> Eventually, none of these options worked for me. What I see is that >> when I command my software to invoke the bootloader in ISP mode, the >> board resets and goes to bootloader, but the bootloader jumps to >> application code instead of staying in the ISP mode and wait for >> firmware upgrade.
There are a few undocumented things you need to set up - basically you need to make sure the hardware is in the same state it was at reset, in particular ensuring the stack pointer is set up (top of RAM- 32 bytes), and disable the fractional baudrate divider and (maybe?) fast IO. I've only ever used it on the LPC2136/01 - other parts may have additional things that need setting to their reset states. Single-stepping the call to reinvoke will usually find where it's breaking - stack is the most likely. From memory I think it is also necessary to make sure R1 is initialised (can be set to value of R0) , as although the call doesn't return, I think it shares code with calls that do, and at some point accesses memory pointed to R1, which would cause an exception if R1 points somewhere invalid. This is sime code I use on LPC2136 : __disable_interrupt(); PLLCON=0; PLLFEED = 0xAA; PLLFEED = 0x55; SCS=0; // disable fast IO U0FDR=0x10; // no FDR - causes wrong baud asm("mov r0,#0x40000000"); asm("mov r1,r0"); asm("mov r2,#0x39"); asm("str r2,[r0]"); asm("mov r2,#0x7ffffff1"); asm("add r13,r0,#0x8000"); // stack at top-32, as per Philips reccommendation asm("sub r13,r13,#0x20"); asm("bx r2"); while(1); // should never get here }