嵌入式中的数据缓存,用于高速设备与低速设备数据传输中一个中间键,提高计算机各硬件的使用率。
对于嵌入式开发中,由于内存不足,一般得RAM只有几十K或者几十M,对于页高速缓存这么duang的东西自然高攀不上。
嵌入用到数据缓存的地方有很多,这次的背景是串口接受数据,创建新的任务进行数据的处理。当串口发送数据过快,而数据处理任务对数据处理不过来,无形中就变成高速设备与低速设备间的通讯,此时就需要引入数据缓存。
串口每次接收8位数据,当中断再次来临时,串口寄存器会重新刷新数据,所以为了将该字节数据存起来,我们需要把该数据定义为全局变量,方便后续对该数据进行操作。
思路一:单向链表存储数据
1.创建一个全局字符数组,当接收到开始码,把后续接收到的字节放入数组当中直至收到结束码为止。
2.当收到结束码,发送信号到链表任务,让链表任务进入运行队列。
3.链表任务在初始化时创建链表头,然后死循环等待中断程序发送信号量,把数据挂入链表,然后创建数据处理的一系列任务,再把链表任务挂起等待下一次信号到达。(多任务系统中死循环不会阻塞其他任务)
4.数据处理任务把数据处理完后需要把头指针的NEXT指向下一个数据,把当前处理的数据FREE掉。
不知道大家有没有发现上述方法的BUG:
1.链表数据中的数组每次大小一致,但我们收到的指令长度却不同,在多次创建后会导致内存空间浪费。
2.C库的malloc采用堆算法进行内存,多次分配内存后会造成内存碎片化,后续的程序就难以申请大块数据了。
3.由于在嵌入式系统中,中断的发生非常频繁,而malloc函数也不是一个可重入函数,在分配内存的过程中可能会出错。
4.内存的有限,一旦中断出错,不断发送数据,容易造成内存溢出,程序挂掉。
思路二:缓存池
1.第一步与上述第一步相同。
2.静态队列任务,在初始化是定义一个数组作为缓存池,两个全局指针,一个头指针,一个尾指针。头指针指向下一个要处理的数据,尾指针指向数据尾存放下一个到来的数据。
3.因为每次接收的指令有结束码,所以在拷贝指令到数组的时候可以根据结束码纪录数据长度,保证缓存池没有空闲位置。
4.缓存池循环使用,当尾指针指向缓存池最后且缓存池的头数据已经处理完时,把尾指针指向缓存池头部,依次循环。但尾指针与头指针之间不足以存放该次数据则反应消息给用户并丢弃该次数据。
5.数据处理任务处理完一次数据后把头指针指向下一个数据。
该思路不足处:
1.固定了缓存池大小,当数据量过大时只能丢弃一部分数据。
2.缓存池的大小需要把握好,过大浪费内存,过小存储不了数据。
成都it培训哪家好,当然是成都达内培训,成都达内是一家专业的程序员培训机构,专注于成都嵌入式培训,成都web前端培训,成都.NET培训,成都大数据培训,成都会计实操培训,成都IT培训,成都编程培训等IT培训,专业的成都软件培训机构,专业师资授课,真实项目实战、零首付、低押金、名企就业。
(责任编辑:成都达内)