单片机工控的工程分离是什么?

描述

单片机电路板一般专有的,如汽车的车灯控制电路板和EPS控制的电路板是完全不同的。专有的电路板,软件就比较难通用,软件编程比较强调的是单片机系统。用单片机来做工控板则有很强的通用性,如一个工控电路板既可以用来控制口罩设备,也可以用来控制电梯运行,还可以控制自助发银行的设备等等.如此说来,工控电路板不仅仅是电路板,而是一个工控平台.平台的软件是高度抽象的,如个人电脑,手机, 浏览器都是平台,开发者都是基于平台接口编程的,不用知道底层CPU寄存器,时钟等.工控平台也一样,也是希望业务程序代码中不要有单片机的寄存器设置,固件库,时钟相关的代码.

要达到这个目的,就要把业务代码和驱动系统代码实现工程级分离;或者业务代码使用脚本实现(PLC的梯形图就是一种图形脚本),下面说明一下前面的一种方式.

业务代码和驱动系统代码实现工程级分离

工程分离有静态分离和动态分离两种.静态分离是把业务程序当做一个静态库嵌入到驱动系统工程. 这个有一个缺点,业务程序修改,整个驱动软件系统都要重新编译,驱动系统和业务程序是一个Hex文件,业务程序也无法单独升级。动态分离是把业务程序当做一个单独的Hex放到单片机内部flash某一个扇区,业务程序代码修改时,驱动系统不用重新编译,工程代码少,简洁,代码复用最大化.只需编译业务程序代码的工程,这时驱动系统不止是完成电机驱动,传感器状态获取,还要完成业务程序的在线升级,加载业务程序运行.

内存及Flash区域划分

由于驱动和业务是两个不同的Hex,那么两者的RAM就不能有重叠的空间.于是可以把整个单片机RAM48K用作驱动系统软件,后面的12K RAM留给App.

单片机

keil驱动工程设置:

单片机

keil App设置:

单片机

Flash区域也应该划分为两个区域,前64K用作Boot驱动,从0x8000000开始。中间的128K扇区用作App程序存储,其它扇区用作设备参数,电机参数等.

单片机

App加载

App加载分三步:检测App是否存在以及完整性检测,App的全局变量初始化,跳转到App区域运行.

App完整性检测可以通过App的启动文件的DCD伪指令实现,start.s:

AREA    RESET, Code, READONLY,ALIGN=4
IMPORT InitApp
IMPORT |Load$$ER_IROM1$$Limit|
IMPORT |Load$$RW_IRAM1$$Limit|
DCD 365            ;标志单片机中已经存在App
DCD 111           ;CRC校验数值
DCD |Load$$ER_IROM1$$Limit|  ;RO Code大小,用于确定程序大小,用于确定Hex二进制代码的RAM初始化位置
DCD |Load$$RW_IRAM1$$Limit|  ;RW结束位置,用于确定Hex二进制代码的RAM结束位置                                    
DCD InitApp          
END

DCD 365是单片机的第一条指令,位于Flash区域的0x8020000处,这样DCD是在0x8020000处放置数值365。驱动Boot执行读取0x8020000处数值是否为365。

unsigned int IsAppExist = *(unsigned int*)0x8020000;
  if(IsAppExist!=365)//App没有烧录
  {
    return ;
  }

DCD 111是单片机的第二条指令,位于0x8020004,预留存放App的CRC数值,App在升级前,上位机先计算好Hex文件的CRC数值,下发到单片机,单片机收到CRC,写到0x8020004处.

**DCD |Load$$

ER_IROM1

Limit|** 单片机第三条指令,位置0x8020008,Load

ER_IROM1

Limit是Keil的内置宏,代表App编译后的Code大小.

**DCD |Load

RW_IRAM1

Limit|** 是单片机的第四条指令,位置0x802000c,Load

RW_IRAM1

Limit也是Keil内置宏,表示App编译后的RW大小,也就是全局变量的大小.

uint16_t Crc_16(uint8_t *buf, int len) {
  uint16_t crc = 0;
  uint16_t i;


  while (len--) {
    crc ^= *buf++;
    for (i = 0; i < 8; i++) {
      crc = (crc >> 1) ^ ((crc & 1) ? 0xA001 : 0);
    }
  }


  return crc;
}


//App CRC完整性检测
uint8_t Check_AppCRC()
{
  uint16_t SrcCRC= *(unsigned int*)0x8020004;
  int CodeSize = *(unsigned int*)0x8020008;  
  int RWSize = *(unsigned int*)0x802000c;
  uint16_t DstCRC = Crc_16((uint8_t*)0x8020000,CodeSize+RWSize);
  if(SrcCRC==DstCRC)
  {
    return 1;
  }
  
  return 0;
}

Check_AppCrc校验App的CRC是否正确,正确才能跳转到App运行.

App全局变量初始化

全局变量的初始化一般是启动文件里边调用keil内置的__main函数实现的,初始化完成以后就跳到main函数去了.为了使App的启动文件简单,可以Boot跳转App前,Boot实现App的全局变量的初始化,全局变量初始化即把全局变量的初始数值拷贝到RAM区域,初始值编译时属于RW数据,存在hex文件里边,对于单片机就是存在于Falsh区域.

单片机

要实现初始化就需要知道RW区域的起始地址,区域大小.Load

ER_IROM1

Limit即是RW区域的偏移地址,Load

RW_IRAM1

Limit是区域大小,再一次使用这两个宏

/***************************************************************************************************************
  * 函数名称: InitAppVar
  * 函数描述: 初始化业务程序的全局变量 静态变量
  * 其它说明  :
****************************************************************************************************************/
void InitAppVar()
{
  unsigned int HexVarStartAddr = *(unsigned int*)0x8020000;//Load$$ER_IROM1$$Limit
  unsigned int HexVarEndAddr =   *(unsigned int*)0x8020004;//Load$$RW_IRAM1$$Limit
  unsigned char* pRamStartAddr = (unsigned char*)0x2000C000;
  memset(pRamStartAddr,0,10*1024); //默认App最多10K数据清零 
  memcpy(pRamStartAddr,(unsigned char*)HexVarStartAddr,(HexVarEndAddr-HexVarStartAddr));
}

Boot与App交互

不同于一般的Boot,App的代码和Boot代码有很大程度的复用的,这个复用就是Boot把自己的一些功能函数封装到一个函数结构体,也就是一个接口文件,Boot跳转到App时把这个函数结构体作为跳转函数的参数传递给App,App就可以通过这个结构体调用系统功能.

Boot区加载代码:

typedef struct _ActLib
{
    //步进
  void (*RunSM)(char sm_id,int nLen);
  //输入传感器,输出
  char (*IsSensorOn)(char SensorNum);
  
  void (*SetPrjName)(char* name);
}ActLib;


ActLib gLib;


PtrInitApp InitApp;
InitApp = (PtrInitApp)0x8020008;
InitApp(&gLib);  //加载业务app初始化入口

App入口代码

ActLib* l;
 void InitApp(ActLib* pLib)
{  
  l = pLib;
  l->SetPrjName("口罩设备项目");
  
  if(l->IsSensorOn(X101))
  {
    l->RunSM(SM101,200);
  }


}

上面简单介绍了工程分离及引导App的方法.

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分