我正在开发一个带有STM32F1 MCU的定制电路板应用程序,该应用程序需要能够从意外的数据损坏中恢复。
数据流如下: 主设备(Linux机器)向从设备发送请求,该请求解析消息并准备发送回复。然后主人读取答复。交换速度很快(@ 18MHz)并且实现如下:
if (::ioctl(_fd, SPI_IOC_MESSAGE(2), &transaction) < 0) {
warn("message not sent");
return false;
}
这两条消息之间的延迟约为50us。消息长度是固定的。
在STM端,我使用DMA驱动的SPI驱动程序,该驱动程序以我将在下面编写的方式实现。
我使用的SPI2是APB1 @ 36MHz(HSE @ 24 MHz; AHB @ 72MHz; APB1 @ 36MHz)。
SPI配置为通过在RXNEIE(CR2-> RXDMAEN)上发出DMA请求来读取消息(固定长度!)。处理完消息后,答案将通过DMA1(CR2-> TXDMAEN)传输。
一切都像魅力一样,直到我以某种方式干涉。我尝试恢复的方案是在转移时拔掉SCLK线。
我正努力从中恢复过来。我要表达自己的想法,因为我不确定错误的位置。DMA配置为处理固定长度的消息。这就是为什么当我以某种方式干涉时,DMA控制器等待直到整个消息被处理并且缓冲器被移位。假设,当SCLK突然消失时,我收到了三分之一的消息。 DMA将等待剩下的三分之二。主设备继续发送请求。因此,在SCLK返回后,下一条消息的2/3将被放入缓冲区。发出DMA中断但丢失了最后一条消息的剩余踪迹。它肯定会丢失,但我可以检测到使用ERRIE标志在OVR标志上发出中断,该中断将被设置。
我试图处理那个中断但无济于事。
我现在检查中断处理程序是否设置了BSY标志(该路径正由SPI控制器进行处理)。如果它设置了我杀死DMA(已经开始处理下一条消息)并留下OVR标志。一旦BSY被清除,我清除OVR并重置DMA以进行接收。
这并没有多大帮助。
我可能使用的另一个选项是专用定时器,它在SCLK的上升沿复位(AN3109应用笔记启发式解决方案)。这样我就可以实现DMA超时。如果我只得到一条消息的一部分,如果SCLK长时间不在我们身上,我可以在定时器溢出时产生一个中断。不过,这个解决方案存在问题。
我知道描述含糊不清但我已尽力而为,希望有更深入见解的人可以提供帮助。
答案 0 :(得分:0)
在CS线上安装中断处理程序。在上升沿,如果传输尚未完成,则中止所有内容并重新开始DMA。使用SPI_CR1中的SSI位,在上升沿设置,在下降沿清零。