打印

一线研发之声:嵌入式C编程经验 之 只有一条清狗语

[复制链接]
13002|60
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sedatefire 于 2012-1-13 23:15 编辑

/********************************************************************
* Filename: 一线研发之声:嵌入式C编程经验 只有一条清狗语句
* Author:SedateFire E-mail:SedateFire@126.com
* Version:1.000 Time: 2012-01-05
* key: 看门狗 系统架构 os-less 嵌入式
********************************************************************/

一个好的os-less系统,只有一条清狗语句,它位置就固定在main函数中的
while(1) /* or for(;;;) */
{
__watchdog_reset();
}

如果你有两条以上看门狗语句,那么会有什么后果呢? 在系统足够复杂的时候,很能引起当机,由于静电或者程序自身逻辑的原因,进入了某个思维的盲点,系统进入一个有清狗语句的死循环里面,退不出来。这是最危险的,尴尬的,蒙羞的事情。

那么多出来的清狗语句,一般会用在哪里呢?

1. 系统初始化,有些设备初始化需要读取它的反馈状态,用while,担心复位,于是清狗。我一般用While (dev_read_status() && (i--)),这个i,32位顶天了。一般mcu没这么快法。

2. mcu睡眠前清狗。有些人喜欢在系统进入睡眠前清狗一下,担心系统刚好在那一刻复位。这只能说明你对自己的程序不了解,主回圈程序一圈下来,最大执行时间其实心中有数。函数多少深度宽度心中要有低。如果刚好睡眠前一刻复位,那也有可能在跑别的函数过程中复位。

3. 某些应用逻辑貌似要需要hold住,比如屏幕的暂停显示2秒钟等。许多人生生地把这种逻辑做成“硬延时”,就是死等。这是一个令人戚眉的做法,因为这意味麻烦的开始。在你需要暂停显示n秒的过程中,我的一切用户体验你无法响应我了,按键没反应,蜂鸣器不响,led灯不闪烁,一切好像死机了一样。等到系统显示完成后,用户心中大舒一口气,心中悬石落地,你终于又回气儿活过来了。这是糟糕的体验。

好吧,为了改善体验,许多人就想办法来。把用户体验搬到中断里面做,这是另外一个麻烦的开始,全局变量的增多和跨模块的判断,其根源之一始于此,弄个不好,就是随机性崩溃。中断程序变胖,终究是不方便的,于是为了改进,就只好在中断程序中置标志位,然后在hold_delay(TIME)函数的循环中清狗,并且判断标志位作响应动作。许多应用逻辑需要hold住的地方何其多,上九天下地府处处添加,函数深度不可测,逻辑递归难判断,系统大乱的祸患就此埋下。

那如何解决呢,事件--状态机,一句话概括,在当前状态下,遇到某某事件,则执行什么动作后,进入下一个状态。它似表非表,如水般自然,像空气般无痕……好了,其实是我不愿多讲,若要具体讲下去,恐怕涉及公司知识产权。尽管这个事件状态机思想是个公开的秘密,原理大家都懂,但做得好的还不多见。Hold住本身就是一种状态,看你如何抽象它了。

佛曰:菩萨畏因,凡夫畏果。那灾难之源,是需要敬畏戒惧的,待到结果发生,悔之莫及。
评分
参与人数 3威望 +3 收起 理由
张允 + 1
匠人粉丝团 + 1
xyz549040622 + 1

相关帖子

沙发
sedatefire|  楼主 | 2012-1-6 23:36 | 只看该作者
嚣张的口吻,只为引君拍砖....
《匠人手记》我上班第一年就买的书,至今时常研读,收益颇深,在此谢过。
前辈风采,心向往之......

使用特权

评论回复
板凳
Ryanhsiung| | 2012-1-7 13:08 | 只看该作者

使用特权

评论回复
地板
DownCloud| | 2012-1-7 13:24 | 只看该作者
是啊,好的软件就应该流水般自然。
其实我发现,程序规划才是最关键的,不然只会越写越累。

使用特权

评论回复
5
linfuchi| | 2012-1-7 14:39 | 只看该作者
支持

使用特权

评论回复
6
nayaix| | 2012-1-7 17:25 | 只看该作者

