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.

[参考译文] TMS570LS0432:HalCoGen SPI、RXINTFLG 从不置位

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/589292/tms570ls0432-halcogen-spi-rxintflg-never-sets

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

大家好、

我使用的是 Hercules TMS570LS0432 Launchpad、我使用的是 HalCoGen 驱动程序、并且取得了很大的成功。 但是、SPI 驱动程序一直给我带来问题。  

调用 spiTransmitData()或 spiTransmitAndReceiveData()函数时,有时(但不是所有时间)会在等待 RXINTFLG 位设置时卡住,即“while ((SPI->FLG & 0x00000100U)!= 0x00000100U)”。 通过调试器、我可以看到 SPI 标志寄存器设置为0x01000200 (TXINTFLG 设置)。

我连接了一个4通道示波器、可以看到在计时8位后、芯片选择和时钟线被拉高、因此传输似乎已经正常。 我做了什么错了、我可以做什么来解决这个问题?  

下面是一些代码片段、我希望这方面的帮助足以满足我的要求。

我的函数调用:

TransmitData (spiREG2、&spiFmt0、1、txBuf);

我的 spiDAT1_t 结构传入相关函数:

DAT1_t spiFmt0 ={
.CS_HOLD = 1、
.WDEL = 1、
.DFSEL = SPI_FMT_0、
CSNR = 0x00
};

在 HalCoGen 的 spiInit (void)中:

spiREG2->FMT0 =(uint32)((uint32) 2U <<24U)/* wdelay */
|(uint32)((uint32) 0U << 23U)/*奇偶校验极性*/
|(uint32)((uint32) 0U << 22U)/*奇偶校验使能*/
|(uint32)((uint32) 0U << 21U)//等待启用
|(uint32)((uint32) 0U << 20U)/*移位方向*/
|(uint32)((uint32) 1U << 17U)/*时钟极性*/
|(uint32)((uint32) 0U << 16U)/*时钟相位*/
|(uint32)((uint32) 159U << 8U)/*波特率预分频*
|(uint32)((uint32) 8U << 0U);/*数据字长度*/

