ST意法半导体
直播中

贾大林

7年用户 1324经验值
私信 关注
[问答]

SPI DMA循环缓冲区奇怪的位翻转是什么意思?

你好
测试场景:
  • 将 uint64_t 计数器从 STM 传输到另一个名为 ALFA 的 MC。
  • ALFA 有一个单独的 uint64_t 计数器。
  • 每次传输都会对计数器进行计数。
  • ALFA 比较两个计数器并报告不匹配
设置:
  • ALFA -> SPI Master @ 10Mhz
  • STMG4 -> SPI 从机 -> DMA
  • SPI Transation 是 9 Bytes 长,其中第一个字节是占位符字节(被其他东西使用,但不重要)
  • STMG4 SPI DMA 事务在 ALFA 的片选回到高电平时启动
    • 我们会故意错过第一笔交易以确保一个干净的开始
    • 进行额外检查以保持 STMG4 和 ALFA 之间的数据同步

变量:
  • volatile uint32_t spiTransferState = SPI_TRANSFER_IDLE;
DMA 通函代码:
  • [somewhere in main while loop]
  • volatile static uint64_t counter = 0;
  • if(spiTransferState == SPI_TRANSFER_COMPLETE){
  •         counter++;
  •         spiTxBuffer[0] = 8;
  •         memcpy(&spiTxBuffer[1],(uint8_t*)&counter,8);
  •         spiTransferState = SPI_TRANSFER_WAIT;
  • }
  • void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
  •         spiTransferState = SPI_TRANSFER_COMPLETE;
  • }
DMA 正常模式
第 9 行不同
  • [somewhere in main while loop]
  • volatile static uint64_t counter = 0;
  • if(spiTransferState == SPI_TRANSFER_COMPLETE){
  •         counter++;
  •         spiTxBuffer[0] = 8;
  •         memcpy(&spiTxBuffer[1],(uint8_t*)&counter,8);
  •         spiTransferState = SPI_TRANSFER_WAIT;
  •         HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*) spiTxBuffer, (uint8_t*) spiRxBuffer, SPI_BUFFER_SIZE);
  • }
循环方式记录接收数据时:
  • b[0]: 8 b[1]: fe b[2]: ff b[3]: 0 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
  • b[0]: 8 b[1]: ff b[2]: ff b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
  • alfa counter: 65535
  • received counter: 131071 //check b[3] flipped to early?
  • b[0]: 8 b[1]: 0 b[2]: 0 b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
  • b[0]: 8 b[1]: 1 b[2]: 0 b[3]: 1 b[4]: 0 b[5]: 0 b[6]: 0 b[7]: 0 b[8]: 0
在没有循环模式的情况下运行它。这个问题不会发生。
我做错了什么?什么会导致这个?或者可能是我在使用圆形模式时不明白什么?

回帖(1)

张鑫

2022-12-26 11:37:42
这里的部分问题是您依赖预编译的 Cube/HAL 函数,而不是编写您自己的函数,这样您就可以了解正在发生的事情。
当接收方 DMA 抛出传输完成中断时调用 HAL_SPI_TxRxCpltCallback(),此时整个数据包已传输完毕。然而,如果 Tx DMA 是循环的,它已经将前 3 个字节传输到 SPI Tx FIFO 中,带有*旧*值,之后发生递增,因此第 4 个字节已经在递增之后传输。
你想在 Tx DMA 传输完成中断中执行增量,如果你能保证它会在它的第一个字节传输到 FIFO 之前完成。或者,您可以尝试使用 Double-Buffer DMA 模式。
举报

更多回帖

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