单片机/MCU论坛
直播中

Arvinhw

10年用户 1023经验值
擅长:嵌入式技术
私信 关注
[问答]

当波特率设置为高时,SPI 时钟延长,数据丢失问题怎么解决?

我在TRAVEO™ II (CYT4BF) MCU 上遇到了 SPI 通信问题。
设置详细信息:

  • SPI模式:主控
  • 时钟频率:5 MHz
  • 时钟极性和相位:CPOL = 0,CPHA = 0
  • SCB实例:SCB10
  • 数据传输方式:带中断的 DMA
  • 数据大小:连续传输~4 KB数据
问题:
当使用 DMA 以 5 MHz 的频率通过 SPI 传输大型数据缓冲区(例如 4 KB)时,我观察到间歇性时钟拉伸(即时钟脉冲之间的间隙),这会导致数据丢失或损坏。请查看附件中的图像 - 该图像是使用逻辑分析仪捕获的


但是,当我将 SPI 时钟降低到2 MHz时,问题消失并且数据传输可靠。你能帮助我们找到这背后的根本原因吗?
任何见解或指导都将不胜感激。

回帖(1)

萧蔼晨

2025-7-30 18:04:11

针对您在使用TRAVEO™ II CYT4BF MCU时遇到的SPI时钟拉伸和数据丢失问题(在5 MHz波特率下传输4 KB数据时出现),以下是系统性解决方案:


根本原因分析




  1. DMA与SPI FIFO速度不匹配  



    • 5 MHz SPI时钟要求TX FIFO以 625 KB/s(5 Mbps) 的速率持续供数据。

    • DMA可能因总线竞争、配置效率低或延迟无法及时填充FIFO,导致FIFO变空,触发时钟拉伸(SCLK间隙)。




  2. 总线仲裁延迟  



    • 若DMA源缓冲区位于Flash或共享SRAM,CPU或其他主设备竞争总线会抢占DMA访问权,增加延迟。




  3. 中断延迟  



    • 若使用DMA完成中断重新配置传输,中断响应延迟可能造成FIFO断供。




  4. FIFO阈值配置不当  



    • 默认TX FIFO触发阈值可能过高,DMA请求触发太晚,无法及时响应。






解决方案


1. 优化DMA配置



  • 提升传输效率
     // 使用32位宽突发传输(假设SPI数据为8位)
    Cy_DMA_Descriptor_SetDataSize(&descriptor, CY_DMA_BURST_TRANSFER_X4); // 4*32位突发
    Cy_DMA_Descriptor_SetSrcTransferSize(&descriptor, CY_DMA_TRANSFER_SIZE_DATA_WORD); // 32位源
    Cy_DMA_Descriptor_SetDstTransferSize(&descriptor, CY_DMA_TRANSFER_SIZE_DATA_WORD); // 32位目标


    • 突发传输减少总线请求次数,提升吞吐量。


  • 优先级设置
     Cy_DMA_Channel_SetPriority(dmaChannel, 3); // 最高优先级(0-3)


2. 调整SPI FIFO阈值



  • 降低TX FIFO触发阈值,确保DMA提前响应:
     Cy_SCB_SPI_SetTxFifoLevel(SCB10_HW, 2); // 当FIFO≤2空位时触发DMA请求


    • 原理:避免FIFO完全排空前触发DMA,预留缓冲时间。



3. 优化内存布局



  • 将源缓冲区移至零等待SRAM(如TCM)
     #pragma __attribute__((section(".cy_ram0"))) // 使用TCM SRAM
    uint8_t txBuffer[4096];


    • 避免Flash/低速SRAM访问延迟(Flash访问需插入等待周期)。



4. 启用DMA循环模式



  • 替代单次传输模式,避免传输结束中断延迟:
     Cy_DMA_Descriptor_SetNextDescriptor(&descriptor, &descriptor); // 循环指向自身
    Cy_DMA_Channel_Enable(descriptor.channel);

  • 中断处理:仅用于错误处理,而非传输重启。


5. 时钟与总线配置检查



  • 确认PERI_CLK频率

    • 5 MHz SPI时钟需PERI_CLK ≥ 20 MHz(理想 ≥ 40 MHz)。

    • 例:若PERI_CLK=80 MHz,分频值 = (80e6 / (2 * 5e6)) - 1 = 7
      Cy_SCB_SPI_SetBaudRate(SCB10_HW, 5000000, periClkFreq);



6. 监控SPI状态寄存器



  • 检测FIFO下溢标志:
     if (Cy_SCB_SPI_GetTxFifoStatus(SCB10_HW) & CY_SCB_SPI_TX_UNDERFLOW) {
         // 处理下溢错误
    }

  • 出现下溢表明FIFO饥饿,需进一步优化DMA或阈值。




验证步骤



  1. 逐步提升波特率

    从2 MHz开始,逐步提高至3 MHz/4 MHz/5 MHz,观察时钟拉伸是否再现。

  2. 逻辑分析仪监测:  

    • 检查SCLK间隙是否消失。

    • 确认MOSI数据与预期一致。


  3. 压力测试

    连续传输10次4 KB数据,统计错误率。



关键提示:若问题仅在5 MHz出现,根本原因通常是DMA/FIFO时序裕量不足。通过降低FIFO阈值 + 32位突发DMA + TCM内存组合方案可解决95%以上类似问题。



若仍存在问题,请提供:



  • 系统时钟树配置(PLL/PERI_CLK频率)

  • DMA和SPI的完整初始化代码

  • 芯片具体型号(如CYT4BF8CDS)

举报

更多回帖

发帖
×
20
完善资料,
赚取积分