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.

[参考译文] LAUNCHXL-CC3235SF:将 CC3200移植到 CC3235SF:如果 sl_Send ()长度>396、则 UDMA GSPI 损坏

Guru**** 2560390 points
Other Parts Discussed in Thread: CC3235SF, CC3200, LAUNCHXL-CC3235S, CC3235S

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

https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/1045270/launchxl-cc3235sf-porting-cc3200-to-cc3235sf-udma-gspi-corrupted-if-sl_send-length-396

器件型号:LAUNCHXL-CC3235SF
主题中讨论的其他器件:CC3235SFCC3200LAUNCHXL-CC3235SCC3235S

尊敬的先生:

  我正在将 CC3200中成功运行的代码移植到 CC3235SF。  数据通过具有 UDMA 的 GSPI 传入、然后通过 sl_Send()通过 WiFi 发送。

在 CC3235SF 中、如果 sl_Send()的数据包长度大于396字节、GSPI 停止 wokring。  我需要再次对 GSPI 和 UDMA 进行编程、否则不会触发中断:

MAP_SPIReset(GSPI_BASE);

UDMAInit();

MAP_SPIConfigSetExpClk( GSPI_BASE,
MAP_PRCMPeripheralClockGet(PRCM_GSPI),
SPI_IF_BIT_RATE,
SPI_MODE_SLAVE,
SPI_SUB_MODE_0,
(SPI_HW_CTRL_CS |
SPI_3PIN_MODE |
SPI_TURBO_OFF |
SPI_CS_ACTIVEHIGH |
SPI_WL_32));

MAP_SPIIntRegister(GSPI_BASE,interrupt_handler);

MAP_SPIWordCountSet(GSPI_BASE, 0);
MAP_SPIFIFOLevelSet(GSPI_BASE, 1, 1);
MAP_SPIFIFOEnable(GSPI_BASE, SPI_RX_FIFO);
MAP_SPIDmaEnable(GSPI_BASE,SPI_RX_DMA);
MAP_SPIIntEnable(GSPI_BASE,SPI_INT_DMARX);
MAP_SPIEnable(GSPI_BASE);

重新编程 GSPI 和 UDMA 会破坏传入数据的完整性。

将 SL_Send ()拆分为长度不超过396字节的多个数据包会影响传输速率。

在 CC3200中、sl_Send()数据包长度可能高达1460、不需要对 GSPI UDMA 进行重新编程。

在 CC3235SF 中、LSPI DMA 长度大于396字节会影响 GPSI UDMA。

你有什么建议吗?

感谢你能抽出时间。

此致、

