【问题标题】:How to exploit interrupts for data transfer over SPI peripheral如何利用中断通过 SPI 外设进行数据传输
【发布时间】:2020-06-16 06:24:46
【问题描述】:

我一直在用 C 语言为 MCU 的 SPI 外设实现设备驱动程序。 我想利用中断机制进行接收和传输。

就接收部分而言,我认为我可以通过公开来实现这一点 SpiRegisterCallback 函数进入 SPI 驱动接口。这个功能 使客户端注册其函数,该函数将被调用 接收到数据字节(调用接收缓冲区满中断)。

至于传输部分,我想使用一些 SpiTransmit 功能 它将接收指向要传输的数据字节和字节数的指针 被传送。至于实现,我将定义一些内部 SPI驱动的回调函数。这个内部回调将被注册 用于传输缓冲区空中断。在此回调函数中,传递的数据字节将逐渐放入传输缓冲区。我不确定这种方法是否 是合适的。谁能给我一个建议如何实现 SPI 外设 利用中断进行数据传输的驱动程序?提前感谢任何 建议。

【问题讨论】:

    标签: c callback embedded interrupt spi


    【解决方案1】:

    SPI 通常对实时性非常关键,引入带有函数指针的回调意味着不必要的开销代码。数据从 SPI 到 RAM 的实际复制必须由驱动程序在内部完成。这就是 ISR 应该做的所有事情。可以在here 找到一些一般指导。

    所以你的 ISR 应该填满一个缓冲区,然后以一种受保护的方式交换指向缓冲区的指针(不慢memcpy!),以便调用者始终拥有一个包含有效数据的缓冲区,并且 ISR 总是有一个工作缓冲区要填满。让调用者轮询一个标志,而不是从 ISR 内部调用回调。如果可以节省 RAM,我喜欢使用三重缓冲。即:ISR 的一个缓冲区,调用者的一个缓冲区和 ISR 可以在不中断调用者的情况下交换的备用缓冲区。

    这对代码来说相当复杂,大多数程序员都搞错了。在这里,DMA 优于中断,因此您应该真正考虑使用 DMA。这是您在选择 MCU 时应该考虑的问题。

    【讨论】:

    • '让调用者轮询一个标志' .. 或者'如果可用/相关,等待一个信号量,直到中断处理程序发出一个已满缓冲区的信号。
    • @MartinJames 如果您肯定有更高级别的操作系统。否则,在裸机的情况下,您必须自己实现信号量。
    • 环形缓冲区或 FIFO 是替代乒乓缓冲区的可能替代方案。
    【解决方案2】:

    请求“任何建议”并不能真正使这个问题成为一个好问题,因为可以接受多个答案,但很少有全面的答案。它邀请 cmets 而不是回答。不过我会放纵:

    首先,这在任何定义上都不是漏洞利用。 “利用”意味着将某些东西用于非预期的目的 - 在这种情况下,这不是正确的术语,您不是在“利用”中断机制,您只是使用它。

    在高时钟频率下,在某些情况下,处理中断所涉及的中断延迟和上下文切换时间可能比简单的忙等待效率低。如果一次传输超过两个或三个字节,则在任何情况下都应考虑使用 DMA(如果可用)——因此中断将是完整传输的 DMA 中断,而不是单个字符。对于 SD 卡接口或 EEPROM 等应用,DMA 将对性能产生重大影响,并释放 CPU 以同时执行其他有用的工作。对单字节/字传输使用忙等待和对块传输使用 DMA 的驱动程序可能是最佳的。如果您使用 RTOS 并且 ISR 触发任务上下文来处理数据,则尤其如此 - 上下文切换开销可能几乎与单个字节的忙等待一样多或更多。例如,如果您的 SPI 时钟 > 1MHz,您将等待 8us 进行字节传输,您的 ISR 和回调可能很容易大于该值,在这种情况下不值得。

    所以我的建议是,如果您使用较慢的时钟并且可以在等待中断时完成其他有用的工作,那么我的建议是只考虑 SPI 的中断。

    在中断中允许回调的一个问题是它允许回调提供者在中断上下文中做不明智或非法的事情,并且您失去了控制中断处理时间的能力。如果回调是供编写设备驱动程序的人使用的,这可能很好——他们应该知道自己在做什么,但是这是设备驱动程序。

    【讨论】:

      猜你喜欢
      • 2019-02-21
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      • 2011-06-04
      • 2020-03-17
      • 2014-05-19
      • 2012-01-27
      • 1970-01-01
      相关资源
      最近更新 更多