Invoke bootloader in ISP mode on LPC2368

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

Reply to
maximb
Loading thread data ...

Do you disable interrupts (especially before any feed sequences, and entering the bootloader)?

Mike

Reply to
Michael Anton

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 }

Reply to
Mike Harrison

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.