Other Parts Discussed in Thread: INA188
Tool/software: Code Composer Studio
Hello,
We have an application which requires long battery life and infrequent use of the device. I'm implementing BLE5SimplePeripheral. Out of the box the CC2640r2 never enters Power_shutdown, rather it returns to advertising mode. This consumes 2+ mA RMS. I have implemented a button that can be used to wake-up the CC2640r2 and code following the pinShutdown example. The tread is shown here:
//****************************************************************************** // Includes //*****************************************************************************/ //#include <stdint.h> //#include <stddef.h> #include <xdc/std.h> #include <xdc/runtime/Error.h> //#include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Semaphore.h> #include <ti/sysbios/knl/Swi.h> #include "Board.h" #include <ti/drivers/GPIO.h> //#include <ti/drivers/Power.h> //#include <ti/drivers/power/PowerCC26XX.h> #include <ti/drivers/pin/PINCC26XX.h> #include <ti/devices/DeviceFamily.h> #include DeviceFamily_constructPath(inc/hw_prcm.h) #include DeviceFamily_constructPath(driverlib/sys_ctrl.h) //****************************************************************************** // Globals //*****************************************************************************/ /* Task and tast stack */ Task_Struct myTask; #define THREADSTACKSIZE 512 uint8_t myTaskStack[THREADSTACKSIZE]; /* Semaphore used to gate for shutdown */ Semaphore_Struct shutdownSem; /* Clock used for debounce logic */ Clock_Struct buttonClock; Clock_Handle hButtonClock; /* Pin driver handles */ PIN_Handle hPins; PIN_Handle hButtons; /* LED pin state */ PIN_State LedPinState; /* Button pin state */ PIN_State buttonState; /* Flag to store whether we woke up from shutdown or not */ bool isWakingFromShutdown; /* PIN_Id for active button (in debounce period) */ PIN_Id activeButtonPinId; /* Led pin table used when waking from reset. LED initially on*/ PIN_Config LedPinTable[] = { Board_BLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, PIN_TERMINATE }; /* Led pin table used when waking from shutdown. LED initially off */ PIN_Config LedPinTableSd[] = { Board_BLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, PIN_TERMINATE }; /* Wake-up Button pin table */ PIN_Config ButtonTableWakeUp[] = { Board_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE, PIN_TERMINATE }; /* Shutdown Button pin table */ PIN_Config ButtonTableShutdown[] = { Board_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE, PIN_TERMINATE }; /*!***************************************************************************** * @brief Button clock callback * * Called when the debounce periode is over. Stopping the clock, toggling * the device mode based on activeButtonPinId. Board_BTN1 will put the device * in shutdown mode. Reenabling the interrupts and resetting the activeButtonPinId. * * @param arg argument (PIN_Handle) connected to the callback * * @return none * ******************************************************************************/ static void buttonClockCb(UArg arg) { PIN_Handle buttonHandle = (PIN_State *) arg; /* Stop the button clock */ Clock_stop(hButtonClock); /* Check that there is active button for debounce logic*/ if (activeButtonPinId != PIN_TERMINATE) { /* Debounce logic, only toggle if the button is still pushed (low) */ if (!PIN_getInputValue(activeButtonPinId)) { /* Toggle LED based on the button pressed */ switch (activeButtonPinId) { case Board_PIN_BUTTON1: Semaphore_post(Semaphore_handle(&shutdownSem)); break; default: /* Do nothing */ break; } } } /* Re-enable interrupts to detect button release. */ PIN_setConfig(buttonHandle, PIN_BM_IRQ, activeButtonPinId | PIN_IRQ_NEGEDGE); /* Set activeButtonPinId to none... */ activeButtonPinId = PIN_TERMINATE; } /*!***************************************************************************** * @brief Button callback * * Initiates the debounce period by disabling interrupts, setting a timeout * for the button clock callback and starting the button clock. * Sets the activeButtonPinId. * * @param handle PIN_Handle connected to the callback * * @param pinId PIN_Id of the DIO triggering the callback * * @return none ******************************************************************************/ static void buttonCb(PIN_Handle handle, PIN_Id pinId) { /* Set current pinId to active */ activeButtonPinId = pinId; /* Disable interrupts during debounce */ PIN_setConfig(handle, PIN_BM_IRQ, activeButtonPinId | PIN_IRQ_DIS); /* Set timeout 50 ms from now and re-start clock */ Clock_setTimeout(hButtonClock, (50 * (1000 / Clock_tickPeriod))); Clock_start(hButtonClock); } /*!***************************************************************************** * @brief wakeUpTread used to construct power up thread * * @param none * * @return none ******************************************************************************/ void wakeUpThread(UArg a0, UArg a1) { uint32_t rSrc = SysCtrlResetSourceGet(); Board_initGeneral(); /* Do pin init before starting BIOS */ /* If coming from shutdown, use special gpio table.*/ if (rSrc == RSTSRC_WAKEUP_FROM_SHUTDOWN) { isWakingFromShutdown = true; hPins = PIN_open(&LedPinState, LedPinTableSd); } else { isWakingFromShutdown = false; hPins = PIN_open(&LedPinState, LedPinTable); } /* Setup button pins with ISR */ hButtons = PIN_open(&buttonState, ButtonTableShutdown); PIN_registerIntCb(hButtons, buttonCb); /* Construct clock for debounce */ Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg)hButtons; Clock_construct(&buttonClock, buttonClockCb, 0, &clockParams); hButtonClock = Clock_handle(&buttonClock); /* If we are waking up from shutdown, toggle BLED several times. */ if (isWakingFromShutdown) { uint32_t sleepUs = 500000; Task_sleep(sleepUs / Clock_tickPeriod); PIN_setOutputValue(hPins, Board_BLED, 0); Task_sleep(sleepUs / Clock_tickPeriod); PIN_setOutputValue(hPins, Board_BLED, 1); Task_sleep(sleepUs / Clock_tickPeriod); PIN_setOutputValue(hPins, Board_BLED, 0); Task_sleep(sleepUs / Clock_tickPeriod); PIN_setOutputValue(hPins, Board_BLED,1); Task_sleep(sleepUs / Clock_tickPeriod); PIN_setOutputValue(hPins, Board_BLED, 0); Task_sleep(sleepUs / Clock_tickPeriod); } /* Turn on LED0 to indicate active */ PIN_setOutputValue(hPins, Board_BLED, 1); /* Pend on semaphore before going to shutdown */ //Semaphore_pend(Semaphore_handle(&shutdownSem), BIOS_WAIT_FOREVER); /* Turn off BLED */ PIN_setOutputValue(hPins, Board_BLED, 0); /* Configure DIO for wake up from shutdown */ PINCC26XX_setWakeup(ButtonTableWakeUp); /* Go to shutdown */ // (0, 0); /* Should never get here, since shutdown will reset. */ while (1); } /* wakeUpThread_create. */ void wakeUpThread_create(void) { Task_Params taskParams; //Configure task Task_Params_init(&taskParams); taskParams.stack = myTaskStack; taskParams.stackSize = sizeof(myTaskStack); taskParams.priority = 1; Task_construct(&myTask, wakeUpThread, &taskParams, NULL); }
I declare the extern in main here:
and call wakeUpThread_create in main here:
Finally my questions is where in simplePeripheral or main should I call Power_shutdown(0, 0) if the device fails to connect (or becomes disconnected) for some period of time, say 90 seconds?
Thanks in advance,
Patrick