Luke

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

    您好、Luke、

    更确切地说、当您使用较大的数据包长度时、会出现一些故障、因此 SPI 外设停止工作。 您是否尝试过增大线程的堆栈大小? 您是否能够使用 ROV 进行调试?

    此致、

    Sarah

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

    尊敬的 Sarah:

      是的、当 TCP 数据包长度大于396字节时、SPI 外设 停止工作。
    我尝试将堆栈大小从1024字节扩大到4096字节、 当发送更大的 TCP 数据包时、SPI 外设仍然停止工作。

    实际上、使用 sl_Recv ()接收长度大于396字节的 TCP 数据包、SPI 外设也会停止工作。

    我不知道在 ROV 调试模式下该怎么办。  在 ROV 调试模式下应检查什么?

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    外部 SPI 外设和主机驱动程序不相关、这意味着如果您传递给 sl_Send 的缓冲区的大小影响它、则 可能会在应用程序的某个位置发生硬故障。

    此外、我们还使用较大的数据包进行测试。  在 network_terminal 示例中、TCPCLient 正在发送长度为1400的数据包。

    ROV 工具 可帮助您进行调试。 您使用的是什么 RTOS? SDK 版本是什么?

    此致、

    Sarah

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

    尊敬的 Sarah:

      我使用的是 TI-RTOS。  SDK 为 5_20_00_06。

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    好的、如果您使用的是 LaunchPad、则只需在 CCS 中启动调试会话、然后打开 ROV 即可。 请观看入门视频以获得快速概览: https://training.ti.com/how-use-runtime-object-view

    以下也是 ROV 文档: https://software-dl.ti.com/ccs/esd/documents/rov_guide/html/src/rov.html

    此致、

    Sarah

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

    尊敬的 Sarah:

      我使用 uDMA GSPI 和 TCP 发送/接收命令从可移植示例构建了此项目:

    https://drive.google.com/file/d/12f9BMbPtQJ_pSVoFKi-2QN3e1a-EghN8/view?usp=sharing

    我在 LAUNCHXL-CC3235S 修订版 A 上运行它。

         for(len = 390; len < BUF_SIZE; len++) {
             // TCP client sending data
             iStatus = sl_Send(iClientSockID, g_cBsdBufClient, len, 0);
             UART_PRINT("Client sl_Send: %d\r\n", iStatus);
    
             // TCP server receiving data
             iStatus = sl_Recv(iServerNewSockID, g_cBsdBufServer, len, 0);
             UART_PRINT("Server sl_Recv: %d\r\n", iStatus);
    
             spi_transfer();
         }

    当 for 循环中的"len"等于或小于396时、发送  和接收长度为396或更少字节的 TCP 数据包。

    UDMA SPI" SPI_TRANSFH ()"按预期工作、 并生成 SPI_INT_DMARX 中断。

    一旦 for 循环中的"len"变为397、则发送和接收长度为397字节的 TCP 数据包。

    然后"SPI_TRANSFING ()"挂起、因为不会生成 SPI_INT_DMARX 中断。

    我将 CC3235S 设置为 AP 角色、配置禁用。

    CC3235S 同时用作 TCP 服务器和客户端。

    IP 地址127.0.0.1用于指示 CC3235S 本身。

    当我的项目中的 TCP 数据包大于396字节时、需要您的帮助来阐明为何会影响 GSPI DMA。

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    我在您的最新帖子中看不到任何新信息。 我需要知道您已经调试了哪些内容以进一步帮助您。

    您是否使用 ROV 进行了调试? 是否可以在 sl_Send 执行前后截屏任务和 HeapMem 视图?

    此致、

    Sarah

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

    尊敬的 Sarah:

      我所附的链接包含 与  LAUNCHXL-CC3235S 搭配使用的完整项目。  我认为重现我遇到的问题很有帮助。

    我尝试了 ROV、并在"Task"视图、"heap memory"视图和"stack space"视图中进行了屏幕截图。

    main()的开头:

    https://lh3.googleusercontent.com/d/19Sv8sKvDBY8HmMZ32mrxO_wzsQ0-ZDYn

    在 TCP 396字节之前、发送/接收:

    https://lh3.googleusercontent.com/d/1X7AkoIZ9nri-GPNqeaezblLIl3kFNlpk

    TCP 396字节后、发送/接收:

    https://lh3.googleusercontent.com/d/17Uqa9nX163J1u66A6TiJoLW-35rmlD29

    UDMA SPI 在  检测到 SPI_INT_DMARX 中断时完成:

    https://lh3.googleusercontent.com/d/1l_O6bIHTXPwF-0YkXM5yhwMttDfNgF3u

    TCP 397字节后发送/接收:

    https://lh3.googleusercontent.com/d/1aB3nUhkd95yGGyBOXjCtkfA2Up71yW7n

    由于未  检测到 SPI_INT_DMARX 中断、UDMA SPI 无法完成:

    https://lh3.googleusercontent.com/d/1RVdnTvydDfslB6tHQTx7RfdD5OY0-OzZ

    在发送/接收397字节 TCP 数据包之前和之后没有明显的区别。

    您能指导我下一步做什么吗?

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    我可以查看您的代码片段、但我无法复制您的设置以进行调试。

    您从 SL_Send 和 SL_Recv 获取了哪些返回值? 缓冲区内容是否符合您的期望? 您能在问题发生前后检查 ROV 中的 Hwi 吗?

    此致、

    Sarah

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

    尊敬的 Sarah:

      在 TCP len=396的工作情况下、  sl_Send 和 sl_Recv 的返回值均为396。  缓冲区内容均符合预期。

      在 TCP len=397的挂起情况下、 sl_Send 和 sl_Recv 的返回值均为397。  缓冲区内容也符合预期。

    也就是说、sl_Send 和 sl_Recv 在 len=396且 len=397时正常工作。

     当 TCP len=396且随后是 UDMA GSPI 传输时、会检测到 UDMA 中断 SPI_INT_DMARX。

     当 TCP len=397后跟 UDMA GSPI 传输时、不会检测到 UDMA 中断 SPI_INT_DMARX。

    在 sl_Send/sl_Recv 之前的 Hwi、len=396:

    https://lh3.googleusercontent.com/d/1xUmhAoYg58qrj5XcvILfbWMwC_AZX14s

    sl_Send/sl_Recv 之后的 Hwi、len=396:

    https://lh3.googleusercontent.com/d/16yXkMh3i46NN4WECtR3CEqRaskKgkv98

    sl_Send/sl_Recv 之前的 Hwi、len=397:

    https://lh3.googleusercontent.com/d/1OHBZaPty-Gol_YWMcEj2jioIArElyHqG

    sl_Send/sl_Recv 之后的 Hwi、len=397:

    https://lh3.googleusercontent.com/d/1X7thqbVa_obM9zTdJ3_ooIjHlvYI--Gj

    spiHwiFxn.IRP 在 sl_Send/sl_Recv 且 len=396后不会改变

    spiHwiFxn.IRP 在 sl_Send/sl_Recv 且 len=397后发生变化

    它表示什么?

    static void interrupt_handler()
    {
        uint32_t status = MAP_SPIIntStatus(GSPI_BASE,true);
        if(status & SPI_INT_DMARX)
        {
            UART_PRINT("SPI_INT_DMARX: %d\n\r", g_iSpiCounter);
        }
        MAP_SPIIntClear(GSPI_BASE,status);
        MAP_SPICSDisable(GSPI_BASE);
    
        spi_transfer_done = 1;
    }
    
    void spi_setup()
    {
        MAP_SPIReset(GSPI_BASE);
    
        MAP_SPIConfigSetExpClk(GSPI_BASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),
                         SPI_IF_BIT_RATE, SPI_MODE_MASTER, SPI_SUB_MODE_0,
                         (SPI_SW_CTRL_CS |
                         SPI_3PIN_MODE |
                         SPI_TURBO_OFF |
                         SPI_CS_ACTIVEHIGH |
                         SPI_WL_8));
        MAP_SPIIntRegister(GSPI_BASE, interrupt_handler);
    
        MAP_SPIWordCountSet(GSPI_BASE, DMA_SIZE);
        MAP_SPIFIFOLevelSet(GSPI_BASE, 1, 1);
        MAP_SPIFIFOEnable(GSPI_BASE, SPI_RX_FIFO);
        MAP_SPIFIFOEnable(GSPI_BASE, SPI_TX_FIFO);
        MAP_SPIDmaEnable(GSPI_BASE,SPI_RX_DMA);
        MAP_SPIDmaEnable(GSPI_BASE,SPI_TX_DMA);
        MAP_SPIIntEnable(GSPI_BASE, SPI_INT_DMARX);
        MAP_SPIEnable(GSPI_BASE);
    }
    
    void spi_transfer()
    {
        spi_transfer_done = 0;
        UART_PRINT("uDMA SPI trigger: %d\n\r", g_iSpiCounter);
        UDMASetupTransfer(UDMA_CH30_GSPI_RX,UDMA_MODE_BASIC,DMA_SIZE,
                    UDMA_SIZE_8,UDMA_ARB_1,
                    (void *)(GSPI_BASE + MCSPI_O_RX0),UDMA_SRC_INC_NONE,
                    g_cSpiBufRx,UDMA_DST_INC_8);
    
        UDMASetupTransfer(UDMA_CH31_GSPI_TX,UDMA_MODE_BASIC,DMA_SIZE,
                    UDMA_SIZE_8,UDMA_ARB_1,
                    g_cSpiBufTx,UDMA_SRC_INC_8,
                    (void *)(GSPI_BASE + MCSPI_O_TX0),UDMA_DST_INC_NONE);
        MAP_SPICSEnable(GSPI_BASE);
        while(!spi_transfer_done);
    }

    我的测试结果显示、397字节 SL_Send/SL_Recv 之后的 UDMA 复位有助于以下 UDMA GSPI 传输工作。

    1.以下顺序运行正常:

    SPI_setup();

    sl_Send ()/sl_Recv ()、len=396字节。 (返回值为396、数据符合预期。)

    spi_transfer ();//成功完成

    由于未检测到 SPI_INT_DMARX 中断、以下序列在 SPI_TRANSF()中挂起:

    SPI_setup();

    sl_Send ()/sl_Recv ()、len=397 字节。 (返回值为397 、数据 符合预期。)

    SPI_TRANSFER ();//永久挂起

     

    3.  通过在 TCP sl_Send ()/sl_Recv () 397个字节后重置 UDMA、可以找到以下序列:

    SPI_setup();

    sl_Send ()/sl_Recv ()、len=397字节。 (返回值为397、数据符合预期。)

    uDMAControlTable = MAP_uDMAControlBaseGet ();//保存 UDMA 通道控制表
    MAP_PRCMPeripheralReset (PRCM_UDMA);//重置 UDMA
    MAP_uDMAControlBaseSet (uDMAControlTable); //恢复 UDMA 通道控制表
    MAP_uDMAEnable();//复位后禁用 UDMA。  需要启用 UDMA。

    spi_transfer (); //成功完成

    正如您可能猜到的那样、当 sl_Send ()/sl_Recv ()的 len >= 397 字节时、UDMA 看起来是以某种方式断开的。

    顺便说一下、为了使 NWP 正常工作、以下代码在代码开头运行:

        SPI_init();
    
        //create the sl_Task
        pthread_attr_init(&pAttrs_spawn);
        priParam.sched_priority = SPAWN_TASK_PRIORITY;
        RetVal = pthread_attr_setschedparam(&pAttrs_spawn, &priParam);
        RetVal |= pthread_attr_setstacksize(&pAttrs_spawn, TASK_STACK_SIZE);
    
        if(RetVal == 0)
            RetVal = pthread_create(&g_spawn_thread, &pAttrs_spawn, sl_Task, NULL);
    
         RetVal = sl_Start(0, 0, 0);
    

    出什么问题了吗?

    需要您的指导来解决此问题。

    感谢你能抽出时间。

    此致、

    Luke

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

    您好!

    您是否会想到使用 TI 驱动程序而不是直接使用 driverlib 来尝试您的解决方案? 这对您来说可能更容易创建和调试。  

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

    尊敬的 Sabeeh:

      您是否想给我一个带有 TI 驱动程序的 UDMA 上的主控模式 GSPI 示例?

    感谢你能抽出时间。

    此致、

    Luke

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

    您好!

    CC32xx SDK 中的"spimaster"示例利用了 UDMA。 我相信、实施起来会更容易。  

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

    尊敬的 Sabeeh:

      397字节的 sl_Send ()中断  driverlib  GSPI DMA 的根本原因应该是 LSPI DMA 的"minDmaTransferSize"= 100和397字节仅满足最小 DMA 大小并触发 LSPI DMA、从而中断 driverlib GSPI DMA 的中断。

      TI 驱动程序能否使用 ping 缓冲器触发 GSPI DMA?

      或者是否有任何关于使用 driverlib 运行 LSPI DMA 的建议?

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    SPI TI 驱动器在 乒乓模式下使用 DMA 通道。 请参阅 SPICC32XXDMA.h 文件参考中的注释:

    "为了克服1024项 DMA 通道限制、该驱动程序在乒乓模式下使用 DMA 通道(请参阅器件 TRM)。 这意味着驱动程序可以执行几千件事务、而无需暂停以重新配置 DMA、并导致传输中出现间隙"

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

    尊敬的 Sabeeh:

      是否有任何示例可用于对 TI 驱动器应用乒乓模式?

    根据 TRM、 当触发 UDMA 时、UDMA_PRI_SELECT 和 UDMA_ALT_SELECT 应该交错。

    在"SPICC32XXDMA.c"中, UDMA_PRI_SELECT 始终在"MAP_uDMAChannelControlSet()"中设置,并且  永远不使用 UDMA_ALT_SELECT。

    我不知道如何触发乒乓模式。

    感谢你能抽出时间。

    此致、

    Luke

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

    您好、Luke、

    同时我会调查、但我仍然强烈建议使用驾驶员、因为1024项限制仍然比 您看到的396项转让大得多。  

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

    尊敬的 Sabeeh:

      感谢您的友好支持。

    此致、

    Luke