This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2650: Problem with multiple wakeup pins on the CC2650

Part Number: CC2650

Tool/software: TI-RTOS

Hello

I still have the same problem on my projects.

I think the problem is present when there are 2 waking pins.

What I observe: in order for the product to come out of standby, pin 1 must be grounded and there must be a falling edge on pin 2.

I will like a different behavior. I want the product to come out of standby if the pin 1 to a falling edge or pin 2 to a falling edge.

I want to replace the AND with an OR.

Thanks for your help.

best regards

I enclose the code used

#include "gatt.h"
#include "gattservapp.h"
#include "SensorUtil.h"

#include "board.h"

#include <ti/drivers/pin/PINCC26XX.h>

#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Task.h>

#include "string.h"
/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

// Task configuration
#define SENSOR_TASK_PRIORITY    1
#define SENSOR_TASK_STACK_SIZE  600

 /*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
static PIN_Config SensortagAppPinTable[] =
{
    Board_LED1       | PIN_GPIO_OUTPUT_EN   | PIN_GPIO_LOW  | PIN_PUSHPULL      | PIN_DRVSTR_MAX,               /* LED initially off             */
    Board_LED2       | PIN_GPIO_OUTPUT_EN   | PIN_GPIO_LOW  | PIN_PUSHPULL      | PIN_DRVSTR_MAX,               /* LED initially off             */
    Board_KEY_LEFT   | PIN_INPUT_EN         | PIN_PULLUP    | PIN_HYSTERESIS    | PINCC26XX_WAKEUP_NEGEDGE,                                   /* Button is active low          */
    Board_KEY_RIGHT  | PIN_INPUT_EN         | PIN_PULLUP    | PIN_HYSTERESIS    | PINCC26XX_WAKEUP_NEGEDGE,     /* Button is active low          */

    PIN_TERMINATE
};

PIN_Handle HandleGpioPin;
PIN_State PinGpioState;
/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

// Task setup
static Task_Struct sensorTask;
static Char sensorTaskStack[SENSOR_TASK_STACK_SIZE];

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void sensorTaskFxn(UArg a0, UArg a1);

/*********************************************************************
 * PROFILE CALLBACKS
 */


/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SensorTagBar_createTask
 *
 * @brief   Task creation function for barometer sensor
 *
 * @param   none
 *
 * @return  none
 */
void SensorTagTest_createTask(void)
{
    Task_Params taskParames;

    // Create the task for the state machine
    Task_Params_init(&taskParames);
    taskParames.stack = sensorTaskStack;
    taskParames.stackSize = SENSOR_TASK_STACK_SIZE;
    taskParames.priority = SENSOR_TASK_PRIORITY;

    Task_construct(&sensorTask, sensorTaskFxn, &taskParames, NULL);
}


/*********************************************************************
* Private functions
*/


/*********************************************************************
 * @fn      sensorTaskFxn
 *
 * @brief   The task loop of the humidity readout task
 *
 * @return  none
 */
