串口接收丢失数据的问题

chenccq 2008-05-07 10:25:28
运行在arm-linux上的录像程序,同时要接收响应上位机的命令。
从视频流得到的视频数据放置在内存中的视频文件中,一个文件结束后拷贝到sd卡上。
但是这样做就引起串口接收的问题,当接收一条70多个字节长度的上位机命令时,接收数据经常会丢几个字节,接收正确的概率大约是90%,后来经过问题排查,发现当注释掉从内存向sd卡拷贝数据的那条语句后就没有问题了。
拷贝语句是:system("cp .....")
怀疑问题是由于当向sd卡拷贝文件的时候,会引起DMA中断,由于视频文件较大,经测试拷贝时间需要2秒左右,所以在此期间上位机发送的串口数据得不到中断响应引起的。

请指点一下我得判断是不是正确?问题应该怎么解决?
...全文
2175 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluesonic 2008-05-08
  • 打赏
  • 举报
回复
1、使用 nice 系统命令 或者 nice函数调用,将串口处理的进程优先级提高到-20,对性能有一定影响。
2、有必要的话,检测一下程序中关于串口设置的参数,详情参见:http://blog.csdn.net/qdhuxp/archive/2006/08/09/1041669.aspx
chenccq 2008-05-07
  • 打赏
  • 举报
回复
拷贝与串口接收不在同一进程

有没有提高串口中断优先级的设置方法?提高串口中断优先级不知道是否可以解决
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
不是很清楚具体的解决方法。帮顶。
查了下system,发现它会无视SIGINT和SIGQUIT,并且阻塞SIGCHLD。


不过,你试试看开新线程拷贝文件,等拷贝线程结束再继续后面的动作。避免在进行拷贝动作的时候做别的事情。
chenccq 2008-05-07
  • 打赏
  • 举报
回复
上位机命令是用户发出的,所以什么时候发命令是不可预料的.

分段拷贝也可以,自己写拷贝函数,不过写一个高效的拷贝函数恐怕也不容易,可以试试看.

system调用我也可以不用,用拷贝函数试试看,当时就图省事儿了所以就这么写了.

14楼说的串口进程是否分配到cpu,这个问题我想不太可能,虽然我的系统比较忙,但串口接受是中断响应,因此cpu应该能够及时处理.就算不能及时处理也会在cpu调度进程里面排队,不至于引起数据丢失.
串口驱动程序会在内存中请求一段内存做为串口数据缓冲区,当串口数据到来的时候,会触发驱动程序提供的串口中断处理函数,该函数会将收到的数据放到缓冲区中,编程读取串口用read函数,实际上read函数是从缓冲区中读取数据的,因此只要串口中断得到响应并且串口缓冲区没有溢出的话就不应该丢数据.
现在根据现象看,丢数据是由于拷贝语句引起的,所以我才想是不是由于拷贝是触发了DMA中断,这样如果DMA中断没有退出时串口有数据到来的话,串口中断就不能响应了.不过从感觉上,linux做为一个成熟的操作系统如果连这个问题也不能处理的话就别混了.如果不怀疑操作系统,那么是不是应该怀疑驱动程序呢?但是要搞驱动程序的话,我没有信心.

迷茫啊,困惑中......
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
恩,同14楼。
避免system调用。不划算。
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
所以要把整个拷贝动作分段进行。
每拷贝一点就检查下,是否在接收指令,不是在进行中的话,就继续下一阶段拷贝动作。
air_snake 2008-05-07
  • 打赏
  • 举报
回复
1.不明白为什么向sd卡拷贝的时候一定要 system调用cp命令的。
2.串口接收数据的缓冲区是有限制的,要立即响应,看看你的串口进程是不是分配不到cpu,导致没有及时处理。
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
不是改硬中断处理,,是当你接收上位指令的时候,避免做拷贝动作。等待接收完成再进行拷贝。
这点也做不到么?
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
回忆了一下大学时代的单片机课程。。。。
可能自己写拷贝函数,分段拷贝,比较可行。
chenccq 2008-05-07
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 fuqd273 的回复:]
那么可以使两个进程在处理硬中断的时候同步么?这点在技术上应该不复杂。至少比改变中断属性简单点。可能性能上会有损失?
不过,向楼主学习。呵呵,硬件这方面我完全没概念。
[/Quote]

硬中断处理都是驱动程序带的,我要改就要重写驱动,俺还没这个水平哦
chenccq 2008-05-07
  • 打赏
  • 举报
回复

