STM32H7 SPI通信:FIFO管理问题

STM32H7 SPI通信:FIFO管理问题,stm32,spi,cortex-m,Stm32,Spi,Cortex M,我已经在我的SPI设置上挣扎了很长一段时间 设置如下所示: SPI从机是单工模式下的核子STM32H743,最大时钟频率(sysclk 400MHz,hclck 200Mhz,APB时钟100MHz) SPI主机是单工模式下另一个相同的核子,时钟除以2:sysclk 200MHz,等等。。。和spi_keru_clk=100MHz SPI主机,预分频器为16,即时钟SPI约为6MHz。已启用CRC。数据帧8位。FIFO阈值4字节 SPI从机:启用CRC,8位。FIFO阈值4字节 没有从机选择

我已经在我的SPI设置上挣扎了很长一段时间

设置如下所示:

  • SPI从机是单工模式下的核子STM32H743,最大时钟频率(sysclk 400MHz,hclck 200Mhz,APB时钟100MHz)
  • SPI主机是单工模式下另一个相同的核子,时钟除以2:sysclk 200MHz,等等。。。和spi_keru_clk=100MHz
  • SPI主机,预分频器为16,即时钟SPI约为6MHz。已启用CRC。数据帧8位。FIFO阈值4字节
  • SPI从机:启用CRC,8位。FIFO阈值4字节
没有从机选择信号来控制从机

这是主机的代码。一切都在投票中完成,我增加了一些延迟,让奴隶有时间工作。以下函数是在循环中调用的,其他任何操作都不由主控执行(在我用于调试的简化版本中):

对于从机,接收由中断处理程序完成。主线程正在等待设置标志(由
SPI\u stopReceignment()
设置)并发送5字节的应答

static void SPI_GenericHandler(SpiId_e SpiId)
{
SPI_TypeDef *Spi = SpiMgt[SpiId].SpiInstance;
uint32_t trigger = Spi->IER & Spi->SR;
uint32_t cmd;
uint8_t stat;

if (trigger & SPI_SR_RXP)
{


        cmd = Spi->RXDR;
        if (cmd != 0x12345678)
            while(1);
        while((Spi->SR & SPI_SR_EOT) == 0);

        if (Spi->SR & SPI_SR_CRCE)
            while(1);
        SPI_StopReception(SpiId);


    }

}
(...)
我的问题如下

通信正常工作了几十万次,然后在从端出现故障:我没有从SPI FIFO读取字节78 56 34 12,而是读取例如34 12 00或56 34 12 00

乍一看,有人会说只是从机速度太慢,漏掉了一些字节,但奇怪的是:

  • 我得到一个RXP中断,这意味着从机在4个字节期间正确检测到SPI时钟,并对4个字节进行了采样
  • 没有CRC错误,这意味着从机接收到正确的位。例如,当我从FIFO读取56 34 12 00时,RXCRC为0x08,这是完整帧78 56 34 12的CRC
就好像FIFO的读取有问题一样

我使用了逻辑分析仪,没有发现任何电气问题

在接收错误期间(更准确地说,我在SPI RXP中断处理程序中中断),从机端的寄存器值如下所示。在这次事件中,我读到了34 12 00 00:

  • CR1=1(SPE)
  • CR2=4(TSIZE)
  • CFG1:MBR 0x07,CRCEN,UDRCFG=2,FTHVL=3,DSIZE=7
  • CFG2:SSM=1,COMM=2
  • IER=1(RXPIE)
  • SR=0x0001300A,即CTSIZE=1(奇怪,但参考手册上说“当总线上正在进行通信时,该值不太可靠”),RXPLVL=1(?),EOT=1(预期),TXP=1(预期)
  • RXCRC=0x08(预期为完整帧)。值得一提的是,调试器(Keil)没有正确读取寄存器,我在代码中读取了它
CTSIZE和RXPLVL的值实际上并不一致(至少我不理解它们):因为FTHVL=3(4-data)和TSIZE=4(在主机端相同),所以当我得到一个RXP事件时,我应该至少收到4个字节。我不知道CTSIZE怎么可能是1,也不知道为什么FIFO中会剩下另一个字节(RXPLVL=1)


有什么想法或建议吗

我建议将系统时钟速度降低到250 MHz以下并进行测试。在我的开发过程中,我遇到了一些SPI通信问题,这与速度直接相关。 我相信micro中存在一个bug,当速度超过250 MHz时,它会丢失SPI数据包。我的微控制器是H750VBT6。我希望这有帮助。
最好的问候,Henrique Basso。

我建议将系统时钟速度降低到250 MHz以下并进行测试。在我的开发过程中,我遇到了一些SPI通信问题,这与速度直接相关。 我相信micro中存在一个bug,当速度超过250 MHz时,它会丢失SPI数据包。我的微控制器是H750VBT6。我希望这有帮助。
向你问好,亨里克·巴索。

比赛情况如何?是不是你在第一次发球时被第二次打断?嘿,对于>1000评级,你能用类似于
?无竞态条件的东西来标记你的代码吗。我对轮询中的两个代码进行了相同的测试,没有启用其他中断。不理解您关于代码评级和标记的评论。竞态条件?是不是你在第一次发球时被第二次打断?嘿,对于>1000评级,你能用类似于
?无竞态条件的东西来标记你的代码吗。我对轮询中的两个代码进行了相同的测试,没有启用其他中断。我不理解您关于代码评级和标记的评论。这不是问题。我在480MHz上运行H4,使用SPI时没有任何问题。这是你的代码中的一个问题。我在F103cbt6上运行了我的代码,一切正常。在H7勘误表第2.14.2项中,它指出当频率非常高时,传输可以停止。这不是问题。我在480MHz上运行H4,使用SPI时没有任何问题。这是你的代码中的一个问题。我在F103cbt6上运行了我的代码,一切正常。在H7勘误表第2.14.2项中,规定当频率非常高时,传输可以停止。
static void SPI_GenericHandler(SpiId_e SpiId)
{
SPI_TypeDef *Spi = SpiMgt[SpiId].SpiInstance;
uint32_t trigger = Spi->IER & Spi->SR;
uint32_t cmd;
uint8_t stat;

if (trigger & SPI_SR_RXP)
{


        cmd = Spi->RXDR;
        if (cmd != 0x12345678)
            while(1);
        while((Spi->SR & SPI_SR_EOT) == 0);

        if (Spi->SR & SPI_SR_CRCE)
            while(1);
        SPI_StopReception(SpiId);


    }

}
(...)