static void sensorTaskFxn(UArg a0, UArg a1)
{
    HandleGpioPin = PIN_open(&PinGpioState, SensortagAppPinTable);
  
    // Task loop
    while (true)
    {
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 1);
        DELAY_MS(500);  
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 0);
        DELAY_MS(500); 
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 1);
        DELAY_MS(500);  
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 0);
        DELAY_MS(500); 
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 1);
        DELAY_MS(500);  
        PIN_setOutputValue(HandleGpioPin,Board_LED1, 0);
        DELAY_MS(500); 
        
        /* Configure DIO for wake up from shutdown */
        PINCC26XX_setWakeup(SensortagAppPinTable);
            
        /* Go to shutdown */
        Power_shutdown(NULL, 0);

    }
}

  • Hello User,

    The way the WUC (Wake up controller) works is by setting 1-4 sources to wake up from, and these signals all OR together. See page 240 of the technical reference manual: www.ti.com/.../swcu117h.pdf

    I suggest you go into debug mode and look at this register: MCUWUSEL Register and make sure that the two pins are registered as individual events rather than on one single event.

    Regards,
    AB
  • Hello.

    I observed the MCUWUSEL register just befor the Power_shutdown(NULL, 0).

    there is something strange. 

    the values are : 

    WU3_EV = 0x3F ==> OK i think is normal 

    WU2_EV = 0x3F ==> OK i think is normal

    WU1_EV = 0x20 ==> I think is not normal because we want to wake up on pin 0 and 4.

    WU0_EV = 0x23.

    Are I forgetting to do something ?

    Thanks

  • Hello.

    I still have my problem.
    could anyone have looked at the value of my register?

    Thanks

  • Hello user,

    You are correct, that register value is wrong. I beleive the problem is your setWakeup call.

    Try the following

    static PIN_Config SensortagAppPinTable[] =
    {
        Board_LED1       | PIN_GPIO_OUTPUT_EN   | PIN_GPIO_LOW  | PIN_PUSHPULL      | PIN_DRVSTR_MAX,               /* LED initially off             */
        Board_LED2       | PIN_GPIO_OUTPUT_EN   | PIN_GPIO_LOW  | PIN_PUSHPULL      | PIN_DRVSTR_MAX,               /* LED initially off             */
    
        PIN_TERMINATE
    };
    static PIN_Config wakeupPinTable[] =
    {
        Board_KEY_LEFT   | PIN_INPUT_EN         | PIN_PULLUP       | PINCC26XX_WAKEUP_NEGEDGE, 
        Board_KEY_RIGHT  | PIN_INPUT_EN         | PIN_PULLUP       | PINCC26XX_WAKEUP_NEGEDGE,  
    
        PIN_TERMINATE
    };
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
        /* Configure DIO for wake up from shutdown */
        PINCC26XX_setWakeup(wakeupPinTable);
    
        /* Go to shutdown */
        Power_shutdown(0, 0);
    .
    .
    .
    .
    .
    .
    .
    

  • Hello.

    I tested your modification but I still have the same problem.

    the registers are always at the same value

    I join you standard functions if I ever have a problem in my stack version

    Tanks

    // Internal utility function for setting IOCFG register for pin
    static void PINCC26XX_setIoCfg(PIN_Config bmMask, PIN_Config pinCfg) {
        uint32_t dsCfg;
        PIN_Id pinId = PIN_ID(pinCfg);
        bool bInvChanges;
    
        if (pinCfg&PIN_GEN) {
            // Translate from device-independent to device-specific PIN_Config values
            pinCfg ^= PIN_GEN|PIN_BM_INPUT_EN|PIN_BM_PULLING;
        }
        // Get existing IOCFG, determine whether inversion changes, mask away what will be updated
        dsCfg = HWREG(IOC_BASE+IOC_O_IOCFG0+4*pinId);
        bInvChanges = (dsCfg^pinCfg)&bmMask&PINCC26XX_INV_INOUT;
        dsCfg &= ~bmMask;
    
        // Insert what we want to update, possibly revert IRQ edges, write back to IOCFG
        dsCfg |= (pinCfg&bmMask&PINCC26XX_BM_IOCFG);
        if ((bmMask&PINCC26XX_BM_IRQ)==PINCC26XX_BM_IRQ && (dsCfg&PINCC26XX_INV_INOUT)==0) {
            // We're changing IRQ options but inversion will not be enabled -> keep IRQ options
        } else if ((bmMask&PINCC26XX_BM_IRQ)==0 && !bInvChanges) {
            // We're not changing IRQ options and inversion remains unchanged -> keep IRQ options
        } else {
            // We're updating IRQ options and inversion will be enabled, OR
            // we're not updating IRQ options but inversion settings change
            // -> reverse polarity of edge detection when positive-only or negative-only
            switch (dsCfg&PINCC26XX_BM_IRQ) {
            case PINCC26XX_IRQ_POSEDGE:
                dsCfg &= ~PINCC26XX_BM_IRQ;
                dsCfg |= PINCC26XX_IRQ_NEGEDGE;
                break;
            case PINCC26XX_IRQ_NEGEDGE:
                dsCfg &= ~PINCC26XX_BM_IRQ;
                dsCfg |= PINCC26XX_IRQ_POSEDGE;
                break;
            default:
                break;
            }
        }
        HWREG(IOC_BASE+IOC_O_IOCFG0+4*pinId) = dsCfg;
    
        // Update GPIO output value and enable
        if (bmMask&PINCC26XX_BM_GPIO_OUTPUT_VAL) {
            // Set GPIO output value
            HWREGB(GPIO_BASE+GPIO_O_DOUT3_0+pinId) = (pinCfg&PINCC26XX_BM_GPIO_OUTPUT_VAL) ? 1 : 0;
        }
        if (bmMask&PINCC26XX_BM_GPIO_OUTPUT_EN) {
            // Set GPIO output enable
            uint32_t key = Hwi_disable();
                HWREG(GPIO_BASE+GPIO_O_DOE31_0) =
                    (HWREG(GPIO_BASE+GPIO_O_DOE31_0) & ~(1<<pinId)) |
                    ((pinCfg&PINCC26XX_BM_GPIO_OUTPUT_EN) ? (1<<pinId) : 0);
            Hwi_restore(key);
        }
    }

    PIN_Status PINCC26XX_setWakeup(const PIN_Config aPinCfg[]) {
        uint_t i;
        // TODO: is this enough?
    
        for (i=0; PIN_ID(aPinCfg[i])!=PIN_TERMINATE; i++) {
            PINCC26XX_setIoCfg(PINCC26XX_BM_ALL, aPinCfg[i]);
        }
        return PIN_SUCCESS;
    }

  • Hello user,

    Iv'ed verified that this code works like it should, and how you want it to.

    Once the device goes into shutdown mode, it will start up again once it detects a falling edge on DIO13 OR DIO14.

    I tested this successfully and the WUEV rgisters look like this:

    WU3_EV = 0x3F

    WU2_EV = 0x3F

    WU1_EV = 0x20

    WU0_EV = 0x23

    The IOC registers look like this:

    IOCFG13 = 0x30004000

    IOCFG14 = 0x30004000

    My code looks like this:

    //*****************************************************************************
    //! @file       pinShutdown.c
    //! @brief      Pin shutdown example.
    //!
    //  Copyright (C) 2015-2018 Texas Instruments Incorporated - http://www.ti.com/
    //
    //
    //  Redistribution and use in source and binary forms, with or without
    //  modification, are permitted provided that the following conditions
    //  are met:
    //
    //    Redistributions of source code must retain the above copyright
    //    notice, this list of conditions and the following disclaimer.
    //
    //    Redistributions in binary form must reproduce the above copyright
    //    notice, this list of conditions and the following disclaimer in the
    //    documentation and/or other materials provided with the distribution.
    //
    //    Neither the name of Texas Instruments Incorporated nor the names of
    //    its contributors may be used to endorse or promote products derived
    //    from this software without specific prior written permission.
    //
    //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    //  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    //  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    //  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    //  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    //  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    //  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    //  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    //  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    //  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    //  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //****************************************************************************/
    
    //******************************************************************************
    //! The example will cycle the device between active mode and shutdown mode.
    //! The cycling is controlled by pin interrupts, i.e. buttons.
    //!
    //! The mapping is:
    //!             Board_PIN_BUTTON0 will wake up the chip to active mode.
    //!             Board_PIN_BUTTON1 will put the device in shutdown mode.
    //!
    //! The example is using a simple debounce logic, so it does not support
    //! multiple buttons pushed at the same time.
    //!
    //! The debounce work like this: When the pin interrupt is triggered, a button
    //! clock is configured to trigger 50 ms ahead in time. After 50 ms, when the
    //! clock interrupt is triggered, the LED connected to the active/pushed button
    //! will be inverted if the button is still pushed.
    //*****************************************************************************/
    
    //******************************************************************************
    // Includes
    //*****************************************************************************/
    #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/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;
    Char myTaskStack[512];
    
    /* 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*/
    PIN_Config LedPinTable[] = {
        Board_PIN_LED1    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
        Board_PIN_LED0    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially on */
        PIN_TERMINATE                                                    /* Terminate list */
    };
    
    /* Led pin table used when waking from shutdown */
    PIN_Config LedPinTableSd[] = {
        Board_PIN_LED1    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially on */
        Board_PIN_LED0    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
        PIN_TERMINATE                                                    /* Terminate list */
    };
    
    /* Wake-up Button pin table */
    PIN_Config ButtonTableWakeUp[] = {
        Board_PIN_BUTTON0     | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
        Board_PIN_BUTTON1     | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
        PIN_TERMINATE                                 /* Terminate list */
    };
    
    /*!*****************************************************************************
     *  @brief      Task which runs when the device is active
     *
     *  @param      UArg a0 : User argument that can be passed to the task
     *
     *  @param      UArg a1 : User argument that can be passed to the task
     *
     *  @return     none - Should never return
     ******************************************************************************/
    static void taskFxn(UArg a0, UArg a1)
    {
        /* If we are waking up from shutdown, we do something extra. */
        if (isWakingFromShutdown) {
            /* In this example we toggle LED1 */
            uint32_t sleepUs = 500000;
            Task_sleep(sleepUs / Clock_tickPeriod);
            PIN_setOutputValue(hPins, Board_PIN_LED1, 0);
            Task_sleep(sleepUs / Clock_tickPeriod);
            PIN_setOutputValue(hPins, Board_PIN_LED1, 1);
            Task_sleep(sleepUs / Clock_tickPeriod);
            PIN_setOutputValue(hPins, Board_PIN_LED1, 0);
            Task_sleep(sleepUs / Clock_tickPeriod);
        }
    
        /* Turn on LED0 to indicate active */
        PIN_setOutputValue(hPins, Board_PIN_LED0, 1);
    
        /* Turn off LED0 */
        PIN_setOutputValue(hPins, Board_PIN_LED0, 0);
    
        /* Configure DIO for wake up from shutdown */
        PINCC26XX_setWakeup(ButtonTableWakeUp);
    
        /* Go to shutdown */
        Power_shutdown(0, 0);
    
        /* Should never get here, since shutdown will reset. */
        while (1);
    }
    
    /*!*****************************************************************************
     *  @brief      Application main entry point
     *
     *  @param      none
     *
     *  @return     int - Should never return
     ******************************************************************************/
    int main(void)
    {
         /* Locals */
        Task_Params taskParams;
    
        /* Get the reason for reset.
         * On CC26X2, SysCtrlResetSourceGet() must be called before
         * PIN_init() because unlatching the IOs will clear the
         * wakeup from shutdown bit.
         */
        uint32_t rSrc = SysCtrlResetSourceGet();
    
        /* Call driver init functions */
        Board_init();
    
        /* Do pin init before starting BIOS */
        /* If coming from shutdown, use special gpio table.*/
        if (rSrc == RSTSRC_WAKEUP_FROM_SHUTDOWN) {
            /* The shutdown table has LED1 on to ensure no glitch on the
             * output.
             */
            isWakingFromShutdown = true;
            /* Open LED pins with shutdown table (LED1 on, LED0 off).
             * A separate PIN_config table is used to keep LED1 on.
             */
            hPins = PIN_open(&LedPinState, LedPinTableSd);
        } else {
            /* When not waking from shutdown, use default init table. */
            isWakingFromShutdown = false;
            /* Open LED pins (LED1 off, LED0 on)*/
            hPins = PIN_open(&LedPinState, LedPinTable);
        }
    
        /* Configure task. */
        Task_Params_init(&taskParams);
        taskParams.stack = myTaskStack;
        taskParams.stackSize = sizeof(myTaskStack);
        Task_construct(&myTask, taskFxn, &taskParams, NULL);
    
        /* Start kernel. */
        BIOS_start();
    
        /* Should never get here, keep compiler happy */
        return (0);
    }
    

  • Hello

    Thanks for your test. 

    can you test that : 

    1- press and hold one button when going to sleep.

    2- while keeping the button pressed, try to wake up the product with the other button

    Thanks for your feedback

  • Hello AB

    Have you done the test? 

    Thanks

  • Hello,

    Yes, I tested this particular case and I have taken multiple other actions to try and fix this behavior.

    I am trying to understand what is going on, but it is hard to understand the problem since the device is in shutdown and I cannot debug.

    give some more time to see exactly what is causing this behavior.

    Regards,
    AB
  • Hello

    if I understood correctly, you reproduced my problem?

    I leave you to work on the subject and I will contact our French FAE to organize the schedule.

    Thank you
    and keep me informed

  • Hello

    Have you ways to solve the problem. let me know.

    Thank you

  • Hello,

    Th information gathered by me has been passed down to the team responsible for HW issues, and they will contact you as soon as they find a solution or explanation for this problem.

    Regards,
    AB
  • Hi,
    I appologize for the late answer here. We are still looking into what is causing the behaviour you see. Most likely, this is simply how the HW works, in which case there may not be any alternative work-arounds.

    Do you see the same behaviour when going to Standby instead of Shutdown? What happens if you only configure one pin as wake-up source and hold this low while entering Shutdown?

    Regards,
    Fredrik
  • Hello.

    I did the test with a single wake-up PIN.

    The product remains in standby during key press, and wakes up when release.

    for the test with standby mode instead of Shutdown. can you tell me what function to use in place of 

    /* Configure DIO for wake up from shutdown */
    PINCC26XX_setWakeup(SensortagWakeUpPinTable);

    /* Go to shutdown */
    Power_shutdown(0, 0);

    Have you seen the post of Eirik V, he seems to have an answer.

    Thanks

  • Hi, I can confirm that Eirik V´s post is the answer to this, and what you see is expected behaviour from the HW. As Eirik writes, one solution could be to poll the states of the pins before entering Shutdown.

    Regards,
    Fredrik
  • Unfortunately I have already tried this solution.
    but my wake up pin is plugged into an accelerator that is at a fast rate. therefore between the moment of the reading loop of the PIN and the real shutdown it is possible that the accelerator changes state.
    In this case I fall back into the problem.
    Thanks
  • Hi,
    Unfortunately there is no other workaround, as this is fixed in HW. External logic could be an option though.

    Regards,
    Fredrik