我正在使用 STM32F107VC 微控制器实现高频(>100kHz)数据采集系统。它使用 spi 外设与高频 ADC 芯片通信。我必须使用 RTOS。我怎样才能做到这一点?
我尝试过 FreeRTOS,但它的最大滴答频率是 1000Hz,所以我不能使用 FreeRTOS 每 1us 运行一个线程。我也试过 Keil RTX5,它的滴答频率可以高达 1MHz,但我在某处研究过,不建议将滴答频率设置为高,因为它会增加整体上下文切换时间。所以我该怎么做?谢谢。
我正在使用 STM32F107VC 微控制器实现高频(>100kHz)数据采集系统。它使用 spi 外设与高频 ADC 芯片通信。我必须使用 RTOS。我怎样才能做到这一点?
我尝试过 FreeRTOS,但它的最大滴答频率是 1000Hz,所以我不能使用 FreeRTOS 每 1us 运行一个线程。我也试过 Keil RTX5,它的滴答频率可以高达 1MHz,但我在某处研究过,不建议将滴答频率设置为高,因为它会增加整体上下文切换时间。所以我该怎么做?谢谢。
您不想以此频率运行任务。正如您所提到的,上下文切换会破坏性能。这是非常低效的。
相反,您想使用缓冲、中断和 DMA。由于它是一个高频ADC芯片,它可能有自己的内部缓冲器。检查数据表。如果芯片有 16 个采样缓冲器,则 100kHz 采样只需要 6.25kHz 处理。现在不要使用任务来处理 6.25kHz 的样本。在中断(定时器或某个信号)中进行接收,中断应该只填充一个缓冲区,当缓冲区已满时唤醒一个任务进行处理(并切换到另一个缓冲区直到任务完成)。有了这个,你可以有一个每 10 毫秒左右运行一次的任务。中断不是上下文切换。在 Cortex-M3 上,它将有大约 12 个周期的延迟,这在 6.25kHz 时低到可以忽略不计。
如果您的 ADC 芯片没有缓冲区(但我对此表示怀疑),您可能会接受 100kHz 中断,但在其中放置尽可能少的代码。
如果您的 MCU 支持,更好的解决方案是使用 DMA。例如,您可以设置 DMA 以使用定时器作为请求生成器从 SPI 接收。根据您的情况,配置可能是不可能的或棘手的,但工作的 DMA 意味着您可以接收大量的样本缓冲区,而无需在 MCU 上运行任何代码。
我必须使用 RTOS。
没门。如果这是您的老板或客户的要求,请尽快退出该项目。如果这不可能,请立即以书面形式表达您的疑虑,以便在讨论失败原因时挽救您的后路。如果这是您的想法,请立即重新考虑。
STM32F107 的最大系统时钟速度为 36 MHz(如果有外部 HSE 石英,则为 72),这意味着在 100 kHz 的滴答声之间只有 360 到 720 个系统时钟周期。RTX5 警告是正确的,任务切换开销需要大量时间。
可以有一个 100 kHz 的定时器中断,并在中断处理程序中进行一些简单的处理(甚至不要考虑使用 HAL),但我建议首先调查是否真的有必要每 10 μs 运行一次代码,或者是否有可能将它对 DMA 或定时器硬件所做的事情卸载。
无需设置 RTOS 刻度以匹配数据采集速率 - 两者无关。这样做将是一个非常糟糕和不明智的解决方案。
STM32 对包括 SPI 在内的大多数外设都具有 DMA 功能。您需要配置 DMA 和 SPI 以将一系列样本直接传输到内存。DMA 控制器具有完整和半传输中断,并且可以循环提供的缓冲区,以便当它已满时,它会重新从头开始。这可用于“双重缓冲”样本块。
因此,例如,如果您使用 256 个样本的 DMA 缓冲区并以 100Ksps 进行采样,您将每 1.28 毫秒获得一次 DMA 中断,与 RTOS 滴答中断和调度无关。在半传输中断时,前 128 个样本准备好处理,在全传输时,可以处理后 128 个样本,并且在 1.28ms 间隔内,处理器可以自由地做有用的工作。
在中断处理程序中,而不是在中断处理程序中处理所有块数据 - 如果处理是不确定的或阻塞的,例如将其写入文件系统,这在任何情况下都是不可能的 - 例如,您可以发送通过消息队列以块的形式采样到执行不太确定性处理的任务上下文。
请注意,这些都不依赖于 RTOS 滴答——如果该中断调用调度函数(例如发布到消息队列),调度程序将在任何中断之后运行。将动作同步到与触发事件(即轮询)异步运行的 RTOS 时钟不是实现高度确定性实时响应的好方法,而且是一种特别糟糕的信号采集方法,它需要无抖动的采样间隔以避免虚假伪像在来自非周期性采样的信号中。
您认为您需要通过不适当的高 RTOS 滴答速率来解决此问题的假设是误解了 RTOS 的操作,并且可能仅在您的处理器除了采样数据之外没有其他工作时才有效 - 在这种情况下,您可能不需要完全是 RTOS,但它不是对处理器的非常有效的使用。
由于输入之间只有几百个周期(指令),典型的解决方案是使用中断来提醒数据可用,然后中断处理程序将数据放在某个地方,以便您可以在闲暇时处理它们。当然,如果数据以这样的速度连续输入,您可能会遇到麻烦,没有时间进行实际处理。根据传入的数据量和频率,一个简单的循环缓冲区可能就足够了。如果数据量比较大(有多大?考虑到进行一次内存访问需要超过一个 CPU 周期,并且每个传入的数据需要 2 次内存访问),然后按照@Elderbug 的建议使用 DMA是一个很好的解决方案,因为它消耗最少的 CPU 周期。