×

基于TFTP协议实现STM32的IAP资料下载

消耗积分:3 | 格式:pdf | 大小:198.7KB | 2021-04-15

laisvl

分享资料个

0引言随着嵌入式技术以及32位嵌入式微处理器的发展,嵌入式系统的应用日益广泛,嵌入式产品与人们的生产、生活结合得越来越紧密。然而,嵌入式系统的设计不可能一步到位,尤其是嵌入式软件,需要不断修改和完善。当程序出错或用户需求变更时,传统的方法是安排技术人员到现场或将设备回收对控制器芯片重新编程。这种方式费时费力,效率低下[1]。采用IAP(In-Application Programming)技术则可以免除拆卸设备、烧录MCU(Microcontroller Unit)等繁琐的过程。IAP即“在应用中编程”,是指产品发布后在运行过程中通过预留的通信接口(如USART、I2C、CAN、USB、以太网接口等)对微控制器MCU中的软件进行更新升级。支持IAP技术的首要前提是微控制器必须基于可重复编程的闪存。STM32微控制器带有可编程的内置闪存,拥有在数量上和种类上都非常丰富的外设通信接口,因此在STM32上实现IAP技术是完全可行的[2]。本文针对STM32F407型号的微控制器,基于TFTP(Trivial File Transfer Protocol)协议通过网口实现IAP,可以大大节省维护升级成本, 更方便快捷[3]。1IAP工作原理在实现IAP功能时,MCU内部需要有两块存储区,BOOT区和常态存储区。MCU上电先运行BOOT区代码,检测是否需要更新软件,如果不需要更新,程序指针跳到常态存储区,开始执行放在常态存储区的内容;如果需要更新,则先通过外设通信接口接收新的程序代码,对常态存储区的内容进行改写,然后再跳转执行新写入的程序[4]。相应的,软件程序代码也分为两部分:存放在BOOT区的BootLoader程序和存放在常态存储区的APP程序。BootLoader程序负责通过某种通信方式(如USB、USART等)接收程序或数据,执行对APP程序的更新。 APP程序才是真正的功能代码,完成嵌入式系统需要的各种业务功能。 BootLoader程序必须通过JTAG(Joint Test Action Group)编程方式或ISP(InSystem Programming)方式烧入��APP程序可以和BootLoader程序一起烧入,也可以通过BootLoader程序的IAP功能烧入。2系统硬件设计系统硬件电路主要介绍以太网接口电路的设计。 STM32F407自带MAC控制器,只需外接PHY芯片就可以完成以太网通信。PHY芯片选用LAN8720A,内置10BASET/100BASETX全双工传输模块,支持10 Mb/s和100 Mb/s数据传输。STM32F407采用RMII接口与LAN8720A连接, RMII减少了10/100 Mb/s下微控制器以太网外设与外部PHY间的引脚数,仅需10根线连接即可[4]。RMII和PHY共用的参考时钟必须是50 MHz,且必须由外部提供,如有源晶振或STM32F4的MCO输出。这里,LAN8720A外接25 MHz石英晶振,通过内部倍频到50 MHz,给STM32F407的RMII提供50 MHz参考时钟,输出参考时钟给MAC控制器,这样可以降低BOM(Bill of Material)成本[5]。3系统软件设计本系统中PHY层芯片LAN8720A相当于物理层,STM32F407自带的MAC层相当于数据链路层,而移植的LWIP提供的就是网络层、传输层的功能,应用层需要用户根据具体功能去实现,即BootLoader和APP程序。STM32F407的内部闪存地址起始于0x8000000,一般情况下, BootLoader代码就从该地址开始存放,APP程序存放在Flash中剩余的空间,并且偏移量为0x200的倍数。3.1BootLoader程序BootLoader程序主要完成系统初始化、TFTP数据通信、更新Flash存储区内容和执行程序的跳转等功能[6]。其工作流程如图1所示。系统初始化主要完成外部总线控制器的初始化、堆栈的初始化、定时器配置和LAN8720A网卡芯片的初始化、LWIP内核初始化等操作。之后,通过监测外部按键,判断是否进入IAP模式进行升级,若超时,则跳转到常态存储区,执行原来的APP程序[78]。升级过程中文件的传送采用TFTP协议。TFTP是一个工作在UDP顶层的简单文件传输协议,基于C/S结构。一个TFTP客户端向TFTP服务器发起一个文件传输请求,服务器响应请求,文件传输开始。数据以固定尺寸(本系统采用512 B)的帧进行传输。在下一个数据帧传输前,接收方必须对刚刚收到的数据帧进行回应。如果接收到的数据帧大小小于指定的数据帧大小,说明当前传输的数据帧是最后一个数据帧,传输结束。这里PC机作为客户端,嵌入式平台实现TFTP服务器,TFTP服务器响应PC TFTP客户端发送的写文件请求。由于TFTP基于不可靠的UDP协议, 因此,在程序中添加能够保证数据有效传输的机制来及时处理数据丢失的情况。在接收到每个以太网数据帧后进行CRC校验,如果有错误则通知客户端重新发送该数据帧, 这样能有效提高程序更新的可靠性。3.2APP程序APP程序的生成需注意以下几点:(1)起始地址和存储空间大小设置;(2)中断向量表偏移量设置;(3)生成.bin文件,用于IAP更新。MDK开发工具默认生成的文件是.hex,但利用IAP写入的程序文件不能是.hex格式,可利用MDK自带的格式转换工具fromelf.exe转换成.bin文件。3.3系统软件设计需注意的问题系统在软件设计中需注意以下几点:(1)存储空间的分配。Boot区和常态存储区的大小可以根据应用的具体情况人为分配,但分配时尽可能使常态存储区最大化,为以后程序的升级留出余量。(2)BootLoader代码设计时应尽量简洁,避免使用中断、复杂的底层驱动及算法。(3)BootLoader代码在使用外设后,启动APP代码之前一定要先初始化该外设,即要让APP代码认为MCU只是刚上电运行,而不是跑完一个系统再调用自己。如果BootLoader代码没有执行该动作,当APP代码运行时,MCU的外设处于不确定状态(尤其是中断未关闭),可能会带来一些预料不到的错误。(4)数据通信过程中, 向STM32发送程序文件时需考虑STM32对Flash的写入速度,保证每次传送的数据包都能正确写入。(5)传输过程中,升级文件分段传送,可能存在数据丢失、网络不稳定等现象。对每段数据编号,根据编号判断是否有数据包丢失,并增加CRC校验,保证每段数据传输的正确性。对于错误或丢失的数据包,采取重传机制,提高IAP的成功率[9]。4结论本文对基于TFTP协议的STM32软件更新进行了研究,充分利用以太网的传输能力和便捷性,设计并实现了IAP升级系统。通过实验测试,基于TFTP 协议的STM32软件远程升级系统能够保证数据的正确传输和存储,大大降低了对嵌入式系统软件的升级维护难度,应用广泛。参考文献[1] 温世坚,张伟波.基于STM32的远程升级系统的设计[J].科技广场,2013,26(5):97100.[2] 李兴鹤,蔡亮,宋吉波,等.STM32用户基于IAP的程序更新技术[J].单片机与嵌入式系统应用, 2012,12(1):7475.[3] 王程,周安琳.基于Autofac对乳制品安全风险预警系统的扩展设计[J]. 河北省科学院学报,2013,30(1):14,14.[4] 李婉婉,李宏.单片机IAP升级方法在血液分析仪中的应用[J]. 微型机与应用,2014,33(21):1618.[5] 王娜,成彬,郝友帅.水流量远程智能监测系统的设计与实现[J]. 河北省科学院学报,2011,28(2):3439.[6] 武辉林.模数转换器AD7791及其应用格式[J].河北省科学院学报, 2011,28(2):2629.[7] 李俊,王金海.基于TFTP协议的ARM软件远程更新系统[J].工矿自动化,2010,37(7):2225.[8] 游侃民.嵌入式系统网络化BOOTLOADER的设计与实现[D].广州:华南理工大学,2010.[9] 许青青.一种轻量级Bootloader(LWBL)的设计与实现[D].上海:华东师范大学,2012.(mbbeetchina)

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

评论(0)
发评论

下载排行榜

全部0条评论

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

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'基于TFTP协议实现STM32的IAP资料下载',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);