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.

CC2340R5: Syscfg file missing callback function option when creating new GPIO for a task

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG,

Hello,

I am using CC studio 12.6 and going through the SimplelLink data_stream example.

When I go to configure the GPIO in the syscfg file, I don't see the callback function option. Is there a way to manually link a function to the GPIO generated?

Thanks

  • Hello Joseph,

    Please configure your button callbacks from within the application code, such as following the example from basic_ble menu_module.c

    bStatus_t MenuModule_initButtons(void)
    {
        Button_Params params;
        Button_Params_init(&params);
    
        // Set the buttons parameters
        params.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGPRESSED;
        params.buttonCallback = MenuModule_buttonsCallback;
        params.longPressDuration = MENU_MODULE_LONG_PRESS_DURATION;
        params.debounceDuration = MENU_MODULE_DEBOUNCE_DURATION;
    
        // Open the buttons
        handle_left = Button_open(CONFIG_BUTTON_0, &params);
        handle_right = Button_open(CONFIG_BUTTON_1, &params);
    
        if(handle_left == NULL || handle_right == NULL)
        {
            return FAILURE;
        }
    
        return SUCCESS;
    }

    Here is the Button TI Driver reference, although you could look at GPIO.h as well.

    Regards,
    Ryan

  • How do you set it from the application code. Do you mean in the empty.c file? Do you have an example script that shows that?

  • Here is the example from Button.h

    #include <ti/drivers/apps/Button.h>
    int main(void)
    {
        Button_Params params;
        Button_Handle handle;
        Button_Params_init(&params);
        handle = Button_open(CONFIG_BUTTON0, buttonCallbackFxn, &params);
        ...
    }
    void buttonCallbackFxn(Button_Handle handle, Button_EventMask events)
    {
        if (events & Button_EV_CLICKED)
        {
            // Received a click, handle app condition 0 etc
            handleAppCond(0);
        }
        if (events & Button_EV_LONGCLICKED)
        {
            // Long press, handle app condition 1 etc
            handleAppCond(1);
        }
        ...
    }

    Here, it is assumed that CONFIG_BUTTON0 has been declared in SysConfig.  You can perform this from the data_stream example you started from, as the empty example is not required for button operation.

    Regards,
    Ryan

  • Thank you. The Button_open fcn is giving me an error as it only expects two parameters, 

    Button_Handle Button_open(uint_least8_t buttonIndex, Button_Params *params);

    I circumvented this by editing the params.buttonCallback manually. But this didn't work either. Here is my code.

    /*
     *  ======== empty.c ========
     */
    
    /* For usleep() */
    #include <unistd.h>
    #include <stdint.h>
    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/apps/Button.h>
    // #include <ti/drivers/I2C.h>
    // #include <ti/drivers/SPI.h>
    // #include <ti/drivers/Watchdog.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    /* POSIX Header files */
    #include <pthread.h>
    
    /* RTOS header files */
    #include <FreeRTOS.h>
    #include <task.h>
    
    /* Stack size in bytes */
    #define THREADSTACKSIZE 1024
    
    /*external functions */
    extern void IncrementGatt();
    extern void DecrementGatt();
    
    
    
    void buttonCallbackFxn1(Button_Handle handle_left, Button_EventMask events)
    {
        if (events & Button_EV_CLICKED)
        {
            // Received a click, handle app condition 0 etc
            IncrementGatt();
        }
        if (events & Button_EV_LONGCLICKED)
        {
            // Long press, handle app condition 1 etc
            IncrementGatt();
        }
    }
    
    
    void buttonCallbackFxn2(Button_Handle handle_right, Button_EventMask events)
    {
        if (events & Button_EV_CLICKED)
        {
            // Received a click, handle app condition 0 etc
            DecrementGatt();
        }
        if (events & Button_EV_LONGCLICKED)
        {
            // Long press, handle app condition 1 etc
            DecrementGatt();
        }
    }
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        /* 1 second delay */
        uint32_t time = 1;
    
    
        /* Call driver init functions */
       Button_Params params1;
       Button_Params params2;
    
    
       Button_Handle handle_left;
       Button_Handle handle_right;
    
       Button_Params_init(&params1);
       Button_Params_init(&params2);
    
       params1.buttonCallback = buttonCallbackFxn1;
       params2.buttonCallback = buttonCallbackFxn2;
    
       handle_left = Button_open(CONFIG_BUTTON_0, &params1);
       handle_right = Button_open(CONFIG_BUTTON_1, &params2);
    
        GPIO_init();
        // I2C_init();
        // SPI_init();
        // Watchdog_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
    
        /* Turn on user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
    
        /* Enable interrupts */
        GPIO_enableInt(CONFIG_GPIO_BUTTON_0_INPUT); //Add this Line!
        GPIO_enableInt(CONFIG_GPIO_BUTTON_1_INPUT); //Add this Line!
    
        while (1)
        {
            sleep(time);
            GPIO_toggle(CONFIG_GPIO_LED_0);
        }
    }
    
    void emptyMain(void)
      {
          pthread_t thread;
          pthread_attr_t attrs;
          struct sched_param priParam;
          int retc;
    
          /* Initialize the attributes structure with default values */
          pthread_attr_init(&attrs);
    
          /* Set priority, detach state, and stack size attributes */
          priParam.sched_priority = 5; // Lower the priority of this task
          retc = pthread_attr_setschedparam(&attrs, &priParam);
          retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
          retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
          if (retc != 0)
          {
              /* failed to set attributes */
              while (1) {}
          }
    
          retc = pthread_create(&thread, &attrs, mainThread, NULL);
          if (retc != 0)
          {
              /* pthread_create() failed */
              while (1) {}
          }
      }
    
    /*********************************************************************
     * @fn      BLEConnectionEstablished
     *
     * @brief   Called when a Bluetooth connection has been established
     *          with a peer device.
     *
     * @param   None
     *
     * @return  None.
     */
    void BLEConnectionEstablished(void)
    {
    // Indicate connection by turning on the green LED
    GPIO_write(CONFIG_GPIO_LED_1, CONFIG_LED_ON);
    }
    /*********************************************************************
     * @fn      BLEConnectionTerminated
     *
     * @brief   Called when the Bluetooth connection has been terminated.
     *
     * @param   None
     *
     * @return  None.
     */
    void BLEConnectionTerminated(void)
    {
    // Indicate disconnection by turning off the LED
    GPIO_write(CONFIG_GPIO_LED_1, CONFIG_LED_OFF);
    }
    
    /*********************************************************************
     * @fn      evaluateNewCharacteristicValue
     *
     * @brief   Based on the new value of a given characteristic determine
     *          if the LED should be turned off or on.
     *
     * @param   newValue: Value of the characteristic to consider
     *
     * @return  None.
     */
    void evaluateNewCharacteristicValue(uint8_t newValue)
    {
    // If the new value of the characteristic is 0, then we turn off the red LED
    if(newValue == 0)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_LED_OFF);
    }
    else
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_LED_ON);
    }
    }
    
    

    IncrementGatt and DecrementGatt functions are external and are the following

    void IncrementGatt()
    {
    Count++;
    SimpleGattProfile_setParameter(SIMPLEGATTPROFILE_CHAR1, sizeof(uint8_t), &Count);
    }
    void DecrementGatt()
    {
    if(Count > 0){
        Count--;
    }
    SimpleGattProfile_setParameter(SIMPLEGATTPROFILE_CHAR1, sizeof(uint8_t), &Count);
    }

  • Is see your point about the Button_open parameters.  This is solved by populating the callbacks as part of the Button_Params instead (Button_Callback buttonCallback). Here is the code I've verified works for my setup:

    /*
     * Copyright (c) 2015-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     */
    
    /*
     *  ======== empty.c ========
     */
    
    /* For usleep() */
    #include <unistd.h>
    #include <stdint.h>
    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/apps/Button.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    void button1CallbackFxn(Button_Handle handle, Button_EventMask events)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);
    
    }
    
    void button2CallbackFxn(Button_Handle handle, Button_EventMask events)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
    }
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        /* 1 second delay */
        uint32_t time = 1;
    
        /* Call driver init functions */
        GPIO_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn on user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        Button_Params params;
        Button_Handle button1Handle;
        Button_Handle button2Handle;
        Button_Params_init(&params);
        params.buttonCallback = button1CallbackFxn;
        button1Handle = Button_open(CONFIG_BUTTON_0, &params);
        params.buttonCallback = button2CallbackFxn;
        button2Handle = Button_open(CONFIG_BUTTON_1, &params);
    
        while (1)
        {
            sleep(time);
        }
    }
    

    Note that I also added two Button instances to the SysConfig file, each connected to LP hardware: LaunchPad Button BTN-1 (Left) or LaunchPad Button BTN-2 (Right)

    Regards,
    Ryan

  • Thanks! This works in the domain of the empty_LP_EM_CC2340R5 example. 

    However, the same code is not executing in the basic_ble_LP_EM_CC2340R5 when I copy over the empty.c file into the APP folder and copy the emptyMain(void) function to generate a lower priority task. Below are my empty.c and main_freertos.c files. Is there something different with buttons if you create a lower priority task using pthread?

     *  ======== empty.c ========
     */
    
    /* For usleep() */
    #include <unistd.h>
    #include <stdint.h>
    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/apps/Button.h>
    // #include <ti/drivers/I2C.h>
    // #include <ti/drivers/SPI.h>
    // #include <ti/drivers/Watchdog.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    /* POSIX Header files */
    #include <pthread.h>
    
    /* RTOS header files */
    #include <FreeRTOS.h>
    #include <task.h>
    
    /* Stack size in bytes */
    #define THREADSTACKSIZE 1024
    
    /*external functions */
    extern void IncrementGatt();
    extern void DecrementGatt();
    
    
    
    void buttonCallbackFxn1(Button_Handle handle, Button_EventMask events)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);
        //IncrementGatt();
    }
    
    
    void buttonCallbackFxn2(Button_Handle handle, Button_EventMask events)
    {
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
        //DecrementGatt();
    }
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        /* 1 second delay */
        uint32_t time = 1;
    
    
    
    
    
        GPIO_init();
        // I2C_init();
        // SPI_init();
        // Watchdog_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        //GPIO_setConfig(CONFIG_GPIO_Button_0_INPUT, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); //Add this Line!
        //GPIO_setConfig(CONFIG_GPIO_BUTTON_1_INPUT, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); //Add this Line!
    
        //GPIO_setCallback
    
        //GPIO_enableInt
    
        /* Turn on user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
    
        /* Call driver init functions */
         Button_Params params;
    
         Button_Handle handle_left;
         Button_Handle handle_right;
    
         Button_Params_init(&params);
    
         //params.buttonEventMask = Button_EV_PRESSED;
         params.buttonCallback = buttonCallbackFxn1;
         handle_left = Button_open(CONFIG_BUTTON_0, &params);
         params.buttonCallback = buttonCallbackFxn2;
         handle_right = Button_open(CONFIG_BUTTON_1, &params);
        /* Enable interrupts */
        //GPIO_enableInt(CONFIG_GPIO_BUTTON_0_INPUT); //Add this Line!
       // GPIO_enableInt(CONFIG_GPIO_BUTTON_1_INPUT); //Add this Line!
    
        while (1)
        {
            sleep(time);
            //GPIO_toggle(CONFIG_GPIO_LED_0);
        }
    }
    
    void emptyMain(void)
      {
          pthread_t thread;
          pthread_attr_t attrs;
          struct sched_param priParam;
          int retc;
    
          /* Initialize the attributes structure with default values */
          pthread_attr_init(&attrs);
    
          /* Set priority, detach state, and stack size attributes */
          priParam.sched_priority = 5; // Lower the priority of this task
          retc = pthread_attr_setschedparam(&attrs, &priParam);
          retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
          retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
          if (retc != 0)
          {
              /* failed to set attributes */
              while (1) {}
          }
    
          retc = pthread_create(&thread, &attrs, mainThread, NULL);
          if (retc != 0)
          {
              /* pthread_create() failed */
              while (1) {}
          }
      }

    * INCLUDES
     */
    
    /* RTOS header files */
    #include <FreeRTOS.h>
    #include <stdint.h>
    #include <task.h>
    #ifdef __ICCARM__
        #include <DLib_Threads.h>
    #endif
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC23X0.h>
    #include <ti/display/Display.h>
    #include <ti/drivers/UART2.h>
    #include <ti/common/cc26xx/uartlog/UartLog.h>
    #include <ti/devices/DeviceFamily.h>
    
    #include <icall.h>
    #include "hal_assert.h"
    #include "bcomdef.h"
    
    #ifndef USE_DEFAULT_USER_CFG
    #include "ble_user_config.h"
    #include "ble_stack_api.h"
    // BLE user defined configuration
    icall_userCfg_t user0Cfg = BLE_USER_CFG;
    #endif // USE_DEFAULT_USER_CFG
    
    
    /*******************************************************************************
     * MACROS
     */
    
    /*******************************************************************************
     * CONSTANTS
     */
    
    /*******************************************************************************
     * TYPEDEFS
     */
    
    /*******************************************************************************
     * LOCAL VARIABLES
     */
    
    /*******************************************************************************
     * GLOBAL VARIABLES
     */
    
    /*******************************************************************************
     * EXTERNS
     */
    extern void appMain(void);
    extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
    extern void emptyMain(void);
    
    
    /*******************************************************************************
     * @fn          Main
     *
     * @brief       Application Main
     *
     * input parameters
     *
     * @param       None.
     *
     * output parameters
     *
     * @param       None.
     *
     * @return      None.
     */
    int main()
    {
      /* Register Application callback to trap asserts raised in the Stack */
      halAssertCback = AssertHandler;
      RegisterAssertCback(AssertHandler);
    
      Board_init();
    
      /* Update User Configuration of the stack */
      user0Cfg.appServiceInfo->timerTickPeriod = ICall_getTickPeriod();
      user0Cfg.appServiceInfo->timerMaxMillisecond  = ICall_getMaxMSecs();
    
      /* Initialize all applications tasks */
      appMain();
      emptyMain();
    
    
      /* Start the FreeRTOS scheduler */
      vTaskStartScheduler();
    
      return 0;
    
    }
    
    //*****************************************************************************
    //
    //! \brief Application defined stack overflow hook
    //!
    //! \param  none
    //!
    //! \return none
    //!
    //*****************************************************************************
    void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)
    {
        //Handle FreeRTOS Stack Overflow
        AssertHandler(HAL_ASSERT_CAUSE_STACK_OVERFLOW_ERROR, 0);
    }
    
    /*******************************************************************************
     * @fn          AssertHandler
     *
     * @brief       This is the Application's callback handler for asserts raised
     *              in the stack.  When EXT_HAL_ASSERT is defined in the Stack Wrapper
     *              project this function will be called when an assert is raised,
     *              and can be used to observe or trap a violation from expected
     *              behavior.
     *
     *              As an example, for Heap allocation failures the Stack will raise
     *              HAL_ASSERT_CAUSE_OUT_OF_MEMORY as the assertCause and
     *              HAL_ASSERT_SUBCAUSE_NONE as the assertSubcause.  An application
     *              developer could trap any malloc failure on the stack by calling
     *              HAL_ASSERT_SPINLOCK under the matching case.
     *
     *              An application developer is encouraged to extend this function
     *              for use by their own application.  To do this, add hal_assert.c
     *              to your project workspace, the path to hal_assert.h (this can
     *              be found on the stack side). Asserts are raised by including
     *              hal_assert.h and using macro HAL_ASSERT(cause) to raise an
     *              assert with argument assertCause.  the assertSubcause may be
     *              optionally set by macro HAL_ASSERT_SET_SUBCAUSE(subCause) prior
     *              to asserting the cause it describes. More information is
     *              available in hal_assert.h.
     *
     * input parameters
     *
     * @param       assertCause    - Assert cause as defined in hal_assert.h.
     * @param       assertSubcause - Optional assert subcause (see hal_assert.h).
     *
     * output parameters
     *
     * @param       None.
     *
     * @return      None.
     */
    void AssertHandler(uint8_t assertCause, uint8_t assertSubcause)
    {
        Log_error2(">>>STACK ASSERT Cause 0x%02x subCause 0x%02x",
                   assertCause, assertSubcause);
    
        // check the assert cause
        switch(assertCause)
        {
        case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
            Log_error0("***ERROR***");
            Log_error0(">> OUT OF MEMORY!");
            break;
    
        case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
            // check the subcause
            if(assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
            {
                Log_error0("***ERROR***");
                Log_error0(">> INTERNAL FW ERROR!");
            }
            else
            {
                Log_error0("***ERROR***");
                Log_error0(">> INTERNAL ERROR!");
            }
            break;
    
        case HAL_ASSERT_CAUSE_ICALL_ABORT:
            Log_error0("***ERROR***");
            Log_error0(">> ICALL ABORT!");
            //HAL_ASSERT_SPINLOCK;
            break;
    
        case HAL_ASSERT_CAUSE_ICALL_TIMEOUT:
            Log_error0("***ERROR***");
            Log_error0(">> ICALL TIMEOUT!");
            //HAL_ASSERT_SPINLOCK;
            break;
    
        case HAL_ASSERT_CAUSE_WRONG_API_CALL:
            Log_error0("***ERROR***");
            Log_error0(">> WRONG API CALL!");
            //HAL_ASSERT_SPINLOCK;
            break;
    
        case HAL_ASSERT_CAUSE_STACK_OVERFLOW_ERROR:
            Log_error0("***ERROR***");
            Log_error0(">> STACK OVERFLOW!");
            HAL_ASSERT_SPINLOCK;
            break;
    
        default:
            Log_error0("***ERROR***");
            Log_error0(">> DEFAULT SPINLOCK!");
            //HAL_ASSERT_SPINLOCK;
        }
    
        return;
    }
    

  • basic_ble already enabled push button operation through and callbacks through menu_module.c, so either no modifications are necessary or you have disabled menu operation (by defining Display_DISABLE_ALL).

    Regards,
    Ryan