lpcware

Jump to the USB bootloader from user code

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
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?

Outcomes