如何在内存受限的嵌入式系统上处理大量数据传输?

时间:2008-12-11 15:37:18

标签: c embedded serial-port interrupt spi

我的微控制器必须从PC串口(115200波特)下载大文件,然后通过SPI(~2 MHz)将其写入串行闪存。闪存写入必须是256字节块,然后是写入命令和页面地址。系统上可用的总RAM为1 kB,堆栈大小为80字节。

目前正在通过从UART填充256字节缓冲区然后通过ping到ponging到另一个256字节缓冲区来填充RX缓冲区就绪信号上的中断,同时使用忙写入写入闪存。重复进行缓冲区交换,直到操作完成。

我更愿意为在单独的循环缓冲区上运行的SPI和UART端口设置TX / RX中断处理程序。因此,我可以简单地填充TX缓冲区并启用中断或检查缓冲区是否有输入数据,而不是轮询新字节并等待操作完成。这将为实际工作提供更多的时钟周期,而不是等待外设。

在使用128字节循环缓冲区实现IRQ之后,我轮询UART RX缓冲区以获取数据并立即将其放入SPI TX缓冲区以进行文件传输。我使用这种方法的问题是我没有足够的RAM用于缓冲区,并且PC接收缓冲区的填充速度比我将数据传输到闪存传输缓冲区要快。显然,传输速度不是问题(115.2 kHz输入和2 MHz输出),但在每个256字节页面传输后有一个写周期等待。


频繁的SPI中断似乎阻塞了一些UART中断并导致丢失了字节。我选择的解决方案是使用环形缓冲区用于UART接收中断,并将数据馈送到256字节页缓冲区,通过轮询字节传输和写完成将其发送到串行闪存。 128个环形缓冲区足以防止SPI写入期间出现溢出。

4 个答案:

答案 0 :(得分:4)

应用程序的UART和PC端是否支持RS-232握手(流量控制)?如果是这样,当接收缓冲区接近满时,让ISR丢弃CTS线 - 如果PC端配置为遵守硬件流控制,它应该在看到这种情况时停止发送。一旦你已经耗尽(或几乎耗尽)接收缓冲区,再次断言CTS并且PC应该再次开始发送。

请注意,这会使嵌入式设备上的软件变得更加复杂 - 无论这是您愿意做出的权衡还是必须由您和您的经理进行分析。队。

答案 1 :(得分:4)

这正是创建流控制的原因,我知道它设置了很大的痛苦,但是如果你在串行线上启用流量控制,你的问题将成为历史。

我假设您正在传输二进制文件,因此XON-XOFF不是最佳解决方案,它会留下硬件流控制。

另一种选择是使用具有内置流控制的协议,例如XModem。我有一个类似的嵌入式项目,其中flash以128byte页面写入。 XModem以128byte块发送数据然后在发送下一个数据之前等待ACK是多么巧合。

答案 2 :(得分:3)

我会做一些像PC上的分散聚集一样的事情。创建这样的结构的链接列表:

typedef struct data_buffer {
    char flags;
    char[128] data;
}

标志中的一个位表示“ReadyToFlash”,另一个表示“闪烁”。您应该能够调整链表中的缓冲区数量,以防止闪存在写入时捕获UART,反之亦然。

如果闪存到达不是“ReadyToFlash”的缓冲区,它将停止运行,您需要让UART IRQ重新启动它。如果UART到达“ReadyToFlash”或“Flashing”的块,则填充速度太快,您可能需要另一个缓冲区,如果您有动态内存,则可以在运行时进行此调整,并在运行时向列表中添加缓冲区,否则你只需要做一些经验测试。

答案 3 :(得分:1)

不确定我在这里缺少什么,但如果事实是来自PC的平均数据速率高于您可以将其写入闪存的平均速率,那么您将需要一个很多RAM,或者你需要流量控制。

但是你是说当你有块缓冲区时它会起作用,但现在你有字节缓冲区吗?

您能坚持使用UART RX中断填充的块缓冲区吗?当每个缓冲区已满时,将其关闭到SPI / Flash代码以使用SPI中断清空该缓冲区?这将节省您复制每个字节,而不是每个字节必须执行两次循环缓冲逻辑,您只需要为每个块执行此操作。