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.

[参考译文] MSPM0G3507-Q1:I2C 驱动程序无法正确处理补丁写入?

Guru**** 2782485 points

Other Parts Discussed in Thread: MSPM0G3507-Q1

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1613468/mspm0g3507-q1-i2c-driver-not-handling-patched-writes-correctly

器件型号: MSPM0G3507-Q1

我遇到了一个问题、尝试将 MSPM0G3507-Q1 与 TI-Drivers 和 FreeRTOS 配合使用。 具体来说、我尝试将 16K 缓冲区传递到 I2C_transfe 函数、以执行连续写入...数据...停止事务。

问题在于、在事务过程中、MSPM0+似乎提供了突发长度 (255)……的重复起始 我的外围设备不喜欢的项目:

image.png

通过查看实现代码(特别是 I2CMSPM0.c)、我认为问题出在中  I2CMSPM0_primeWriteBurst 功能:

static void I2CMSPM0_primeWriteBurst(
    I2CMSPM0_Object *object, I2CMSPM0_HWAttrs const *hwAttrs)
{
    /* Wait until bus is available */
    I2C_waitTillBusAvailable(hwAttrs);
    /* Disable the burst before setting up the new transaction */
    DL_I2C_disableControllerBurst(hwAttrs->i2c);
    /* Determine the size of this burst */
    if (object->writeCount > I2CMSPM0_MAX_BURST) {
        object->burstCount = I2CMSPM0_MAX_BURST;
    } else {
        object->burstCount = object->writeCount;
    }

    /* Write burst length */
    DL_I2C_setTransactionLength(hwAttrs->i2c, object->burstCount);

    /* If we will be sending multiple bursts */
    if (object->readCount || object->writeCount > I2CMSPM0_MAX_BURST) {
        DL_I2C_disableStopCondition(hwAttrs->i2c);
    } else {
        DL_I2C_enableStopCondition(hwAttrs->i2c);
    }

    /* Only generate a start condition if the burst hasn't started */
    if (!object->burstStarted) {
        object->burstStarted = true;
    }
    /*Before filling the FIFO, we need to clear the interrupt else it will trigger interrupt immediately*/
    DL_I2C_clearInterruptStatus(
        hwAttrs->i2c, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
    /* Fill transmit FIFO. This will modify the object counts */
    I2CMSPM0_fillTransmitFifo(object, hwAttrs);

    /* Enable TXFIFOEMPTY interrupt and other standard transfer interrupts */
    DL_I2C_enableInterrupt(hwAttrs->i2c,
        DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER |
            DL_I2C_INTERRUPT_CONTROLLER_TX_DONE |
            DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY | I2CMSPM0_TRANSFER_INTS);
    /* Set the target Address */
    DL_I2C_setTargetAddress(
        hwAttrs->i2c, object->currentTransaction->targetAddress);
    /* Set the controller direction */
    DL_I2C_setControllerDirection(
        hwAttrs->i2c, DL_I2C_CONTROLLER_DIRECTION_TX);
    /* Enable the start condition */
    
    DL_I2C_enableStartCondition(hwAttrs->i2c);
    /* Disable the manual ACK, hardware will ack automatically */
    DL_I2C_disableControllerACK(hwAttrs->i2c);
    /* Enable the burst run */
    DL_I2C_enableControllerBurst(hwAttrs->i2c);
}

 

具体而言、 BurstStarted 被设置、但它实际上不会在任何地方被检查/使用。 不管怎样、始终会调用 DL_I2C_enableStartCondition 函数。 如果我将其更改为:

/*
 *  ======== I2CMSPM0_primeWriteBurst =======
 */
static void I2CMSPM0_primeWriteBurst(
    I2CMSPM0_Object *object, I2CMSPM0_HWAttrs const *hwAttrs)
{
    /* Wait until bus is available */
    I2C_waitTillBusAvailable(hwAttrs);
    /* Disable the burst before setting up the new transaction */
    DL_I2C_disableControllerBurst(hwAttrs->i2c);
    /* Determine the size of this burst */
    if (object->writeCount > I2CMSPM0_MAX_BURST) {
        object->burstCount = I2CMSPM0_MAX_BURST;
    } else {
        object->burstCount = object->writeCount;
    }

    /* Write burst length */
    DL_I2C_setTransactionLength(hwAttrs->i2c, object->burstCount);

    /* If we will be sending multiple bursts */
    if (object->readCount || object->writeCount > I2CMSPM0_MAX_BURST) {
        DL_I2C_disableStopCondition(hwAttrs->i2c);
    } else {
        DL_I2C_enableStopCondition(hwAttrs->i2c);
    }

    /* Only generate a start condition if the burst hasn't started */
    if(object->burstStarted == true)
    {
        DL_I2C_disableStartCondition(hwAttrs->i2c);
    }
    else
    {
        DL_I2C_enableStartCondition(hwAttrs->i2c);
    }

    if (!object->burstStarted) {
        object->burstStarted = true;
    }
    /*Before filling the FIFO, we need to clear the interrupt else it will trigger interrupt immediately*/
    DL_I2C_clearInterruptStatus(
        hwAttrs->i2c, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
    /* Fill transmit FIFO. This will modify the object counts */
    I2CMSPM0_fillTransmitFifo(object, hwAttrs);

    /* Enable TXFIFOEMPTY interrupt and other standard transfer interrupts */
    DL_I2C_enableInterrupt(hwAttrs->i2c,
        DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER |
            DL_I2C_INTERRUPT_CONTROLLER_TX_DONE |
            DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_EMPTY | I2CMSPM0_TRANSFER_INTS);
    /* Set the target Address */
    DL_I2C_setTargetAddress(
        hwAttrs->i2c, object->currentTransaction->targetAddress);
    /* Set the controller direction */
    DL_I2C_setControllerDirection(
        hwAttrs->i2c, DL_I2C_CONTROLLER_DIRECTION_TX);
    /* Enable the start condition */

  
    /* Disable the manual ACK, hardware will ack automatically */
    DL_I2C_disableControllerACK(hwAttrs->i2c);
    /* Enable the burst run */
    DL_I2C_enableControllerBurst(hwAttrs->i2c);
}

... 具体添加以下内容:

    /* Only generate a start condition if the burst hasn't started */
    if(object->burstStarted == true)
    {
        DL_I2C_disableStartCondition(hwAttrs->i2c);
    }
    else
    {
        DL_I2C_enableStartCondition(hwAttrs->i2c);
    }

    if (!object->burstStarted) {
        object->burstStarted = true;
    }

... 一切似乎工作,我可以写整个 16K 没有问题. 我只需将 I2CMSPM0.c 文件复制到我的工作区、所有符号都会覆盖 SDK 库中的符号。  

我只是想确保我一开始没有遗漏任何东西或误用驱动程序。 对于固件更新、我通常必须在不重复启动/停止的情况下写入>256 字节的事务。

此致、
Tim

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

    嗨、Tim、

    这看起来像是一个很好的修复。  在驱动器中似乎被忽视。  将这些信息传递给软件团队、以便他们可以查看和更新以供将来的版本使用。   

    谢谢、

    JD