最近在做一个项目,其中用到了多路通信协议,做下总结吧,一边以后自己查阅。
最常见就是一个通信通道,比如:UART,SPI,本地以太网等。一个数据流通道,一种解析模块。这种结构最简单了,
开辟一个接收缓存,然后check解析即可,没啥可说的。如果是N个通道,一种解析协议,我们怎么做?先考虑简单
的情况,就是解析发送,没有ACK等机制,驱动层各自收各自的,然后解析层可重入(即用临时变量传入),然后
各个解析模块都调用同一个解析“函数”,如果有重传机制呢?举例:
1、有三个数据通道,4G,本地以太网,调试串口;
2、有重传机制;
3、协议完成一致;
基于上面的考虑,我在想怎么做到用一个解析驱动去包容三种,而不是写了三遍代码。思路如下:
1、运用函数指针实现多态;
2、整体的接收、解析、发送结构一致;
看下接口定义及初始化:

再看下最终的调用:

是不是很整齐。原来这块,我没有想着把它封装成一个模块,后来同事那边也要用,于是就把它封装成了一个
单独的模块:
需要用户传入的:

提供的对外接口:

这样封装之后,就可以很方便的被其他模块调用。这个模块只是用与多通道多解析,如果是一个通道多解析,则需要
运用peek而不是read,这个就留给诸位思考了。
2019.07.10
今天在看以前的代码,突然想到一个解析上存在的问题。
我的解析架构如下:
同一个状态机里面包含如下功能:
不停的从缓存区check一帧数据;
如果check到了,则进入解析状态;
如果带有ACK重发机制,则上面存在如下问题:
当上一帧解析未完成时候,下一帧数据到来,由于没有收到ACK,则重发,这样就会导致缓存里面有大量的重复性
数据帧。
我的解析思路如下:
1、接收线程就是不停的入队;
2、check线程就是不停的去check一帧数据,如果check到了,则放进接收缓存队列(链表实现);
3、解析线程就是不停的从接收缓存队列里面读取数据帧,去解析,然后把要发送的数据放进发送缓存队列(链表实现);
4、发送缓存就是不停的从发送缓存队列获取数据,然后发送。
如果涉及到ACK机制,这里面需要用到信号量去做同步。当然了,这种架构需要有一些RAM支持,对于复杂的项目比较合适。
2019.07.12
这几天在改写解析架构,把接收数据,check数据,解析数据全部,发送数据,四个task全部解耦。思路就是前面所写。
下面我来说一说我的实现过程。
1、实现一个简单的list内存池,由于数据帧大小未知,因此在初始化时候可设置,如果带有硬件带有MMU,那就更简单了
这里只保留一个指针,在check里面动态绑定即可;由于我是裸跑,为了减少内存碎片化,初始化时候,就绑定了用户指定
大小的buffer,然后用单链表连接成一个内存池;

2、有一个freelist指向一个空闲内存池,txlist指向发送链表,rxlist指向接收链表,
check线程就是不停的从底层接收缓存读取一个完成的数据帧,然后从空闲链表获取一个Item,数据复制完后,
放到rxlist队尾;解析线程就是不停的从rxlsit对手获取一个Item,然后去做解析,解析完成,把它释放给空闲链表;
发送线程就是不停的从txlist的对首获取一个Item,然后发送完成后,把它释放给空闲链表;
实现代码,我就补贴了,太简单了。
本文探讨了在多路通信协议中如何实现统一解析机制,通过函数指针和多态,构建了一个可重用的模块,支持多个数据通道和解析协议。文章详细介绍了接收、检查、解析和发送数据的解耦架构,以及在ACK机制下如何避免重复数据帧的问题。
789

被折叠的 条评论
为什么被折叠?



