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.

[参考译文] MSP430 MSPDRIVERLIB USCI masterReceiveMultiByteFinish 相关函数使用错误的操作顺序

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1059430/msp430-mspdriverlib-usci-masterreceivemultibytefinish-related-functions-use-wrong-operation-order

主题中讨论的其他器件:MSP430F5529CC430F5137MSP430WAREMSP430F5510


大家早上好。

我暂停了数据表分析、只是为了发现另一个错误、这次是在 MSP430 DRIVERLIB 中。

错误描述:
USCI_B_I2C_masterReceiveMultiByteFinish ()和 USCI_B_I2C_masterReceiveMultiByteFinishWithTimeout ()函数在 UCRIFG 标志置为有效前从 OFS_UCBxRXBUF 寄存器执行读取操作。 结果是、使用这两个函数的所有读取操作都将产生纯垃圾。

第一个函数的建议错误修复(补丁):

-- driverlib/MSP430F5xx_6xx/USCI_B_i2c.c 2020-02-27 20:48:53.000000000 +0200
++ atlas430/driverlib/MSP430F5xx_6xx/USCI_B_i2c.c 2021-1205 17:33:18.264094116 +0200
@@-446、16 +446、16 @@ uint8_t USCI_B_I2C_ReceivmasterMultiByt
//发送停止条件。
HWREG8 (baseAddress + OFS_UCBxCTL1)|= UCTXSTP;

-//在将停止位设置为到期后从接收缓冲区捕获数据
-//MSP430 I2C 关键时序。
- receiveData = HWREG8 (baseAddress + OFS_UCBxRXBUF);
-
//等待停止完成
while (HWREG8 (baseAddress + OFS_UCBxCTL1)& UCTXSTP);

//等待 RX 缓冲器
while (!(HWREG8 (baseAddress + OFS_UCBxIFG)& UCRXIFG));

+//将由于而产生的停止位置1后从接收缓冲区捕获数据
+/MSP430 I2C 关键时序。
+ receiveData = HWREG8 (baseAddress + OFS_UCBxRXBUF);
+
返回 receiveData;

需要注意的是、此函数在不同系列和 eusci/USCI 类型的 driverlib 存档中再次出现4次、并且在所有其他地方、读取操作在 IFG 被检查后发生。

在 msp430f5529/cc430f5137和 Cypress FM24V10外部 i2c fram 芯片之间执行单元测试:

8字节写入、8字节读取、重复一次。

图例:
"I2C 写入"只是简单地写入一个包含"0xa1、0xa2、0xa3、0xa4、0xA5、 0xa6、0xa7、0xa8"添加到外部 fram 芯片
"I2C 读取"只会尝试从外部 fram 芯片的同一地址读取8个字节,并且在读取最后一个字节时使用未修补的 USCI_B_I2C_ReceiveMultiByteFinish()。
"(prog)"固件内部缓冲器包含的内容
"(有线)"在线上使用逻辑分析仪可以看到的内容
"[foo]"解释
在理想情况下、'i2c read'必须提供与'i2c write'写入的缓冲器完全相同的缓冲器、因为两个函数的起始地址相同。

I2C 写入(prog):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa8 [确定]
I2C 写入(线):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa8 ACK [确定]

I2C 读取(线):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa8 nack [确定]
I2C 读取(prog):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa7 [读取最后一个字节错误]

I2C 写入(prog):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa8 [确定]
I2C 写入(线):0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa7 0xa8 ACK [确定]

I2C 读取(线):0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 NACK [失败、在第7个字节而不是第8个字节后发出 NAK ]
I2C 读取(prog):0xa8 0xa1 0xa2 0xa3 0xa4 0xA5 0xa6 0xa6 [0xa8是上一次读取操作的垃圾、剩余的字节被移位]

