I've seen a few post that have similar issues but none that solve my problem.
I have two uarts (uarte0 and uarte1).
I disable them before going to sleep.
I wake with a timer from sd_app_evt_wait() after 30 seconds.
If I fully disable the uarts using code from DevZone then the code bounces straight out of sd_app_evt_wait() and doesn't sleep.
If I don't fully disable them then the power consumption is too high (900uA rather than 20uA) but it does sleep properly.
By "fully" disable what i mean is using the fix I found in DevZone (shown below):
UARTE0 *(volatile uint32_t *)0x40002FFC = 0; *(volatile uint32_t *)0x40002FFC; *(volatile uint32_t *)0x40002FFC = 1; UARTE1 *(volatile uint32_t *)0x40028FFC = 0; *(volatile uint32_t *)0x40028FFC; *(volatile uint32_t *)0x40028FFC = 1;
I tried to see if there was a pending IRQ which was waking the system immediately using NVIC_GetPendingIRQ and the following appear set:
Reset_IRQn, HardFault_IRQn, UsageFault_IRQn, SysTick_IRQn
But attempting to clear them with sd_nvic_ClearPendingIRQ made no difference.
If I call sd_app_evt_wait() twice in succession then everything works fine.
Full code below:
{
DebugPrintf("Entering sleep\n\n");
EnterSleep();
/*
// HACK CODE SHOULDN'T BE REQUIRED
sd_nvic_ClearPendingIRQ(UARTE1_IRQn);
sd_nvic_ClearPendingIRQ(UARTE0_UART0_IRQn);
*/
/*
// HACK CODE TO GET PENDING IRQs
uint32_t irq_numA[63];
uint32_t irq_numB[63];
for(int x = -15; x < 48; x++)
{
irq_numA[x+15] = NVIC_GetPendingIRQ((IRQn_Type)x);
}*/
/*
// HACK CODE TO CLEAR PENDING IRQS - MAKES NO DIFFERENCE
sd_nvic_ClearPendingIRQ(Reset_IRQn);
sd_nvic_ClearPendingIRQ(NonMaskableInt_IRQn);
... etc...
sd_nvic_ClearPendingIRQ(UARTE0_UART0_IRQn);
... etc...
sd_nvic_ClearPendingIRQ(UARTE1_IRQn);
... etc...
*/
/*
// HACK CODE TO GET PENDING IRQs
for(int x = -15; x < 48; x++)
{
irq_numB[x+15] = NVIC_GetPendingIRQ((IRQn_Type)x);
}*/
// SLEEP - BOUNCES STRAIGHT OUT IF UARTEn FULLY DISABLED
sd_app_evt_wait();
// SLEEP - WORKS EVERY TIME
sd_app_evt_wait();
DebugPrintf("Exiting sleep\n");
ExitSleep();
}
void EnterSleep(void)
{
DbgUartDeInit();
RfUartDeInit();
}
void ExitSleep(void)
{
DbgUartInit();
RfUartInit();
}
void DbgUartInit(void)
{
/*
// CODE FROM DEVZONE TO FULLY DISABLE/ENABLE UARTE0
*(volatile uint32_t *)0x40002FFC = 1;
*/
NRF_UARTE0->TASKS_STARTTX = 1;
NRF_UARTE0->TASKS_STARTRX = 1;
NRF_UARTE0->ENABLE = 1;
ret_code_t errorCode = nrf_serial_init(&theSerial0.uarte, &theSerial0.drvConfig, &theSerial0.config);
if(NRF_ERROR_MODULE_ALREADY_INITIALIZED != errorCode)
{
APP_ERROR_CHECK(errorCode);
}
}
void DbgUartDeInit(void)
{
ret_code_t errorCode = nrf_serial_uninit(&theSerial0.uarte);
if(NRF_ERROR_MODULE_NOT_INITIALIZED != errorCode)
{
APP_ERROR_CHECK(errorCode);
NRF_UARTE0->TASKS_STOPTX = 1;
NRF_UARTE0->TASKS_STOPRX = 1;
NRF_UARTE0->ENABLE = 0;
/*
// CODE FROM DEVZONE TO FULLY DISABLE/ENABLE UARTE0
// COMMENTING THIS OUT MAKES sd_app_evt_wait() WORK BUT THE CURRENT CONSUMPTION GOES UP
*(volatile uint32_t *)0x40002FFC = 0;
*(volatile uint32_t *)0x40002FFC;
*(volatile uint32_t *)0x40002FFC = 1;
*/
}
}
void RfUartInit(void)
{
/*
// CODE FROM DEVZONE TO FULLY DISABLE/ENABLE UARTE1
*(volatile uint32_t *)0x40028FFC = 1;
*/
NRF_UARTE1->TASKS_STARTTX = 1;
NRF_UARTE1->TASKS_STARTRX = 1;
NRF_UARTE1->ENABLE = 1;
ret_code_t errorCode = nrf_serial_init(&theSerial1.uarte, &theSerial1.drvConfig, &theSerial1.config);
if(NRF_ERROR_MODULE_ALREADY_INITIALIZED != errorCode)
{
APP_ERROR_CHECK(errorCode);
}
}
void RfUartDeInit(void)
{
ret_code_t errorCode = nrf_serial_uninit(&theSerial1.uarte);
if(NRF_ERROR_MODULE_NOT_INITIALIZED != errorCode)
{
APP_ERROR_CHECK(errorCode);
NRF_UARTE1->TASKS_STOPTX = 1;
NRF_UARTE1->TASKS_STOPRX = 1;
NRF_UARTE1->ENABLE = 0;
/*
// CODE FROM DEVZONE TO FULLY DISABLE/ENABLE UARTE1
// COMMENTING THIS OUT MAKES sd_app_evt_wait() WORK BUT THE CURRENT CONSUMPTION GOES UP
*(volatile uint32_t *)0x40028FFC = 0;
*(volatile uint32_t *)0x40028FFC;
*(volatile uint32_t *)0x40028FFC = 1;
*/
}
}