你说的丢是指的没有接收到还是接收错误?

有时一帧数据中会多出几个字节,有时会少几个字节。多出或者少的字节数不定

------------------------------------
应该不是这个原因。如故还怀疑,那就自己测试一下就是了,使用串口和arm机通讯,通过控制台往sd卡上拷贝数据,看串口通讯是否出错。

这个方法没试过,但为什么不拷贝文件时就没有错误呢?还有,当接收的数据帧长度小于20字节的时候也不会出错

简单的作法就是让上位机重发指令.
还有就是自己写拷贝函数,在拷贝过程中加usleep,让出一不分时间来.
由于上位机不是我做的,现在项目要验收,这个方法不满足验收要求啊,我晕
chenccq 2008-05-07
  • 打赏
  • 举报
回复

你说的丢是指的没有接收到还是接收错误?

有时一帧数据中会多出几个字节,有时会少几个字节。多出或者少的字节数不定

------------------------------------
应该不是这个原因。如故还怀疑,那就自己测试一下就是了,使用串口和arm机通讯,通过控制台往sd卡上拷贝数据,看串口通讯是否出错。

这个方法没试过,但为什么不拷贝文件时就没有错误呢?还有,当接收的数据帧长度小于20字节的时候也不会出错

简单的作法就是让上位机重发指令.
还有就是自己写拷贝函数,在拷贝过程中加usleep,让出一不分时间来.
由于上位机不是我做的,现在项目要验收,这个方法不满足验收要求啊,我晕
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
那么可以使两个进程在处理硬中断的时候同步么?这点在技术上应该不复杂。至少比改变中断属性简单点。可能性能上会有损失?
不过,向楼主学习。呵呵,硬件这方面我完全没概念。
xzdwfwt111 2008-05-07
  • 打赏
  • 举报
回复
不懂,学习,关注.
cceczjxy 2008-05-07
  • 打赏
  • 举报
回复
当接收一条70多个字节长度的上位机命令时,接收数据经常会丢几个字节,接收正确的概率大约是90%,后来经过问题排查,发现当注释掉从内存向sd卡拷贝数据的那条语句后就没有问题了。

你说的丢是指的没有接收到还是接收错误?

------------------------------------

windows中,中断是分优先级的,由中断控制器控制,操作系统管理。但是linux好像并不要求硬件中断分优先级,而是将中断管理分为快速中断处理程序和慢速处理程序两部分处理的,慢速处理程序由cpu调度程序调度管理,快速中断处理部分遵循先来先处理的原则处理。具体不太清楚,以前看过记得一点。

应该不是这个原因。如故还怀疑,那就自己测试一下就是了,使用串口和arm机通讯,通过控制台往sd卡上拷贝数据,看串口通讯是否出错。

简单的作法就是让上位机重发指令.
还有就是自己写拷贝函数,在拷贝过程中加usleep,让出一不分时间来.

chenccq 2008-05-07
  • 打赏
  • 举报
回复
串口接收部分处于主进程,该进程负责同上位机的通信,并响应上位机的命令,拷贝语句位于视频处理进程中,视频处理进程是主进程的子进程。

上面说的信号量处理都是软中断,串口接收使用的是硬件中断,向sd卡中拷贝数据用的也应该是DMA硬中断,这两者还是有区别的。

windows中,中断是分优先级的,由中断控制器控制,操作系统管理。但是linux好像并不要求硬件中断分优先级,而是将中断管理分为快速中断处理程序和慢速处理程序两部分处理的,慢速处理程序由cpu调度程序调度管理,快速中断处理部分遵循先来先处理的原则处理。具体不太清楚,以前看过记得一点。

时间较紧再去看书有点慢,请会的指点一下。
fuqd273 2008-05-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 chenccq 的回复:]
拷贝与串口接收不在同一进程
[/Quote]
请看关于system的说明:
NOTES
If the _XOPEN_SOURCE feature test macro is defined, then the macros
described in wait(2) (WEXITSTATUS(), etc.) are made available when includ-
ing <stdlib.h>.

As mentioned, system() ignores SIGINT and SIGQUIT. This may make programs
that call it from a loop uninterruptible, unless they take care themselves
to check the exit status of the child. E.g.

while(something) {
int ret = system("foo");

if (WIFSIGNALED(ret) &&
(WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
break;
}
===========================================

不清楚你的“不在同一进程”是不是这个意思?
嵌云阁主 2008-05-07
  • 打赏
  • 举报
回复
可以从串口通信协议上想想办法

23,216

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