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.

I2C DMA FIFO burst 问题请教

Other Parts Discussed in Thread: TMP100

使用I2C  FIFO  DMA  方式:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

以下为 I2C 设置

I2CRxFIFOConfigSet(i2c_udma_setting[i].I2C_BASE, I2C_FIFO_CFG_RX_MASTER_DMA | I2C_FIFO_CFG_RX_TRIG_3);   设置 tiger 为3 bytes

I2CMasterBurstLengthSet(i2c_udma_setting[i].I2C_BASE, 3);  设置   ui8MasterBytesLength  = 3 ,  3 个bytes  burst 一次

uDMAChannelControlSet(ui32ChannelNum | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);                                                                                               4 byte arbitration   (应该没关系,我只有3 个 bytes burst , 已经 不需要 arbite 了)

 

uDMAChannelTransferSet(ui32ChannelNum | UDMA_PRI_SELECT,
UDMA_MODE, (void *)(i2c_udma_setting[index].I2C_BASE + I2C_O_FIFODATA),
(void *)g_ui8I2CMasterRxDataA[index],
3);                                                                                                                            3 bytes 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

以下为   FIFO burst receive  开始

    I2CMasterSlaveAddrSet(ui32Base, i2c_addr, true);
    I2CMasterControl(ui32Base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

以下为 I2C  中断

 ui32Mode = uDMAChannelModeGet(i2c_udma_setting[index].DMA_Channel | UDMA_PRI_SELECT);

   if (ui32Mode == UDMA_MODE_STOP)
   {
       ui32Mode = I2CMasterBurstCountGet(i2c_udma_setting[index].I2C_BASE);
      I2CMasterControl(i2c_udma_setting[index].I2C_BASE, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH);    这里设置硬件中断
    .....................................
}

                                                                                                             

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在 INT 的  

I2CMasterControl(i2c_udma_setting[index].I2C_BASE, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH);

 处设置硬件中断

问题出在此处:

当执行 I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START 后

I2CMasterControl(ui32Base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START);
用示波器看波形,可以看到 正常的 读取 3 bytes 的 I2C 波形
这时停止在I2C 中断的 
      I2CMasterControl(i2c_udma_setting[index].I2C_BASE, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH); 
这时单步执行, 会看到 又有 3 bytes 数据读出,并且有了一个 I2C  STOP 波形。
按照我的理解, 应该只有一个 I2C STOP 波形, 不应该再有 3 bytes  数据。
如果我把前面的 burst size 设置为4, 就有 8 个 bytes 数据读出, 设置为 8 , 就有16个数据读出。
似乎读出数据是 设置  burst 的 2倍, 这个应该是有问题。
  
  • 我会在确认后给您回复,谢谢
  • Susan, 多谢!

    上述表现和DMA 工作在PINGPONG 模式极象,所以现在怀疑DMA 全部是工作在 pingpong模式, 不管有没有设置 PINGPONG模式
  • 仅查看您提供的代码片段无法看到该问题。您是否已查看应用笔记

    在本说明中有一个示例项目,它执行i2c FIFO uDMA。我已经将该项目更新为使用CCS v10.1,代码生成工具版本20.2.3和TivaWare 2.2.0.205,并将其包括在以下位置:

    ektm4c129_i2c_master_udma_fifo.zip

     

  • hi,Susan

    你可以看出我贴的代码和你给的示例高度相似,我就是参考示例的。

    但是示例里的 receive 方式是 I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE, 而我的接收开始是 

    I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START,所以这2个不具备可比性。
    如有可能,你可以测试一下  burst recieve 方式,我想就会出现我的问题,谢谢!
  • 谢谢您的反馈,我会在测试后给您回复。
  • 我使用的是DK-TM4C129X进行测试,该套件通过I2C连接到TMP100温度传感器。尽管从温度传感器读取burst 信号并没有多大意义,但它足以显示I2C的功能。我使用FIFO和uDMA读取了8个字节。前两个字节是温度,后六个字节是0xFF。当我使用I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE时,所有8个字节将以burst 方式读取,并且主机将在不确认最后一个字节(NACK)的情况下释放总线,并发送停止条件。

    当我使用I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START时,结果是相同的,但是burst 读取在8个字节之后没有结束。

    尽管这不能解释您的代码中发生的情况,但显示了如何使用FIFO和uDMA正确进行burst 读取。我已附上我的项目以供参考。

    dktm4c129_i2c6_master_udma_fifo.zip

  • HI , susan

      你在  int  合适位置  检测   I2CMasterIntStatusEx    当状态为 I2C_MASTER_INT_RX_FIFO_REQ 时, 调用 I2CMasterControl   

    I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH, 就会看到 I2C STOP , 并且又 burst 了 8 个字节,请测试下。
    另, 你这个示波器是什么型号啊? 
  • 我是请一个美国同事测试的。因为我手边没有这个套件.

    我会将您的问题转述给他,谢谢

    “你在 int 合适位置 检测 I2CMasterIntStatusEx ” 能否详细说一下?
  • 在中断合适位置加

    uint32_t ui32I2CMasterInterruptStatus = I2CMasterIntStatusEx(i2c_udma_setting[8].I2C_BASE, true);
    if(ui32I2CMasterInterruptStatus & I2C_MASTER_INT_RX_FIFO_REQ)
    {
    I2CMasterControl(i2c_udma_setting[8].I2C_BASE, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH);

    。。。。。。。。




    另:
    我发现 如果不用I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH,而用 I2C_MASTER_CMD_FIFO_BURST_RECEIVE_ERROR_STOP

    也可以看到 I2C stop, 而且不会 burst, 检查了下, 这2个差别就是是否有 burst bit, 可能有 burst bit , 就会进行一次 burst. 但是这样跑起来会莫名出错
  • 谢谢您的反馈,我会在之后回复给您
  • 请您查看下面的回复。为了便于您更好理解,我以英文原文的形式给出:

     When using FIFO mode, each call to I2CMasterControl() can cause the reception or transmission of multiple bytes. Use of the uDMA extends the FIFO size. 

    Using I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE will cause a start, address, then read as many bytes as are programmed in the uDMA, with a NACK on the last byte and a stop condition. This is the example I showed you and I think what you want to do.

    Using I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START will cause a start, address, then read as may bytes as are programmed in the uDMA acknowledging all bytes including the "last" one and not send a stop condition. (Shown in the second image of my previous post.)

    Using I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH will not generate a start or address, it will then read as may bytes as are programmed in the uDMA with a NACK on the last byte condition and a stop condition.

    So when you call I2CMasterControl() twice, once with I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START and then with I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH, you have run the uDMA twice. If that is not what you want, don't do that!

  • Hi, Susan,

    明白 

    其实这个和 uDMA 没有一点关系, 只要调用  I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START  , I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH 就必然会产生2次 burst, 和使不使用 uDMA  没有任何关系。  

    但是使用了 uDMA 后,如果使用 FIFO_BURST ,则一定要用 pingpong 模式,这点和通常思维不大一致,会给用户带来一定困扰。

    总之,问题得到确认,谢谢你 :-)

  • 谢谢您对TI产品的关注!很高兴能帮到您!