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.

PWM with TI-RTOS 2.18 and BLE Stack 2.2

Other Parts Discussed in Thread: SYSBIOS

Hello,

I would like to use the PWM driver with 2.18 RTOS but I didn't found how to do it properly.

I have already read the RTOS 2.18 Users Guide but there is no explanations on how to setup PWM pin config.

So, can you tell me how to use the PWM properly please ?

ps : I know that the 2.2 RTOS has implemented an operational driver, but as far as I know there isn't any official compatibility with BLE Stack 2.2

  • Hi,

    Please download TI-RTOS 2.20 for the official PWM driver.

    You can copy all the needed driver files from TI-RTOS 2.20 and paste them into corresponding folder in 2.18.
    Then just modify the board files accordingly.

    FYI, TI-RTOS 2.20 also comes with PWM examples.
    http://www.ti.com/tool/ti-rtos
  • I tried, and I get errors when I build.

    Here is the interesting part of console :

    undefined first referenced
    symbol in file
    --------- ----------------
    ti_sysbios_family_arm_lm4_Timer_getAvailMask__E C:/ti/tirtos_cc13xx_cc26xx_2_18_00_03/products/tidrivers_cc13xx_cc26xx_2_16_01_13/packages/ti/drivers/lib/drivers_cc26xxware.aem3<PWMTimerCC26XX.oem3>
    ti_sysbios_family_arm_lm4_Timer_setAvailMask__E C:/ti/tirtos_cc13xx_cc26xx_2_18_00_03/products/tidrivers_cc13xx_cc26xx_2_16_01_13/packages/ti/drivers/lib/drivers_cc26xxware.aem3<PWMTimerCC26XX.oem3>

    error #10234-D: unresolved symbols remain
    error #10010: errors encountered during linking; "LED_simple_peripheral_cc2650lp_app.out" not built
    gmake: *** [LED_simple_peripheral_cc2650lp_app.out] Error 1

    >> Compilation failure
    makefile:194: recipe for target 'LED_simple_peripheral_cc2650lp_app.out' failed
    gmake: Target 'all' not remade because of errors.

    **** Build Finished ****


    What do you think about that ?
  • can you attach the files which you have modified?
  • PWM.h

    /*
     * Copyright (c) 2015-2016, 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.
     */
    /*
     *  ======== PWM.c ========
     */
    
    #include <stdint.h>
    #include <stdlib.h>
    
    #include <ti/drivers/PWM.h>
    
    /* PWM configuration array from application */
    extern const PWM_Config PWM_config[];
    
    /* Used to check status and initialization */
    static int PWM_count = -1;
    
    /* Default PWM parameters structure */
    const PWM_Params PWM_defaultParams = {
        .periodUnits = PWM_PERIOD_HZ,             /* Period is defined in Hz */
        .periodValue = 1e6,                       /* 1MHz */
        .dutyUnits   = PWM_DUTY_FRACTION,         /* Duty is fraction of period */
        .dutyValue   = 0,                         /* 0% duty cycle */
        .idleLevel   = PWM_IDLE_LOW,              /* Low idle level */
        .custom      = NULL                       /* No custom params */
    };
    
    /*
     *  ======== PWM_close ========
     */
    void PWM_close(PWM_Handle handle)
    {
        handle->fxnTablePtr->closeFxn(handle);
    }
    
    /*
     *  ======== PWM_control ========
     */
    int PWM_control(PWM_Handle handle, unsigned int cmd, void *arg)
    {
        return handle->fxnTablePtr->controlFxn(handle, cmd, arg);
    }
    
    /*
     *  ======== PWM_init ========
     */
    void PWM_init(void)
    {
        if (PWM_count == -1) {
            /* Call each driver's init function */
            for (PWM_count = 0; PWM_config[PWM_count].fxnTablePtr != NULL; PWM_count++) {
                PWM_config[PWM_count].fxnTablePtr->initFxn((PWM_Handle) &(PWM_config[PWM_count]));
            }
        }
    }
    
    /*
     *  ======== PWM_open ========
     */
    PWM_Handle PWM_open(unsigned int index, PWM_Params *params)
    {
        PWM_Handle handle;
    
        if (index >= PWM_count) {
            return (NULL);
        }
    
        /* If params are NULL use defaults. */
        if (params == NULL) {
            params = (PWM_Params *) &PWM_defaultParams;
        }
    
        /* Get handle for this driver instance */
        handle = (PWM_Handle) &(PWM_config[index]);
    
        return(handle->fxnTablePtr->openFxn(handle, params));
    }
    
    /*
     *  ======== PWM_Params_init ========
     */
    void PWM_Params_init(PWM_Params *params)
    {
        *params = PWM_defaultParams;
    }
    
    /*
     *  ======== PWM_setDuty ========
     */
    int PWM_setDuty(PWM_Handle handle, uint32_t dutyValue)
    {
        return(handle->fxnTablePtr->setDutyFxn(handle, dutyValue));
    }
    
    /*
     *  ======== PWM_setDuty ========
     */
    int PWM_setPeriod(PWM_Handle handle, uint32_t periodValue)
    {
        return(handle->fxnTablePtr->setPeriodFxn(handle, periodValue));
    }
    
    /*
     *  ======== PWM_start ========
     */
    void PWM_start(PWM_Handle handle)
    {
        handle->fxnTablePtr->startFxn(handle);
    }
    
    /*
     *  ======== PWM_stop ========
     */
    void PWM_stop(PWM_Handle handle)
    {
        handle->fxnTablePtr->stopFxn(handle);
    }
    
    PWMTimerCC26XX.h
    /*
     * Copyright (c) 2015-2016, 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.
     */
    /*!*****************************************************************************
     *  @file       PWMTimerCC26XX.c
     *  @brief      CC26XX/CC13XX implementation of ti/drivers/PWM.h
     *
     *  # Overview #
     *  CC26XX/CC13XX PWM driver using the built-in GPTimer.
     *
     *  # Note #
     *  PWMTimerCC26XX driver calculations for duty cycle are inverted
     *  (for example 25% duty outputs 75%) and output is inverted again in the pad for
     *  correct behavior. This simplifies calculations as period/ timer load value
     *  can be updated independently of duty cycle / match value.
     *
     *  The driver also requires the GPTimer bit GPT.TnMR.TnPLO to be set.
     *  Using this, the PWM output will be always high when load=match and always
     *  low when match>load. Setting match > load is used for 0% duty cycle
     *
     *******************************************************************************
     */
    
    
    #include <xdc/runtime/Assert.h>
    #include <xdc/runtime/Types.h>
    #include <xdc/runtime/Log.h>
    
    #include <ti/sysbios/BIOS.h>
    
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include "ti/drivers/PWM.h"
    #include "ti/drivers/pwm/PWMTimerCC26XX.h"
    #include "ti/drivers/timer/GPTimerCC26XX.h"
    
    /* PWMTimerCC26XX defines */
    #define PWM_COUNT_MAX    0xFFFFFF /* GPTimer has maximum 24 bits incl prescaler */
    
    
    /* PWMTimerCC26XX functions */
    void       PWMTimerCC26XX_close(PWM_Handle handle);
    int        PWMTimerCC26XX_control(PWM_Handle handle, unsigned int cmd, void * arg);
    void       PWMTimerCC26XX_init(PWM_Handle handle);
    PWM_Handle PWMTimerCC26XX_open(PWM_Handle handle, PWM_Params *params);
    int        PWMTimerCC26XX_setDuty(PWM_Handle handle, uint32_t dutyValue);
    int        PWMTimerCC26XX_setPeriod(PWM_Handle handle, uint32_t periodValue);
    void       PWMTimerCC26XX_start(PWM_Handle handle);
    void       PWMTimerCC26XX_stop(PWM_Handle handle);
    
    /* PWMTimerCC26XX internal functions */
    static uint32_t         PWMTimerCC26XX_getperiodCounts(PWM_Period_Units periodUnit, uint32_t periodValue);
    static uint32_t         PWMTimerCC26XX_getdutyCounts(uint32_t periodCounts, PWM_Duty_Units dutyUnit, uint32_t dutyValue);
    
    /* PWM function table for PWMTimerCC26XX implementation */
    /*const PWM_FxnTable PWMTimerCC26XX_fxnTable =
    {
        PWMTimerCC26XX_close,
        PWMTimerCC26XX_control,
        PWMTimerCC26XX_init,
        PWMTimerCC26XX_open,
        PWMTimerCC26XX_setDuty,
        PWMTimerCC26XX_setPeriod,
        PWMTimerCC26XX_start,
        PWMTimerCC26XX_stop,
    };*/
    
    
    /* PIN configuration used for PWMTimerCC26XX implementation. Handle is shared
       across all PWM peripherals
     */
    static PIN_Handle hPins = NULL;
    static PIN_State  pinState;
    
    /*!
     *  @brief PWM CC26XX initialization
     *
     *  This is a dummy function since driver implementation assumes
     *  the handle->object->isOpen flag is set to 0 at boot
     *
     *  @pre    Calling context: Hwi, Swi, Task, Main
     *
     *  @param handle  A SPI_Handle
     *
     */
    void PWMTimerCC26XX_init(PWM_Handle handle)
    {
    }
    
    
    /* Open the specific PWM peripheral with the settings given in params.
       Will return a PWM handle if successfull, NULL if failed.
       PWM will output configured idle level when opened.
       Function sets a dependency on the underlying timer and adds the PWM pin to
       its internal PIN handle.
     */
    PWM_Handle PWMTimerCC26XX_open(PWM_Handle handle, PWM_Params *params)
    {
        PWMTimerCC26XX_HwAttrs *hwAttrs = handle->hwAttrs;
        PWMTimerCC26XX_Object  *object  = handle->object;
    
        /* Check if PWM already open  */
        uint32_t key = Hwi_disable();
        if (object->isOpen)
        {
            Hwi_restore(key);
            Log_error1("PWM_open(%x):  Unit already in use.", (UArg) handle);
            return NULL;
        }
        object->isOpen = 1;
        Hwi_restore(key);
    
        /* Open timer resource */
        GPTimerCC26XX_Params timerParams;
        GPTimerCC26XX_Params_init(&timerParams);
        timerParams.width          = GPT_CONFIG_16BIT;
        timerParams.mode           = GPT_MODE_PWM;
        timerParams.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
        GPTimerCC26XX_Handle hTimer = GPTimerCC26XX_open(hwAttrs->gpTimerUnit, &timerParams);
    
        /* Fail if cannot open timer */
        if (hTimer == NULL)
        {
            Log_error2("PWM_open(%x): Timer unit (%d) already in use.", (UArg) handle, hwAttrs->gpTimerUnit);
            object->isOpen = false;
            return NULL;
        }
    
        /* Open pin resource */
    
        PIN_Config pinConfig;
    
        /* Initial open of pin handle with no pins in it. Should never fail. */
        if (hPins == NULL)
        {
            pinConfig = PIN_TERMINATE;
            hPins     = PIN_open(&pinState, &pinConfig);
        }
    
        /* Invert PWM idle level since pin output is inverted */
        uint32_t idleLevel = PIN_GPIO_HIGH;
        if (params->idleLevel == PWM_IDLE_HIGH)
        {
            idleLevel = PIN_GPIO_LOW;
        }
    
        /* Generate pin config for PWM pin.
         *  Output is inverted to make PWM duty calculations independent of period
         */
        pinConfig = hwAttrs->pwmPin | PIN_INPUT_DIS | PIN_GPIO_OUTPUT_EN | idleLevel |
                    PIN_INV_INOUT | PIN_PUSHPULL | PIN_DRVSTR_MAX;
    
        /* Fail if cannot add pin */
        if (PIN_add(hPins, pinConfig) != PIN_SUCCESS)
        {
            Log_error2("PWM_open(%x): PIN (%d) already in use.", (UArg) handle, hwAttrs->pwmPin);
            GPTimerCC26XX_close(hTimer);
            object->isOpen = false;
            return NULL;
        }
    
    
        /* Store configuration to object */
        object->periodUnit  = params->periodUnits;
        object->periodValue = params->periodValue;
        object->dutyUnit    = params->dutyUnits;
        object->dutyValue   = params->dutyValue;
        object->idleLevel   = params->idleLevel;
        object->hTimer      = hTimer;
    
    
        /* Configure PWM period*/
        uint32_t period = object->periodValue;
    
        if (PWMTimerCC26XX_setPeriod(handle, period) != PWM_STATUS_SUCCESS)
        {
            Log_error1("PWM_open(%x): Failed setting period", (UArg) handle);
            PIN_remove(hPins, hwAttrs->pwmPin);
            GPTimerCC26XX_close(hTimer);
            object->isOpen = false;
            return NULL;
        }
    
        /* Corner case: If using duty unit PWM_DUTY_FRACTION or PWM_DUTY_US with
           value 0, then duty is already set by setPeriod. Skip if so. */
        PWM_Duty_Units unit  = object->dutyUnit;
        uint32_t      value = object->dutyValue;
    
        if (!(unit == PWM_DUTY_FRACTION || (value == 0 && unit == PWM_DUTY_US)))
        {
            if (PWMTimerCC26XX_setDuty(handle, value) != PWM_STATUS_SUCCESS)
            {
                Log_error1("PWM_open(%x): Failed setting duty cycle", (UArg) handle);
                PIN_remove(hPins, hwAttrs->pwmPin);
                GPTimerCC26XX_close(hTimer);
                object->isOpen = false;
                return NULL;
            }
        }
    
        Log_info1("PWM_open(%x): Opened with great success!", (UArg) handle);
        return handle;
    }
    
    
    /* PWMTimerCC26XX_setPeriod -
       Sets / update PWM period. Unit must already be defined in object.
       Also updates duty cycle if using fractional duty cycle
     */
    int PWMTimerCC26XX_setPeriod(PWM_Handle handle, uint32_t periodValue)
    {
        PWMTimerCC26XX_Object *object = handle->object;
        /* Copy current period unit and store new period */
        uint32_t newperiodCounts = PWMTimerCC26XX_getperiodCounts(object->periodUnit, periodValue);
    
        /* Fail if period is out of range */
        if (newperiodCounts > PWM_COUNT_MAX || newperiodCounts == 0)
        {
            Log_error2("PWM(%x): Period (%d) is out of range", (UArg) handle, periodValue);
            return PWM_STATUS_INVALID_PERIOD;
        }
    
    
        PWM_Duty_Units dutyUnit  = object->dutyUnit;
        uint32_t      dutyValue = object->dutyValue;
        /*  Corner case: 0% duty cycle when using fractional or time unit
            Update duty cycle, needs to be higher than new period counts for 0% duty */
        if (dutyUnit == PWM_DUTY_FRACTION || (dutyValue == 0 && dutyUnit == PWM_DUTY_US))
        {
            object->dutyCounts = PWMTimerCC26XX_getdutyCounts(newperiodCounts, dutyUnit, dutyValue);
            GPTimerCC26XX_setMatchValue(object->hTimer, object->dutyCounts);
        }
        /* Fixed time duty cyle other than 0. No checking when using PWM_DUTY_COUNTS */
        else if (dutyUnit != PWM_DUTY_COUNTS)
        {
            /* Compare to new period and fail if invalid */
            if (newperiodCounts < object->dutyCounts)
            {
                Log_error2("PWM(%x): Period is shorter than duty (%d)", (UArg) handle, periodValue);
                return PWM_STATUS_INVALID_PERIOD;
            }
        }
    
        /* Store new period and update timer */
        object->periodValue  = periodValue;
        object->periodCounts = newperiodCounts;
        GPTimerCC26XX_setLoadValue(object->hTimer, newperiodCounts);
    
        Log_info1("PWM_setPeriod(%x): Period set with great success!", (UArg) handle);
        return PWM_STATUS_SUCCESS;
    }
    
    /* PWMTimerCC26XX_setDuty -
       Sets / update PWM duty. Unit must already be defined in object.
       Period must already be configured in object before calling this API.
     */
    int PWMTimerCC26XX_setDuty(PWM_Handle handle, uint32_t dutyValue)
    {
        PWMTimerCC26XX_Object *object = handle->object;
        /* Copy current period unit and store new period */
        PWM_Duty_Units     dutyUnit = object->dutyUnit;
        uint32_t newdutyCounts     = PWMTimerCC26XX_getdutyCounts(object->periodCounts, dutyUnit, dutyValue);
    
        /* Fail if duty cycle count is out of range */
        if (newdutyCounts > PWM_COUNT_MAX)
        {
            Log_error2("PWM(%x): Duty (%d) is out of range", (UArg) handle, dutyValue);
            return PWM_STATUS_INVALID_PERIOD;
        }
    
        /* Error checking:
         *  Unit PWM_DUTY_FRACTION will always be within range
         *  Unit PWM_DUTY_US with value 0 will always be correct(set by getdutyCounts)
         *  Unit PWM_DUTY_US value != 0 needs error checking
         *  Unit PWM_DUTY_COUNTS is not checked
         */
        if (dutyUnit == PWM_DUTY_US &&
            dutyValue != 0 &&
            newdutyCounts > object->periodCounts)
        {
            Log_error2("PWM(%x): Duty (%d) is larger than period", (UArg) handle, dutyValue);
            return PWM_STATUS_INVALID_DUTY;
        }
    
        /* Store new duty cycle and update timer */
        object->dutyValue  = dutyValue;
        object->dutyCounts = newdutyCounts;
        GPTimerCC26XX_setMatchValue(object->hTimer, newdutyCounts);
    
        Log_info1("PWM_setDuty(%x): Duty set with great success!", (UArg) handle);
        return PWM_STATUS_SUCCESS;
    }
    
    /* Return period in timer counts */
    static uint32_t PWMTimerCC26XX_getperiodCounts(PWM_Period_Units periodUnit, uint32_t periodValue)
    {
        Types_FreqHz freq;
        BIOS_getCpuFreq(&freq);
    
        uint32_t periodCounts;
    
        switch (periodUnit)
        {
        case PWM_PERIOD_US:
            periodCounts = ((uint64_t)freq.lo * (uint64_t)periodValue / 1000000) - 1;
            break;
        case PWM_PERIOD_HZ:
            periodCounts = (freq.lo / periodValue) - 1;
            break;
        case PWM_PERIOD_COUNTS:
        /* Fall through */
        default:
            periodCounts = periodValue;
            break;
        }
        return periodCounts;
    }
    
    /* Return duty cycle in timer counts */
    static uint32_t PWMTimerCC26XX_getdutyCounts(uint32_t periodCounts, PWM_Duty_Units dutyUnit, uint32_t dutyValue)
    {
        Types_FreqHz freq;
        BIOS_getCpuFreq(&freq);
    
        uint32_t dutyCounts;
    
        /* Corner case, 0% duty cycle. Set timer count higher than period */
        if (dutyValue == 0 &&
            (dutyUnit == PWM_DUTY_US || dutyUnit == PWM_DUTY_FRACTION))
        {
            dutyCounts = periodCounts + 1;
        }
        else
        {
            switch (dutyUnit)
            {
            case PWM_DUTY_US:
                dutyCounts = ((uint64_t)freq.lo * (uint64_t)dutyValue / 1000000) - 1;
                break;
            case PWM_DUTY_FRACTION:
                dutyCounts = (uint64_t)dutyValue * (uint64_t)periodCounts /
                             PWM_DUTY_FRACTION_MAX;
                break;
            case PWM_DUTY_COUNTS:
            /* Fall through */
            default:
                dutyCounts = dutyValue;
                break;
            }
        }
        return dutyCounts;
    }
    
    /* Stop PWM output for given PWM peripheral. PWM pin will be routed
       to the GPIO module to provide Idle level and timer is stopped
     */
    void PWMTimerCC26XX_stop(PWM_Handle handle)
    {
        PWMTimerCC26XX_HwAttrs *hwAttrs = handle->hwAttrs;
        PWMTimerCC26XX_Object  *object  = handle->object;
    
        GPTimerCC26XX_stop(object->hTimer);
        /* Route PWM pin to GPIO module */
        PINCC26XX_setMux(hPins, hwAttrs->pwmPin, IOC_PORT_GPIO);
    }
    
    /* Start PWM output for given PWM peripheral.
       PWM pin will be routed to the Timer module and timer is started
     */
    void PWMTimerCC26XX_start(PWM_Handle handle)
    {
        PWMTimerCC26XX_HwAttrs *hwAttrs = handle->hwAttrs;
        PWMTimerCC26XX_Object  *object  = handle->object;
    
        /* Route PWM pin to timer output */
        GPTimerCC26XX_PinMux pinMux = GPTimerCC26XX_getPinMux(object->hTimer);
        PINCC26XX_setMux(hPins, hwAttrs->pwmPin, pinMux);
        GPTimerCC26XX_start(object->hTimer);
    }
    
    /* Close the specific PWM peripheral. A running PWM must be stopped first.
       PWM output will revert to output value given in PIN_init if any is defined.
     */
    void PWMTimerCC26XX_close(PWM_Handle handle)
    {
        PWMTimerCC26XX_HwAttrs *hwAttrs = handle->hwAttrs;
        PWMTimerCC26XX_Object  *object  = handle->object;
    
        /* Restore PWM pin to GPIO module with default configuration from PIN_init */
        PIN_remove(hPins, hwAttrs->pwmPin);
        /* Close and delete timer handle */
        GPTimerCC26XX_close(object->hTimer);
        object->hTimer = NULL;
    
        /* Clear isOpen flag */
        uint32_t key = Hwi_disable();
        object->isOpen = 0;
        Hwi_restore(key);
    }
    
    /* Driver specific control options. PWM peripheral must be opened before
       using this API */
    int PWMTimerCC26XX_control(PWM_Handle handle, unsigned int cmd, void * arg)
    {
        PWMTimerCC26XX_Object *object = handle->object;
        int stat = PWM_STATUS_SUCCESS;
    
        switch (cmd)
        {
        case PWMTimerCC26XX_CMD_DEBUG_STALL:
            GPTimerCC26XX_configureDebugStall(object->hTimer, *(GPTimerCC26XX_DebugMode *)arg);
            break;
        default:
            stat = PWM_STATUS_UNDEFINEDCMD;
            break;
        }
        return stat;
    }
    



    Into PWMTimerCC26XX.c I commented the PWM_FxnTable because I got an error about redefinitions of this table.

  • To be more exhaustive, I did the following into "ti/drivers" :

    - I added folders from RTOS 2.20 to 2.18 : adc, adcbuf, timer
    - I replaced the old folder pwm with the one included in RTOS 2.2, and I commented PWM_fxnTable into PWMTimerCC26XX.c like I said before
    - I added/changed files from RTOS 2.20 to 2.18 : ADC.c, ADC.h, ADCBuf.c, ADCBuf.h, PWM.c, PWM.h

    So, what's wrong ?
  • Have you modified the board files?
  • Yes

    1682.Board.h

    /*
     * Copyright (c) 2016, 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.
     */
    
    /*
     *  ====================== CC2650_LAUNCHXL.c ===================================
     *  This file is responsible for setting up the board specific items for the
     *  CC2650 LaunchPad.
     */
    
    
    /*
     *  ====================== Includes ============================================
     */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/family/arm/m3/Hwi.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include <ti/drivers/PWM.h>
    #include <ti/drivers/pwm/PWMTimerCC26XX.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    
    #include <inc/hw_memmap.h>
    #include <inc/hw_ints.h>
    #include <driverlib/ioc.h>
    #include <driverlib/udma.h>
    
    #include <Board.h>
    
    /*
     *  ========================= IO driver initialization =========================
     *  From main, PIN_init(BoardGpioInitTable) should be called to setup safe
     *  settings for this board.
     *  When a pin is allocated and then de-allocated, it will revert to the state
     *  configured in this table.
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(BoardGpioInitTable, ".const:BoardGpioInitTable")
    #pragma DATA_SECTION(PINCC26XX_hwAttrs, ".const:PINCC26XX_hwAttrs")
    #endif
    
    const PIN_Config BoardGpioInitTable[] = {
    
        Board_RLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
        Board_GLED   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,         /* LED initially off             */
        Board_BTN1   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
        Board_BTN2   | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,            /* Button is active low          */
        Board_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select    */
        Board_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
        Board_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
        Board_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
        Board_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
        Board_SPI0_CLK | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* SPI clock */
    
        PIN_TERMINATE
    };
    
    const PINCC26XX_HWAttrs PINCC26XX_hwAttrs = {
        .intPriority = ~0,
        .swiPriority = 0
    };
    /*============================================================================*/
    
    /*
     *  ============================= Power begin ==================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(PowerCC26XX_config, ".const:PowerCC26XX_config")
    #endif
    const PowerCC26XX_Config PowerCC26XX_config = {
        .policyInitFxn      = NULL,
        .policyFxn          = &PowerCC26XX_standbyPolicy,
        .calibrateFxn       = &PowerCC26XX_calibrate,
        .enablePolicy       = TRUE,
        .calibrateRCOSC_LF  = TRUE,
        .calibrateRCOSC_HF  = TRUE,
    };
    /*
     *  ============================= Power end ====================================
     */
    
    /*
     *  ============================= UART begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(UART_config, ".const:UART_config")
    #pragma DATA_SECTION(uartCC26XXHWAttrs, ".const:uartCC26XXHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTCC26XX.h>
    
    /* UART objects */
    UARTCC26XX_Object uartCC26XXObjects[CC2650_LAUNCHXL_UARTCOUNT];
    
    /* UART hardware parameter structure, also used to assign UART pins */
    const UARTCC26XX_HWAttrsV1 uartCC26XXHWAttrs[CC2650_LAUNCHXL_UARTCOUNT] = {
        {
            .baseAddr       = UART0_BASE,
            .powerMngrId    = PowerCC26XX_PERIPH_UART0,
            .intNum         = INT_UART0_COMB,
            .intPriority    = ~0,
            .swiPriority    = 0,
            .txPin          = Board_UART_TX,
            .rxPin          = Board_UART_RX,
            .ctsPin         = PIN_UNASSIGNED,
            .rtsPin         = PIN_UNASSIGNED
        }
    };
    
    /* UART configuration structure */
    const UART_Config UART_config[] = {
        {
            .fxnTablePtr = &UARTCC26XX_fxnTable,
            .object      = &uartCC26XXObjects[0],
            .hwAttrs     = &uartCC26XXHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ============================= UART end =====================================
     */
    
    /*
     *  ============================= UDMA begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(UDMACC26XX_config, ".const:UDMACC26XX_config")
    #pragma DATA_SECTION(udmaHWAttrs, ".const:udmaHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/dma/UDMACC26XX.h>
    
    /* UDMA objects */
    UDMACC26XX_Object udmaObjects[CC2650_LAUNCHXL_UDMACOUNT];
    
    /* UDMA configuration structure */
    const UDMACC26XX_HWAttrs udmaHWAttrs[CC2650_LAUNCHXL_UDMACOUNT] = {
        {
            .baseAddr    = UDMA0_BASE,
            .powerMngrId = PowerCC26XX_PERIPH_UDMA,
            .intNum      = INT_DMA_ERR,
            .intPriority = ~0
        }
    };
    
    /* UDMA configuration structure */
    const UDMACC26XX_Config UDMACC26XX_config[] = {
        {
             .object  = &udmaObjects[0],
             .hwAttrs = &udmaHWAttrs[0]
        },
        {NULL, NULL}
    };
    /*
     *  ============================= UDMA end =====================================
     */
    
    /*
     *  ========================== SPI DMA begin ===================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(SPI_config, ".const:SPI_config")
    #pragma DATA_SECTION(spiCC26XXDMAHWAttrs, ".const:spiCC26XXDMAHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/spi/SPICC26XXDMA.h>
    
    /* SPI objects */
    SPICC26XXDMA_Object spiCC26XXDMAObjects[CC2650_LAUNCHXL_SPICOUNT];
    
    /* SPI configuration structure, describing which pins are to be used */
    const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[CC2650_LAUNCHXL_SPICOUNT] = {
        {
            .baseAddr           = SSI0_BASE,
            .intNum             = INT_SSI0_COMB,
            .intPriority        = ~0,
            .swiPriority        = 0,
            .powerMngrId        = PowerCC26XX_PERIPH_SSI0,
            .defaultTxBufValue  = 0,
            .rxChannelBitMask   = 1<<UDMA_CHAN_SSI0_RX,
            .txChannelBitMask   = 1<<UDMA_CHAN_SSI0_TX,
            .mosiPin            = Board_SPI0_MOSI,
            .misoPin            = Board_SPI0_MISO,
            .clkPin             = Board_SPI0_CLK,
            .csnPin             = Board_SPI0_CSN
        },
        {
            .baseAddr           = SSI1_BASE,
            .intNum             = INT_SSI1_COMB,
            .intPriority        = ~0,
            .swiPriority        = 0,
            .powerMngrId        = PowerCC26XX_PERIPH_SSI1,
            .defaultTxBufValue  = 0,
            .rxChannelBitMask   = 1<<UDMA_CHAN_SSI1_RX,
            .txChannelBitMask   = 1<<UDMA_CHAN_SSI1_TX,
            .mosiPin            = Board_SPI1_MOSI,
            .misoPin            = Board_SPI1_MISO,
            .clkPin             = Board_SPI1_CLK,
            .csnPin             = Board_SPI1_CSN
        }
    };
    
    /* SPI configuration structure */
    const SPI_Config SPI_config[] = {
        {
             .fxnTablePtr = &SPICC26XXDMA_fxnTable,
             .object      = &spiCC26XXDMAObjects[0],
             .hwAttrs     = &spiCC26XXDMAHWAttrs[0]
        },
        {
             .fxnTablePtr = &SPICC26XXDMA_fxnTable,
             .object      = &spiCC26XXDMAObjects[1],
             .hwAttrs     = &spiCC26XXDMAHWAttrs[1]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ========================== SPI DMA end =====================================
    */
    
    
    /*
     *  ============================= I2C Begin=====================================
    */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(I2C_config, ".const:I2C_config")
    #pragma DATA_SECTION(i2cCC26xxHWAttrs, ".const:i2cCC26xxHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/i2c/I2CCC26XX.h>
    
    /* I2C objects */
    I2CCC26XX_Object i2cCC26xxObjects[CC2650_LAUNCHXL_I2CCOUNT];
    
    /* I2C configuration structure, describing which pins are to be used */
    const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CC2650_LAUNCHXL_I2CCOUNT] = {
        {
            .baseAddr = I2C0_BASE,
            .powerMngrId = PowerCC26XX_PERIPH_I2C0,
            .intNum = INT_I2C_IRQ,
            .intPriority = ~0,
            .swiPriority = 0,
            .sdaPin = Board_I2C0_SDA0,
            .sclPin = Board_I2C0_SCL0,
        }
    };
    
    /* I2C configuration structure */
    const I2C_Config I2C_config[] = {
        {
            .fxnTablePtr = &I2CCC26XX_fxnTable,
            .object = &i2cCC26xxObjects[0],
            .hwAttrs = &i2cCC26xxHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    /*
     *  ========================== I2C end =========================================
     */
    
    /*
     *  ========================== Crypto begin ====================================
     *  NOTE: The Crypto implementation should be considered experimental
     *        and not validated!
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(CryptoCC26XX_config, ".const:CryptoCC26XX_config")
    #pragma DATA_SECTION(cryptoCC26XXHWAttrs, ".const:cryptoCC26XXHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/crypto/CryptoCC26XX.h>
    
    /* Crypto objects */
    CryptoCC26XX_Object cryptoCC26XXObjects[CC2650_LAUNCHXL_CRYPTOCOUNT];
    
    /* Crypto configuration structure, describing which pins are to be used */
    const CryptoCC26XX_HWAttrs cryptoCC26XXHWAttrs[CC2650_LAUNCHXL_CRYPTOCOUNT] = {
        {
            .baseAddr       = CRYPTO_BASE,
            .powerMngrId    = PowerCC26XX_PERIPH_CRYPTO,
            .intNum         = INT_CRYPTO_RESULT_AVAIL_IRQ,
            .intPriority    = ~0,
        }
    };
    
    /* Crypto configuration structure */
    const CryptoCC26XX_Config CryptoCC26XX_config[] = {
        {
             .object  = &cryptoCC26XXObjects[0],
             .hwAttrs = &cryptoCC26XXHWAttrs[0]
        },
        {NULL, NULL}
    };
    /*
     *  ========================== Crypto end ======================================
     */
    
    
    /*
     *  ========================= RF driver begin ==================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(RFCC26XX_hwAttrs, ".const:RFCC26XX_hwAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/rf/RF.h>
    
    /* RF hwi and swi priority */
    const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = {
        .hwiCpe0Priority = ~0,
        .hwiHwPriority   = ~0,
        .swiCpe0Priority =  0,
        .swiHwPriority   =  0,
    };
    
    /*
     *  ========================== RF driver end ===================================
     */
    
    /*
     *  ========================= Display begin ====================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(Display_config, ".const:Display_config")
    #pragma DATA_SECTION(displaySharpHWattrs, ".const:displaySharpHWattrs")
    #pragma DATA_SECTION(displayUartHWAttrs, ".const:displayUartHWAttrs")
    #endif
    
    #include <ti/mw/display/Display.h>
    #include <ti/mw/display/DisplaySharp.h>
    #include <ti/mw/display/DisplayUart.h>
    
    /* Structures for UartPlain Blocking */
    DisplayUart_Object        displayUartObject;
    
    #ifndef BOARD_DISPLAY_UART_STRBUF_SIZE
    #define BOARD_DISPLAY_UART_STRBUF_SIZE    128
    #endif
    static char uartStringBuf[BOARD_DISPLAY_UART_STRBUF_SIZE];
    
    const DisplayUart_HWAttrs displayUartHWAttrs = {
        .uartIdx      = Board_UART,
        .baudRate     =     115200,
        .mutexTimeout = BIOS_WAIT_FOREVER,
        .strBuf = uartStringBuf,
        .strBufLen = BOARD_DISPLAY_UART_STRBUF_SIZE,
    };
    
    /* Structures for SHARP */
    DisplaySharp_Object displaySharpObject;
    
    #ifndef BOARD_DISPLAY_SHARP_SIZE
    #define BOARD_DISPLAY_SHARP_SIZE    96 // 96->96x96 is the most common board, alternative is 128->128x128.
    #endif
    static uint8_t sharpDisplayBuf[BOARD_DISPLAY_SHARP_SIZE * BOARD_DISPLAY_SHARP_SIZE / 8];
    
    const DisplaySharp_HWAttrs displaySharpHWattrs = {
        .spiIndex    = Board_SPI0,
        .csPin       = Board_LCD_CS,
        .extcominPin = Board_LCD_EXTCOMIN,
        .powerPin    = Board_LCD_POWER,
        .enablePin   = Board_LCD_ENABLE,
        .pixelWidth  = BOARD_DISPLAY_SHARP_SIZE,
        .pixelHeight = BOARD_DISPLAY_SHARP_SIZE,
        .displayBuf  = sharpDisplayBuf,
    };
    
    /* Array of displays */
    const Display_Config Display_config[] = {
    #if !defined(BOARD_DISPLAY_EXCLUDE_UART)
        {
            .fxnTablePtr = &DisplayUart_fxnTable,
            .object      = &displayUartObject,
            .hwAttrs     = &displayUartHWAttrs,
        },
    #endif
    #if !defined(BOARD_DISPLAY_EXCLUDE_LCD)
        {
            .fxnTablePtr = &DisplaySharp_fxnTable,
            .object      = &displaySharpObject,
            .hwAttrs     = &displaySharpHWattrs
        },
    #endif
        { NULL, NULL, NULL } // Terminator
    };
    
    /*
     *  ========================= Display end ======================================
     */
    
    /*
     *  ============================ GPTimer begin =================================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(GPTimerCC26XX_config, ".const:GPTimerCC26XX_config")
    #pragma DATA_SECTION(gptimerCC26xxHWAttrs, ".const:gptimerCC26xxHWAttrs")
    #endif
    
    /* GPTimer hardware attributes, one per timer part (Timer 0A, 0B, 1A, 1B..) */
    const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[CC2650_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0A, },
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0B, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1A, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1B, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2A, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2B, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3A, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3B, },
    };
    
    /*  GPTimer objects, one per full-width timer (A+B) (Timer 0, Timer 1..) */
    GPTimerCC26XX_Object gptimerCC26XXObjects[CC2650_LAUNCHXL_GPTIMERCOUNT];
    
    /* GPTimer configuration (used as GPTimer_Handle by driver and application) */
    const GPTimerCC26XX_Config GPTimerCC26XX_config[CC2650_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[0], GPT_A },
        { &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[1], GPT_B },
        { &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[2], GPT_A },
        { &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[3], GPT_B },
        { &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[4], GPT_A },
        { &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[5], GPT_B },
        { &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[6], GPT_A },
        { &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[7], GPT_B },
    };
    
    /*
     *  ============================ GPTimer end ===================================
     */
    
    
    
    /*
     *  ============================= PWM begin ====================================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(PWM_config, ".const:PWM_config")
    #pragma DATA_SECTION(pwmtimerCC26xxHWAttrs, ".const:pwmtimerCC26xxHWAttrs")
    #endif
    
    /* PWM configuration, one per PWM output.   */
    PWMTimerCC26XX_HwAttrs pwmtimerCC26xxHWAttrs[CC2650_LAUNCHXL_PWMCOUNT] = {
        { .pwmPin = Board_PWMPIN0, .gpTimerUnit = Board_GPTIMER0A },
        { .pwmPin = Board_PWMPIN1, .gpTimerUnit = Board_GPTIMER0B },
        { .pwmPin = Board_PWMPIN2, .gpTimerUnit = Board_GPTIMER1A },
        { .pwmPin = Board_PWMPIN3, .gpTimerUnit = Board_GPTIMER1B },
        { .pwmPin = Board_PWMPIN4, .gpTimerUnit = Board_GPTIMER2A },
        { .pwmPin = Board_PWMPIN5, .gpTimerUnit = Board_GPTIMER2B },
        { .pwmPin = Board_PWMPIN6, .gpTimerUnit = Board_GPTIMER3A },
        { .pwmPin = Board_PWMPIN7, .gpTimerUnit = Board_GPTIMER3B },
    };
    
    /* PWM object, one per PWM output */
    PWMTimerCC26XX_Object pwmtimerCC26xxObjects[CC2650_LAUNCHXL_PWMCOUNT];
    
    extern const PWM_FxnTable PWMTimerCC26XX_fxnTable;
    
    /* PWM configuration (used as PWM_Handle by driver and application) */
    const PWM_Config PWM_config[CC2650_LAUNCHXL_PWMCOUNT + 1] = {
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[0], &pwmtimerCC26xxHWAttrs[0] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[1], &pwmtimerCC26xxHWAttrs[1] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[2], &pwmtimerCC26xxHWAttrs[2] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[3], &pwmtimerCC26xxHWAttrs[3] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[4], &pwmtimerCC26xxHWAttrs[4] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[5], &pwmtimerCC26xxHWAttrs[5] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[6], &pwmtimerCC26xxHWAttrs[6] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[7], &pwmtimerCC26xxHWAttrs[7] },
        { NULL,                NULL,                 NULL                 }
    };
    
    
    /*
     *  ============================= PWM end ======================================
     */
    
    /*
     *  ========================== ADCBuf begin =========================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(ADCBuf_config, ".const:ADCBuf_config")
    #pragma DATA_SECTION(adcBufCC26xxHWAttrs, ".const:adcBufCC26xxHWAttrs")
    #pragma DATA_SECTION(ADCBufCC26XX_adcChannelLut, ".const:ADCBufCC26XX_adcChannelLut")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/ADCBuf.h>
    #include <ti/drivers/adcbuf/ADCBufCC26XX.h>
    
    /* ADCBuf objects */
    ADCBufCC26XX_Object adcBufCC26xxObjects[CC2650_LAUNCHXL_ADCBufCOUNT];
    
    /*
     *  This table converts a virtual adc channel into a dio and internal analogue input signal.
     *  This table is necessary for the functioning of the adcBuf driver.
     *  Comment out unused entries to save flash.
     *  Dio and internal signal pairs are hardwired. Do not remap them in the table. You may reorder entire entries though.
     *  The mapping of dio and internal signals is package dependent.
     */
    const ADCBufCC26XX_AdcChannelLutEntry ADCBufCC26XX_adcChannelLut[] = {
        {PIN_UNASSIGNED, ADC_COMPB_IN_VDDS},
        {PIN_UNASSIGNED, ADC_COMPB_IN_DCOUPL},
        {PIN_UNASSIGNED, ADC_COMPB_IN_VSS},
        {Board_DIO23_ANALOG, ADC_COMPB_IN_AUXIO7},
        {Board_DIO24_ANALOG, ADC_COMPB_IN_AUXIO6},
        {Board_DIO25_ANALOG, ADC_COMPB_IN_AUXIO5},
        {Board_DIO26_ANALOG, ADC_COMPB_IN_AUXIO4},
        {Board_DIO27_ANALOG, ADC_COMPB_IN_AUXIO3},
        {Board_DIO28_ANALOG, ADC_COMPB_IN_AUXIO2},
        {Board_DIO29_ANALOG, ADC_COMPB_IN_AUXIO1},
        {Board_DIO30_ANALOG, ADC_COMPB_IN_AUXIO0},
    };
    
    const ADCBufCC26XX_HWAttrs adcBufCC26xxHWAttrs[CC2650_LAUNCHXL_ADCBufCOUNT] = {
        {
            .intPriority = ~0,
            .swiPriority = 0,
            .adcChannelLut = ADCBufCC26XX_adcChannelLut,
            .gpTimerUnit = Board_GPTIMER0A,
            .gptDMAChannelMask = 1 << UDMA_CHAN_TIMER0_A,
        }
    };
    
    const ADCBuf_Config ADCBuf_config[] = {
        {&ADCBufCC26XX_fxnTable, &adcBufCC26xxObjects[0], &adcBufCC26xxHWAttrs[0]},
        {NULL, NULL, NULL},
    };
    /*
     *  ========================== ADCBuf end =========================================
     */
    
    
    
    /*
     *  ========================== ADC begin =========================================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(ADC_config, ".const:ADC_config")
    #pragma DATA_SECTION(adcCC26xxHWAttrs, ".const:adcCC26xxHWAttrs")
    #endif
    
    /* Include drivers */
    #include <ti/drivers/ADC.h>
    #include <ti/drivers/adc/ADCCC26XX.h>
    
    /* ADC objects */
    ADCCC26XX_Object adcCC26xxObjects[CC2650_LAUNCHXL_ADCCOUNT];
    
    
    const ADCCC26XX_HWAttrs adcCC26xxHWAttrs[CC2650_LAUNCHXL_ADCCOUNT] = {
        {
            .adcDIO = Board_DIO23_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO7,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO24_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO6,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO25_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO5,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO26_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO4,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO27_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO3,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO28_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO2,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO29_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO1,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = Board_DIO30_ANALOG,
            .adcCompBInput = ADC_COMPB_IN_AUXIO0,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_10P9_MS,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_DCOUPL,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_VSS,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        },
        {
            .adcDIO = PIN_UNASSIGNED,
            .adcCompBInput = ADC_COMPB_IN_VDDS,
            .refSource = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .triggerSource = ADCCC26XX_TRIGGER_MANUAL
        }
    };
    
    const ADC_Config ADC_config[] = {
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[0], &adcCC26xxHWAttrs[0]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[1], &adcCC26xxHWAttrs[1]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[2], &adcCC26xxHWAttrs[2]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[3], &adcCC26xxHWAttrs[3]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[4], &adcCC26xxHWAttrs[4]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[5], &adcCC26xxHWAttrs[5]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[6], &adcCC26xxHWAttrs[6]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[7], &adcCC26xxHWAttrs[7]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[8], &adcCC26xxHWAttrs[8]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[9], &adcCC26xxHWAttrs[9]},
        {&ADCCC26XX_fxnTable, &adcCC26xxObjects[10], &adcCC26xxHWAttrs[10]},
        {NULL, NULL, NULL},
    };
    
    /*
     *  ========================== ADC end =========================================
     */
    
    CC2650_LAUNCHXL.h

  • What's your ccs version and the compiler version used on CCS?
  • CCS Version: 6.1.3.00033

    TI Compiler 15.12.3 LTS
  • NEWS

    I decided to uncomment the fxn table, and here is the console :

    undefined first referenced
    symbol in file
    --------- ----------------
    GPTimerCC26XX_Params_init <whole-program>
    GPTimerCC26XX_close <whole-program>
    GPTimerCC26XX_configureDebugStall <whole-program>
    GPTimerCC26XX_open <whole-program>
    GPTimerCC26XX_setLoadValue <whole-program>
    GPTimerCC26XX_setMatchValue <whole-program>
    GPTimerCC26XX_start <whole-program>
    GPTimerCC26XX_stop <whole-program>

    error #10234-D: unresolved symbols remain
    error #10010: errors encountered during linking; "LED_simple_peripheral_cc2650lp_app.out" not built
    gmake: *** [LED_simple_peripheral_cc2650lp_app.out] Error 1

    >> Compilation failure
    makefile:194: recipe for target 'LED_simple_peripheral_cc2650lp_app.out' failed
    gmake: Target 'all' not remade because of errors.

    **** Build Finished ****


    What's wrong ?

    Thank you
  • Sorry for the delay, we are currently investigating this, will get back to you asap.
  • FIXED

    Solution :

    I replaced :
    #include "ti/drivers/timer/GPTimerCC26XX.h" into PWMTimerCC26XX.c

    with :
    #include "ti/drivers/timer/GPTimerCC26XX.c"
  • Hi,

    You should not need to do that. Can you revert the changes and try delete the FlashROM folder and rebuild it.

  • Thank you, it's ok now