lpcware

LPC11U14 is drawing too much current (200uA) in Power Down mode due to floating D+/D- USB signals

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 18, 2016 by lpcware
Content originally posted in LPCWare by scottwild65 on Mon May 09 19:06:58 MST 2016
Greetings.

I am building a battery powered device that uses the LPC11U14 as a UART to USB bridge.  When not being used (i.e. USB not plugged in), I put it the LPC11U14 into Power Down mode so that it doesn’t drain the battery.

My problem is that the LPC11U14 still draws around 200uA when in power down mode instead of the 2uA specified in the data sheet.

To debug the problem, I created a bare-minimum firmware project and I removed all components from my circuit board except for the LPC11U14 and a few support components (an LDO and a few resistors).  All signals are unused except for a couple that have an external 10k pulldown resistor on them.  I disable the internal pullups on those signals to prevent the ~50uA current draw they would incur.

My code essentially configures the watchdog timer to run off of the watchdog oscillator and trigger the watchdog interrupt every second or so.  It then places the LPC11U14 into Power Down mode except for when the watchdog interrupt is being handled.  I can then look at the current draw on my scope using a low-current probe.  What I see is a 200uA current draw baseline with a 300us pulse of a few mA when the WDT interrupt is being handled.

If I repeat the experiment but go into Deep Power Down mode, the current drops to almost nothing (but doesn’t wake up since WDT won’t wake up in that mode).

Do you have any ideas why I’m drawing so much current in Power Down mode?

Thank you
Scott Wild



Here is my code:

#include <stdio.h>
#include <string.h>
#include "chip.h"
#include "common.h"

const unsigned int OscRateIn = 12000000;

//***************************************************************************
//
//***************************************************************************
void SystemInit( )
{
}

//***************************************************************************
//
//***************************************************************************
int main( )
{
volatile int wdtFreq;

// Enable Watchdog timer
SystemCoreClockUpdate();
Chip_WWDT_Init(LPC_WWDT);
Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_WDTOSC_PD);
Chip_Clock_SetWDTOSC(WDTLFO_OSC_1_05, 20); // 50 KHz WDT oscillator (1MHz / 20)
Chip_WWDT_SelClockSource(LPC_WWDT, WWDT_CLKSRC_WATCHDOG_WDOSC); // Choose watchdog oscillator
wdtFreq = Chip_Clock_GetWDTOSCRate() / 4;
Chip_WWDT_SetTimeOut(LPC_WWDT, wdtFreq ); // Feed time const ~1s
//Chip_WWDT_SetOption(LPC_WWDT, WWDT_WDMOD_LOCK); // Interrupt on timeout
Chip_WWDT_ClearStatusFlag(LPC_WWDT, WWDT_WDMOD_WDTOF | WWDT_WDMOD_WDINT); // Clear watchdog warning and timeout interrupts
NVIC_ClearPendingIRQ(WDT_IRQn);// Clear and enable watchdog interrupt
NVIC_EnableIRQ(WDT_IRQn);
Chip_WWDT_Start(LPC_WWDT);// Start watchdog

// Power down and wakeup setup
Chip_SYSCTL_SetDeepSleepPD( SYSCTL_DEEPSLP_BOD_PD ); // Power down Brownout Detector but not WDT oscillator
Chip_SYSCTL_EnablePeriphWakeup( SYSCTL_WAKEUP_WWDTINT ); // Wake up on watchdog interrupt
Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD | SYSCTL_SLPWAKE_IRC_PD | SYSCTL_SLPWAKE_FLASH_PD));

// Set up IO pins
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
Chip_IOCON_PinMuxSet( LPC_IOCON, 0, 3, IOCON_FUNC0 | IOCON_MODE_INACT); // PIO0_3/USB_VBUS has an external pulldown, so I disable the internal pullup
Chip_IOCON_PinMuxSet( LPC_IOCON, 0, 10, IOCON_FUNC1 | IOCON_MODE_INACT); // SWCLK has an external pulldown, so I disable the internal pullup

while( 1 )
{
// Go into powerdown mode until the next watchdog interrupt occurs (about one second)
Chip_PMU_PowerDownState( LPC_PMU );
}
}

//***************************************************************************
// WDT is only used to periodically wake from PowerDown to check if we need to wake up
//***************************************************************************
void WDT_IRQHandler(void)
{
uint32_t wdtStatus = Chip_WWDT_GetStatus(LPC_WWDT);

// Handle warning interrupt
if (wdtStatus & WWDT_WDMOD_WDINT)
{
// A watchdog feed didn't occur prior to warning timeout
Chip_WWDT_ClearStatusFlag(LPC_WWDT, WWDT_WDMOD_WDINT);
Chip_WWDT_Feed(LPC_WWDT);
}
}

Outcomes