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.

[参考译文] MCSPI-AM243X:MCU-PLUS-SDK 外设模式、如何检查接收到的数据路径长度

Guru**** 2616255 points

Other Parts Discussed in Thread: AM2434

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1431077/mcu-plus-sdk-am243x-mcspi-peripheral-mode-how-to-check-received-dataes-length

器件型号:MCU-PLUS-SDK AM243X
主题中讨论的其他器件:AM2434

工具与软件:

尊敬的专家:

   AM2434ALV EVM 板配合使用时、 我的方案如下:

   EVM MCSPI 作为 SPI 从器件(外设)与另一个模块进行通信。 从器件每次都知道来自主机的长度、但从器件需要在主机发送请求数据时同步发送特定数据(例如0xAA 0xAA ... 0xAA)。 因此、我使用一个 GPIO 来监控主机 CS 引脚状态、并 在主机发送(MCSPI 模式:中断和回调)之前通过 MCSPI_TRANSFER ()预先发送最大长度0xAA。 当触发 GPIO/CS 引脚上升沿中断时、则认为已完成传输、然后从器件会解析所有接收到的数据和响应。  我的问题:

   1.如何知道实际接收了多少个字节?

   2. txfifo 内 尚未发出的数据是否 需要人工清除,以免影响有效数据的后续传输? 以及如何在需要时进行清除。

     

   

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

    您好!

    我请求您浏览此页面: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1305146/sk-am64b-r5f-spi-dma-in-mcspi_ms_mode_peripheral/5064289#5064289

    。 如何知道实际上已经接收了多少个字节?

    这可以在"购买"检查 MCSPI RX 寄存器中找到。 您是否尝试过进行研究?

    此致、

    Vaibhav

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

    尊敬的 Vaibhav:

       您提供的示例适合从机提前知道主机将发送多少字节。 但对于我的场景来说、数据长度是未知的。 例如、主机可能发送一个包 、其中包括5个字节、7个字节或10个字节。 为了与这两种情况兼容、从器件需要提前将10个字节0xAA 填充到 txfifo 中。 当通信只有7个字节时、通信结束时从器件的 txfifo 中还剩余3个字节、并且不会触发 SPI 中断、因为并非所有的10个字节都已发送。

      MCSPI RX 寄存器存储接收到的数据、而不是长度。 我想 MCSPI_CHSTAT 寄存器可能是合适的、但我还没有尝试过。

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

    您好!

    请等待延迟响应、因为我正在进行高优先级调试。

    感谢您的耐心。

    此致、

    Vaibhav

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

    大家好、罗亮:
    1.

    您的数据是否具有计时概念: 例如: 当您的从设备发送 5个字节、7个字节或10个字节时、 它们会连续出现。   间隔将为100纳秒。  然后有一个 大于1毫秒的间隔被视为另一个数据包。 、   

    例如:

    x <-ZNS->x <-ZNS->x <-ZNS->x <-ZNS->x   <- y 毫秒->  x x x x x x x  (7个字节)

    红色部分是5字节数据包、  蓝色部分是7字节。  x 是它自己的数据。   z 是纳秒间隔。  Y 是毫秒间隔?

    2.您是否能够对从器件进行编程,从器件是否可能将引脚驱动为高电平,引脚驱动为低电平,以指示数据完成?

    谢谢。

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

    大家好、Jun、是的、这就是它的工作方式。

      现在我找到了解决方案:

      将 RXFIFO 配置为2、这可以每2个字节触发一次 SPI ISR、以便可以通过 gMcspiConfig[0].object->mcspiLldInitObj[0].curRxBufPtr 间接获得接收到的长度、然后检查 CHSTAT 寄存器以确认 FIFO 中是否仍然存在字节。

      我使用了 CS 引脚的 GPIO 存根 来监控通信结束。 不确定 AM243X 上的 CS0是否可同时用于 SPI CS 和 IO 中断、您可以帮助确认吗?

      此外、我发现 在通信完成后需要手动清除 txfifo 内的剩余数据。 目前、我只能通过重新初始化 MCSPI 来清除它、是否有更明显的方法?

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

    AM243X 上的 CS0可同时用于 SPI CS 和 IO 中断、您能帮助确认吗?

    我敢肯定、它不能同时用于 SPI CS 和 IO 中断。  

    原因:  IO 中断表示 GPIO 输入、  SPI CS 表示 GPIO 输出。  


    (但是、您可以动态配置引脚。)  引脚是可配置的、如果您配置为引脚模式(7)、则表示 GPIO_42。  
    发送时、您将引脚配置为引脚 mode0。  当您想要接收时,您可以将其配置为输入引脚,引脚鼠标7.

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

    大家好、Jun、我的问题基于作为从器件的 SPI 配置。

       

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

    感谢澄清、如果您的 SPI 是从设备、那么我认为没有任何问题。 您的 CS 已配置为输入引脚。  我们等待 

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

    您好!

    Jun、感谢您澄清了一些疑问。

    不确定 AM243X 上的 CS0是否可同时用于 SPI CS 和 IO 中断、您能帮忙确认吗?

    最好仅将 CS0引脚用于 SPI_CS、即使 SPI 配置为从器件也是如此。

    此致、

    Vaibhav

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

    好的、谢谢。

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

    尊敬的 Vaibhav:

       更新可能的错误。

       最近、我做了一些最坏情况测试。 将 AM2434配置为 SPI 从器件、如果通过 MCSPI_TRANSFER ()预填充的数据长度小于 SPI 主机发送的长度、则会触发系统异常。

     1) 1) SPI 中断不会自动清除并将重复进入 ISR:MCSPI_LLD_peripheralIsr ()。  

    2) 2) 如果在回调函数中清除 MCSPI->IRQSTATUS、 在触发一些错误后、soc 将在以下汇编代码中继续循环、无法通过修改 mcspi 寄存器退出。为什么?

      

    3) 3)清除 MCSPI->IRQENABLE 在回调函数中、可以解决该问题。 我认为 这个问题可能与 SDK 错误有关。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    最近、我做了一些最坏情况的测试。 如果通过 MCSPI_TRANSFER ()预填充的数据长度小于 SPI 主机发送的数据长度、则将 AM2434配置为 SPI 从器件[/QUOT]

    感谢您执行该测试。

    您能纠正一下我对您刚才提到的内容的理解吗?

    在声明从器件的 MCSPI 传输时、您在字段中写入了一些值  计数(假设为 x) 主器件发送 y 量的数据。

    如果 x < y、则会出现问题、否则如果 x = y、则不会出现问题?

    此致、

    Vaibhav

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

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

    您好!

    这非常有效。

    想象一下、SoC 上的控制器即将与从器件通信、我想从任何从器件中收集有关基本"我是谁"寄存器的信息。

    在本例中、如果从器件需要计数1、我们以8位命令为例、那么我将发送的就是这条命令;在本例中、如果我发送的计数小于1、这将导致从器件不会使用"我是谁"寄存器的值做出响应。

    从顶层讲、这是预期行为。

    如果您认为您有其他几点、请改正我的理解、请告知我。

    谢谢!

    Vaibhav

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

    在我的示例中作为 SPI 从器件、我假设主机接下来将发送最多10个字节。 为了接收这10字节的数据,我 提前调用了 length=10的 MCSPI_TRANSFORT()函数。 实际上、主机在一个通信中发送12或20个字节或更多字节、然后问题重新出现。

    大家可以尝试复制、如果不复制、我明天会尝试向大家展示一些示例代码。

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

    这是一个可以触发该问题的简单代码示例。  

    和 EVM 板。

    1.导入示例工程:mcspi_loopback_am243x-evm_r5fss0-0

    2.按照下图修改 SPI 配置

    3.添加 GPIO 中断(I2C0_SDA/B18)

    4.添加以下代码

    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/CycleCounterP.h>
    
    #include <kernel/dpl/AddrTranslateP.h>
    #include <kernel/dpl/HwiP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #include "FreeRTOS.h"
    #include "semphr.h"
    
    #include <string.h>
    #include <stdint.h>
    
    #define GPIO_SPISLV_CS      CONFIG_GPIO0_CSISR_PIN
    
    #define APP_MCSPI_MSGSIZE                   (128U)
    #define APP_MCSPI_TRANSFER_LOOPCOUNT        (10U)
    
    uint8_t gMcspiTxBuffer[APP_MCSPI_MSGSIZE];
    uint8_t gMcspiRxBuffer[APP_MCSPI_MSGSIZE];
    
    MCSPI_Transaction spiTransaction;
    
    SemaphoreHandle_t sem;
    
    uint32_t spiBaseAddr;
    
    uint32_t            gGpioBaseAddr = CONFIG_GPIO0_CSISR_BASE_ADDR;
    HwiP_Object         gGpioHwiObject;
    
    extern void Drivers_mcspiOpen(void);
    extern void Drivers_mcspiClose(void);
    extern void Board_gpioInit(void);
    extern void Board_gpioDeinit(void);
    extern uint32_t Board_getGpioButtonIntrNum(void);
    extern uint32_t Board_getGpioButtonSwitchNum(void);
    
    void spislv_cs_isr(void *args)
    {
        BaseType_t prior = pdFAIL;
        uint32_t    pinNum = (uint32_t) args;
        uint32_t    bankNum =  GPIO_GET_BANK_INDEX(pinNum);
        uint32_t    intrStatus, pinMask = GPIO_GET_BANK_BIT_MASK(pinNum);
    
        /* Get and clear bank interrupt status */
        intrStatus = GPIO_getBankIntrStatus(gGpioBaseAddr, bankNum);
        GPIO_clearBankIntrStatus(gGpioBaseAddr, bankNum, intrStatus);
    
        if (intrStatus & pinMask)
        {
            if (sem)
            {
                xSemaphoreGiveFromISR(sem, &prior);
            }
        }
    }
    
    void spislv_transferCb(MCSPI_Handle handle, MCSPI_Transaction *transaction)
    {
        CSL_McspiRegs *spiReg = (CSL_McspiRegs *)spiBaseAddr;
        BaseType_t prior = pdFAIL;
    
        //@note: Delete this code can trigger the issue
        //spiReg->IRQENABLE = 0;   
    
        if (sem)
        {
            xSemaphoreGiveFromISR(sem, &prior);
        }
    }
    
    void spislv_reset(void)
    {
        Drivers_mcspiClose();
        MCSPI_deinit();
        MCSPI_init();
        Drivers_mcspiOpen();
    }
    
    int spislv_xfer(uint8_t *tx, uint8_t *rx, int len, int timeout)
    {
        int rcvCnt = 0;
    
        spiTransaction.txBuf = (void*)tx;
        spiTransaction.rxBuf = (void*)rx;
        spiTransaction.count = len/(spiTransaction.dataSize/8);
    
        MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction);
        if (sem && xSemaphoreTake(sem, pdMS_TO_TICKS(timeout)))
        {
            if (rx != NULL)
            {
                if ( (uint32_t)gMcspiConfig[0].object->mcspiLldInitObj.chObj[0].curRxBufPtr > (uint32_t)rx)
                    rcvCnt = (uint32_t)(gMcspiConfig[0].object->mcspiLldInitObj.chObj[0].curRxBufPtr) - (uint32_t)rx;
            }
        }
    
        spislv_reset();
        return rcvCnt;
    }
    
    
    int spislv_hw_init(void)
    {
        uint32_t        pinNum, intrNum;
        HwiP_Params     hwiPrms;
        int32_t         retVal;
    
        Board_gpioInit();
    
    
        gGpioBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(gGpioBaseAddr);
    
        pinNum          = CONFIG_GPIO0_CSISR_PIN;
        intrNum         = Board_getGpioButtonIntrNum();
    
        /* Register pin interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum   = intrNum;
        hwiPrms.callback = &spislv_cs_isr;
        hwiPrms.args     = (void *) pinNum;
        /* GPIO interrupt is a pulse type interrupt */
        hwiPrms.isPulse  = TRUE;
        retVal = HwiP_construct(&gGpioHwiObject, &hwiPrms);
        DebugP_assert(retVal == SystemP_SUCCESS );
    
        sem = xSemaphoreCreateBinary();
    
         MCSPI_Transaction_init(&spiTransaction);
         spiTransaction.channel  = gConfigMcspi0ChCfg[0].chNum;
         spiTransaction.dataSize = 8;
         spiTransaction.csDisable = FALSE;//TRUE;
         spiTransaction.args     = NULL;
    
         spiBaseAddr = MCSPI_getBaseAddr(gMcspiHandle[CONFIG_MCSPI0]);
    
        return 0;
    }
    
    
    void spislv_Task(void *args)
    {
        int rcvCnt;
    
        spislv_hw_init();
    
        while(1)
        {
            DebugP_log("\r\n\r\n====================================================================\r\n");
            rcvCnt = spislv_xfer(gMcspiTxBuffer, gMcspiRxBuffer, 5, 5000);
            if (rcvCnt > 0)
            {
                DebugP_log("Rcv(%d):", rcvCnt);
            }
        }
    }
    
    int spislv_init(void)
    {
        Drivers_open();
        Board_driversOpen();
    
        spislv_Task(NULL);
    
        return 0;
    }

    5.连接 SPI 主机(J1-PIN2 -> MOSI、J1-PIN4 -> MISO、J1-PIN16 -> CLK、J1->PIN6/J5->PIN2 -> CS、J1-PIN23 -> GND)、发送7个字节(>5字节)、复制之后发送7个字节(>5字节)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    实际上、主机在一个通信中发送12或20个字节或更多字节、然后问题再次出现。

    我假设主机最初发送10个字节、然后在某个时候发送12/20个字节。 那么、当发送12/20字节时、此间隔是固定的吗?

    还是非常随机?

    此致、

    Vaibhav

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

    请不要过多关注主机发送12个字节的原因、或者主机发送这些字节的时间、这只是最坏情况测试。  只要主机发送的长度比预期长、am2434就会崩溃

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

    尊敬的梁先生/女士:

    因此、根据您在此处的步骤、我需要在 AM243上配置 SPI 从器件、并且让主机发送的字节长度大于 SPI 从器件的事务长度还是小于 SPI 从器件的事务长度?

    此致、

    Vaibhav

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

    是的、在我的项目中如上层所示、AM2434在主机发送之前预填充5个字节。  让主机发送6个或更多字节可以复制问题。

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

    您好!

    感谢您的耐心。

    5.连接 SPI 主机(J1-PIN2 -> MOSI、J1-PIN4 -> MISO、J1-PIN16 -> CLK、J1->PIN6/J5->PIN2 -> CS、J1-PIN23 -> GND)、发送7个字节(复制后的字节)、发送7个字节(> 5个字节)。

    您在这里使用的是什么 SPI 主机?

    您能否详细说明是否需要按特定顺序运行应用程序?  

    首先是 SPI 主机应用程序、然后是从应用程序

     首先是 SPI 从站应用程序、然后是主机应用程序

    此致、

    Vaibhav

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

    也许您可以使用 另一个 EVM 作为 SPI 主机、并  以每秒20字节的速率发送数据。

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

    您好!

    关闭螺纹、因为很长时间没有响应。 如果您想继续讨论、请随时回过头来。

    此致

    Ashwani