×

μC/OS-Ⅱ嵌入式以太网通信的设计解析

消耗积分:1 | 格式:rar | 大小:0.3 MB | 2017-10-23

分享资料个

 uC/OS-Ⅱ是一个源码开放的抢占式实时操作系统。它内核短小精悍、可裁减、执行时间确定。系统大部分代码采用C语言编写,与硬件有关的部分都集中在两个文件中,给出了规范的接口说明,移植相当方便,可应用于目前大多数型号的8位、16位、32位CPU。
  uC/OS-Ⅱ提供的仅仅只是一个实时的调度及任务间通信的内核,没有集成网络协议。上网是当前嵌入式设备的广泛需求,本文讨论轻型TCP/IP协议栈的引入以及相关网络设备驱动程序,实现嵌入式系统的网络功能。
  本文所用的硬件系统结构如图1所示。开发板基于TMS320LF2407A的含DSP核微处理器和LAN91C111以太网控制器。在成功移植了μCOS-Ⅱ的基础上进一步实现了以太网通讯功能。下面重点介绍TCP/IP协议栈的引入和LAN91C111驱动的编写。
  μC/OS-Ⅱ嵌入式以太网通信的设计解析
  图1 嵌入式以太网硬件系统结构图
  TCP/IP网络协议栈的引入
  在μCOS-Ⅱ上引入下TCP/IP协议栈,由于嵌入式系统的硬件资源有限,必须使用小型协议栈。这种协议栈很多,LwIP是其中之一。
  关于LwIP简介
  LwIP是瑞士计算机科学院(SCICS)的Adam Dunkels等开发的一套用于嵌入式系统的开放源码的轻型TCP/IP协议栈,但Lwip实现了较为完备的IP,ICMP, UDP, TCP协议,具有超时时间估计、快速恢复和重发、窗口调整等功能。IwIP在保持协议主要功能的基础上减少对RAM和ROM的占用,一般它只需要几十K的RAM和40K左右的ROM就可以运行,很适合同μCOS-Ⅱ相配合用在嵌入式系统中。LwIP在设计时就考虑到了将来的移植问题,它把所有与硬件、操作系统、编译器相关的部分独立出来,放在/src/arch目录下,因此LwIP在μCOS-Ⅱ上的实现就是修改这个目录下的文件,其它的文件一般不需要修改。下面分别予以说明:
  协议栈的实现
  ·与CPU及编译器相关的include文件 /src/arch/include/arch目录下cc.h、cpu.h、perf.h中有一些与CPU或编译器相关的定义,如数据长度,字的高低位顺序等。这应该与用户实现μCOS-Ⅱ时定义的数据长度等参数一致。
  ·与操作系统相关部分 sys_arch.c中的内容是与操作系统相关的一些结构和函数,主要分四个部分: (1)sys_sem_t信号量LwIP中需用信号量通信,所以在sys_arch中应实现信号量结构体和处理函数:struct sys_sem_t{ sys_sem_new( )/创建一个信号量结构 sys_sem_free()/释放一个信号量结构sys_sem_signal( )/发送信号量 sys_arch_sem_wait( )/请求信号量}由于μCOS-Ⅱ已经实现了信号量OS_EVENT的各种操作,并且功能和LwlP上面几个函数的目的功能是完全一样的,所以只要把μCOS-Ⅱ的函数重新包装成上面的函数,就可以直接使用了。
  (2 )sys_mbox_t消息
  LwIP使用消息队列来缓冲、传递数据报文,因此要在sys_arch中实现消息队列结构sys_mbox_t,以及相应的操作函数。
  sys_mbox_new()/创建一个消息队列 sys_mbox_free( ) /释放一个消息队列
  sys_mbox_post( )/向消息队列发送消息
  sys_arch_mbox_fetch( )/从消息队列中获取消息
  μCOS-Ⅱ同样实现了消息队列结构及其操作,但是μCOS-Ⅱ没有对消息队列中的消息进行管理,因此不能直接使用,必须在μCOS-Ⅱ的基础上重新实现。
  (3)sys_arch_timeout函数
  LwIP中每个与外界网络连接的线程都有自己的timeout属性,即等待超时时间。这个属性表现为每个线程都对应一个sys_timeout结构体队列,包括这个线程的timeout时间长度
  ,以及超时后应调用的timeout函数,该函数会做一些释放连接,回收资源的工作.timeout结构体已经由LwIP自己在sys.h中定义好了,而且对结构体队列的数据操作也由LwIP负责,我们所要实现的是如下函数:
  struct sys_timeouts*sys_arch_timeouts(void)
  这个函数的功能是返回目前正处于运行态的线程所对应的timeout队列指针。timeout队列属于线程的属性,它是OS相关的函数,只能由用户实现。
  (4)sys_thread_new创建新线程
  LwIP可以是单线程运行,也可以多线程运行。为提高效率并降低编程复杂度,就需要用户实现创建新线程的函数:
  void sys_thread_new(void(*thread)(void*arg), void*arg);
  在μCOS-Ⅱ中,没有线程(thread)的概念,只有任务(Task)。它已经提供了创建新任务的系统API调用OSTaskCreate,因此只要把OSTaskCreate封装一下,就可以实现sys_hread_new.
  ·lib_ arch中库函数的实现
  LwIP协议栈中用到了8个外部函数,这些函数通常与用户使用的系统或编译器有关,因此留给用户自己实现,有关程序如下:
  u16_t htons(u16_t n); /16位数据高低字节交换
  u16_t ntohs(u16_t n);
  int strlen(const char * str);/返回字符串长度
  int strncmp(const char * strl,const char * str2,int len);/字符串比较
  void bcopy(const void * src, void * dest, int len);/内存数据块之间的互相拷贝
  void bzero(void *data, int n); /内存中指定长度的数据块清零
  类似于操作系统在硬件上的移植,LwIP的移植也是根据实现的硬件以及操作系统对象,对相应的文件进行修改。整个通讯协议的引入可以很快实现。
  LAN91C111驱动的实现
  在上面为μCOS-Ⅱ引入了TCP/IP协议栈之后,为了实现以太网通信功能还必须完成相关网络设备驱动程序的添加。LwIP的网络驱动有一定的模板,其中src/netif/ethernetif.c文件即为驱动的模板,用户为自己的网络设备实现驱动时应参照这个模板,根据相应的网络芯片来实现。本系统选用的网络芯片是由SMSC公司生产的自适应10M/100M第三代快速以太网控制器芯片LAN91C111,集成了SMSC/CD协议的MAC(媒体层)和PHY(物理层)。由于其灵活性和集成度高,具有较高的性价比。
  LAN91C111工作流程比较简单,驱动程序将要发送的数据包按指定格式写入芯片并启动发送命令,LAN91C111会自动把数据包转换成物理帧格式在物理信道上传输;反之芯片收到物理信号后自动将其还原成数据,并按指定格式存放在芯片RAM中以便主机程序取用。简言之就是LAN91C111完成数据包和电信号之间的相
  互转换: 数据包 电信号。LAN91C111的编程主要包括:初始化、发送数据包、接收数据包三部分。

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

评论(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.obk20.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:'μC/OS-Ⅱ嵌入式以太网通信的设计解析',//标题 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.obk20.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);