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.

[参考译文] RTOS/AM5728:DMA 不工作时的 I2C 接收

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/668063/rtos-am5728-i2c-receive-with-dma-not-working

器件型号:AM5728

工具/软件:TI-RTOS

您好!

由于现有 I2C 驱动程序中不存在支持 DMA 的 I2C、因此我已经尝试通过查看 UART 和 SPI 驱动程序 TI RTOS PDK v 4.0.0.4来构建 DMA 支持

使用 EEPROM 示例测试支持 DMA 的 I2C 驱动程序。 我能够将数据从 DSP 传输到 EEPROM。 据说、我们可以通过发送2字节从器件地址、然后触发从 EEPROM 接收的数据来读回该数据。  

当我尝试接收数据时、我会得到全0、而不是我写入的数据。 但是、当我尝试使用 DMA 传输数据/在不使用 DMA 的情况下接收数据时、我能够接收我写入的数据

我的代码遵循用于 DMA 的 UART TX 和 Rx 参数、大多数逻辑都来自 SPI 驱动器。

可以分享任何想法、以便我也可以处理接收部分。

提前感谢

相关信息

Manjula

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    RTOS 团队已收到通知。 他们将在这里作出回应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    您能否使用最新的 Processor SDK RTOS 4.2版本、然后尝试支持 DMA 的 pdk_am57xx_1_0_9\packages/ti\drv\i2c\test\master_slave 示例?

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

    你(们)好

    我下载了最新的 Processor SDK RTOS 4.2版本、并查看 了 pdk_am57xx_1_0_9\packages/ti\drv\i2c\test\master_slave 示例以获得 DMA 支持。 尽管它提到在这里执行 DMA 初始化和 dmamode 标志、但驱动程序不支持 EDMA、应用程序也没有提到使用 EDMA 进行的数据传输。

    如果有任何 EDMA 参数配置示例使用 EDMA 执行 i2c 传输、将会非常有帮助。

    此致

    Manjula  

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

    很抱歉我忽略了这一点! 代码中的 dma_mode 是未来实现的占位符、但尚未规划。 在使用 DMA 从 EEPROM 读取 I2C 的代码中、我假设您在 I2C 协议之后发送一条读取命令、此命令仍由 CPU 执行、对吧? 然后、数据通过总线从 EEPROM 返回到 I2C 控制器。 当 I2C FIFO 达到特定级别时、它会自动触发 DMA 传输、传输完成会触发中断。 这是您实现的方式吗? 在应用方面、您有一个回调函数? 然后您读取 DMA 目标缓冲区、它都为零?

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

    在使用 DMA 从 EEPROM 读取 I2C 的代码中、我仅使用 DMA 发送2个字节、然后从 EEPROM 读取 DMA 到 I2C 控制器。 当到达 FIFO 并且我已经接收到传输完成中断时、DMA 传输被自动触发。

    为了便于参考、我附加了代码片段。 实际上、我在阻塞模式下工作。 一旦传输完成、I2C 将根据我比较数据的状态返回。

    /*清除所有中断*/
    I2CMasterIntClearEx (hwAttrs->baseAddr、I2C_INT_ALL);

    /*配置 TX DMA 参数*/

    /*发送参数集*/
    EDMA3_DRV_getPaRAM ((EDMA3_DRV_Handle) hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    txParamSet);

    /*根据事务参数更新参数组*/
    I2C_DMA_localEdmaUpdateParams_v1 (句柄、
    事务、
    rxParamSet (&Y)、
    txParamSet);

    /*虚拟参数集配置*/
    EDMA3_DRV_getPaRAM (hwAttrs->edmaHandle、
    EDMA3_DRV_LINK_CHANNEL、
    dummyParamSet (&U);

    dummyParamSet.aCnt = I2C_EDMA3CC_PARAM_ACNT;
    dummyParamSet.linkAddr = I2C_EDMA3CC_PARAM_LINK_ADDRESS;
    dummyParamSet.opt &=~((uint32_t) 0x01U <<I2C_EDMA3CC_opt_static_shift);

    /*现在,写入参数集。 *
    EDMA3_DRV_setPaRAM (hwAttrs->edmaHandle、
    EDMA3_DRV_LINK_CHANNEL、
    dummyParamSet (&U);

    /*写入 Tx 参数集*/
    EDMA3_DRV_setPaRAM ((EDMA3_DRV_Handle)(hwAttrs->edmaHandle)、
    hwAttrs->txDmaEventNumber,
    txParamSet);

    /*链接虚拟参数集*/
    EDMA3_DRV_linkChannel (hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    EDMA3_DRV_LINK_CHANNEL);

    /*将 I2C 器件设置为主器件、TX 模式*/
    /*启用7BIT 从器件 ADDR */
    /* TODO:检查10位从器件地址*/
    I2CMasterControl (hwAttrs->baseAddr、I2C_CFG_MST_TX | I2C_CFG_7BIT_SLAVE_ADDR | I2C_CFG_STOP);

    /*启用中断*/
    I2CMasterIntEnableEx (hwAttrs->baseAddr、I2C_INT_Transmit 就绪| I2C_INT_NO_ACK | I2C_INT_ANTRICAT_Lost);

    /*对 TX 端进行编程*/
    // TODO:检查返回值
    结果= EDMA3_DRV_enableTransfer (hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    EDMA3_DRV_TRIG_MODE_EVENT);

    /*启用 DMA TX 事件*/
    I2CDMATxEventEnablehwAttrs->baseAddr;

    //在主控模式下,设置 I2C 从器件地址*/
    I2CMasterSlaveAddrSet (hwAttrs->baseAddr、
    object->currentTransaction->slaveAddress);

    /*设置要传输的字节数*/
    I2CSetDataCount (hwAttrs->baseAddr、object->writeCountIdx);

    printf ("\n I2C:(0x%x)写入、带 start \n"、hwAttrs->baseAddr);

    /*启用开始位以开始传输*/
    i2CMasterStarthwAttrs->baseAddr;

    /*等待 TX 待完成且总线空闲*/
    /* TODO:转换为 SEM 等待,不是轮询的理想解决方案*/
    while (I2CMasterBusy (hwAttrs->baseAddr)=0);

    /*使用 TX 完成、启动 RX */

    /*配置 RX DMA 参数*/

    /*接收参数集*/
    EDMA3_DRV_getPaRAM ((EDMA3_DRV_Handle) hwAttrs->edmaHandle、
    hwAttrs->rxDmaEventNumber,
    rxParamSet (&rxParamSet);

    /*根据事务参数更新参数组*/
    I2C_DMA_localEdmaUpdateParams_v1 (句柄、
    事务、
    rxParamSet (&Y)、
    txParamSet);

    /*写入 Rx 参数集*/
    EDMA3_DRV_setPaRAM ((EDMA3_DRV_Handle)(hwAttrs->edmaHandle)、
    hwAttrs->rxDmaEventNumber,
    rxParamSet (&rxParamSet);

    /*将 I2C 器件设置为主器件、RX 模式*/
    /*启用停止位*/
    /*启用7BIT 从器件 ADDR */

    I2CMasterControl (hwAttrs->baseAddr、I2C_CFG_MST_RX | I2C_CFG_7BIT_SLAVE_ADDR | I2C_CFG_STOP);

    /*对 RX 端进行编程*/
    // TODO:检查返回值
    结果= EDMA3_DRV_enableTransfer (hwAttrs->edmaHandle、
    hwAttrs->rxDmaEventNumber,
    EDMA3_DRV_TRIG_MODE_EVENT);

    /*启用 DMA RX 事件*/
    I2CDMARxEventEnablehwAttrs->baseAddr;

    // TODO:检查是否确实需要此操作、是否已在执行 TX 时进行编程
    //在主控模式下,设置 I2C 从器件地址*/
    I2CMasterSlaveAddrSet (hwAttrs->baseAddr、
    object->currentTransaction->slaveAddress);

    /*设置要接收的字节数*/

    I2CSetDataCount (hwAttrs->baseAddr、object->readCountIdx);

    i2CMasterStarthwAttrs->baseAddr;

    我正在使用 AB 同步 DMA Rx 和 TX 参数

    rxParamSet->srcAddr = hwAttrs->baseAddr + 0x9C;

    rxParamSet->destAddr =(uint32_t) object->readBufIdx;

    rxParamSet->aCnt = 1;

    rxParamSet->bCnt = object->currentTransaction ->ReadCount;

    rxParamSet->ccnt = 1;  

    rxParamSet->srcBIdx = 0;  

    rxParamSet->destBIdx = rxParamSet->aCnt;

    rxPararxParamSet->destCIdx = rxParamSet->bcnt;

    rxParamSet->linkAddr = 0xFFFF;

    rxParamSet->bCntReload = rxParamSet->bcnt;

    rxParamSet->OPT &= I2C_EDMA3CC_OPT_DAM_INCR_MODE;

    rxParamSet->OPT |= I2C_EDMA3CC_OPT_SAM_CONST_MODE;

    rxParamSet->OPT &= I2C_EDMA3CC_OPT_FIFO_WIDTH;

    rxParamSet->OPT &= I2C_EDMA3CC_OPT_SYNC_MASK_VALUE;

    rxParamSet->OPT |= I2C_EDMA3CC_OPT_SYNC_AB;

    /* EDMA3_DRV_OPT_FIELD_TCINTEN */
    rxParamSet->OPT |= 1U << I2C_OPT_TCINTE_SHIFT;

    /*更新传输完成代码*/
    rxParamSet->OPT &=(~I2C_OPT_TCC_MASK);
    rxParamSet->opT|=(hwAttrs->rxDmaEventNumber)<<
    I2C_OPT_TCC_SHIFT);

    TX 参数如下所示

    /*传输参数集配置*/

    txParamSet->srcAddr =(uint32_t) object->writeBufIdx;

    txParamSet->destAddr =(uint32_t) hwAttrs->baseAddr + 0x9C;

    txParamSet->aCnt = 1;

    txParamSet->bCnt = object->currentTransaction ->writeCount;

    txParamSet->ccnt = 1;

    txParamSet->srcBIdx = txParamSet->aCnt;
    txParamSet->destBIdx=0;

    txParamSet->srcCIdx = txParamSet->bcnt;
    txParamSet->destCIdx=0;

    txParamSet->linkAddr = I2C_EDMA3CC_PARAM_LINK_ADDRESS;
    txParamSet->bCntReload = txParamSet->bCnt;

    txParamSet->OPT &= I2C_EDMA3CC_OPT_SAM_INCR_MODE;
    txParamSet->opt |= I2C_EDMA3CC_opt_DAM_CONST_MODE;

    txParamSet->OPT &= I2C_EDMA3CC_OPT_FIFO_WIDTH;

    txParamSet->OPT &= I2C_EDMA3CC_OPT_SYNC_MASK_VALUE;
    txParamSet->OPT |= I2C_EDMA3CC_OPT_SYNC_AB;

    txParamSet->OPT |=(1U <<I2C_OPT_TCINTEN 位移);

    txParamSet->OPT &=(~I2C_OPT_TCC_MASK);
    txParamSet->opt|=(hwAttrs->txDmaEventNumber)<<
    I2C_OPT_TCC_SHIFT);

    请告诉我、我缺少任何内容。 我需要向我发送代码片段、我可以尝试接收这些代码片段以与 DMA 配合使用

    谢谢、此致

    Manjula

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

    提醒...

    对这个问题的任何见解都非常有帮助。 提前感谢。