Jump to the USB bootloader from user code

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Jump to the USB bootloader from user code

996 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by psatyshur on Sun Nov 17 10:20:21 MST 2013
I am using LPCOpen v2 on an LPC11u37 device. I am trying to write a function that can be called by my code that will reset the device into the USB bootloader. I started with the example code here (http://www.nxp.com/documents/application_note/AN11305.zip) in the autoisp_11U section. Based on this code, I modified their functions to be compatible with the LPCOpen.

uint32_t command[5], result[4];
#define init_msdstate() *((uint32_t *)(0x10000054)) = 0x0

void ReinvokeISP(void)
{
vPortEnterCritical();
WDTInit();

  /* make sure USB clock is turned on before calling ISP */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);
  /* make sure 32-bit Timer 1 is turned on before calling ISP */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CT32B1);
  /* make sure GPIO clock is turned on before calling ISP */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO);
  /* make sure IO configuration clock is turned on before calling ISP */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);

  /* make sure AHB clock divider is 1:1 */
Chip_Clock_SetSysClockDiv(1);

  /* Send Reinvoke ISP command to ISP entry point*/
  command[0] = 57;

  init_msdstate(); /* Initialize Storage state machine */
  /* Set stack pointer to ROM value (reset default) This must be the last
     piece of code executed before calling ISP, because most C expressions
     and function returns will fail after the stack pointer is changed. */
  __set_MSP(*((uint32_t *)0x00000000));

  /* Enter ISP. We call "iap_entry" to enter ISP because the ISP entry is done
     through the same command interface as IAP. */
  iap_entry(command, result);
  // Not supposed to come back!
}

void WDTInit( void )
{
uint32_t i;
uint32_t wdtFreq;

/* Initialize WWDT (also enables WWDT clock) */
Chip_WWDT_Init(LPC_WWDT);

/* Prior to initializing the watchdog driver, the clocking for the
   watchdog must be enabled. This example uses the watchdog oscillator
   set at a 50KHz (1Mhz / 20) clock rate. */
Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_WDTOSC_PD);
Chip_Clock_SetWDTOSC(WDTLFO_OSC_1_05, 20);

/* The WDT divides the input frequency into it by 4 */
wdtFreq = Chip_Clock_GetWDTOSCRate() / 4;

/* LPC1102/4, LPC11XXLV, and LPC11CXX devices select the watchdog
   clock source from the SYSCLK block, while LPC11AXX, LPC11EXX, and
   LPC11UXX devices select the clock as part of the watchdog block. */
/* Select watchdog oscillator for WDT clock source */
Chip_WWDT_SelClockSource(LPC_WWDT, WWDT_CLKSRC_WATCHDOG_WDOSC);

Chip_WWDT_SetTimeOut(LPC_WWDT, 0x7FFF);
Chip_WWDT_SetOption(LPC_WWDT, (WWDT_WDMOD_WDEN|WWDT_WDMOD_WDRESET));
Chip_WWDT_Feed(LPC_WWDT);

/* Make sure feed sequence executed properly */
for (i = 0; i < 0x80; i++);

return;
}


I don't think the watchdog function is needed, but I included it for completeness. An astute observer may note that I call a FreeRTOS function at the beginning of the ReinvokeISP() function. I am running FreeRTOS if that matters.

This code does not seem to have the desired effect. When I call the ReinvokeISP() function, it breaks the USB functionality of the device (a USB CDC device), but does not start the USB bootloader. How is this function supposed to work? I was expecting the CDC device to disappear and a MSC device to appear with the firmware.bin file. Is there any easier way to do this?
Labels (1)
0 Kudos
7 Replies

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by alany on Thu Mar 20 14:43:02 MST 2014
I worked it out...  The 11U24 bootloader ROM requires a different RAM range reservation.

0x1000017C - 0x1000025B

0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by alany on Wed Mar 19 23:21:22 MST 2014
I've been trying to do the same thing on the 11U24 and it doesn't seem to work.

When I use the same code on an 11U37 it works fine.  I assume there is some difference with the RAM usage of the ROM code?  Is that magic 0x10000054 offset getting zeroed or the RAM region to reserve for the bootloader different on the 11U24?
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Muis on Thu Feb 13 12:43:05 MST 2014
Okay, I finally found the problem..

I was calling:

   __disable_irq(); (which executes ASM "cpsid i" behind the scenes)

right before ReinvokeISP().

Removing that line solved the problem and USB bootloader works fine. Also the IRCOUT has to be powered (which the example doesnt do). However, in all documentation it is mentioned that you should disable interrupts before entering ISP mode, so Im still not sure why this could cause any problem.

0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Muis on Thu Feb 13 11:48:42 MST 2014
I'm 100% sure that the VBUS is high, and I'm using the exact same code from AN11305. Also other IAP calls work fine, just ReinvokeISP has no effect. I'm running the SystemCoreClock at 48 Mhz before entering ISP, is that correct? Do you know of any other mis-configuration that could prevent the MCU from executing the bootloader?
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ratiafak on Thu Feb 13 05:13:29 MST 2014
I tested it on LPC11U35 with custom board.
Reinvoke ISP is copied from AN11305 (there is link above).
The ISP should sample USB VBUS (perhaps PIO0_3?) and init USB or UART accordingly. I would look if you really have high level on VBUS.
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Muis on Thu Feb 13 04:43:29 MST 2014
I can't get this to work on a LPC11U3xx, it seems it invokes the UART bootloader instead of the USB MSC one.

Can you tell me on which model you tested this, and what your ReinvokeISP contains exactly?
0 Kudos

732 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ratiafak on Tue Feb 11 08:16:30 MST 2014
Try to reset the chip before invoking ISP. I stored some constant to SRAM1 and immediatelly after reset I reinvoke ISP or continue to work normally.
When I want to go to ISP:
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 26);//enable SRAM1
*((uint32_t *)(0x20000000)) = 0x12345678;
NVIC_SystemReset();

and at the top of main:
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 26);//enable SRAM1
if(*((uint32_t *)(0x20000000)) == 0x12345678)//stored by interrupt before reset
{
ReinvokeISP();//Jump to USB ISP bootloader
}
0 Kudos