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.

[参考译文] TMS570LC4357:用于 DMA 控制器进行 I2C 读写的示例源代码和 HalcGen 配置

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1390906/tms570lc4357-example-source-code-and-halcogen-configuration-for-i2c-read-and-write-by-dma-controller

器件型号:TMS570LC4357
主题中讨论的其他器件:HALCOGEN

工具与软件:

尊敬的 TI 支持部门:

您是否具有用于 DMA 控制器进行 I2C 读写的示例源代码和 HalcGen 配置?

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

    尊敬的 Manoraj:

    我没有任何直接示例可以与您分享、但您可以通过以下方式实现:

    首先了解 DMA 将如何与 i2c 模块配合使用:

    另请参阅以下主题、在这里可以找到一些代码参考。

    (+) TMS570LC4357:如何将 DMA 用于 I2C 发送和接收? -基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    只是尝试从你自己的一方实施,如果你在实施中遇到任何困难,那么我将进一步帮助你。

    ——
    谢谢、此致、
    Jagadish。

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

    尊敬的 Jagadish:

    感谢 您的答复。

    我使用内部回送以16位大小读回数据。

    我只能通过 DMA 读取前8位。

    请在下面找到我的代码


    /*
    *版权所有(C) 2009-2015德州仪器(TI)公司- www.ti.com
    *
    *
    *以源代码和二进制形式重新分发和使用,无论有无
    *修改,只要满足以下条件即可
    *已满足:
    *
    *源代码的再分发必须保留上述版权
    *通知,本条件列表及以下免责声明。
    *
    *二进制形式的再分发必须复制上述版权
    *通知,本条件列表和以下免责声明在
    *随附的文档和/或其他材料
    *分发。
    *
    *既不是德州仪器(TI)公司的名称、也不是公司的名称
    *其贡献者可用于认可或推广衍生产品
    *未经事先书面许可使用本软件。
    *
    *本软件由版权所有者和贡献者提供
    "按现状"和"按可得到"的基础提供
    本站明确声明不作出任何种类的所有明示或暗示的保证
    *不得使用特定目的。 在任何情况下均不得享有版权
    *所有者或贡献者对任何直接的、间接的、附带的、
    *特殊、示例性或后果性损害,包括但不包括
    *仅限于采购替代商品或服务;不能使用,
    *数据,或利润;或业务中断,然而造成和任何
    *责任理论,无论是合同,严格的责任,或侵权
    *包括疏忽或以任何方式产生的使用
    *本软件,即使被告知此类损坏的可能性。
    *
    */

    /*用户代码 begin (0)*/
    /*用户代码结束*/

    /*包含文件*/

    #include "HL_sys_common.h"
    #include "HL_system.h"
    #include "HL_sys_dma.h"

    /*用户代码 begin (1)*/
    #include "HL_i2c.h"

    #define own_add 0x20
    #define SLV_ADD 0x10
    第16章不是你
    #define I2C1_TX_ADDR ((uint32_t)(&(i2cREG1->DXR))+ 3)
    #define I2C1_RX_ADDR ((uint32_t)(&(i2cREG1->DRR))+ 3)

    UINT8 TX_PACK[bsize]={'H'、'E'、'R'、'C'、'U'、'L'、'E'、'S'、'M'、'I'、'C'、'R'、'O'、'-'、'T'、'A'};
    uint8 DMA_RX_PACK[bsize]={0};


    void i2cEnableLoopback (i2cbase_t * i2c);
    /*用户代码结束*/


    /*用户代码 begin (2)*/
    /*用户代码结束*/


    void main (void)

    /*用户代码 begin (3)*/

    g_dmaCTRL g_dmaCTRLPKT2、g_dmaCTRLPKT1;

    //启用 CPU 对中断请求的响应
    _enable_irq();

    /* i2c 初始化*/
    i2cInit ();

    /*配置要与之通信的从器件地址*/
    i2cSetSlaveAdd (i2cREG1、SLV_ADD);
    i2cSetDirection (i2cREG1、I2C_transmitter);

    /*设置 i2c 自身地址*/
    i2cSetOwnAdd (i2cREG1、own_add);

    /*启用内部回送*/
    i2cEnableLoopback (i2cREG1);

    dmaReqAssign (DMA_CH0、DMA_REQ10);
    dmaReqAssign (DMA_CH1、DMA_REQ11);

    dmaSetChEnable (DMA_CH0、DMA_HW);
    dmaSetChEnable (DMA_CH1、DMA_HW);

    dmaEnableInterrupt (DMA_CH0、BTC、DMA_INTA);
    dmaEnableInterrupt (DMA_CH1、BTC、DMA_INTA);

    /*为通道1*/配置控制数据包
    G_dmaCTRLPKT1.Sadd = I2C1_RX_ADDR;/*源地址*/
    g_dmaCTRLPKT1.DADD =(uint32_t) DMA_RX_PACK;/*目标地址 ss */
    G_dmaCTRLPKT1.CHCTRL = 0;/*通道控制*/
    g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/
    g_dmaCTRLPKT1.ELCNT = 1;/*元素计数*/
    G_dmaCTRLPKT1.ELDOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT1.ELSOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT1.FRDOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT1.FRSOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT1.PORTAGN = PORTB_READ_PORTA_WRITE;
    G_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT;/*读取大小*/
    G_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT;/*写入大小*/
    g_dmaCTRLPKT1.tType = FRAME_TRANSFER;/*传输类型*/
    G_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED;/*地址模式读取*/
    G_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1;/*地址模式写入*/
    G_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF;/* autoinit */

    /*配置通道0的控制包*/
    g_dmaCTRLPKT2.Sadd =(uint32_t) TX_Pack;/*源地址*/
    G_dmaCTRLPKT2.DADD = I2C1_TX_ADDR;/*目标地址*/
    G_dmaCTRLPKT2.CHCTRL = 0;/*通道控制*/
    g_dmaCTRLPKT2.FRCNT = bsize;/*帧计数*/
    g_dmaCTRLPKT2.ELCNT = 1;/*元素计数*/
    g_dmaCTRLPKT2.ELDOFFSET = 0;/*元素目标偏移*/
    g_dmaCTRLPKT2.ELSOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT2.FRDOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT2.FRSOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT2.PORTAGN = PORTA_READ_PORTB_WRITE;
    G_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT;/*读取大小*/
    G_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT;/*写入大小*/
    g_dmaCTRLPKT2.tType = FRAME_TRANSFER;/*传输类型*/
    G_dmaCTRLPKT2.ADDMODERD = ADDR_INC1;/*地址模式读取*/
    G_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;/*地址模式写入*/
    G_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF;/* autoinit */

    /*-设置 DMA 控制数据包以进行传输*/
    dmaSetCtrlPacket (DMA_CH0、g_dmaCTRLPKT1);
    dmaSetCtrlPacket (dma_ch1、g_dmaCTRLPKT2);

    dmaEnable();

    i2cREG1->DMACR |= 0x3;

    i2cSetStop (i2cREG1);

    /*传输启动条件*/
    i2cSetStart (i2cREG1);

    /*等待永远*/
    while (1);

    /*用户代码结束*/
    }

    /*用户代码 begin (4)*/
    /*用户代码结束*/

    请找到快照 DMA 接收缓冲区

    您是否可以检查 控制数据包的配置?

    问题可能是什么?

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

    尊敬的 Manoraj:

    您不能直接从 I2C 接收或发送16位数据

    您可以看到、数据宽度仅为8位。 因此、如果您希望接收16位、则应该需要发送2个字节。

    因此、如果您要传输2个字节或接收2个字节、则应按如下方式配置 DMA

    /*Configure control packet for Channel 1*/
    g_dmaCTRLPKT1.SADD = I2C1_RX_ADDR; /* source address */
    g_dmaCTRLPKT1.DADD = (uint32_t)DMA_RX_PACK; /* destination addr ss */
    g_dmaCTRLPKT1.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT1.FRCNT = 2; /* frame count */
    g_dmaCTRLPKT1.ELCNT = 1; /* element count */
    g_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT1.ELSOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT1.PORTASGN = PORTB_READ_PORTA_WRITE;
    g_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT; /* read size */
    g_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT; /* write size */
    g_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
    g_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED; /* address mode read */
    g_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
    g_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF; /* autoinit */
    
    /*Configure control packet for Channel 0*/
    g_dmaCTRLPKT2.SADD = (uint32_t)TX_PACK; /* source address */
    g_dmaCTRLPKT2.DADD = I2C1_TX_ADDR; /* destination address */
    g_dmaCTRLPKT2.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT2.FRCNT = 2; /* frame count */
    g_dmaCTRLPKT2.ELCNT = 1; /* element count */
    g_dmaCTRLPKT2.ELDOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT2.ELSOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT2.FRDOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT2.FRSOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT2.PORTASGN = PORTA_READ_PORTB_WRITE;
    g_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT; /* read size */
    g_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT; /* write size */
    g_dmaCTRLPKT2.TTYPE = FRAME_TRANSFER; /* transfer type */
    g_dmaCTRLPKT2.ADDMODERD = ADDR_INC1; /* address mode read */
    g_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;; /* address mode write */
    g_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF; /* autoinit */

    配置2个帧和1个大小为8位的元素、因此、通过这种方式、您可以使用 I2C 上的 DMA 接收或传输两个8字节。

    ——
    谢谢、此致、
    Jagadish。

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

    尊敬的 Jagadish:

    我尝试 配置了2个帧和1个大小为8位的元素

    我仅读取前2位

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

    尊敬的 Jagadish:

    我能够使用以下 DMA 和 HalCoGen 配置通过 DMA 读取16位数据


    /*为通道1*/配置控制数据包
    G_dmaCTRLPKT1.Sadd = I2C1_RX_ADDR;/*源地址*/
    g_dmaCTRLPKT1.DADD =(uint32_t) DMA_RX_PACK;/*目标地址 ss */
    G_dmaCTRLPKT1.CHCTRL = 0;/*通道控制*/
    g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/
    g_dmaCTRLPKT1.ELCNT = 1;/*元素计数*/
    G_dmaCTRLPKT1.ELDOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT1.ELSOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT1.FRDOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT1.FRSOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT1.PORTAGN = PORTB_READ_PORTA_WRITE;
    G_dmaCTRLPKT1.RDSIZE = ACCESS_8_BIT;/*读取大小*/
    G_dmaCTRLPKT1.WRSIZE = ACCESS_8_BIT;/*写入大小*/
    g_dmaCTRLPKT1.tType = FRAME_TRANSFER;/*传输类型*/
    G_dmaCTRLPKT1.ADDMODERD = ADDR_FIXED;/*地址模式读取*/
    G_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1;/*地址模式写入*/
    G_dmaCTRLPKT1.AUTOINIT = AUTOINIT_OFF;/* autoinit */

    /*配置通道0的控制包*/
    g_dmaCTRLPKT2.Sadd =(uint32_t) TX_Pack;/*源地址*/
    G_dmaCTRLPKT2.DADD = I2C1_TX_ADDR;/*目标地址*/
    G_dmaCTRLPKT2.CHCTRL = 0;/*通道控制*/
    g_dmaCTRLPKT2.FRCNT = bsize;/*帧计数*/
    g_dmaCTRLPKT2.ELCNT = 1;/*元素计数*/
    g_dmaCTRLPKT2.ELDOFFSET = 0;/*元素目标偏移*/
    g_dmaCTRLPKT2.ELSOFFSET = 0;/*元素目标偏移*/
    G_dmaCTRLPKT2.FRDOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT2.FRSOFFSET = 0;/*帧目标偏移*/
    G_dmaCTRLPKT2.PORTAGN = PORTA_READ_PORTB_WRITE;
    G_dmaCTRLPKT2.RDSIZE = ACCESS_8_BIT;/*读取大小*/
    G_dmaCTRLPKT2.WRSIZE = ACCESS_8_BIT;/*写入大小*/
    g_dmaCTRLPKT2.tType = FRAME_TRANSFER;/*传输类型*/
    G_dmaCTRLPKT2.ADDMODERD = ADDR_INC1;/*地址模式读取*/
    G_dmaCTRLPKT2.ADDMODEWR = ADDR_FIXED;/*地址模式写入*/
    G_dmaCTRLPKT2.AUTOINIT = AUTOINIT_OFF;/* autoinit */

    HalCoGen 配置:将 I2C 位计数从8更改为16  

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

    尊敬的 Jagadish:

    对于 I2C 环回、此配置非常有效。

    如果我想 从从设备读取,我需要在 控制数据包的配置中更改什么?

     

    在突出显示的配置中配置哪些内容?

    因为我希望只从从器件读取数据   

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

    尊敬的 Manoraj:

    我认为您之前用于接收16位数据的配置也不正确。

    突出显示的设置不适用于16位数据传输、这意味着需要在 i2c 上接收16个字符的数据。

    [报价 userid="495032" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1390906/tms570lc4357-example-source-code-and-halcogen-configuration-for-i2c-read-and-write-by-dma-controller/5322466 #5322466"]g_dmaCTRLPKT1.FRCNT = bsize;/*帧计数*/[/QUOT]

    此设置也不正确、因为您可以看到它的名称是帧计数、即需要发送或接收的帧数。 您不应在此处使用位大小进行初始化。

    要接收或传输16位、只需将上述两个设置保持为2。

    您的从设备是什么?

    ——
    谢谢、此致、
    Jagadish。

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

    尊敬的 Jagadish:

    感谢您的反馈。

    我的从器件是 LSM6DSO32:常开3轴加速计和3轴陀螺仪

    在 控制数据包配置中、需要对来自从器件  LSM6DSO32的数据进行哪些更改?

    我已经实现了 通过正常 I2C 从 LSM6DSO32读取数据。

    由于我想从 LSM6DSO32读取更多数据、因此我想使用 DMA 来降低 CPU 负载

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

    尊敬的 Manoraj:

    我为发送和接收创建了一个 i2c 示例项目。

    我的项目如下:

    e2e.ti.com/.../I2C_5F00_DMA_5F00_TEST_5F00_LC4357.zip

    我通过连接到从器件(另一个被配置为从器件的 TI 电路板)测试了该项目。

    当我配置为发送器时、我将向从器件发送以下突出显示的数据:

    这里是我的输出、大家可以看到我从从器件收到了 ACK、然后 TMS 板将数据正确发送到 DMA 上的从器件。

    同样、我还测试了接收功能:

    为了测试接收功能、我将在从器件侧发送下面突出显示的数据、

    这是我的主输出、我能够将数据从从从器件正确接收到主 RX 缓冲区中。

    因此、应将此代码作为参考、并根据您的从设备正确配置从设备地址和数据计数。

    同时确保您正确遵循从站协议、如果您正确执行这些操作、那么您的代码肯定会起作用。

    我另一条建议是、客户通常不会更喜欢 DMA 上的 i2c。 这是因为 i2c 从器件发送少量字节可能是几个字节、对于这个数量的数据不是必需的 DMA。 如果有很大的数据块、那么它可能很有用、但对于几个字节来说、它不是必需的。 "你是我的女人,我知道你是我的女人。"

    ——
    谢谢、此致、
    Jagadish。

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

    尊敬的 Jagadish:

    非常感谢您分享该项目。

    使用 DMA I2C、我将从从器件的 FIFO 中读取3kB 的数据  

    这就是我尝试 DMA 以避免 CPU 负载的原因。

    我使用 I2C2外设。  

    如何识别 i2c2的自身地址?

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    使用 DMA I2C、我将从从设备的 FIFO 读取3kb 的数据 

    在这种情况下、选择 DMA 是合理的。

    如何识别 i2c2的自有地址?

    在这种情况下、自身地址可能不重要、仅确保您配置了正确的从器件地址。 忽略自身的地址。

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

    尊敬的 Jagadish:

    我已经配置了从器件、能够从从器件中读取 FIFO。

    但从器件具有一个限制条件  

    为了读取完整的 FIFO、我需要单独读取7个寄存器以获得已配置的采样数量。

    这意味着我需要调用 i2cSetStart (i2cREG2) 来获取7 *个 已配置采样数。

    需要始终使用 I2C 来清除使 CPU 保持忙状态的 FIFO

    I2C 或 DMA 中是否有重复模式用于读取 n 次数据?

     Google.ie/URL?sa=t&RCT=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwi5vLv9ktaAxVMRkEAHa35NbYQFnoECBsQAQAQAQAQ&url=https%3A%2F%2F%2Fwww.st.com%2Fresource%2Fen%2Fapplication_note%2Fan5473-lsm6dso32-alwayson-3axis-accelerometer-and-3axis-gyroscope-stmicroelectronics.pdf&usg=AOvVaw3lHrm0eDvuJPU5xnAmc1MZ&opi=89978449

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

    尊敬的 Jagadish:

    如何 在 DMA 中使用自动启动模式(AIM)?

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

    尊敬的 Manoraj:

    [报价 userid="495032" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1390906/tms570lc4357-example-source-code-and-halcogen-configuration-for-i2c-read-and-write-by-dma-controller/5339802 #5339802"]

    但从器件具有一个限制条件  

    为了读取完整的 FIFO、我需要单独读取7个寄存器以获得已配置的采样数量。

    [报价]

    我完全不知道该从设备。

    如果我们对从器件的处理能力存在限制、但我建议完全检查从器件、继续 FIFO 读取模式等功能可能会有所帮助。

     自动启动模式(AIM)如何在 DMA 中工作?

    关于自动初始化模式理解、请参阅以下主题:

    (+) TMS570LC4357:DMA 翻转-基于 Arm 的微控制器论坛-基于 Arm 的微控制器- TI E2E 支持论坛

    我的意思是、在传输完成后、它将再次自动初始化所有参数、例如源地址、目标地址、帧计数、以便启动 下一次传输。 如果我们启用 DMA 通道、则下一次传输将自动启动。

    ——
    谢谢、此致、
    Jagadish。