Skip to content

Commit

Permalink
Enter ISP mode on lpc11u35 if button held on boot
Browse files Browse the repository at this point in the history
If the reset button is held on boot then enter ISP mode manually.
This allows devices without the ISP pin wired up to enter ISP mode.

Also add a delay before reading the reset button to make sure board
voltages have stabilized before reading the reset button.  This
prevents the Switch Science LPC824 from occasionally entering ISP
mode when initially connected.
  • Loading branch information
c1728p9 committed Feb 24, 2016
1 parent fc33466 commit 0a19970
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions source/hif_hal/nxp/lpc11u35/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,57 @@ COMPILER_ASSERT(DAPLINK_HIF_ID == DAPLINK_HIF_ID_LPC11U35);
#define PIN_MSD_LED (1<<20)
#define PIN_CDC_LED (1<<11)


// taken code from the Nxp App Note AN11305
/* This data must be global so it is not read from the stack */
typedef void (*IAP)(uint32_t [], uint32_t []);
static IAP iap_entry = (IAP)0x1fff1ff1;
static uint32_t command[5], result[4];
#define init_msdstate() *((uint32_t *)(0x10000054)) = 0x0

/* This function resets some microcontroller peripherals to reset
hardware configuration to ensure that the USB In-System Programming module
will work properly. It is normally called from reset and assumes some reset
configuration settings for the MCU.
Some of the peripheral configurations may be redundant in your specific
project.
*/
void ReinvokeISP(void)
{
/* make sure USB clock is turned on before calling ISP */
LPC_SYSCON->SYSAHBCLKCTRL |= 0x04000;
/* make sure 32-bit Timer 1 is turned on before calling ISP */
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00400;
/* make sure GPIO clock is turned on before calling ISP */
LPC_SYSCON->SYSAHBCLKCTRL |= 0x00040;
/* make sure IO configuration clock is turned on before calling ISP */
LPC_SYSCON->SYSAHBCLKCTRL |= 0x10000;

/* make sure AHB clock divider is 1:1 */
LPC_SYSCON->SYSAHBCLKDIV = 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(*((volatile 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!
}

static void busy_wait(uint32_t cycles)
{
volatile uint32_t i;
i = cycles;
while (i > 0) i--;
}

void gpio_init(void) {
// enable clock for GPIO port 0
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6);
Expand Down Expand Up @@ -62,6 +113,21 @@ void gpio_init(void) {

/* Enable AHB clock to the FlexInt, GroupedInt domain. */
LPC_SYSCON->SYSAHBCLKCTRL |= ((1<<19) | (1<<23) | (1<<24));

// Give the cap on the reset button time to charge
busy_wait(10000);

if (gpio_get_sw_reset() == 0) {
IRQn_Type irq;
// Disable SYSTICK timer and interrupt before calling into ISP
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
// Disable all nvic interrupts
for (irq = (IRQn_Type)0; irq < (IRQn_Type)32; irq++) {
NVIC_DisableIRQ(irq);
NVIC_ClearPendingIRQ(irq);
}
ReinvokeISP();
}
}

void gpio_set_hid_led(gpio_led_state_t state) {
Expand Down

0 comments on commit 0a19970

Please sign in to comment.