基于飞思卡尔的Bootloader程序下载更新_第1页
基于飞思卡尔的Bootloader程序下载更新_第2页
基于飞思卡尔的Bootloader程序下载更新_第3页
基于飞思卡尔的Bootloader程序下载更新_第4页
基于飞思卡尔的Bootloader程序下载更新_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于飞思卡尔的Bootloader程序下载更新前言写这篇文档是因为大三暑假时在一家公司实习,做一个基于飞思卡尔的bootloader远程更新工程,刚开始定的技术指标是基于MC9S12XS128单片机的Bootloader程序、远程〔基于GSM网络〕和CAN总线通信。但因为我只是一个本科实习生而且实习时间只有一个多月,所以只完成了基于SCI的本地写入.S19文件的更新。这大概也就是这篇文档所包含的内容啦。整个程序是存在瑕疵甚至根本上可以说是不成功的,但是我觉得自己在做这个工程的过程中确实也解决了网上没有提到或者没有答案的一些问题,特写此文档,希望大家各取所需,如果有什么高见或者发现了我明显错误的地方,也非常欢送大家给我指出。欢送大家前来指教。小目录一、Bootloader的含义---------------------------------------------------------2二、SCI串口的使用------------------------------------------------------------3三、Flash的擦除和写入--------------------------------------------------------5四、.S19文件的写入-----------------------------------------------------------13五、心得体会-----------------------------------------------------------------14一、Bootloader的意义与作用关于Bootloader的意义网上非常之多,这里针对单片机的Bootloader程序进行说明。Bootloader是在单片机上电启动时执行的一小段程序。也称作固件,通过这段程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个适宜的状态,以便为最终调用应用程序准备好正确的环境。Boot代码由MCU启动时执行的指令组成。这里的loader指向MCU的Flash中写入新的应用程序。因此,Bootloader是依赖于特定的硬件而实现的,因此,在众多嵌入式产品中目前还不可能实现通用Bootloader。Bootloader的最大优点是:在不需要外部编程器的情况下,对嵌入式产品的应用代码进行更新升级。它使得通过局域网或者Intemet远程更新程序成为可能。例如,如果有5000个基于MCU的电能表应用程序需要更新,电能表制造商的技术人员就可以防止从事对每一个电能表重新编程的巨大工作量,通过使用Bootloader的功能,由控制中心通过电能表抄表系统网络,远程对5

