我现在使用的是TI微型设备,它包括DMA UART驱动程序和支持并行任务的操作系统。UART驱动程序的功能包括:
我正在尝试与另一个外围设备通信,它接受以回车结束的消息,然后用回车返回来响应消息。
我很好奇如何才能最好地架构这种类型的通信状态机。我的问题是设计UART端口的回调函数,这样它.
基本理论是这样的:
//send messsage to peripheral
HalUARTWriteDMA("tx\r",4);
//wait a little bit for the device to process the message
//start reading from the peripheral
do {
//how many bytes are at the RX port?
int len = HalUARTRxAvailDMA();
//Read those bytes
HalUARTReadDMA(msg, len);
//append the rx msg to the buffer
strcat(rxbuf, msg)
//does the response contain a CR?
} while(strchr(rxbuf, 0x0D));这个想法有几个明显的缺陷。我希望有人能分享一些关于这种沟通方式的想法?
谢谢!
发布于 2012-10-22 08:35:25
如果您打算阻止等待消息的线程,设计中有一个直接的问题,就是使用可变大小的消息和一个CR作为分隔符。
我设想HalUARTReadDMA()的设计是为了阻止调用线程,直到接收到len字节为止,因此您显然无法可靠地使用它来阻塞可变长度的消息。
代码看起来类似于(做了一些假设):
while (1)
{
static const size_t bufferSize = sizeof(Message_t);
uint8_t buffer[bufferSize];
// blocks until message received
unsigned len = HalUARTReadDMA(buffer, bufferSize);
if (len == bufferSize)
processMessage(buffer);
}对于在DMA中使用不涉及轮询的可变大小消息的问题,没有特别好或可靠的解决方案--除非DMA控制器能够为您检测消息结束分隔符。
如果您不能更改消息格式,您最好使用中断驱动的IO来阻止单个消息字节的接收,特别是在数据速率相对较低的UART的情况下。
发布于 2012-10-22 23:20:57
除非DMA驱动程序具有接受缓冲区指针队列的功能,否则当接收到CR并自行移动到下一个缓冲区指针时,可以生成一个中断,您将继续迭代rx数据,寻找CR。
如果你必须迭代数据,你也可以在一个“经典的”ISR中这样做,从rx中一个接一个地从rx中获取字符,并将它们推入一个缓冲区,直到接收到CR。
然后,您可以将缓冲区指针排队到一个合适的循环队列中,为下一条消息从另一个“空”缓冲区循环池队列中获取另一个缓冲区,向一个信号量发送信号,以便运行将要处理该消息的线程,并通过操作系统从ISR退出,以便立即执行重新调度。
rx线程可以将消息排出队列,进行处理,然后将其请求到池队列中,以供ISR重用。
用strchr()继续搜索CR的完整缓冲区不太可能是特别有效或容易的-- CR可能位于DMA缓冲区的中间,而您需要参与重新挖掘部分缓冲区的数据复制。
。
https://stackoverflow.com/questions/13003971
复制相似问题