使用特权

评论回复
7
xyz549040622| | 2012-1-7 20:34 | 只看该作者
再接再励,看十遍都嫌少:victory:

使用特权

评论回复
8
xhtxzxw| | 2012-1-7 22:13 | 只看该作者
茅塞顿开......

使用特权

评论回复
9
haphard| | 2012-1-8 15:32 | 只看该作者
好东西

使用特权

评论回复
10
jiabin1024| | 2012-1-8 16:32 | 只看该作者
mark

使用特权

评论回复
11
cjseng| | 2012-1-8 23:41 | 只看该作者
砖在哪里?砖在哪里?:curse:
假如由于意外,中断被关掉了,只剩下这个main()函数还能运行,是不是就这么傻等下去了?

使用特权

评论回复
评分
参与人数 2威望 +11 收起 理由
第二道彩虹 + 1 我很赞同
xwj + 10 无条件喂狗,狗就白养了
12
红金龙吸味| | 2012-1-9 09:03 | 只看该作者
状态读取,一般时间稍长需要加超时处理,防止一直等待下去。人机交互确实用事件-状态机做比较好,还可以多层嵌套。

1.jpg (63.24 KB )

1.jpg

2.jpg (84.14 KB )

2.jpg

使用特权

评论回复
13
匠人粉丝团| | 2012-1-9 09:15 | 只看该作者
学习了

使用特权

评论回复
14
zxcscm| | 2012-1-9 09:16 | 只看该作者
LS是看的什么文档呢?

使用特权

评论回复
15
红金龙吸味| | 2012-1-9 11:22 | 只看该作者
我准备写的新书:从单片机初学者迈向单片机工程师,网上有以前的博文,可以搜搜看。

使用特权

评论回复
16
joinj| | 2012-1-11 14:11 | 只看该作者
事件状态机?呵呵 我在学校就用过这种方法·····只是不知道叫啥名····

使用特权

评论回复
17
Periodic| | 2012-1-11 21:32 | 只看该作者
void(*ReceiveByteStatus[4])()={Write_Queue,Write_Queue_Receipt,Read_Queue,Read_Queue_Receipt};
               
(*ReceiveByteStatus[ReceiveByteStatusCnt])(); //状态轮转

不知道这样 用 算不算状态 转换

使用特权

评论回复
18
Periodic| | 2012-1-11 21:34 | 只看该作者
ReceiveByteStatusCnt=1;//状态机标记
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
          ReceiveByteStatusCnt=2;//状态机标记
。。。。。。。。。。。。。。。。。。。。。。。。。。。

使用特权

评论回复
19
Periodic| | 2012-1-11 21:39 | 只看该作者
本帖最后由 Periodic 于 2012-1-11 21:52 编辑

还有一种 方式
不过比上面 哪个效率低

switch(......) //读取状态
  {
     case 0x01: 1_Mode();  //;0=
       break;
     case 0x02: 2_Mode();   //;1=
       break;                                                  
     case 0x04: 3_Mode();   //;2=  
       break;   
     case 0x08: 4_Mode();  //;3=
       break;                                 
     case 0x10: 5_Mode();  //;4=        
       break;
     case 0x20: 6_Mode();   //;5=
       break;
     case 0x40: 7_Mode();//;6=         
       break;
     case 0x80: 8_Mode();   //;7=        
       break;
     case 0x100: 9_Mode();     //;8=        
       break;
     default:
       break;
  }

使用特权

评论回复
20
Periodic| | 2012-1-11 21:43 | 只看该作者
本帖最后由 Periodic 于 2012-1-11 21:52 编辑

int main(void)
{

NVIC_Configuration();       //中断向量配置   
RCC_Configuration();        //时钟
GPIO_Configuration();      //IO
TIM_Config();        //TIM
SimulateInput_Init();      //模拟量配置
Communication_Init();            //通讯配置
    RamClear();//清内存
   // (*(void (*)(void))(0x08000000))();//跳转绝对地址


        while(1)
        {        
                Time_Dispatch();//时间片调度
                //watchdog_reset();

        }

使用特权

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

本版积分规则

4393

主题

5935

帖子

33

粉丝