感谢您对该问题的任何深入了解、
Matthew

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

    正如我所怀疑的那样、函数 spiTransmitData 和 spiTransmitAndReceive 中的轮询仅查看 RXINTFLG、因为在全双工模式下使用 SPI 时、每次传输都有一个接收信号。 因此、当 SPI 标志寄存器的值为0x01000200时、TXINTFLG 被置位、它将保持在轮询环路中。

    您的帖子中不清楚的是、如果您打算在全双工或半双工模式下使用 SPI。 也就是说、当数据被移出时、是否有数据也被移入器件? 我假设这是案例、或者至少是您的帖子标题中给出的预期案例。 但是、您没有看过 Tx 和 SPICLK、并且示波器 bu 上的 CS 引脚没有明确说明 RX 线的条件。 我还想在同一页上、假设您在兼容模式下使用标准 SPI 或 MibSPI、并且 LS0432是主器件? 这些假设是否正确?

    如果您看到 Rx (SOMI)信号良好并反映预期/预期数据、则设置 Tx 标志时 Rx 缓冲器的内容是什么? Rx 缓冲区中的数据是否正确且反映的内容与示波器图相同?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好,Chuck!

    您的假设是正确的;很抱歉、我应该在我的帖子中提供更多详细信息。 全双工;LS0432是主设备。

    我的从器件(LTC6811-1电池堆栈监视器)读取4字节命令并以一定数量的数据进行响应。 LTC6811期望在整个事务中将 CS 引脚拉低、而我发现的唯一方法是使用 spiTransmitAndReceive()函数(CSHOLD=1)并传递总字节数(即4字节命令+从器件传输的 X 字节数据)。 但是、在我发送前4个字节时、LTC6811从器件实际上不会在 SOMI 线上置位任何内容。 这可能是问题的一部分吗? 我假设它将被读作全为1 (因为 SOMI 线被上拉)、我可以输出数据。

    此外、需要在 SPI 事务发生前唤醒 LTC6811从器件。 LTC 的一位应用工程师告诉我、我可以通过在 SIMO 线路上计时8位0或1来实现此目的(CS 引脚具有完整的高电平到低电平到高电平周期)、然后再发送实际命令。 我使用 spiTransmitData (spiREG2、&spiFmt0、1、&onesBuf)执行此操作。 有时 RXINTFLG 会在此处捕获陷阱、有时它会成功并捕获在下一个调用中、即 spiTransmitAndReceiveData (spiREG2、&spiFmt0、12、txData、 rxData)。

    在直接回答您的最后一个问题时、RX 缓冲寄存器与我在示波器上看到的内容之间存在匹配。 RXINTFLG 无限循环似乎总是在8位为1的从器件"唤醒"之后或在命令的第一个字节之后发生。 因此、SOMI 线永远不会被置为有效(从器件永远不会输出数据)、所以该线被保持在高电平。 因此、SPI RX 缓冲寄存器读取为0xFF、这正是我所期望的。

    希望这能更好地传达我的情况、感谢您的帮助、

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

    与同事交谈并阅读更多 TRM、需要考虑几个因素。 首先、Nena 引脚的状态是什么? 如果您不使用 GIO、您是否已将其配置为 GIO? 否则、它应处于绑定无效状态。 如果保持悬空、可能会导致如您所述的间歇行为、因为这会导致 Tx 被保持关闭。 此外、对于 TxINTFlg、该标志仅指示 Tx 缓冲区为空。 如果 Nena 可能处于悬空状态、则意味着 Tx 数据已从 Tx 缓冲区移出到移位寄存器中、但实际上并未放置到总线上。

    您能否查看 Nena 配置并通过将其初始化为非功能模式来确保其不浮动?

    如果您的应用已经是这种情况(处理 Nena)、我需要更深入地了解行为。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Chuck、

    SPI2 ENA 引脚被设定为一个 GPIO。 为了尝试一些操作、我已经将引脚设置为具有高逻辑电平和低逻辑电平的输出;这两种情况都不会改变我所经历的行为。

    我很难理解 TXINTFLG 为什么会置位、而不是 RXINTFLG。 我只知道 TRM 中的内容、但似乎 SPI 外设应该乐意随时钟入 SOMI 引脚上的任何值、而不管它们的状态如何。 当然、除非 SPI 硬件期望电流像推挽设置那样。

    下面是一些更完整的代码片段、可能会有所帮助。 它包括我的主循环的白减版本、以及 HalCoGen 生成的 spiInit()和 spiTransmitAndReceive()函数。 我对它们所做的唯一更改(如果我记错了)位于 spiInit()中,并更改了 Nena 引脚的设置。  

    有时代码会到达 while ()循环并在停止 RXINTFLG 的 b/c 之前运行最后的 spiTransmitAndReceiveData()函数几次。 在其它情况下,它会在第一个 spiTransmitData()调用中停止。

    同时、我已经编写了自己的 SPI 函数、忽略了 RXINTFLG 位、并且与我的从器件成功通信。 这可能是一个危险的做法、所以如果可能的话、我想使用 HalCoGen 驱动程序。  

    再次感谢、

    Matthew

    #include "sys_common.h"
    #include "spi.h"
    
    
    void main (void)
    {
    uint16_t zeroBuf = 0xFF;
    uint16_t spiTxData[12]={0、2、0x2b、0x0a、0、0、0、0、0、0、0、0、0、0};
    uint16_t spiRxData[12];
    
    spiInit();
    
    //唤醒从
    器件 spiTransmitData (spiREG2、&spiFmt0、1、&zeroBuf);
    
    //发送第一个命令
    spiTransmitAndReceiveData (spiREG2、&spiFmt0、12、TxData、SpiRxData);
    
    while (1)
    {
    for (i=0;i<10000;i++);
    spiTransmitAndReceiveData (spiREG2、&spiFmt0、 12、spiTxData、spiRxData);
    }
    
    
    void spiInit (void)
    {
    //用户代码开始(2)*/
    //*用户代码结束*/
    
    /**@b 初始化@b SPI2 */
    
    /**使 SPI 退出复位*/
    spiREG2->GCR0 = 0U;
    spiREG2->GCR0 = 1U;
    
    /** SPI2主控模式和时钟配置*/
    spiREG2->GCR1 =(spiREG2->GCR1 & 0xFFFFFFFCU)|((uint32)((uint32) 1U << 1U)/* CLOKMOD */
    | 1U);/*主设备*/
    
    /** SPI2使能引脚配置*/
    spiREG2->INT0 =(spiREG2->INT0 & 0xFEFFFFFFU)|(uint32)((uint32) 0U << 24U);//启用 HICHZ */
    
    /**-延迟*/
    spiREG2->delay =(uint32)((uint32) 200U <<24U)/* C2TDELAY */
    |(uint32)((uint32) 2U <<16U)/* T2CDELAY */
    |(UINT32)((UINT32) 0U <<8U)/* T2EDELAY */
    |(uint32)((uint32) 0U << 0U);// C2EDELAY *
    
    /**-数据格式0 */
    spiREG2->FMT0 =(uint32)((uint32) 2U <<24U)/* wdelay */
    |(uint32)((uint32) 0U << 23U)/*奇偶校验极性*/
    |(uint32)((uint32) 0U << 22U)/*奇偶校验使能*/
    |(uint32)((uint32) 0U << 21U)//等待启用
    |(uint32)((uint32) 0U << 20U)/*移位方向*/
    |(uint32)((uint32) 1U << 17U)/*时钟极性*/
    |(uint32)((uint32) 0U << 16U)/*时钟相位*/
    |(uint32)((uint32) 159U << 8U)/*波特率预分频*
    |(uint32)((uint32) 8U << 0U);/*数据字长度*/
    /**-数据格式1 */
    spiREG2->FMT1 =(uint32)((uint32) 2U <<24U)/* wdelay */
    |(uint32)((uint32) 0U << 23U)/*奇偶校验极性*/
    |(uint32)((uint32) 0U << 22U)/*奇偶校验使能*/
    |(uint32)((uint32) 0U << 21U)//等待启用
    |(uint32)((uint32) 0U << 20U)/*移位方向*/
    |(uint32)((uint32) 1U << 17U)/*时钟极性*/
    |(uint32)((uint32) 0U << 16U)/*时钟相位*/
    |(uint32)((uint32) 79U << 8U)/*波特率预分频*
    |(uint32)((uint32) 8U << 0U);/*数据字长度*/
    
    /**-数据格式2 */
    spiREG2->FMT2 =(uint32)((uint32) 2U <<24U)/* wdelay */
    |(uint32)((uint32) 0U << 23U)/*奇偶校验极性*/
    |(uint32)((uint32) 0U << 22U)/*奇偶校验使能*/
    |(uint32)((uint32) 0U << 21U)//等待启用
    |(uint32)((uint32) 0U << 20U)/*移位方向*/
    |(uint32)((uint32) 1U << 17U)/*时钟极性*/
    |(uint32)((uint32) 0U << 16U)/*时钟相位*/
    |(uint32)((uint32) 79U << 8U)/*波特率预分频*
    |(uint32)((uint32) 8U << 0U);/*数据字长度*/
    
    /**-数据格式3 */
    spiREG2->FMT3 =(uint32)((uint32) 0U <<24U)/* wdelay */
    |(uint32)((uint32) 0U << 23U)/*奇偶校验极性*/
    |(uint32)((uint32) 0U << 22U)/*奇偶校验使能*/
    |(uint32)((uint32) 0U << 21U)//等待启用
    |(uint32)((uint32) 0U << 20U)/*移位方向*/
    |(uint32)((uint32) 1U << 17U)/*时钟极性*/
    |(uint32)((uint32) 0U << 16U)/*时钟相位*/
    |(uint32)((uint32) 79U << 8U)/*波特率预分频*
    |(uint32)((uint32) 8U << 0U);/*数据字长度*/
    
    /**-设置中断级别*/
    spiREG2->LVL =(uint32)((uint32) 1U <<9U)/* TXINT */
    |(UINT32)((UINT32) 1U <<8U)/* RXINT */
    |(uint32)((uint32) 1U <<6U)/* OVRNINT */
    |(uint32)((uint32) 1U << 4U)/* BITER */
    |(uint32)((uint32) 1U << 3U)/* DESYNC */
    |(uint32)((uint32) 1U << 2U)/* PARERR */
    |(uint32)((uint32) 1U << 1U)/*超时*/
    |(uint32)((uint32) 1U <<0U);/* DLENERR */
    
    /**-清除所有挂起的中断*/
    spiREG2->FLG |= 0xFFFFFFU;
    
    /**-启用中断*/
    spiREG2->INT0 =(spiREG2->INT0 & 0xFFFF0000U)
    |(UINT32)((UINT32) 0U <<9U)/* TXINT */
    |(UINT32)((UINT32) 1U <<8U)/* RXINT */
    |(UINT32)((UINT32) 0U << 6U)/* OVRNINT */
    |(uint32)((uint32) 0U << 4U)/* BIERR */
    |(uint32)((uint32) 0U << 3U)/* DESYNC */
    |(uint32)((uint32) 0U << 2U)/* PARERR */
    |(uint32)((uint32) 0U << 1U)/*超时*/
    |(UINT32)((UINT32) 0U << 0U);/* DLENERR */
    
    /**@b 初始化@b SPI2 @b 端口*/
    
    /**- SPI2端口输出值*/
    spiREG2->PC3 =(uint32)((uint32) 1U <<0U)/* SCS[0]*/
    |(uint32)((uint32) 1U << 1U)/* scs[1]*/
    |(uint32)((uint32) 1U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 1U << 3U)/* SCS[3]*/
    |(uint32)((uint32) 1U <<9U)/* CLK */
    |(uint32)((uint32) 0U <<10U)/* SIMO */
    |(UINT32)((UINT32) 0U << 11U)/* SOMI */
    |(UINT32)((UINT32) 0U <<8U);/* ENA */
    
    /**- SPI2端口方向*/
    spiREG2->PC1 =(uint32)((uint32) 1U <<0U)/* SCS[0]*/
    |(uint32)((uint32) 1U << 1U)/* scs[1]*/
    |(uint32)((uint32) 1U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 1U << 3U)/* SCS[3]*/
    |(uint32)((uint32) 1U <<9U)/* CLK */
    |(uint32)((uint32) 1U <<10U)/* SIMO */
    |(UINT32)((UINT32) 0U << 11U)/* SOMI */
    |(uint32)((uint32) 1U <<8U);/* ENA */
    
    /**- SPI2端口开漏使能*/
    spiREG2->PC6 =(uint32)((uint32) 0U <<0U)/* scs[0]*/
    |(uint32)((uint32) 0U << 1U)/* scs[1]*/
    |(uint32)((uint32) 0U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 0U << 3U)/* SCS[3]*/
    |(UINT32)((UINT32) 0U <<9U)/* CLK */
    |(uint32)((uint32) 0U <<10U)/* SIMO */
    |(uint32)((uint32) 0U << 11U);/* SOMI *
    
    /**- SPI2端口上拉/下拉选择*/
    spiREG2->PC8 =(uint32)((uint32) 1U <<0U)/* SCS[0]*/
    |(uint32)((uint32) 1U << 1U)/* scs[1]*/
    |(uint32)((uint32) 1U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 1U << 3U)/* SCS[3]*/
    |(uint32)((uint32) 1U <<9U)/* CLK */
    |(uint32)((uint32) 1U <<10U)/* SIMO */
    |(uint32)((uint32) 1U <<11U);/* SOMI */
    
    /**- SPI2端口上拉/下拉使能*/
    spiREG2->PC7 =(uint32)((uint32) 0U <<0U)/* scs[0]*/
    |(uint32)((uint32) 0U << 1U)/* scs[1]*/
    |(uint32)((uint32) 0U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 0U << 3U)/* SCS[3]*/
    |(UINT32)((UINT32) 0U <<9U)/* CLK */
    |(uint32)((uint32) 0U <<10U)/* SIMO */
    |(uint32)((uint32) 0U << 11U);/* SOMI *
    
    /* SPI2将所有引脚设置为功能*/
    spiREG2->PC0 =(uint32)((uint32) 1U <<0U)/* SCS[0]*/
    |(uint32)((uint32) 1U << 1U)/* scs[1]*/
    |(uint32)((uint32) 1U << 2U)/* scs[2]*/
    |(UINT32)((UINT32) 1U << 3U)/* SCS[3]*/
    |(uint32)((uint32) 1U <<9U)/* CLK */
    |(uint32)((uint32) 1U <<10U)/* SIMO */
    |(uint32)((uint32) 1U <<11U);/* SOMI */
    
    
    spiREG2->PC5 =(uint32)((uint32) 1U <<8U);/* ENA */
    
    /**-初始化 TX 和 RX 数据缓冲区状态*/
    G_spiPacket_t[1U].TX_DATA_STATUS = SPI_READY;
    G_spiPacket_t[1U].Rx_DATA_STATUS = SPI_READY;
    
    /**-最后启动 SPI2 */
    srREG2->GCR1 =(spiREG2->GCR1 & 0xFEFFFFFFU)| 0x01000000U;
    
    //用户代码开始(3)*//
    *//* UINT32 INTTransmitReceiveData
    
    
    
    (spiBASE-t * SPI、spiDAT1_t * spionfap_t、Uint32 * intbuff * 16 *
    
    uint16 Tx_Data;
    uint32 Chip_Select_Hold =(dataconfig _t->CS_Hold)? 0x10000000U:0U;
    uint32 WDray =(dataconfig _t->WDEL)? 0x04000000U:0U;
    SPIDATAFMT_t DataFormat =数据通信 fap_t->DFSEL;
    uint8 ChipSelect = dataconfig t->CSNR;
    
    //用户代码开始(14)*/
    //*用户代码结束*/
    while (blocksize!= 0U)
    {
    if ((SPI->FLG & 0x000000FFU)!=0U)
    {
    中断;
    }
    
    if (blocksize == 1U)
    {
    CHIP_Select_HOLD = 0U;
    }
    /*SAFETYMCUSW 45 D MR:21.1 "仅此驱动程序允许有效的非 NULL 输入参数"*/
    TX_Data =* srcbuff;
    
    SPI->DAT1 =((UINT32) DataFormat << 24U)|
    ((UINT32) ChipSelect << 16U)|
    (威德莱) |
    (CHIP_Select_HOLD)|
    (uint32) Tx_Data;
    /*SAFETYMCUSW 567 S MR:17.1,17.4 "需要指针增量"*/
    srcbuff +;
    /*SAFETYMCUSW 28 D MR:NA "硬件状态位读取检查"*/
    while ((SPI->FLG & 0x00000100U)!= 0x00000100U)
    {
    } /*等待*/
    /*SAFETYMCUSW 45 D MR:21.1 "仅此驱动程序允许有效的非 NULL 输入参数"*/
    *缓冲区=(uint16) SPI->BUF;
    /*SAFETYMCUSW 567 S MR:17.1,17.4 "需要指针增量"*/
    减持器++;
    
    blocksize-;
    } 

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

    我还没有确切的答案、但根据您的代码和我对某些格式选项的理解、我确实有几个观察结果。

    首先、正如您在原始帖子中所述、CSHOLD = 1。 当 CSHOLD = 1时、C2TDELAY 和 T2CDELAY 设置将被忽略、因此按照上述初始化代码中的操作进行设置不会导致这些设置、并且不会导致与这些延迟值相关的特定行为。 另一方面、即使 CSHOLD=1、WDELAY 参数仍然有效。 这意味着在数据包之间的(WDELAY+2) X VCLK 周期内、CS 将失效。 我曾认为您说过您的从器件要求在传输之间保持 CS 有效?

    最后、出于测试目的、您是否考虑启用环回、以便接收发送的内容、从而查看这是否是外部器件的问题或与 LS0432完全相关的某些奇怪行为? 该器件具有数字回路和可使用的模拟回路模式。 数字环回全部是内部逻辑、其中模拟实际上通过引脚的模拟输入和输出缓冲器。