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.

CC2652R7: CC2652R7 - Connecting two slave devices with I2C0 bus and trying to access parallely

Part Number: CC2652R7

Hi Team

We are connecting two I2C devices in the I2C0 bus to the controller

The slave address of the two device is 0x28 and 0x29

The issue what we are facing is when we run separately two threads, its working seems to be fine

Whereas when we run parallely we are not able to communicate with the slave device that ie slave address is even not getting acknowledged 

Can you please help here?

can you let us know what could be the issue?

  • Hi,

    Can you share more information:

    1. Logic analyzer shot of both cases (working and not-working)
    2. Code for both cases (code snippets first)

    The I2C TI Driver uses a semaphore which should accommodate for multiple accesses. (Note only one I2C transaction can occur at a time).


    Thanks,
    Toby

  • Hi 

    The I2C TI Driver uses a semaphore which should accommodate for multiple accesses. (Note only one I2C transaction can occur at a time) ==> Even we checked your driver and found the same but in our case its is not working.

    We cannot share the code because of the copyrights 

    Can you please help us like what could be the possible mistakes we might be doing. I am sharing the some inputs for your reference

    1. Our i2c handle is still open and it is not getting closed

    2. Independent threads are working fine with no issues

    3. Even we have implemeneted pthread_mutex_lock and pthread_mutex_unlock in the appliactions

    4. One issue which we found is when 0x29 slave is not acknowledged, after this instance 0x28 is also getting failed that is acknowledgement is not coming 

    Please help us

  • Is this on a custom board?

  • Hi Team

    This is not the custom board 

    We are using the CC2652-R7 launchpad 

    We are connecting the both the slave devices to the DIO4 and DIO5

  • Hi 

    Do you have pull-up resistors, as hinted by this thread: ==> 

    What is the status of the I2C_transfer when it fails? ==> The status is I2C_STATUS_DATA_NACK

    " Display_printf(display, 0, 0, "I2C target address 0x%x not"
    " acknowledged!",
    transaction->targetAddress);"

  • Do you have pull-up resistors, as hinted by this thread: ==> 

    Is this a yes or a no? Do you a have pull-up resistor?

    Can you share your I2C configuration?
    This may be accomplished by sharing the ti_drivers_config.c/h files or the .syscfg file.

  • Hi

    Is this a yes or a no? Do you a have pull-up resistor? ==> yes we have

    This may be accomplished by sharing the ti_drivers_config.c/h files or the .syscfg file. ==> Please find the attached file

    6683.ti_drivers_config.h

  • I only see the .h file

    Please also share the .c file.

  • HI 

    I am attaching the .c file 

    Please check 

    1423.ti_drivers_config.c
    /*
     *  ======== ti_drivers_config.c ========
     *  Configured TI-Drivers module definitions
     *
     *  DO NOT EDIT - This file is generated for the LP_CC2652R7
     *  by the SysConfig tool.
     */
    
    #include <stddef.h>
    #include <stdint.h>
    
    #ifndef DeviceFamily_CC26X2X7
    #define DeviceFamily_CC26X2X7
    #endif
    
    #include <ti/devices/DeviceFamily.h>
    
    #include "ti_drivers_config.h"
    
    /*
     *  ============================= Display =============================
     */
    
    #include <ti/display/Display.h>
    #include <ti/display/DisplayUart2.h>
    
    #define CONFIG_Display_COUNT 1
    
    
    #define Display_UART2BUFFERSIZE 128
    static char displayUART2Buffer[Display_UART2BUFFERSIZE];
    
    DisplayUart2_Object displayUart2Object;
    
    const DisplayUart2_HWAttrs displayUart2HWAttrs = {
        .uartIdx      = CONFIG_DISPLAY_UART,
        .baudRate     = 115200,
        .mutexTimeout = (unsigned int)(-1),
        .strBuf       = displayUART2Buffer,
        .strBufLen    = Display_UART2BUFFERSIZE
    };
    
    const Display_Config Display_config[CONFIG_Display_COUNT] = {
        /* CONFIG_Display_0 */
        /* XDS110 UART */
        {
            .fxnTablePtr = &DisplayUart2Min_fxnTable,
            .object      = &displayUart2Object,
            .hwAttrs     = &displayUart2HWAttrs
        },
    };
    
    const uint_least8_t Display_count = CONFIG_Display_COUNT;
    
    /*
     *  =============================== ADC ===============================
     */
    
    #include <ti/drivers/ADC.h>
    #include <ti/drivers/adc/ADCCC26XX.h>
    #include <ti/drivers/GPIO.h>
    
    #define CONFIG_ADC_COUNT 2
    
    /*
     *  ======== adcCC26xxObjects ========
     */
    ADCCC26XX_Object adcCC26xxObjects[CONFIG_ADC_COUNT];
    
    /*
     *  ======== adcCC26xxHWAttrs ========
     */
    const ADCCC26XX_HWAttrs adcCC26xxHWAttrs[CONFIG_ADC_COUNT] = {
        /* CONFIG_ADC_THERMISTOR */
        {
            .adcDIO              = CONFIG_GPIO_ADC_THERMISTOR_AIN,
            .adcCompBInput       = ADC_COMPB_IN_AUXIO5,
            .refSource           = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration    = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .refVoltage          = 3300000,
            .triggerSource       = ADCCC26XX_TRIGGER_MANUAL,
            .returnAdjustedVal   = false
        },
        /* CONFIG_ADC_BATTERY_VOLT */
        {
            .adcDIO              = CONFIG_GPIO_ADC_BATTERY_VOLT_AIN,
            .adcCompBInput       = ADC_COMPB_IN_AUXIO2,
            .refSource           = ADCCC26XX_FIXED_REFERENCE,
            .samplingDuration    = ADCCC26XX_SAMPLING_DURATION_2P7_US,
            .inputScalingEnabled = true,
            .refVoltage          = 3300000,
            .triggerSource       = ADCCC26XX_TRIGGER_MANUAL,
            .returnAdjustedVal   = false
        },
    };
    
    /*
     *  ======== ADC_config ========
     */
    const ADC_Config ADC_config[CONFIG_ADC_COUNT] = {
        /* CONFIG_ADC_THERMISTOR */
        {
            .fxnTablePtr = &ADCCC26XX_fxnTable,
            .object = &adcCC26xxObjects[CONFIG_ADC_THERMISTOR],
            .hwAttrs = &adcCC26xxHWAttrs[CONFIG_ADC_THERMISTOR]
        },
        /* CONFIG_ADC_BATTERY_VOLT */
        {
            .fxnTablePtr = &ADCCC26XX_fxnTable,
            .object = &adcCC26xxObjects[CONFIG_ADC_BATTERY_VOLT],
            .hwAttrs = &adcCC26xxHWAttrs[CONFIG_ADC_BATTERY_VOLT]
        },
    };
    
    const uint_least8_t CONFIG_ADC_THERMISTOR_CONST = CONFIG_ADC_THERMISTOR;
    const uint_least8_t CONFIG_ADC_BATTERY_VOLT_CONST = CONFIG_ADC_BATTERY_VOLT;
    const uint_least8_t ADC_count = CONFIG_ADC_COUNT;
    
    /*
     *  =============================== AESCCM ===============================
     */
    
    #include <ti/drivers/AESCCM.h>
    #include <ti/drivers/aesccm/AESCCMCC26XX.h>
    
    #define CONFIG_AESCCM_COUNT 1
    AESCCMCC26XX_Object aesccmCC26XXObjects[CONFIG_AESCCM_COUNT];
    
    /*
     *  ======== aesccmCC26XXHWAttrs ========
     */
    const AESCCMCC26XX_HWAttrs aesccmCC26XXHWAttrs[CONFIG_AESCCM_COUNT] = {
        {
            .intPriority = (~0),
        },
    };
    
    const AESCCM_Config AESCCM_config[CONFIG_AESCCM_COUNT] = {
        {   /* CONFIG_AESCCM0 */
            .object  = &aesccmCC26XXObjects[CONFIG_AESCCM0],
            .hwAttrs = &aesccmCC26XXHWAttrs[CONFIG_AESCCM0]
        },
    };
    
    const uint_least8_t CONFIG_AESCCM0_CONST = CONFIG_AESCCM0;
    const uint_least8_t AESCCM_count = CONFIG_AESCCM_COUNT;
    
    /*
     *  =============================== AESCTRDRBG ===============================
     */
    
    #include <ti/drivers/AESCTRDRBG.h>
    #include <ti/drivers/aesctrdrbg/AESCTRDRBGXX.h>
    
    #define CONFIG_AESCTRDRBG_COUNT 1
    
    /*
     *  ======== aesctrdrbgXXObjects ========
     */
    AESCTRDRBGXX_Object aesctrdrbgXXObjects[CONFIG_AESCTRDRBG_COUNT];
    
    /*
     *  ======== aesctrdrbgXXHWAttrs ========
     */
    const AESCTRDRBGXX_HWAttrs aesctrdrbgXXHWAttrs[CONFIG_AESCTRDRBG_COUNT] = {
        /* CONFIG_AESCTRDRBG_0 */
        {
            .aesctrHWAttrs.intPriority = (~0)
        },
    };
    
    /*
     *  ======== AESCTRDRBG_config ========
     */
    const AESCTRDRBG_Config AESCTRDRBG_config[CONFIG_AESCTRDRBG_COUNT] = {
        /* CONFIG_AESCTRDRBG_0 */
        {
            .object = &aesctrdrbgXXObjects[CONFIG_AESCTRDRBG_0],
            .hwAttrs = &aesctrdrbgXXHWAttrs[CONFIG_AESCTRDRBG_0]
        },
    };
    
    const uint_least8_t CONFIG_AESCTRDRBG_0_CONST = CONFIG_AESCTRDRBG_0;
    const uint_least8_t AESCTRDRBG_count = CONFIG_AESCTRDRBG_COUNT;
    
    /*
     *  =============================== AESECB ===============================
     */
    
    #include <ti/drivers/AESECB.h>
    #include <ti/drivers/aesecb/AESECBCC26XX.h>
    
    #define CONFIG_AESECB_COUNT 1
    
    
    AESECBCC26XX_Object aesecbCC26XXObjects[CONFIG_AESECB_COUNT];
    
    /*
     *  ======== aesecbCC26XXHWAttrs ========
     */
    const AESECBCC26XX_HWAttrs aesecbCC26XXHWAttrs[CONFIG_AESECB_COUNT] = {
        {
            .intPriority = (~0),
        },
    };
    
    const AESECB_Config AESECB_config[CONFIG_AESECB_COUNT] = {
        {   /* CONFIG_AESECB0 */
            .object  = &aesecbCC26XXObjects[CONFIG_AESECB0],
            .hwAttrs = &aesecbCC26XXHWAttrs[CONFIG_AESECB0]
        },
    };
    
    
    const uint_least8_t CONFIG_AESECB0_CONST = CONFIG_AESECB0;
    const uint_least8_t AESECB_count = CONFIG_AESECB_COUNT;
    
    /*
     *  =============================== DMA ===============================
     */
    
    #include <ti/drivers/dma/UDMACC26XX.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/driverlib/udma.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_memmap.h>
    
    UDMACC26XX_Object udmaCC26XXObject;
    
    const UDMACC26XX_HWAttrs udmaCC26XXHWAttrs = {
        .baseAddr        = UDMA0_BASE,
        .powerMngrId     = PowerCC26XX_PERIPH_UDMA,
        .intNum          = INT_DMA_ERR,
        .intPriority     = (~0)
    };
    
    const UDMACC26XX_Config UDMACC26XX_config[1] = {
        {
            .object         = &udmaCC26XXObject,
            .hwAttrs        = &udmaCC26XXHWAttrs,
        },
    };
    
    /*
     *  =============================== ECDH ===============================
     */
    
    #include <ti/drivers/ECDH.h>
    #include <ti/drivers/ecdh/ECDHCC26X2.h>
    
    #define CONFIG_ECDH_COUNT 1
    
    
    ECDHCC26X2_Object ecdhCC26X2Objects[CONFIG_ECDH_COUNT];
    
    /*
     *  ======== ecdhCC26X2HWAttrs ========
     */
    const ECDHCC26X2_HWAttrs ecdhCC26X2HWAttrs[CONFIG_ECDH_COUNT] = {
        {
            .intPriority = (~0),
        },
    };
    
    const ECDH_Config ECDH_config[CONFIG_ECDH_COUNT] = {
        {   /* CONFIG_ECDH0 */
            .object         = &ecdhCC26X2Objects[CONFIG_ECDH0],
            .hwAttrs        = &ecdhCC26X2HWAttrs[CONFIG_ECDH0]
        },
    };
    
    const uint_least8_t CONFIG_ECDH0_CONST = CONFIG_ECDH0;
    const uint_least8_t ECDH_count = CONFIG_ECDH_COUNT;
    
    /*
     *  =============================== GPIO ===============================
     */
    
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/gpio/GPIOCC26XX.h>
    
    /* The range of pins available on this device */
    const uint_least8_t GPIO_pinLowerBound = 0;
    const uint_least8_t GPIO_pinUpperBound = 30;
    
    /*
     *  ======== gpioPinConfigs ========
     *  Array of Pin configurations
     */
    GPIO_PinConfig gpioPinConfigs[31] = {
        GPIO_CFG_NO_DIR, /* DIO_0 */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_RISING | GPIO_CFG_PULL_NONE_INTERNAL, /* OR */
        /* Owned by CONFIG_DISPLAY_UART as RX */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_UART_RX */
        /* Owned by CONFIG_DISPLAY_UART as TX */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, /* CONFIG_GPIO_UART_TX */
        /* Owned by CONFIG_I2C_MS as SDA */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_UP_INTERNAL, /* CONFIG_GPIO_I2C_MS_SDA */
        /* Owned by CONFIG_I2C_MS as SCL */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_UP_INTERNAL, /* CONFIG_GPIO_I2C_MS_SCL */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_BOTH_EDGES | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_IMU_INT */
        /* Owned by CONFIG_SPI_ICM as POCI */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_SPI_ICM_POCI */
        /* Owned by CONFIG_SPI_ICM as PICO */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_SPI_ICM_PICO */
        /* Owned by CONFIG_SPI_ICM as SCLK */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_SPI_ICM_SCLK */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_IMU_CS */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* MS1_NRST */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* MS2_NRST */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_BTN1 */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_BTN2 */
        GPIO_CFG_NO_DIR, /* DIO_15 */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_RISING | GPIO_CFG_PULL_NONE_INTERNAL, /* MS2_DET */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_RISING | GPIO_CFG_PULL_NONE_INTERNAL, /* MS1_DET */
        GPIO_CFG_NO_DIR, /* DIO_18 */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* MS1_CE */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* MS2_CE */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_RISING | GPIO_CFG_PULL_NONE_INTERNAL, /* MS2_OR */
        /* Owned by CONFIG_GPTIMER_0 as PWM Pin */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_PWM_0 */
        /* Owned by CONFIG_UART2_QCS as TX */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, /* CONFIG_GPIO_UART2_QCS_TX */
        /* Owned by CONFIG_UART2_QCS as RX */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_UART2_QCS_RX */
        /* Owned by CONFIG_ADC_THERMISTOR as ADC Pin */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_ADC_THERMISTOR_AIN */
        /* Owned by CONFIG_GPTIMER_1 as PWM Pin */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_PWM_1 */
        GPIO_CFG_NO_DIR, /* DIO_27 */
        /* Owned by CONFIG_ADC_BATTERY_VOLT as ADC Pin */
        GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_NONE_INTERNAL, /* CONFIG_GPIO_ADC_BATTERY_VOLT_AIN */
        /* Owned by CONFIG_GPTIMER_2 as PWM Pin */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_PWM_2 */
        /* Owned by CONFIG_GPTIMER_3 as PWM Pin */
        GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_PWM_3 */
    };
    
    /*
     *  ======== gpioCallbackFunctions ========
     *  Array of callback function pointers
     *  Change at runtime with GPIO_setCallback()
     */
    GPIO_CallbackFxn gpioCallbackFunctions[31];
    
    /*
     *  ======== gpioUserArgs ========
     *  Array of user argument pointers
     *  Change at runtime with GPIO_setUserArg()
     *  Get values with GPIO_getUserArg()
     */
    void* gpioUserArgs[31];
    
    const uint_least8_t CONFIG_GPIO_ADC_THERMISTOR_AIN_CONST = CONFIG_GPIO_ADC_THERMISTOR_AIN;
    const uint_least8_t CONFIG_GPIO_ADC_BATTERY_VOLT_AIN_CONST = CONFIG_GPIO_ADC_BATTERY_VOLT_AIN;
    const uint_least8_t CONFIG_GPIO_BTN1_CONST = CONFIG_GPIO_BTN1;
    const uint_least8_t CONFIG_GPIO_BTN2_CONST = CONFIG_GPIO_BTN2;
    const uint_least8_t MS1_CE_CONST = MS1_CE;
    const uint_least8_t MS1_NRST_CONST = MS1_NRST;
    const uint_least8_t MS1_DET_CONST = MS1_DET;
    const uint_least8_t OR_CONST = OR;
    const uint_least8_t MS2_CE_CONST = MS2_CE;
    const uint_least8_t MS2_DET_CONST = MS2_DET;
    const uint_least8_t MS2_OR_CONST = MS2_OR;
    const uint_least8_t MS2_NRST_CONST = MS2_NRST;
    const uint_least8_t CONFIG_GPIO_IMU_INT_CONST = CONFIG_GPIO_IMU_INT;
    const uint_least8_t CONFIG_IMU_CS_CONST = CONFIG_IMU_CS;
    const uint_least8_t CONFIG_GPIO_I2C_MS_SDA_CONST = CONFIG_GPIO_I2C_MS_SDA;
    const uint_least8_t CONFIG_GPIO_I2C_MS_SCL_CONST = CONFIG_GPIO_I2C_MS_SCL;
    const uint_least8_t CONFIG_GPIO_PWM_0_CONST = CONFIG_GPIO_PWM_0;
    const uint_least8_t CONFIG_GPIO_PWM_1_CONST = CONFIG_GPIO_PWM_1;
    const uint_least8_t CONFIG_GPIO_PWM_2_CONST = CONFIG_GPIO_PWM_2;
    const uint_least8_t CONFIG_GPIO_PWM_3_CONST = CONFIG_GPIO_PWM_3;
    const uint_least8_t CONFIG_GPIO_SPI_ICM_SCLK_CONST = CONFIG_GPIO_SPI_ICM_SCLK;
    const uint_least8_t CONFIG_GPIO_SPI_ICM_POCI_CONST = CONFIG_GPIO_SPI_ICM_POCI;
    const uint_least8_t CONFIG_GPIO_SPI_ICM_PICO_CONST = CONFIG_GPIO_SPI_ICM_PICO;
    const uint_least8_t CONFIG_GPIO_UART2_QCS_TX_CONST = CONFIG_GPIO_UART2_QCS_TX;
    const uint_least8_t CONFIG_GPIO_UART2_QCS_RX_CONST = CONFIG_GPIO_UART2_QCS_RX;
    const uint_least8_t CONFIG_GPIO_UART_TX_CONST = CONFIG_GPIO_UART_TX;
    const uint_least8_t CONFIG_GPIO_UART_RX_CONST = CONFIG_GPIO_UART_RX;
    
    /*
     *  ======== GPIO_config ========
     */
    const GPIO_Config GPIO_config = {
        .configs = (GPIO_PinConfig *)gpioPinConfigs,
        .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,
        .userArgs = gpioUserArgs,
        .intPriority = (~0)
    };
    
    /*
     *  =============================== I2C ===============================
     */
    
    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CCC26XX.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(inc/hw_ints.h)
    #include DeviceFamily_constructPath(inc/hw_memmap.h)
    #include DeviceFamily_constructPath(driverlib/ioc.h)
    
    #define CONFIG_I2C_COUNT 1
    
    /*
     *  ======== i2cCC26xxObjects ========
     */
    I2CCC26XX_Object i2cCC26xxObjects[CONFIG_I2C_COUNT];
    
    /*
     *  ======== i2cCC26xxHWAttrs ========
     */
    const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CONFIG_I2C_COUNT] = {
        /* CONFIG_I2C_MS */
        {
            .baseAddr    = I2C0_BASE,
            .powerMngrId = PowerCC26XX_PERIPH_I2C0,
            .intNum      = INT_I2C_IRQ,
            .intPriority = (~0),
            .swiPriority = 0,
            .sclPin      = CONFIG_GPIO_I2C_MS_SCL,
            .sclPinMux   = IOC_PORT_MCU_I2C_MSSCL,
            .sdaPin      = CONFIG_GPIO_I2C_MS_SDA,
            .sdaPinMux   = IOC_PORT_MCU_I2C_MSSDA
        },
    };
    
    /*
     *  ======== I2C_config ========
     */
    const I2C_Config I2C_config[CONFIG_I2C_COUNT] = {
        /* CONFIG_I2C_MS */
        {
            .object      = &i2cCC26xxObjects[CONFIG_I2C_MS],
            .hwAttrs     = &i2cCC26xxHWAttrs[CONFIG_I2C_MS]
        },
    };
    
    const uint_least8_t CONFIG_I2C_MS_CONST = CONFIG_I2C_MS;
    const uint_least8_t I2C_count = CONFIG_I2C_COUNT;
    
    /*
     *  =============================== NVS ===============================
     */
    
    #include <ti/drivers/NVS.h>
    #include <ti/drivers/nvs/NVSCC26XX.h>
    
    /*
     *  NVSCC26XX Internal NVS flash region definitions
     *
     * Place uninitialized char arrays at addresses
     * corresponding to the 'regionBase' addresses defined in
     * the configured NVS regions. These arrays are used as
     * place holders so that the linker will not place other
     * content there.
     *
     * For GCC targets, the char arrays are each placed into
     * the shared ".nvs" section. The user must add content to
     * their GCC linker command file to place the .nvs section
     * at the lowest 'regionBase' address specified in their NVS
     * regions.
     */
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__clang__)
    
    static char flashBuf0[0x4000] __attribute__ ((retain, noinit, location(0x48000)));
    
    #elif defined(__IAR_SYSTEMS_ICC__)
    
    __no_init static char flashBuf0[0x4000] @ 0x48000;
    
    #elif defined(__GNUC__)
    
    __attribute__ ((section (".nvs")))
    static char flashBuf0[0x4000];
    
    #endif
    
    NVSCC26XX_Object nvsCC26XXObjects[1];
    
    static const NVSCC26XX_HWAttrs nvsCC26XXHWAttrs[1] = {
        /* CONFIG_NVSINTERNAL */
        {
            .regionBase = (void *) flashBuf0,
            .regionSize = 0x4000
        },
    };
    
    #define CONFIG_NVS_COUNT 1
    
    const NVS_Config NVS_config[CONFIG_NVS_COUNT] = {
        /* CONFIG_NVSINTERNAL */
        {
            .fxnTablePtr = &NVSCC26XX_fxnTable,
            .object = &nvsCC26XXObjects[0],
            .hwAttrs = &nvsCC26XXHWAttrs[0],
        },
    };
    
    const uint_least8_t CONFIG_NVSINTERNAL_CONST = CONFIG_NVSINTERNAL;
    const uint_least8_t NVS_count = CONFIG_NVS_COUNT;
    
    /*
     *  =============================== PWM ===============================
     */
    
    #include <ti/drivers/PWM.h>
    #include <ti/drivers/pwm/PWMTimerCC26XX.h>
    
    /* include driverlib definitions */
    #include <ti/devices/cc13x2x7_cc26x2x7/driverlib/ioc.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_ints.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_memmap.h>
    
    #define CONFIG_PWM_COUNT 4
    
    /*
     *  ======== pwmCC26XXObjects ========
     */
    PWMTimerCC26XX_Object pwmTimerCC26XXObjects[CONFIG_PWM_COUNT];
    
    /*
     *  ======== pwmCC26XXHWAttrs ========
     */
    const PWMTimerCC26XX_HwAttrs pwmTimerCC26XXHWAttrs[CONFIG_PWM_COUNT] = {
        /* CONFIG_PWM_R */
        {
            .pwmPin = CONFIG_GPIO_PWM_0,
            .gpTimerUnit = CONFIG_GPTIMER_0
        },
        /* CONFIG_PWM_G */
        {
            .pwmPin = CONFIG_GPIO_PWM_1,
            .gpTimerUnit = CONFIG_GPTIMER_1
        },
        /* CONFIG_PWM_B */
        {
            .pwmPin = CONFIG_GPIO_PWM_2,
            .gpTimerUnit = CONFIG_GPTIMER_2
        },
        /* CONFIG_PWM_FAN */
        {
            .pwmPin = CONFIG_GPIO_PWM_3,
            .gpTimerUnit = CONFIG_GPTIMER_3
        },
    };
    
    /*
     *  ======== PWM_config ========
     */
    const PWM_Config PWM_config[CONFIG_PWM_COUNT] = {
        /* CONFIG_PWM_R */
        {
            .fxnTablePtr = &PWMTimerCC26XX_fxnTable,
            .object = &pwmTimerCC26XXObjects[CONFIG_PWM_R],
            .hwAttrs = &pwmTimerCC26XXHWAttrs[CONFIG_PWM_R]
        },
        /* CONFIG_PWM_G */
        {
            .fxnTablePtr = &PWMTimerCC26XX_fxnTable,
            .object = &pwmTimerCC26XXObjects[CONFIG_PWM_G],
            .hwAttrs = &pwmTimerCC26XXHWAttrs[CONFIG_PWM_G]
        },
        /* CONFIG_PWM_B */
        {
            .fxnTablePtr = &PWMTimerCC26XX_fxnTable,
            .object = &pwmTimerCC26XXObjects[CONFIG_PWM_B],
            .hwAttrs = &pwmTimerCC26XXHWAttrs[CONFIG_PWM_B]
        },
        /* CONFIG_PWM_FAN */
        {
            .fxnTablePtr = &PWMTimerCC26XX_fxnTable,
            .object = &pwmTimerCC26XXObjects[CONFIG_PWM_FAN],
            .hwAttrs = &pwmTimerCC26XXHWAttrs[CONFIG_PWM_FAN]
        },
    };
    
    const uint_least8_t CONFIG_PWM_R_CONST = CONFIG_PWM_R;
    const uint_least8_t CONFIG_PWM_G_CONST = CONFIG_PWM_G;
    const uint_least8_t CONFIG_PWM_B_CONST = CONFIG_PWM_B;
    const uint_least8_t CONFIG_PWM_FAN_CONST = CONFIG_PWM_FAN;
    const uint_least8_t PWM_count = CONFIG_PWM_COUNT;
    
    /*
     *  =============================== Power ===============================
     */
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26X2.h>
    #include "ti_drivers_config.h"
    
    extern void PowerCC26XX_standbyPolicy(void);
    extern bool PowerCC26XX_calibrate(unsigned int);
    
    const PowerCC26X2_Config PowerCC26X2_config = {
        .enablePolicy             = true,
        .policyInitFxn            = NULL,
        .policyFxn                = PowerCC26XX_standbyPolicy,
        .calibrateFxn             = PowerCC26XX_calibrate,
        .calibrateRCOSC_LF        = true,
        .calibrateRCOSC_HF        = true,
        .enableTCXOFxn            = NULL
    };
    
    
    
    /*
     *  =============================== RF Driver ===============================
     */
    #include <ti/drivers/GPIO.h>
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(driverlib/ioc.h)
    #include <ti/drivers/rf/RF.h>
    
    /*
     * Platform-specific driver configuration
     */
    const RFCC26XX_HWAttrsV2 RFCC26XX_hwAttrs = {
        .hwiPriority        = (~0),
        .swiPriority        = (uint8_t)0,
        .xoscHfAlwaysNeeded = true,
        .globalCallback     = NULL,
        .globalEventMask    = 0
    };
    
    
    /*
     *  =============================== SPI DMA ===============================
     */
    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPICC26X2DMA.h>
    #include <ti/drivers/dma/UDMACC26XX.h>
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(driverlib/ioc.h)
    
    #define CONFIG_SPI_COUNT 1
    
    /*
     *  ======== spiCC26X2DMAObjects ========
     */
    SPICC26X2DMA_Object spiCC26X2DMAObjects[CONFIG_SPI_COUNT];
    
    /*
     * ======== spiCC26X2DMA uDMA Table Entries  ========
     */
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaSpi0TxControlTableEntry, UDMA_CHAN_SSI0_TX);
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaSpi0RxControlTableEntry, UDMA_CHAN_SSI0_RX);
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaSpi0TxAltControlTableEntry, (UDMA_CHAN_SSI0_TX | UDMA_ALT_SELECT));
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaSpi0RxAltControlTableEntry, (UDMA_CHAN_SSI0_RX | UDMA_ALT_SELECT));
    
    
    /*
     *  ======== spiCC26X2DMAHWAttrs ========
     */
    const SPICC26X2DMA_HWAttrs spiCC26X2DMAHWAttrs[CONFIG_SPI_COUNT] = {
        /* CONFIG_SPI_ICM */
        {
            .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,
            .dmaTxTableEntryPri = &dmaSpi0TxControlTableEntry,
            .dmaRxTableEntryPri = &dmaSpi0RxControlTableEntry,
            .dmaTxTableEntryAlt = &dmaSpi0TxAltControlTableEntry,
            .dmaRxTableEntryAlt = &dmaSpi0RxAltControlTableEntry,
            .minDmaTransferSize = 10,
            .txPinMux    = IOC_PORT_MCU_SSI0_TX,
            .rxPinMux    = IOC_PORT_MCU_SSI0_RX,
            .clkPinMux   = IOC_PORT_MCU_SSI0_CLK,
            .csnPinMux   = IOC_PORT_MCU_SSI0_FSS,
            .picoPin = CONFIG_GPIO_SPI_ICM_PICO,
            .pociPin = CONFIG_GPIO_SPI_ICM_POCI,
            .clkPin  = CONFIG_GPIO_SPI_ICM_SCLK,
            .csnPin  = GPIO_INVALID_INDEX
        },
    };
    
    /*
     *  ======== SPI_config ========
     */
    const SPI_Config SPI_config[CONFIG_SPI_COUNT] = {
        /* CONFIG_SPI_ICM */
        {
            .fxnTablePtr = &SPICC26X2DMA_fxnTable,
            .object = &spiCC26X2DMAObjects[CONFIG_SPI_ICM],
            .hwAttrs = &spiCC26X2DMAHWAttrs[CONFIG_SPI_ICM]
        },
    };
    
    const uint_least8_t CONFIG_SPI_ICM_CONST = CONFIG_SPI_ICM;
    const uint_least8_t SPI_count = CONFIG_SPI_COUNT;
    
    /*
     *  =============================== TRNG ===============================
     */
    
    #include <ti/drivers/TRNG.h>
    #include <ti/drivers/trng/TRNGCC26XX.h>
    
    #define CONFIG_TRNG_COUNT 1
    
    
    TRNGCC26XX_Object trngCC26XXObjects[CONFIG_TRNG_COUNT];
    
    /*
     *  ======== trngCC26XXHWAttrs ========
     */
    static const TRNGCC26XX_HWAttrs trngCC26XXHWAttrs[CONFIG_TRNG_COUNT] = {
        {
            .intPriority = (~0),
            .swiPriority = 0,
            .samplesPerCycle = 240000
        },
    };
    
    const TRNG_Config TRNG_config[CONFIG_TRNG_COUNT] = {
        {   /* CONFIG_TRNG_0 */
            .object         = &trngCC26XXObjects[CONFIG_TRNG_0],
            .hwAttrs        = &trngCC26XXHWAttrs[CONFIG_TRNG_0]
        },
    };
    
    const uint_least8_t CONFIG_TRNG_0_CONST = CONFIG_TRNG_0;
    const uint_least8_t TRNG_count = CONFIG_TRNG_COUNT;
    
    /*
     *  =============================== UART2 ===============================
     */
    
    #include <ti/drivers/UART2.h>
    #include <ti/drivers/uart2/UART2CC26X2.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/dma/UDMACC26XX.h>
    #include <ti/drivers/power/PowerCC26X2.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/driverlib/ioc.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_memmap.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_ints.h>
    
    #define CONFIG_UART2_COUNT 2
    
    UART2CC26X2_Object uart2CC26X2Objects[CONFIG_UART2_COUNT];
    
    static unsigned char uart2RxRingBuffer0[32];
    /* TX ring buffer allocated to be used for nonblocking mode */
    static unsigned char uart2TxRingBuffer0[32];
    static unsigned char uart2RxRingBuffer1[32];
    /* TX ring buffer allocated to be used for nonblocking mode */
    static unsigned char uart2TxRingBuffer1[32];
    
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaUart1RxControlTableEntry, UDMA_CHAN_UART1_RX);
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaUart1TxControlTableEntry, UDMA_CHAN_UART1_TX);
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaUart0RxControlTableEntry, UDMA_CHAN_UART0_RX);
    ALLOCATE_CONTROL_TABLE_ENTRY(dmaUart0TxControlTableEntry, UDMA_CHAN_UART0_TX);
    
    static const UART2CC26X2_HWAttrs uart2CC26X2HWAttrs[CONFIG_UART2_COUNT] = {
      {
        .baseAddr           = UART1_BASE,
        .intNum             = INT_UART1_COMB,
        .intPriority        = (~0),
        .rxPin              = CONFIG_GPIO_UART2_QCS_RX,
        .txPin              = CONFIG_GPIO_UART2_QCS_TX,
        .ctsPin             = GPIO_INVALID_INDEX,
        .rtsPin             = GPIO_INVALID_INDEX,
        .flowControl        = UART2_FLOWCTRL_NONE,
        .powerId            = PowerCC26XX_PERIPH_UART1,
        .rxBufPtr           = uart2RxRingBuffer0,
        .rxBufSize          = sizeof(uart2RxRingBuffer0),
        .txBufPtr           = uart2TxRingBuffer0,
        .txBufSize          = sizeof(uart2TxRingBuffer0),
        .txPinMux           = IOC_PORT_MCU_UART1_TX,
        .rxPinMux           = IOC_PORT_MCU_UART1_RX,
        .ctsPinMux          = IOC_PORT_MCU_UART1_CTS,
        .rtsPinMux          = IOC_PORT_MCU_UART1_RTS,
        .dmaTxTableEntryPri = &dmaUart1TxControlTableEntry,
        .dmaRxTableEntryPri = &dmaUart1RxControlTableEntry,
        .rxChannelMask      = 1 << UDMA_CHAN_UART1_RX,
        .txChannelMask      = 1 << UDMA_CHAN_UART1_TX,
        .txIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_1_8,
        .rxIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_4_8
      },
      {
        .baseAddr           = UART0_BASE,
        .intNum             = INT_UART0_COMB,
        .intPriority        = (~0),
        .rxPin              = CONFIG_GPIO_UART_RX,
        .txPin              = CONFIG_GPIO_UART_TX,
        .ctsPin             = GPIO_INVALID_INDEX,
        .rtsPin             = GPIO_INVALID_INDEX,
        .flowControl        = UART2_FLOWCTRL_NONE,
        .powerId            = PowerCC26XX_PERIPH_UART0,
        .rxBufPtr           = uart2RxRingBuffer1,
        .rxBufSize          = sizeof(uart2RxRingBuffer1),
        .txBufPtr           = uart2TxRingBuffer1,
        .txBufSize          = sizeof(uart2TxRingBuffer1),
        .txPinMux           = IOC_PORT_MCU_UART0_TX,
        .rxPinMux           = IOC_PORT_MCU_UART0_RX,
        .ctsPinMux          = IOC_PORT_MCU_UART0_CTS,
        .rtsPinMux          = IOC_PORT_MCU_UART0_RTS,
        .dmaTxTableEntryPri = &dmaUart0TxControlTableEntry,
        .dmaRxTableEntryPri = &dmaUart0RxControlTableEntry,
        .rxChannelMask      = 1 << UDMA_CHAN_UART0_RX,
        .txChannelMask      = 1 << UDMA_CHAN_UART0_TX,
        .txIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_1_8,
        .rxIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_4_8
      },
    };
    
    const UART2_Config UART2_config[CONFIG_UART2_COUNT] = {
        {   /* CONFIG_UART2_QCS */
            .object      = &uart2CC26X2Objects[CONFIG_UART2_QCS],
            .hwAttrs     = &uart2CC26X2HWAttrs[CONFIG_UART2_QCS]
        },
        {   /* CONFIG_DISPLAY_UART */
            .object      = &uart2CC26X2Objects[CONFIG_DISPLAY_UART],
            .hwAttrs     = &uart2CC26X2HWAttrs[CONFIG_DISPLAY_UART]
        },
    };
    
    const uint_least8_t CONFIG_UART2_QCS_CONST = CONFIG_UART2_QCS;
    const uint_least8_t CONFIG_DISPLAY_UART_CONST = CONFIG_DISPLAY_UART;
    const uint_least8_t UART2_count = CONFIG_UART2_COUNT;
    
    
    /*
     *  =============================== Watchdog ===============================
     */
    
    #include <ti/drivers/Watchdog.h>
    #include <ti/drivers/watchdog/WatchdogCC26XX.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_memmap.h>
    
    #define CONFIG_WATCHDOG_COUNT 1
    
    
    WatchdogCC26XX_Object watchdogCC26XXObjects[CONFIG_WATCHDOG_COUNT];
    
    const WatchdogCC26XX_HWAttrs watchdogCC26XXHWAttrs[CONFIG_WATCHDOG_COUNT] = {
        /* CONFIG_WATCHDOG_0: period = 1000 */
        {
            .baseAddr    = WDT_BASE,
            .reloadValue = 1000
        },
    };
    
    const Watchdog_Config Watchdog_config[CONFIG_WATCHDOG_COUNT] = {
        /* CONFIG_WATCHDOG_0 */
        {
            .fxnTablePtr = &WatchdogCC26XX_fxnTable,
            .object      = &watchdogCC26XXObjects[CONFIG_WATCHDOG_0],
            .hwAttrs     = &watchdogCC26XXHWAttrs[CONFIG_WATCHDOG_0]
        }
    };
    
    const uint_least8_t CONFIG_WATCHDOG_0_CONST = CONFIG_WATCHDOG_0;
    const uint_least8_t Watchdog_count = CONFIG_WATCHDOG_COUNT;
    
    /*
     *  =============================== GPTimer ===============================
     */
    
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_memmap.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/inc/hw_ints.h>
    
    #define CONFIG_GPTIMER_COUNT 4
    
    /*
     *  ======== gptimerCC26XXObjects ========
     */
    GPTimerCC26XX_Object gptimerCC26XXObjects[CONFIG_GPTIMER_COUNT];
    
    /*
     *  ======== gptimerCC26XXHWAttrs ========
     */
    const GPTimerCC26XX_HWAttrs gptimerCC26XXHWAttrs[CONFIG_GPTIMER_COUNT] = {
        /* CONFIG_GPTIMER_0, used by CONFIG_PWM_R */
        {
            .baseAddr = GPT0_BASE,
            .intNum      = INT_GPT0A,
            .intPriority = (~0),
            .powerMngrId = PowerCC26XX_PERIPH_GPT0,
            .pinMux      = GPT_PIN_0A
        },
        /* CONFIG_GPTIMER_1, used by CONFIG_PWM_G */
        {
            .baseAddr = GPT1_BASE,
            .intNum      = INT_GPT1A,
            .intPriority = (~0),
            .powerMngrId = PowerCC26XX_PERIPH_GPT1,
            .pinMux      = GPT_PIN_1A
        },
        /* CONFIG_GPTIMER_2, used by CONFIG_PWM_B */
        {
            .baseAddr = GPT2_BASE,
            .intNum      = INT_GPT2A,
            .intPriority = (~0),
            .powerMngrId = PowerCC26XX_PERIPH_GPT2,
            .pinMux      = GPT_PIN_2A
        },
        /* CONFIG_GPTIMER_3, used by CONFIG_PWM_FAN */
        {
            .baseAddr = GPT3_BASE,
            .intNum      = INT_GPT3A,
            .intPriority = (~0),
            .powerMngrId = PowerCC26XX_PERIPH_GPT3,
            .pinMux      = GPT_PIN_3A
        },
    };
    
    /*
     *  ======== GPTimer_config ========
     */
    const GPTimerCC26XX_Config GPTimerCC26XX_config[CONFIG_GPTIMER_COUNT] = {
        /* CONFIG_GPTIMER_0 */
        {
            .object    = &gptimerCC26XXObjects[CONFIG_GPTIMER_0],
            .hwAttrs   = &gptimerCC26XXHWAttrs[CONFIG_GPTIMER_0],
            .timerPart = GPT_A
        },
        /* CONFIG_GPTIMER_1 */
        {
            .object    = &gptimerCC26XXObjects[CONFIG_GPTIMER_1],
            .hwAttrs   = &gptimerCC26XXHWAttrs[CONFIG_GPTIMER_1],
            .timerPart = GPT_A
        },
        /* CONFIG_GPTIMER_2 */
        {
            .object    = &gptimerCC26XXObjects[CONFIG_GPTIMER_2],
            .hwAttrs   = &gptimerCC26XXHWAttrs[CONFIG_GPTIMER_2],
            .timerPart = GPT_A
        },
        /* CONFIG_GPTIMER_3 */
        {
            .object    = &gptimerCC26XXObjects[CONFIG_GPTIMER_3],
            .hwAttrs   = &gptimerCC26XXHWAttrs[CONFIG_GPTIMER_3],
            .timerPart = GPT_A
        },
    };
    
    const uint_least8_t CONFIG_GPTIMER_0_CONST = CONFIG_GPTIMER_0;
    const uint_least8_t CONFIG_GPTIMER_1_CONST = CONFIG_GPTIMER_1;
    const uint_least8_t CONFIG_GPTIMER_2_CONST = CONFIG_GPTIMER_2;
    const uint_least8_t CONFIG_GPTIMER_3_CONST = CONFIG_GPTIMER_3;
    const uint_least8_t GPTimer_count = CONFIG_GPTIMER_COUNT;
    
    #include <stdbool.h>
    
    #include <ti/devices/cc13x2x7_cc26x2x7/driverlib/ioc.h>
    #include <ti/devices/cc13x2x7_cc26x2x7/driverlib/cpu.h>
    
    #include <ti/drivers/GPIO.h>
    
    /* Board GPIO defines */
    #define BOARD_EXT_FLASH_SPI_CS      20
    #define BOARD_EXT_FLASH_SPI_CLK     10
    #define BOARD_EXT_FLASH_SPI_PICO    9
    #define BOARD_EXT_FLASH_SPI_POCI    8
    
    
    /*
     *  ======== Board_sendExtFlashByte ========
     */
    void Board_sendExtFlashByte(uint8_t byte)
    {
        uint8_t i;
    
        /* SPI Flash CS */
        GPIO_write(BOARD_EXT_FLASH_SPI_CS, 0);
    
        for (i = 0; i < 8; i++) {
            GPIO_write(BOARD_EXT_FLASH_SPI_CLK, 0); /* SPI Flash CLK */
    
            /* SPI Flash PICO */
            GPIO_write(BOARD_EXT_FLASH_SPI_PICO, (byte >> (7 - i)) & 0x01);
            GPIO_write(BOARD_EXT_FLASH_SPI_CLK, 1);  /* SPI Flash CLK */
    
            /*
             * Waste a few cycles to keep the CLK high for at
             * least 45% of the period.
             * 3 cycles per loop: 8 loops @ 48 Mhz = 0.5 us.
             */
            CPUdelay(8);
        }
    
        GPIO_write(BOARD_EXT_FLASH_SPI_CLK, 0);  /* CLK */
        GPIO_write(BOARD_EXT_FLASH_SPI_CS, 1);  /* CS */
    
        /*
         * Keep CS high at least 40 us
         * 3 cycles per loop: 700 loops @ 48 Mhz ~= 44 us
         */
        CPUdelay(700);
    }
    
    /*
     *  ======== Board_wakeUpExtFlash ========
     */
    void Board_wakeUpExtFlash(void)
    {
        /* SPI Flash CS*/
        GPIO_setConfig(BOARD_EXT_FLASH_SPI_CS, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_HIGH | GPIO_CFG_OUT_STR_MED);
    
        /*
         *  To wake up we need to toggle the chip select at
         *  least 20 ns and ten wait at least 35 us.
         */
    
        /* Toggle chip select for ~20ns to wake ext. flash */
        GPIO_write(BOARD_EXT_FLASH_SPI_CS, 0);
        /* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
        CPUdelay(1);
        GPIO_write(BOARD_EXT_FLASH_SPI_CS, 1);
        /* 3 cycles per loop: 560 loops @ 48 Mhz ~= 35 us */
        CPUdelay(560);
    }
    
    /*
     *  ======== Board_shutDownExtFlash ========
     */
    void Board_shutDownExtFlash(void)
    {
        /*
         *  To be sure we are putting the flash into sleep and not waking it,
         *  we first have to make a wake up call
         */
        Board_wakeUpExtFlash();
    
        /* SPI Flash CS*/
        GPIO_setConfig(BOARD_EXT_FLASH_SPI_CS, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_HIGH | GPIO_CFG_OUT_STR_MED);
        /* SPI Flash CLK */
        GPIO_setConfig(BOARD_EXT_FLASH_SPI_CLK, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW | GPIO_CFG_OUT_STR_MED);
        /* SPI Flash PICO */
        GPIO_setConfig(BOARD_EXT_FLASH_SPI_PICO, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW | GPIO_CFG_OUT_STR_MED);
        /* SPI Flash POCI */
        GPIO_setConfig(BOARD_EXT_FLASH_SPI_POCI, GPIO_CFG_IN_PD);
    
        uint8_t extFlashShutdown = 0xB9;
    
        Board_sendExtFlashByte(extFlashShutdown);
    
        GPIO_resetConfig(BOARD_EXT_FLASH_SPI_CS);
        GPIO_resetConfig(BOARD_EXT_FLASH_SPI_CLK);
        GPIO_resetConfig(BOARD_EXT_FLASH_SPI_PICO);
        GPIO_resetConfig(BOARD_EXT_FLASH_SPI_POCI);
    }
    
    
    #include <ti/drivers/Board.h>
    
    /*
     *  ======== Board_initHook ========
     *  Perform any board-specific initialization needed at startup.  This
     *  function is declared weak to allow applications to override it if needed.
     */
    void __attribute__((weak)) Board_initHook(void)
    {
    }
    
    /*
     *  ======== Board_init ========
     *  Perform any initialization needed before using any board APIs
     */
    void Board_init(void)
    {
        /* ==== /ti/drivers/Power initialization ==== */
        Power_init();
    
        /* ==== /ti/devices/CCFG initialization ==== */
    
        /* ==== /ti/drivers/RF initialization ==== */
    
        /* ==== /ti/drivers/GPIO initialization ==== */
        /* Setup GPIO module and default-initialise pins */
        GPIO_init();
    
        Board_shutDownExtFlash();
    
        Board_initHook();
    }
    
    

  • Hi Team

    while accessing two slave address from different thread in a single bus, we are receiving a below error 

    I2C bus is already in use!

    I2C bus is already in use!

    I2C bus is already in use!

    I2C bus is already in use!

    I2C bus is already in use!

    Can you check that also

  • The I2C config looks fine, and the bus being busy is expected behavior (if the I2C lines are currently being used).

    The I2C bus being busy means the application is trying to perform an I2C transfer while the I2C master is currently trying to perform an I2C transaction.

    If you get this status (I2C_STATUS_BUS_BUSY == transaction.status), then try having the application wait for a bit  (e.g. usleep) and afterwards attempt the I2C_transfer again.

  • Yes understood

    But as per your input I2C driver is even having the semaphore post and pend and in addition to that we have also added our mutex lock in our application for every function that does the I2C transactions.

    But still in that case any one thread is getting failed whereas if we implement the application one by one like in a single thread i am trying communicate with both sensors . But this cannot fullfill our requirement 

    We are also setting the drive strength for the I2C SDA/SCL like below

    IOCIODrvStrengthSet(IOID_4, IOC_CURRENT_8MA, IOC_STRENGTH_MAX);
    IOCIODrvStrengthSet(IOID_5, IOC_CURRENT_8MA, IOC_STRENGTH_MAX);

    Is there anything else that we are missing?

  • Have you tried the previous suggestion?

    If you get this status (I2C_STATUS_BUS_BUSY == transaction.status), then try having the application wait for a bit  (e.g. usleep) and afterwards attempt the I2C_transfer again.

    Please confirm.

    A few more tests to try below.

    1. In your multi-thread application, have your threads perform this sequence for any I2C interaction: I2C_open --> I2C_transfer --> I2C_close. This will maximally ensure that the state of I2C driver is clean for each individual access.

    2. Keep your same multi-thread application, but do not call IOCIODrvStrengthSet (use default).

    3. Reset the state of the I2C_transaction each time (in case the same is shared between the I2C sensors). E.g.

    I2C_Transaction g_i2cTrans;
    
    static void do_sensor1_i2c()
    {
        memset(&g_i2cTrans, 0x00, sizeof(g_i2cTrans));
        // ... other code
    }
    
    static void do_sensor2_i2c()
    {
        memset(&g_i2cTrans, 0x00, sizeof(g_i2cTrans));
        // ... other code
    }


  • Hi 

    If you get this status (I2C_STATUS_BUS_BUSY == transaction.status), then try having the application wait for a bit  (e.g. usleep) and afterwards attempt the I2C_transfer again. ==> yes we tried this and this didnt help us

    1. In your multi-thread application, have your threads perform this sequence for any I2C interaction: I2C_open --> I2C_transfer --> I2C_close. This will maximally ensure that the state of I2C driver is clean for each individual access. ==> We do i2c open in the main and do transfer in our multi theard application.But we also have tried this method also

    2. Keep your same multi-thread application, but do not call IOCIODrvStrengthSet (use default). => Okay. This was made because in our HW setup we would see some voltage drop over the SCL line and when we raised query for the same they suggested to chnage tha drive strength.I am sharing the forum link below for the same

    https://www.google.com/url?sa=j&url=https%3A%2F%2Fe2e.ti.com%2Fsupport%2Fwireless-connectivity%2Fbluetooth-group%2Fbluetooth%2Ff%2Fbluetooth-forum%2F1303085%2Fcc2652r7-lp-cc2652r7-i2c-clock-line-voltage-lift-and-dip%2F4962618%234962618&uct=1700197693&usg=bUfbiBRZJcmJBbhKQGqtHn8205M.&opi=73833047&source=chat

    3. Reset the state of the I2C_transaction each time (in case the same is shared between the I2C sensors). E.g. ==> Will try this