This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Jump straight out of sleep (sd_app_evt_wait) when fully disable uarte0 and uarte1

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;
		*/
    }
}

Parents
  • Hi,

    Please try to read out the NVIC->ISPR[0] and the NVIC->ISPR[1] register directly instead of looping through each bit with NVIC_GetPendingIRQ(). The should both read as zero if there are no pending interrupts.

    I'm not exactly sure why your "for loop" iteration isn't working, but it would not make sense for the reset and fault exceptions to be pending then have the program successfully enter sleep on the next call to sd_app_evt_wait(). 

Reply
  • Hi,

    Please try to read out the NVIC->ISPR[0] and the NVIC->ISPR[1] register directly instead of looping through each bit with NVIC_GetPendingIRQ(). The should both read as zero if there are no pending interrupts.

    I'm not exactly sure why your "for loop" iteration isn't working, but it would not make sense for the reset and fault exceptions to be pending then have the program successfully enter sleep on the next call to sd_app_evt_wait(). 

Children
Related