TLDR:因此、如果没有补丁、两个函数就会产生垃圾、而在 CC430F5137和 MSP430F5529上测试的补丁则一切都很棒。 请修复。

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

    你(们)好  

    请下载最新的 MSP430WARE 并使用最新的驱动程序。

    "="">MSP430WARE_3.80.14.01" href="https://www.ti.com/tool/download/MSP430WARE/?keyMatch=MSP430WARE">MSP430WARE_3.80.14.01

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

    该版本的 msp430ware 包含此错误所属的 driverlib 的确切版本(v2.91.13.01)

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

    刚刚使用 msp430f5510进行了测试、结果完全相同-在检查 IFG 后、driverlib 需要执行读取。

    我使用的代码位于 GitHub 上、网址 为:github.com/.../cypress_fm24
    它在很大程度上基于预处理脚本、makefile 文件和 Linux MSP430工具链、不支持 CCS。抱歉。

    有问题的函数在以下行中使用: github.com/.../i2c.c

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

    您好、Petre、

    我将进行测试、然后回复您

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

    您好、Petre、

    接收多字节数据的示例 drivelib 工程没有问题。

    作为示例代码。  

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_B0_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(USCI_B0_VECTOR)))
    #endif
    void USCI_B0_ISR (void)
    {
        switch (__even_in_range(UCB0IV,12)){
            case USCI_I2C_UCRXIFG:
            {
                //Decrement RX byte counter
                receiveCount--;
    
                if (receiveCount){
                    if (receiveCount == 1) {
                        //Initiate end of reception -> Receive byte with NAK
                        *receiveBufferPointer++ =
                            USCI_B_I2C_masterReceiveMultiByteFinish(
                            		USCI_B0_BASE
                                );
                    }
                    else {
                        //Keep receiving one byte at a time
                        *receiveBufferPointer++ = USCI_B_I2C_masterReceiveMultiByteNext(
                        		USCI_B0_BASE
                            );
                    }
                }
                else {
                    //Receive last byte
                    *receiveBufferPointer = USCI_B_I2C_masterReceiveMultiByteNext(
                    		USCI_B0_BASE
                        );
                    __bic_SR_register_on_exit(LPM0_bits);
                }
                break;
            }
        }
    }

    当运行到<receiveData = HWREG8(baseAddress + OFS_UCBxRXBUF);> 时、它处于中断例程中、并且 RX 标志已经被置位。 这意味着主器件已从从器件接收到数据。 然后发送 STOP 信号并将最终字节接收到 RXBUFFER。  

    这是为了确认最后一个字节已经被接收到缓冲区。

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

    Allen、我非常感谢您的快速回复、我知道有很多票进来、人们倾向于度假、有人需要关闭这些票、但我非常不同意您对这张票的意见。

    请保持友好、并向 driverlib 的维护人员开一个内部票据、其中包括我的所有信息。

    我理解您的推理和所有涉及的寄存器、您的代码看起来可能起作用。 但是、还有另一个用例无法使用该函数、如上所述、它在三种不同的 MSP430上是可行的。 根据我在上一篇文章中提供的链接,我将在非中断驱动的环境中使用 masterReceiveMultiByteFinish()函数。 对于 UCRXIFG 的这种特殊检查在中断实现中没有什么意义、因为该函数在实际接收到字节后调用、并且已经调用了中断处理程序。 在您的示例代码中、IFG 校验是冗余的、但在非中断实现中、校验是强制性的、必须在读取 UCBxRXBUF 寄存器之前执行。

    回到正轨。 masterReceiveMultiByteFinish()在 driverlib 中出现5次-在其中4次中、在从 UCBxRXBUF 读取之前正确执行 UCRXIFG 检查。 这一简单的事实应该已经促使您发现有问题、但您说、在这1种情况下、订单被反转的情况下、它的"好"程度是多少。 在所有这4种情况下、该函数可在非中断驱动的环境中完美使用、因为在 UCRXIFG 被置为有效之前、UCBxRXBUF 的读取将被正确延迟。 在这1种情况下、我为忘记支票存在原因的人打开了此错误。

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

    我开始相信非中断实现不是一个好主意、我将删除它。

    很抱歉听到噪音。