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 Reply
  • OK. Thanks.  I've put a loop in the code and set a flag in the interrupt.  I'll test later and accept answer as fixed.

    {
    	...
    	wakeFlag = false;
    	while(false == wakeFlag)
    	{
    		sd_app_evt_wait();
    	}
    	...	
    }
    
    
    void InitTimers(void)
    {
        ret_code_t errorCode = app_timer_init();
        APP_ERROR_CHECK(errorCode);
    
        errorCode = app_timer_create(&theAdvTimer, APP_TIMER_MODE_REPEATED, AdvertisingInterrupt);
        APP_ERROR_CHECK(errorCode);
    }
    
    void AdvertisingInterrupt(void* context)
    {
        UNUSED_VARIABLE(context);
        SetWakeFlag();
    }
    
    void SetWakeFlag(void)
    {
        wakeFlag = true;
    }
    

    Shame to have to use a work-round but as long as it works then fine.

Children
No Data
Related