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.

[参考译文] LP-CC2652RB:IDE 行为不稳定、无法将 I2C 与示例工程一起使用。

Guru**** 2465890 points
Other Parts Discussed in Thread: CC2652RB, SYSCONFIG, Z-STACK, SYSBIOS

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/zigbee-thread-group/zigbee-and-thread/f/zigbee-thread-forum/1158265/lp-cc2652rb-erratic-ide-behaviour-and-unable-to-use-i2c-with-sample-project

器件型号:LP-CC2652RB
Thread 中讨论的其他器件:CC2652RBSysConfigZ-stackSYSBIOS

我想使用示例项目  zr_temperaturesenser_LP_CC2652Rb_tirtos_ccs  并实现我自己的温度测量传感器、尝试使用 zigbee2mqtt 连接电路板、并评估可能的新项目。 我使用了带 I2C 的 BME680温度传感器、我之前为其编写了一个驱动程序、它在另一个项目中工作正常、我可以在该项目上从传感器读取和写入数据。 我可以确认通信在协议合规性方面是正确的、正如我使用示波器检查过的。 但是,这在将驱动程序引入示例项目时根本不起作用,因为 i2c 通信似乎会在 MID 传输时失败(这仅在使用示例 ztack 项目时发生)。 我将尝试并详细说明我在下面执行的步骤:

在 main 中、在创建新任务之前、我初始化 i2c 外设和传感器。  

#define SPI_BUFFER_SIZE 64
#define I2C_BUS_ADDR 0x00

static struct bme680_dev gBME680Struct = { };
bool gResult = true;
uint16_t gMeasPeriod = 0;

static I2C_Handle gI2C = { 0 };
static I2C_Params gI2CParams = { 0 };
static I2C_Transaction gI2CTransaction = { 0 };
static bool gI2CInitDone = false;

static uint8_t txBuf[SPI_BUFFER_SIZE];
static uint8_t rxBuf[SPI_BUFFER_SIZE];

int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
void userDelay(uint32_t period);

int8_t sensorBME680Init()
{
    if (!gI2CInitDone){
        return __LINE__;
    }

    int8_t rslt = BME680_OK;

    gBME680Struct.dev_id = BME680_I2C_ADDR_PRIMARY;
    gBME680Struct.intf = BME680_I2C_INTF;
    gBME680Struct.read = userRead;
    gBME680Struct.write = userWrite;
    gBME680Struct.delay_ms = userDelay;
    gBME680Struct.amb_temp = 25;

    rslt = bme680_init(&gBME680Struct);

    if (0 != rslt)
    {
        return __LINE__;
    }

    uint16_t setRequiredSettings;
    /* Set the temperature, pressure and humidity settings */
    gBME680Struct.tph_sett.os_hum = BME680_OS_2X;
    gBME680Struct.tph_sett.os_pres = BME680_OS_4X;
    gBME680Struct.tph_sett.os_temp = BME680_OS_8X;
    gBME680Struct.tph_sett.filter = BME680_FILTER_SIZE_3;
    /* Set the remaining gas sensor settings and link the heating profile */
    gBME680Struct.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
    /* Create a ramp heat waveform in 3 steps */
    gBME680Struct.gas_sett.heatr_temp = 320; /* degree Celsius */
    gBME680Struct.gas_sett.heatr_dur = 150; /* milliseconds */
    /* Select the power mode */
    gBME680Struct.power_mode = BME680_FORCED_MODE;
    /* Must be set before writing the sensor configuration */
    /* Set the required sensor settings needed */
    setRequiredSettings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL
            | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
    /* Set the desired sensor configuration */
    rslt = bme680_set_sensor_settings(setRequiredSettings, &gBME680Struct);
    /* Set the power mode */
    rslt = bme680_set_sensor_mode(&gBME680Struct);
    bme680_get_profile_dur(&gMeasPeriod, &gBME680Struct);
    gBME680Struct.delay_ms(gMeasPeriod); /* Delay till the measurement is ready */

    memset(txBuf, 0, SPI_BUFFER_SIZE);
    memset(rxBuf, 0, SPI_BUFFER_SIZE);

    return rslt;
}

int8_t sensorBME680I2CInit()
{
    I2C_init();
    I2C_Params_init(&gI2CParams);
    gI2C = I2C_open(I2C_BUS_ADDR, &gI2CParams);

    if (NULL == gI2C)
    {
        return __LINE__;
    }

    gI2CInitDone = true;

    return 0;
}

