打印
[程序源码]

这是不可重入函数引起的吗?

[复制链接]
1869|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
无名蚂蚁|  楼主 | 2013-12-6 18:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
比如:

unsigned char flag;
unsigned char buf[50];

中断:
//串口中断
void hander(state)
{
      //
      if(state == 1)
     {
         //将数据读进buf
         read(buf);
         flag = 1;
     }
}
main()
{
     if(flag)
    {
         //需要运行的代码
        fun(buf);
        flag = 0;
    }
}

问题来了,假如在fun(buf)执行完后,进入中断,导致buf区加入了新的值,然后flag = 1了,退出中断,程序再执行flag = 0,这样会使得fun(buf)不能被执行,问题严重了。
有人说,直接将fun(buf)加入在中断里面执行,这样虽然不会漏掉执行,但是如果这个fun执行时间很长,会导致后续的串口接收的中断进不了,数据丢掉了。
也有人说,加入关中断,开中断,这样问题解决了,程序中因为用定时中断做了时间功能,关了中断,时间不准了。。请问大家是怎么解决的?

相关帖子

沙发
craaazyfor| | 2013-12-6 22:23 | 只看该作者
如果可以加流控最好,不行的话还是中断只做标志位的处理,大循环处理数据

使用特权

评论回复
板凳
无名蚂蚁|  楼主 | 2013-12-6 23:04 | 只看该作者
craaazyfor 发表于 2013-12-6 22:23
如果可以加流控最好,不行的话还是中断只做标志位的处理,大循环处理数据 ...

是的,流控对于串口来说还行,有些没有的就麻烦了,比如还有CAN,其它一些类似没有流控之类的东西,在中断里面将收的数据更新到RAM后,再在大循环处理,这时候,容易出问题,虽然出问题的概率比较小。
看了论坛里高手Cortex-M0所说,如果在一个周期内没有读完的数据,退出来后,数据可能被破坏,加volatile也没有,只能加强硬件。

使用特权

评论回复
地板
泰山特曲123| | 2013-12-6 23:36 | 只看该作者
你先清flag标志位再读不就行了吗?

使用特权

评论回复
5
ayb_ice| | 2013-12-7 09:30 | 只看该作者
这个程序逻辑上本来就有一些问题

当中断来时,主循环又没有处理完数据,数据就会被覆盖,

可以通过双缓冲来处理,最好是通过队列来处理

中断直接将数据存入队列,主循环不断的从队列取数据,分析处理

使用特权

评论回复
6
lhchen922| | 2013-12-7 16:58 | 只看该作者
中断中尽量少用全局变量。

使用特权

评论回复
7
lhchen922| | 2013-12-7 17:00 | 只看该作者
推荐一本书《嵌入式系统设计与实践>>

使用特权

评论回复
8
JasonWangSE| | 2013-12-7 23:17 | 只看该作者
可以用ring buffer实现

使用特权

评论回复
9
无名蚂蚁|  楼主 | 2013-12-9 09:43 | 只看该作者
泰山特曲123 发表于 2013-12-6 23:36
你先清flag标志位再读不就行了吗?

在中断里先清flag再读与读了再清flag有区别吗

使用特权

评论回复
10
无名蚂蚁|  楼主 | 2013-12-9 09:54 | 只看该作者
ayb_ice 发表于 2013-12-7 09:30
这个程序逻辑上本来就有一些问题

当中断来时,主循环又没有处理完数据,数据就会被覆盖,

中断来的时候,存入队列,还没处理完的时候,就不覆盖当前这个队列,选择别一个队列,这样先保证数据的完整性,是吗?

使用特权

评论回复
11
无名蚂蚁|  楼主 | 2013-12-9 09:55 | 只看该作者
lhchen922 发表于 2013-12-7 16:58
中断中尽量少用全局变量。

请问你是怎么处理的。

使用特权

评论回复
12
fsaok| | 2013-12-9 09:56 | 只看该作者
队列可长可短,可软可硬

使用特权

评论回复
13
ayb_ice| | 2013-12-9 09:57 | 只看该作者
无名蚂蚁 发表于 2013-12-9 09:54
中断来的时候,存入队列,还没处理完的时候,就不覆盖当前这个队列,选择别一个队列,这样先保证数据的完 ...

你这不是队列,
不过也可以一定程序解决问题

总之一点,必须要考虑这种情况出现,以及用什么方法对应,
除非有手段不让此情况出现

使用特权

评论回复
14
无名蚂蚁|  楼主 | 2013-12-14 19:54 | 只看该作者
其实问题还是没有解决 。。。。

使用特权

评论回复
15
i55| | 2013-12-14 21:00 | 只看该作者
其实你解决fun(buf)执行时间太长导致没处理完就再来中断read(buf)之前,说别的都没用。

使用特权

评论回复
16
elife| | 2013-12-15 10:08 | 只看该作者
中断和大循环共用变量要考虑互锁问题,包括你的flag. 在判断标志前禁止中断,操作结束后开中断,可以拷贝数据到缓冲区后,提前开中断,再执行fun. 如果fun的周期太长,导致数据丢失,那就是处理器速度不足了.

使用特权

评论回复
17
无名蚂蚁|  楼主 | 2014-1-2 17:06 | 只看该作者
好像最常用的方法就是关中断了。

使用特权

评论回复
18
wolension| | 2014-1-3 09:34 | 只看该作者
肯定要临时关中断,开中断,如果是RTC或者有自动重载的定时器,只要你关中断的时间很短,对计时是没有什么影响,如果你是在中断里软件重载的定时器,本身计时也不会准(相对于RTC来说)。
  我觉得可以还是先把数据读到缓冲区再处理,但这种做法只是针对串口数据是不定时接收的那种情况,如果你的串口是以固定的频率收到的包,你处理不完,那就是系统设计的问题了。
void hander(state)
{
      //
      if(state == 1)
     {
         //将数据读进buf
        if(flag == 0)
        {
             read(buf);
             flag = 1;
         }
     }
}

void task(void)
{
   u8 i,temp[N];  
   if(flag)
    {     
        //关中断
        for(i=0;i<N,i++) temp[i] = buf[i];
        flag = 0;
        //开中断
        fun(temp);   
    }
}

使用特权

评论回复
19
xppx1987| | 2014-11-27 09:42 | 只看该作者
elife 发表于 2013-12-15 10:08
中断和大循环共用变量要考虑互锁问题,包括你的flag. 在判断标志前禁止中断,操作结束后开中断,可以拷贝数据 ...

中断和大循环共用变量是不是都要考虑互锁问题呢?比如按键修改一个全局变量的值,然后定时中断中动态扫描数码管显示这个全局变量的值,那按键修改这个全局变量的值时也要考虑互锁问题?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

226

帖子

1

粉丝