000个电表重新编程。可见,Bootloader功能对于嵌入式系统的广泛应用具有十分重要的意义。再举一个例子。就拿我自己做这个程序的目的来说,我所在的公司将自己的产品卖到全国各地,如果哪一天公司的底层软件工程师〔单片机工程师〕想要升级底层软件,就可以借助GSM网络直接通过单片机中的Bootloader程序进行底层软件的自我更新,而不是派出售后人员一台一台的进行更新,节省了大量的人力物力。注意点:平时我们最常用到的下载程序的方法是通过USB数据线或其他数据线进行程序的烧写,这个方式是通过外界提供应单片机高电压来对flash擦除和写入完成的。而Bootloader不需要外界提供高电压仅靠正常工作电压便可完成对flash的擦除和写入,从而到达更新程序的目的。二、SCI串口的使用前面也提到,我做的是通过SCI串口的本地更新。SCI(SerialCommunicationInterface,串行通信接口)是最常用、最经典的串行通信接口方式。通信双方除了要按照约定的真个是进行数据通信外,还要约定相同的通信速率,在SCI通信中使用波特率来表示。串行通信的波特率被定义为每秒内传送的位数,单位为b/s或bps,常用的波特率有1200bps,4800bps,9600bps,19200bps,38400bps等。SCI的使用主要注意两点:波特率的设置和工作方式的选择,我选择的是中断工作方式。波特率:设置波特率的主要目的是使单片机和上位机〔上位机在这里就指将信息发给单片机的PC端〕保持同步。MC9S12XS128的波特率存放器是SCIBDH和SCIBDL,总共16位但是只有13位可以写入。SBR[12:0]:波特率常数,取值1~8191.波特率发生器的时钟输出是由MCU内部总线时钟BUSCLK分频而来,SBR[12:0]就是分频系数,而SCI模块需要的工作时钟为波特率的16倍。SCI的波特率计算公式如下:SCI=fBUS/(16*SBR[12:0])波特率的计算数结果些许误差可以忽略,以约等于常见通用的串行通信波特率数值。说了一大堆,到底如何设置不同的波特率呢,通过具体的程序代码来表达一下。#defineSCIBusClock8000000//MC9S12XS128的总线时钟是8MHz#defineSCI38400bps(unsignedint)((unsignedlong)(SCIBusClock)/(unsignedlong)(614400))//38400*1638400波特率#defineSCI19200bps(unsignedint)((unsignedlong)(SCIBusClock)/(unsignedlong)(307200))//19200*1619200波特率#defineSCI9600bps(unsignedint)((unsignedlong)(SCIBusClock)/(unsignedlong)(153600))//9600*169600波特率#defineSCI4800bps(unsignedint)((unsignedlong)(SCIBusClock)/(unsignedlong)(76800))//4800*164800波特率#defineSCIBaudRateSCI9600bps//大多数情况下用9600波特率中断工作方式:选择中断的工作方式,一有数据从SCI串口输出,单片机便立马进行接收处理。主要对SCI0CR1和SCI0CR2进行操作。SCI0CR2=0x2C;//00101100RIE=1,TE=1,RE=1//RIE=1接收数据存放器满和重叠中断请求使能//TE=1发送器使能//RE=1接收器使能具体的数据接收代码为://SCIReceiveN:串行接收N个字节数据------------------------------------------*byteSCIReceiveN(void){while(!SCI0SR1_RDRF);//如果SCI0SR1_RDRF为1那么表示数据起存器接收到的数据有效returnSCI0DRL;//返回接收到的值,即SCI数据存放器SCIDRL中的数据}温馨提醒:SCI程序到底对不对,有没有正常的工作,还是要通过上位机来观察。这就牵扯到用什么软件来作为单片机和上位机的接口。网上很多资料推荐一款很经典的软件“超级终端〞,但是我个人认为这款软件太“经典〞啦,太老啦,导致我一直不知道怎么用的。如果大家也遇到了这个问题,那么我向大家推荐“友善串口调试〞,完全的免费,而且界面简洁,使用简单,英文名为“SerialPortUtility〞。三、Flash的擦除和写入关于Flash的擦除和写入,真的是让我最费力的一局部,网上的相关资料很少,好不容易找到了一点相关代码,却发现程序不能正常的运行,而且更令人无解的是程序本身怎么检查都检查不出错误。好啦,一点一点的说说我的辛酸史。首先,如果你在寻找飞思卡尔的flash擦除写入操作,很遗憾的告诉你,如果你用的不是MC9S12XS系列,那么很有可能,你所需要的flash擦除写入操作和我接下来将要说明的擦除写入操作根本上不沾边〔除了原理上〕,因为飞思卡尔不同系列的单片机对flash的擦除写入操作的定义差异很大,不注意型号的话反而会被误导。至于擦除和写入的原理是什么,这个不是我们关心的,我也不去赘述,我主要说明一下相关的具体操作。我们主要是对飞思卡尔Flash中的PFlash即存放程序段的Flash进行操作。如图,步骤大概分为:1、设置Flash分频存放器:Flash的操作对频率有一定的要求,过低擦除不成功,过高会损毁Flash如图为MC9S12XS128的FCLKDIV存放器,所有位都是可读的但是只有7位可写入。至于应该如何设置分频数,有一张表格可以参考:如表格说明,分频数是根据外部时钟来定的,MC9S12XS128的外部时钟是16MHz,所以我选择了0x10作为分频数。给出一一些具体的代码:/*************************************************************名称:voidPFlash_Init(void)**功能:PFlash初始化**入口参数:无**出口参数:无**使用说明:无************************************************************/voidPFlash_Init(void){while(FSTAT_CCIF==0);//等待正在处理的Flash操作,即CCIF=1时,操作完成FCLKDIV=0x10;//外部晶振为16MHz,Flash时钟设置为1MHzFCNFG=0x00;//禁止中断while(FCLKDIV_FDIVLD==0);//等待时钟设置成功,即FDIVLD为1时设置成功}这里补充一下对FCLKDIV_FDIVLD的说明:说明很简单,一看就看懂。2、FSTAT状态存放器在上面的代码中出现了一行,这就涉及到一个很重要的存放器,就是Flash操作的状态存放器,就像是Flash操作步骤中的“红绿灯〞一样,告诉程序什么时候可以执行什么操作,什么时候必须要等待一下。如图:其中我们比拟关心的是CCIF位、ACCERR位和FPVIOL位,这三位也都是可读可写的。CCIF:指令完成标志位,当CCIF位为1时,表示上一个Flash操作完成了。注意图中的高亮局部,如果想要使当前操作的指令完成,需要手动将CCIF清零〔标志位置位就是令标志位为0,但具体操作是令标志位等于1〕,才能触发指令,令指令完成,也就是前面流程图中说明的,才能launch指令。ACCERR和FPVIOL:这两位主要标志是否有错误操作发生,当为1时,说明检测到错误。那检测到作物怎么办呢?解决方法也比拟奇葩,将两个标志位清零〔清零操作如上〕就行,,,,,至于什么原理,我也不太明白。数据手册如图,强烈建议还是自己读一下原文,很有好处。再给出一些具体的代码:CCIF的操作代码:FSTAT_CCIF=1;//启动执行命令,即launch指令while(FSTAT_CCIF==0);//等待执行完成ACCERR和FPVIOL的操作代码:if(FSTAT_ACCERR)//判断并去除标志位;FSTAT_ACCERR=1;//将标志位清零if(FSTAT_FPVIOL)//判断并去除标志位;FSTAT_FPVIOL=1;//将标志位清零注意点:说实话,当时我自己写程序的时候,就对标志位清零操作感到非常的疑惑,说好的清零操作呢,为什么是令标志位为等于1?后来才想明白,对于标志位,写0等效于没有操作,写1代表清零。原因主要有两点:标志位为1一般表示有什么事情发生啦,对于标志位什么时候为1,应该是单片机根据具体的情况作出自己的判断,是根据实际情况来置1的,而不应该是人为的置1。如果某次操作我们只想对状态存放器中的某一位或某几位进行操作,那么对其余位就必须没有任何的影响,如果规定写0时等效于无操作。3、执行具体的指令将分频和状态存放器弄好后,就可以开开心心的执行具体的指令啦。指令具体的指令主要涉及到FCCOBIX存放器和FCCOB存放器:FCCOBIX存放器和FCCOB存放器必须要配合使用。FCCOBIX进行选择,然后往FCCOB中写入具体的指令、地址和数据。Flash操作命令表如图:这里我们只关心P-Flash的擦除和写入操作。P-Flash的擦除操作:如图,;令CCOBIX为000,往FCCOB中写入0x0A和高地址位,对照指令表,0X0A表示擦除操作,高地址位就是Globaladdress模式下地址的高八位。然后令CCOBIX为001,往FCCOB写入Globaladdress模式下地址的第八位,就可以擦除你想要的擦除的地址片区。/*************************************************************名称:voidPFlash_Erase(wordADDR16)**功能:擦除P-FLASH的一个分区**入口参数:无**出口参数:无**使用说明:无************************************************************/voidPFlash_Erase(wordADDR16){while(FSTAT_CCIF==0);if(FSTAT_ACCERR)//判断并去除标志位;FSTAT_ACCERR=1;if(FSTAT_FPVIOL)//判断并去除标志位;FSTAT_FPVIOL=1;FCCOBIX_CCOBIX=0x00;FCCOB=0x0A7E;//写入擦除命令和高位地址,0A是指令,7E是高地址位FCCOBIX_CCOBIX=0x01;FCCOB=ADDR16;//写入低16位的地址FSTAT_CCIF=1;//启动执行命令while(FSTAT_CCIF==0);//等待执行完成}P-Flash的写入操作:写入操作和擦除操作是差不多的,模式是不是和擦除操作很像。CCOBIX为000和001时的含义和擦除操作是完全一样的。主要讲一下CCOBIX为010~101时的含义。因为MC9S12XS128规定Flash写入时,必须一次性写入8个字节,,,是的就是这么蛋疼。不多说啦,直接来一些具体的代码,就很好理解啦。/*************************************************************名称:voidPFlash_Write(uint16ADDR16)**功能:向PFLASH写入数据**入口参数:无**出口参数:无**使用说明:无************************************************************/voidPFlash_Write(wordADDR16){bytei,j;//i为Buffer的下标,j为string的下标for(i=0,j=0;i<4;i++,j++){Buffer[i]=0x0000;Buffer[i]=Buffer[i]|(string[j]<<8);j++;Buffer[i]=Buffer[i]|string[j];}while(FSTAT_CCIF==0);if(FSTAT_ACCERR)//判断并去除标志位;FSTAT_ACCERR=1;if(FSTAT_FPVIOL)//判断并去除标志位;FSTAT_FPVIOL=1;FCCOBIX_CCOBIX=0x00;FCCOB=0x067E;//写入命令和高位地址(06是对P-Flash进行固化的指令)FCCOBIX_CCOBIX=0x01;//地址后16位FCCOB=ADDR16;//写入低16位地址FCCOBIX_CCOBIX=0x02;//写入第一个数据FCCOB=Buffer[0];FCCOBIX_CCOBIX=0x03;//写入第二个数据FCCOB=Buffer[1];FCCOBIX_CCOBIX=0x04;//写入第三个数据FCCOB=Buffer[2];FCCOBIX_CCOBIX=0x05;//写入第四个数据FCCOB=Buffer[3];FSTAT_CCIF=1;//写入执行命令while(FSTAT_CCIF==0);//等待执行完毕}这段程序理解起来应该没有问题吧。4、最后一步:好啦,看到这里是不是想要自己写一个Flash操作代码尝试一下,然后你单步调制的时候会发现太好啦,终于擦除和写入啦,然后开始全速运行,咦,发现程序跑飞啦,不放弃,接着尝试,然后怎么检查都检查不出错误来,单步运行就是可以,全速运行就是不可以,反复屡次,你会感到抓狂,会感到。好啦好啦,不瞎扯啦,其实这个问题也困扰了我很久,因为我没有系统的学习过单片机,终于,在TI的论坛上,没错,你没有看错,一个飞思卡尔的问题最终在TI论坛上找到了解决方法〔吐槽一下,飞思卡尔真是奇葩,资料超少,软件也超贵,相关的论坛也超冷淡。相比来说,TI做的就很好,资料很多,软件免费而且好用,论坛也很火〕。其实原因是,Flash不能对本身就行操作,也就是说在Flash中的代码不能对Flash进行操作,必须转移到RAM中才可以。怎么解决这个问题呢,我自己用的是#pragma关键字,再配合上codewarrior的.prm文件,就可以啦,全速运行下没有问题。#pragmaCODE_SEGFLASH_RAM//在.prm文件中将FLASH_RAM定义在RAM区中//对flash进行操作的代码#pragmaCODE_SEGDEFAULF关于#pragma和.prm怎么用,又是另一个主题啦,在这里就不赘述。除此之外还有一个方法,就是利用RELOCATE_TO,至于RELOCATE_TO怎么用,也是另外一个话题,在这里给出一些资料,要用到的同学可以自己去看看。关于RELOCATE_TO的关键定义: Inthisexam

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论