int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    if (!gI2CInitDone)
    {
        return __LINE__;
    }

    if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
    {
        return __LINE__;
    }

    memset(txBuf, 0, SPI_BUFFER_SIZE);
    txBuf[0] = reg_addr;

    gI2CTransaction.slaveAddress = dev_id /*<< 1*/;
    gI2CTransaction.readCount = len;
    gI2CTransaction.readBuf = data;
    gI2CTransaction.writeCount = 1;
    gI2CTransaction.writeBuf = txBuf;

    gResult = I2C_transfer(gI2C, &gI2CTransaction);

    if (!gResult)
    {
        return -1;
    }

    return 0;
}

int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    if (!gI2CInitDone)
    {
        return -1;
    }

    if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
    {
        return -1;
    }

    memset(txBuf, 0, SPI_BUFFER_SIZE);
    txBuf[0] = reg_addr;
    memcpy(&txBuf[1], data, len);

    gI2CTransaction.slaveAddress = dev_id;
    gI2CTransaction.writeCount = len + 1;
    gI2CTransaction.writeBuf = txBuf;
    gI2CTransaction.readCount = 0;

    gResult = I2C_transfer(gI2C, &gI2CTransaction);

    if (!gResult)
    {
        return 1;
    }

    return 0;
}

void userDelay(uint32_t period)
{
    usleep(1000 * period);
}

int8_t getSensorData(struct bme680_field_data *pData)
{
    if (!gI2CInitDone)
    {
        return -2;
    }

    if (NULL == pData)
    {
        return -1;
    }

    static int8_t rslt = 0;
    rslt = bme680_get_sensor_data(pData, &gBME680Struct);

    if (gBME680Struct.power_mode == BME680_FORCED_MODE)
    {
        rslt = bme680_set_sensor_mode(&gBME680Struct);
    }

    return rslt;
}

void sensorBME680CommInit()
{
    int8_t rslt = sensorBME680I2CInit();

    if (0 != rslt)
    {
        return;
    }

    rslt &= sensorBME680Init();

    if (0 == rslt)
    {
        gInitDone = true;
    }
}

然后、我创建一个新任务来轮询传感器并报告温度变化:

void pollTask()
{
    static int16_t temp = 0;
    static zstack_bdbRepChangedAttrValueReq_t zReq;

    while (1)
    {
        if (gInitDone)
        {
            GPIO_toggle(CONFIG_GPIO_RLED);

            getSensorData(&gZSensorData);
            temp = gZSensorData.temperature;

            if (temp < zclSampleTemperatureSensor_MaxMeasuredValue
                    && temp > zclSampleTemperatureSensor_MinMeasuredValue)
            {

                zclSampleTemperatureSensor_MeasuredValue = temp;
            }
            else if (temp >= zclSampleTemperatureSensor_MaxMeasuredValue)
            {
                zclSampleTemperatureSensor_MeasuredValue =
                        zclSampleTemperatureSensor_MaxMeasuredValue;
            }
            else if (temp <= zclSampleTemperatureSensor_MinMeasuredValue)
            {
                zclSampleTemperatureSensor_MeasuredValue =
                        zclSampleTemperatureSensor_MinMeasuredValue;
            }

#ifdef BDB_REPORTING
            zReq.attrID = ATTRID_TEMPERATURE_MEASUREMENT_MEASURED_VALUE;
            zReq.cluster = ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT;
            zReq.endpoint = SAMPLETEMPERATURESENSOR_ENDPOINT;

            Zstackapi_bdbRepChangedAttrValueReq(appServiceTaskId, &zReq);
#endif

            Task_sleep(100 * (1000 / Clock_tickPeriod));
        }
    }
}

我在 main 中初始化它并启动任务:

#define SENSOR_TASK_STACK_SIZE 1000
Task_Struct gPollTask;
Char pollTaskStack[SENSOR_TASK_STACK_SIZE];

Void sensorPollTask(UArg a0, UArg a1)
{
    extern void pollTask();
    pollTask();
}

// in main
{
sensorBME680CommInit();


Task_Params sensorTaskParams;
Task_Params_init(&sensorTaskParams);
sensorTaskParams.stack = pollTaskStack;
sensorTaskParams.priority = 2;
sensorTaskParams.stackSize = SENSOR_TASK_STACK_SIZE;
Task_construct(&gPollTask, sensorPollTask, &sensorTaskParams, NULL);

BIOS_start();
}

我无法将调试器用于调试目的、因为调试器会跳转至整个位置、我无法按照每条指令执行操作、即使在 示波器中的某一行上暂停、也无法看到大多数变量的值。 我以前从未在任何 IDE 中发生过这种情况。 不管怎样、我可以使用示波器、看到代码的某些部分没有执行、但程序似乎没有失败。 更清楚的是、初始化传感器的第一步是通过 i2c 执行软复位命令(设置了写入位的发送地址、发送寄存器地址和发送寄存器值)。 外设只发送从机地址和寄存器地址(从 机已成功确认)、然后突然中断、不发送寄存器值、也不使用停止位结束 i2c 传输。 将附加照片:

我假设传输不会以失败结束、但正如我说过的、一旦调试器到达 I2C_Transfer 线路、它就会自行自由运行、不会让我跳过来查看传输结果。  sensorBME680CommInit()之后的代码; 在 main 中,当主 ZigBee 任务正在运行并且电路板看起来没有复位时,似乎执行了。  

摘要如下:在 main 中、我调用 rslt = BME680_init (&gBME680Struct); 该函数又调用  rslt &= sensorBME680Init();调用  rslt = BMEM680_init (&gBMEM680Struct);该函数应向传感器发送软复位命令。 命令的前两个帧被发送并应答、但传输 突然结束、而代码的其余部分似乎被执行。 在我的整个生命周期中、我无法获得 用于初始化传感器的电路板、也无法检查我编写的其余内容是否正常工作。 传感器轮询任务启动、但传感器未初始化、因此我无法验证它应该发送的数据。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尝试降低编译器优化级别以重新调试。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好。

    我已将优化减少为无、但看不到任何差异。 如果有任何差异、我仍然无法单步执行有问题的代码。 即使如此、在 i2c 传输的中间什么会导致中止?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、A V、

    请为我澄清一下、I2C_transfer 是否会返回、如果是、状态值是多少?  您是否曾尝试更改 I2C 位时钟速度或使 I2C 任务具有比 Z-Stack 任务更高的优先级?  无论 Zigbee 应用的连接状态如何、I2C 是否会失败?  根据逻辑分析器屏幕截图、它几乎看起来好像最后一个 SDA ACK 与 SCL 位转换的同时出现、我很好奇任务是否错过了它。  您是否比较了工作版本和损坏版本之间的屏幕截图?  此外、正在使用哪些 I2C SysConfig 设置以及 SDK 和编译器版本?

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好

    1. i2c_transfer 函数不会返回。 我做了更深入的研究、看起来好像它崩溃了程序中间传输(希望它不是其他原因、我会误解它)、代码的其余部分不会执行。 在此之后暂停调试器会显示 CPU 一直停留在 ti_sysbios_family_arm_m3/hwi_exHandler __i ()内的循环中、并且之前有一个对 strlen()的调用、该调用似乎尝试读取大量无效地址。 我在 strlen 之前看不到任何其他呼叫。
    2. 我已经尝试使用100kHz 默认比特率和400kHz。 我已将任务优先级设置为1级、但现在可以清楚地看到问题是某个位置发生故障。
    3. 无论程序是否已连接、程序似乎都会崩溃。
    4. ACK 看起来不错、我已经检查过、还有许多其他帧样本、其中 ACK 位在时钟变为低电平时出现。
    5. I2C 配置设置是默认设置、没有更改任何内容、我使用的是 I2C_0 SDK 版本6.20.00.29

    看到这个调用 strlen 之后是 HWI、我再次查看了 BME680和 I2C 上的包装器、以检查在任何缓冲器中可能会留下一些垃圾、但我看不到任何明显的东西。 我 尝试进入 I2C_Transfer 函数、但调试器会跳转至所有位置、无法可靠地单步执行指令。 我可以看到程序在  I2C.c 中 I2C_transferTimeout 的第217行崩溃。 该行是 SemaphoneP_pend、如果它返回 OK。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、A V、

    感谢您提供更多调试信息、因为它进一步帮助您了解转置的内容。  如 Z-Stack 调试指南中所述、可以使用 ROV 进一步研究 m3.Hwi 异常。  确认没有程序或堆栈溢出后、请对 ROV -> Hwi ->异常内的异常进行解码。   总线故障的原因通常是指针未初始化,函数获取指针,假设指针有效并降级指针,然后写入无效地址。  在第一个 I2C_transfer 期间是否总是会出现此问题?  您可以将来自 source\ti\drivers\i2c 的 I2CCC26XX.c/h 直接添加到项目工作区中、以进一步调试传输函数。 您应该将传递的指针与您正在工作的 I2C 示例进行比较。

    此致、
    Ryan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan。 我自己解决了这个问题、因为我怀疑这是一个愚蠢的错误、而不是 I2C 问题。 如果其他人在与我的类似的条件下遇到系统崩溃、我正在初始化 I2C (成功)、然后尝试通过发送命令在允许 BIOS 启动之前对传感器进行软复位。 这会导致对 SemaphoreP_PEND 的调用失败。 我通过初始化 I2C 并发送传感器轮询任务中的软复位数据包来解决了这一问题、所有内容都按预期工作、包括属性报告。 我能够在 zigbee2mqtt 内正确报告 BME680参数。 感谢你的所有帮助。