范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

嵌入式开发中的防御性C语言编程

  文章下方附学习资源,自助领取
  嵌入式产品的可靠性自然与硬件密不可分,但在硬件确定、并且没有第三方测试的前提下,使用防御性编程思想写出的代码,往往具有更高的稳定性。
  防御性编程首先需要认清C语言的种种缺陷和陷阱,C语言对于运行时的检查十分弱小,需要程序员谨慎的考虑代码,在必要的时候增加判断;防御性编程的另一个核心思想是假设代码运行在并不可靠的硬件上,外接干扰有可能会打乱程序执行顺序、更改RAM存储数据等等。 1 具有形参的函数,需判断传递来的实参是否合法
  程序员可能无意识的传递了错误参数;外界的强干扰可能将传递的参数修改掉,或者使用随机参数意外的调用函数,因此在执行函数主体前,需要先确定实参是否合法。
  2 仔细检查函数的返回值
  对函数返回的错误码,要进行全面仔细处理,必要时做错误记录。
  3 防止指针越界
  如果动态计算一个地址时,要保证被计算的地址是合理的并指向某个有意义的地方。特别对于指向一个结构或数组的内部的指针,当指针增加或者改变后仍然指向同一个结构或数组。 4 防止数组越界
  数组越界的问题前文已经讲述的很多了,由于C不会对数组进行有效的检测,因此必须在应用中显式的检测数组越界问题。下面的例子可用于中断接收通讯数据。
  在使用一些库函数时,同样需要对边界进行检查,比如下面的memset(RecBuf,0,len)函数把RecBuf指指向的内存区的前len个字节用0填充,如果不注意len的长度,就会将数组RecBuf之外的内存区清零:
  5 数学算数运算5.1除法运算,只检测除数为零就可靠吗?
  除法运算前,检查除数是否为零几乎已经成为共识,但是仅检查除数是否为零就够了吗?
  考虑两个整数相除,对于一个signed long类型变量,它能表示的数值范围为:-2147483648 ~+2147483647,如果让-2147483648/ -1,那么结果应该是+2147483648,但是这个结果已经超出了signedlong所能表示的范围了。所以,在这种情况下,除了要检测除数是否为零外,还要检测除法是否溢出。  #include   signed long sl1,sl2,result;  /*初始化sl1和sl2*/      if((sl2==0)||(sl1==LONG_MIN && sl2==-1))  {      //处理错误      }  else     {      result = sl1 / sl2;  }
  嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!
  无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。
  点击这里找小助理0元领取:嵌入式物联网学习资料(头条)
  5.2检测运算溢出
  整数的加减乘运算都有可能发生溢出,在讨论未定义行为时,给出过一个有符号整形加法溢出判断代码,这里再给出一个无符号整形加法溢出判断代码段:
  嵌入式硬件一般没有浮点处理器,浮点数运算在嵌入式也比较少见并且溢出判断严重依赖C库支持,这里不讨论。 5.3检测移位
  在讨论未定义行为时,提到有符号数右移、移位的数量是负值或者大于操作数的位数都是未定义行为,也提到不对有符号数进行位操作,但要检测移位的数量是否大于操作数的位数。下面给出一个无符号整数左移检测代码段: unsigned int ui1; unsigned int ui2; unsigned int uresult; /*初始化ui1,ui2*/ if(ui2>=sizeof(unsigned int)*CHAR_BIT)  { //处理错误    } else  {      uresult=ui1<=0x00040000)&&(dst<=0x0007FFFF));      PLC_ASSERT("Copy bytes number is 512",(no==512));      PLC_ASSERT("ProgStart==0xA5",(ProgStart==0xA5));      paramin[0] = IAP_RAMTOFLASH;       // 设置命令字        paramin[1] = dst;                  // 设置参数        paramin[2] = src;      paramin[3] = no;      paramin[4] = Fcclk/1000;      if(ProgStart==0xA5)                //只有软件锁标志正确时,才执行关键代码        {          iap_entry(paramin, paramout);  // 调用IAP服务程序                           ProgStart=0;      }      else        {          paramout[0]=PROG_UNSTART;      }  }
  该程序段是编程lpc1778内部Flash,其中调用IAP程序的函数iap_entry(paramin, paramout)是关键安全代码,所以在执行该代码前,先判断一个特定设置的安全锁标志ProgStart,只有这个标志符合设定值,才会执行编程Flash操作。如果因为意外程序跑飞到该函数,由于ProgStart标志不正确,是不会对Flash进行编程的。 10 通信
  通讯线上的数据误码相对严重,通讯线越长,所处的环境越恶劣,误码会越严重。抛开硬件和环境的作用,我们的软件应能识别错误的通讯数据。对此有一些应用措施: 制定协议时,限制每帧的字节数;
  每帧字节数越多,发生误码的可能性就越大,无效的数据也会越多。对此以太网规定每帧数据不大于1500字节,高可靠性的CAN收发器规定每帧数据不得多于8字节,对于RS485,基于RS485链路应用最广泛的Modbus协议一帧数据规定不超过256字节。因此,建议制定内部通讯协议时,使用RS485时规定每帧数据不超过256字节; 使用多种校验
  编写程序时应使能奇偶校验,每帧超过16字节的应用,建议至少编写CRC16校验程序。 增加额外判断
  1)增加缓冲区溢出判断。这是因为数据接收多是在中断中完成,编译器检测不出缓冲区是否溢出,需要手动检查,在上文介绍数据溢出一节中已经详细说明。
  2)增加超时判断。当一帧数据接收到一半,长时间接收不到剩余数据,则认为这帧数据无效,重新开始接收。可选,跟不同的协议有关,但缓冲区溢出判断必须实现。这是因为对于需要帧头判断的协议,上位机可能发送完帧头后突然断电,重启后上位机是从新的帧开始发送的,但是下位机已经接收到了上次未发送完的帧头,所以上位机的这次帧头会被下位机当成正常数据接收。这有可能造成数据长度字段为一个很大的值,填满该长度的缓冲区需要相当多的数据(比如一帧可能1000字节),影响响应时间;另一方面,如果程序没有缓冲区溢出判断,那么缓冲区很可能溢出,后果是灾难性的。 重传机制
  如果检测到通讯数据发生了错误,则要有重传机制重新发送出错的帧。 11 开关量输入的检测、确认
  开关量容易受到尖脉冲干扰,如果不进行滤除,可能会造成误动作。一般情况下,需要对开关量输入信号进行多次采样,并进行逻辑判断直到确认信号无误为止。 12 开关量输出
  开关信号简单的一次输出是不安全的,干扰信号可能会翻转开关量输出的状态。采取重复刷新输出可以有效防止电平的翻转。 13 初始化信息的保存和恢复
  微处理器的寄存器值也可能会因外界干扰而改变,外设初始化值需要在寄存器中长期保存,最容易被破坏。由于Flash中的数据相对不易被破坏,可以将初始化信息预先写入Flash,待程序空闲时比较与初始化相关的寄存器值是否被更改,如果发现非法更改则使用Flash中的值进行恢复。
  公司目前使用的4.3寸LCD显示屏抗干扰能力一般。如果显示屏与控制器之间的排线距离过长或者对使用该显示屏的设备打静电或者脉冲群,显示屏有可能会花屏或者白屏。
  对此,我们可以将初始化显示屏的数据保存在Flash中,程序运行后,每隔一段时间从显示屏的寄存器读出当前值和Flash存储的值相比较,如果发现两者不同,则重新初始化显示屏。下面给出校验源码,仅供参考。
  定义数据结构:
  定义const修饰的结构体变量,存储LCD部分寄存器的初始值,这个初始值跟具体的应用初始化有关,不一定是表中的数据,通常情况下,这个结构体变量被存储到Flash中。  /*LCD部分寄存器设置值列表*/    lcd_redu_list_struct const lcd_redu_list_str[]=  {    {SSD1963_Get_Address_Mode,{0x20}                                   ,1}, /*1*/     {SSD1963_Get_Pll_Mn      ,{0x3b,0x02,0x04}                         ,3}, /*2*/     {SSD1963_Get_Pll_Status  ,{0x04}                                   ,1}, /*3*/     {SSD1963_Get_Lcd_Mode    ,{0x24,0x20,0x01,0xdf,0x01,0x0f,0x00}     ,7}, /*4*/     {SSD1963_Get_Hori_Period ,{0x02,0x0c,0x00,0x2a,0x07,0x00,0x00,0x00},8}, /*5*/     {SSD1963_Get_Vert_Period ,{0x01,0x1d,0x00,0x0b,0x09,0x00,0x00}     ,7}, /*6*/     {SSD1963_Get_Power_Mode  ,{0x1c}                                   ,1}, /*7*/     {SSD1963_Get_Display_Mode,{0x03}                                   ,1}, /*8*/     {SSD1963_Get_Gpio_Conf   ,{0x0F,0x01}                              ,2}, /*9*/     {SSD1963_Get_Lshift_Freq ,{0x00,0xb8}                              ,2}, /*10*/  };
  实现函数如下所示,函数会遍历结构体变量中的每一个命令,以及每一个命令下的初始值,如果有一个不正确,则跳出循环,执行重新初始化和恢复措施。这个函数中的MY_DEBUGF宏是我自己的调试函数,使用串口打印调试信息,在接下来的第五部分将详细叙述。
  通过这个函数,我可以长时间监控显示屏的哪些命令、哪些位容易被干扰。程序里使用了一个被妖魔化的关键字:goto。大多数C语言书籍对goto关键字谈之色变,但你应该有自己的判断。在函数内部跳出多重循环,除了goto关键字,又有哪种方法能如此简洁高效!  /**   * lcd 显示冗余   * 每隔一段时间调用该程序一次   */    void lcd_redu(void)    {      uint8_t  tmp[8];      uint32_t i,j;      uint32_t lcd_init_flag;      lcd_init_flag =0;      for(i=0;i
今明两年,做好资产贬值的准备?2大信号出现,房价走向逐渐清晰在房地产业界朋友圈传着一张表,这张表的数据来源是CRTC中国房地产决策咨询系统,统计的是19月份全国12个重点城市的二手房成交量。说实在的,应该跟我们所在城市的感受应该差不多,但看山东菏泽彩礼数排山东第一了?菏泽在山东人的印象里一直都是经济欠发达地区。但是这两年GDP有点起色了,增速省内数一数二,2021年GDP总量能排在山东前八了!鲁南经济圈第三,全省第八不过呢,由于菏泽人口众多,人重庆有个网红打卡点,当地人摸不着头脑,不知道有什么好看的这里是刘小顺的旅行和生活研究所。重庆位于我国的西南地区,是我国四大直辖市之一,最近这些年重庆的经济发展速度很快,大家有目共睹,前景也被很多人所看好。由于互联网传播的推动,重庆常常被震撼!重庆武隆鸡尾山地质公园,4000多万方巨石倾泻而下在重庆武隆大洞河乡,有一个因为山体垮塌而形成的地质遗址公园。时光远去,再次到达此地,远处看山,可以想象半座山塌下来的震撼,不由感叹生命不易,敬畏大自然!这里就是武隆鸡尾山地质公园,获央视聚焦,永悦无人机产业入选中国品牌创新发展工程近日,永悦科技被中央电视台品质中国栏目关注,收到了节目的访谈邀约,而盐城永悦智能装备有限公司更是入选中国品牌创新发展工程。永悦科技盐城永悦之所以能受到中国品牌创新发展工程的的关注,外商对中国经济投下信任票(环球热点)来源人民日报海外版近日,中国商务部数据显示,今年18月,中国实际使用外资1384亿美元,增长20。2。从行业看,中国服务业实际使用外资金额6621。3亿元人民币,增长8。7。高技术媒体揭秘朱婷缺席女排世锦赛背后隐情,称张常宁处于待孕阶段北京时间10月12日凌晨,中国女排结束了2022女排世锦赛之旅。在荷兰阿珀尔多伦进行的14决赛中,她们以1比3不敌世界排名第一的意大利队。虽然没有进入四强,但是中国女排经历东京奥运市值刚过200亿,代糖龙头金禾实业拟99亿投建新项目,钱从哪里来?记者吴治邦编辑在前期投资计划终止后,有着代糖龙头之称的金禾实业(002597。SZ)抛出了一份新的投资计划,公司拟与定远县人民政府签订金禾实业定远县二期项目投资协议书,在定远盐化工女排世锦赛巴西队3比2大逆转淘汰日本队将与意大利队争夺决赛权京报体育记者孔宁北京时间10月12日凌晨,2022年女排世锦赛14决赛荷兰赛区第二场比赛在阿珀尔多伦市结束,巴西女排在大比分0比2落后之下,以3比2大逆转击败日本女排,时隔8年重返CBA最新积分榜马布里渔翁得利,首钢遭绝杀,新疆初露冠军相CBA常规赛火热进行,第二个比赛日一共进行了5场比赛,除了北京北控与广东队的比赛,因为广东队不能按时参加比赛被判020输球之外,其余的比赛都打得非常激烈和精彩。其中南京同曦和福建队水利部提前三个月完成水利建设投资8000亿元年度任务封面新闻记者代睿10月11日,水利部举行前三季度水利基础设施建设进展和成效新闻发布会。水利部副部长刘伟平介绍,今年水利建设投资要完成8000亿元的年度目标任务已提前完成。刘伟平介绍
好书分享人生海海无论是驱赶迷茫,还是对抗平庸,读书都是最简单也最实用的方法。给自己一点时间,静下心来读书,它会一点一滴地滋养你改变你。今天想给大家分享的是中国作家麦家的人生海海内容简介本书围绕村里宝可梦朱紫培育努力值攻略注意所有图中加减数字均为努力值。1努力值(基础点数)每次升级时获得的隐藏数值,累积的数值影响最终呈现出来的宝可梦各项能力值。每积累4点努力值1点能力值,每项最高提升252点努力值。禹唐体育报告I电子竞技产业报告(上)国际篇作为数字体育的新形态,电竞产业在全球迈入蓬勃发展阶段。1。国外电子竞技产业发展情况电子竞技是以电竞游戏为基础,信息技术为核心的软硬件设备为器械在信息技术营造的虚拟环境中,在统一的竞原神玩法设定问题分析任务驱动型游戏。这种流程架构模式算是非常经典的了,这类模式最大的特点就是文本或是对话型叙事特别多以及要经常到对应点位触发任务(参考育碧式点位)。R星一直在用,目前这类模式发挥得最好镜的三大飞雷神教学第三个进阶飞雷神第三个进阶飞雷神进阶飞雷神主要用于实战因为实战的时候敌人不一定在你的中心位置但是只要他在你的镜像里你就可以无限飞雷神进阶飞雷神和飞雷神差不多只是进阶飞雷神可以不用把本体放在中间也能宝宝便秘2年五谷杂粮食谱分享,希望可以帮到正在便秘的宝宝们儿童慢性便秘2年,评测有效,目前脱离便秘快半年,希望有共同烦恼的妈妈可以及时调整便秘食谱。经常姐妹问我米油喝多少?米油怎么煮?多长时间有效果?米油主要是用哪些米来煮?生津的食物是哪宝妈感冒了可以哺乳吗哺乳期间女性的饮食摄入会关乎到宝宝的健康因而女性需要合理的搭配饮食营养以免对胎儿造成影响问题来了宝妈感冒了可以哺乳吗?宝妈感冒了能否哺乳,要根据具体情况来看1只要没有发热,以及全身已证实这种皮疹,后果可能会很严重,一旦发现立马去医院4岁的跳跳,是个非常活泼好动的小男孩,一天到晚,只要眼睛是睁开的,就是这边跑来,那边跳去的,因此,磕磕碰碰在所难免,身上的淤青总是这块刚消下去,那块又起来了。妈妈也从一开始的心疼不陪孩子读中国少儿百科全书我们生活的世界美丽而神奇,面对这大千世界,我们不免会产生数不尽的疑问,而童年正是一个人求知欲最强的时期,孩子喜欢观察事物,巨大的好奇心吸引着他们去了解世界,寻找真相。中国少儿百科全1岁男孩反复发烧,原来是得了猫抓病湖南日报11月28日讯(全媒体记者王铭俊通讯员刘颖)1岁男孩多多,近半个月来反复发烧,一直找不到原因。日前,焦急的妈妈带着孩子来到湖南省儿童医院求助。经过专家会诊,通过NGS(下一宝宝的坏习惯现在越来越多的宝宝不爱吃饭,即便吃了也会食物消化不良,甚至有大便不成形,不长肉也不见长高,这些症状都是宝宝长期积食脾胃弱,大部分都是这些坏习惯喂出来的!昊妈分享来了坏习惯一追着宝宝