14823|4

92

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

在RTOS上移植uIP TCP/IP协议栈[转自itspy的博客] [复制链接]

在RTOS上移植uIP TCP/IP协议栈

RT-Thread是国人(ffxz)写的一个实时性(RTOS)嵌入式操作系统。和著名的uCOS-II系统相似,但又很不一样!二者都是以抢占式任务调度的。但RT-Thread初次之外还可以以时间片轮转算法进行任务调度的。这在uCOS-II中是没有的,更具有特色的是RT-Thread采用的一种面向对象的编程思想。这是一种巧妙而有趣的编程方法,更接近于人类对事物的认知本性。

内核对象模型:

RT-Thread的内核对象模型是一种非常有趣的面向对象实现方式。由于C语言更为面向系统底层,操作系统核心通常都是采用C语言和汇编语言混合编写而成。C语言作为一门高级计算编程语言,一般被认为是一种面向过程的编程语言:程序员按照特定的方式把要处理事物的过程一级级分解成一个个子过程。

面向对象源于人类对世界的认知多偏向于类别模式,根据世界中不同物品的特性分门别类的组织在一起抽象并归纳,形成各个类别的自有属性。在计算机领域一般采用一门新的,具备面向对象特征的编程语言实现面向对象的设计,例如常见的编程语言C++,Java,Python等。那么RTThread既然有意引入对象系统,为什么不直接采用C++来实现? 这个需要从C++的实现说起,用过C++的开发人员都知道,C++的对象系统中会引入很多未知的东西,例如虚拟重载表,命名粉碎,模板展开等。对于一个需要精确控制的系统,这不是一个很好的方式,假于它人之手不如握入己手!面向对象有它非常优越的地方,取其精华(即面向对象思想,面向对象设计),也就是RT-Thread内核对象模型的来源。RT-Thread实时操作系统中包含一个小型的,非常紧凑的对象系统,这个对象系统完全采用C语言实现。在了解RT-Thread内部或采用RT-Thread编程时有必要先熟悉它,它是RT-Thread实现的基础。

到目前为止,RT-Thread还算是一个年轻的系统吧。但RT-Thread可以称得上优秀的,RT-Thread的团队也是一支优秀的团队。看看RT-Thread的简介吧:

RT-Thread的基本构架:

A.      实时内核

B.      虚拟文件系统

C.      轻型IP协议栈

D.     Shell系统

E.      图形界面(GUI)

 

出色的Shell系统:

RT-Thread的shell系统——FinSH,提供了一套供用户在命令行操作的接口,可以用于调试、查看系统信息。由于系统程序大多数采用C语言来编写,FinSH命令行的设计被设计成类似C语言表达式的风格:它能够解析执行大部分C语言的表达式,也能够使用类似于C语言的函数调用方式(或函数指针方式)访问系统中的函数及全局变量。

 

OK,先介绍到这了,关于RT-Thread,更多可以关注其官方网站: http://www.Rt-Thread.org

虽然官方的RT-Thread是和LwIP结合的,但考虑到移植一个LwIP,相比之下要消耗更多的RAM(>30K)和CODE(>80K),对于很多嵌入式MCU应用而言,是很残酷的。所以这次打算把uIP移植到RT-Thread,而且只用内核部分,这样估计10K以下(或者会更少)的RAM空间和20K左右的Code空间即可了。

软件平台:

RT-Thread + uIP1.0

硬件平台:

深蓝DevBoard(STM32F107RC)

首先要搭建RT-thread 平台。这个就用官方的就好了。移植的思路大体如下:

平台搭建成功之后,关键的以太网初始化代码:

/* Reset ETHERNET on AHB Bus */

  ETH_DeInit();

  /* Software reset */

  ETH_SoftwareReset();

  /* Wait for software reset */

  while(ETH_GetSoftwareResetStatus()==SET);

 

  /* ETHERNET Configuration ------------------------------------------------------*/

  /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */

  ETH_StructInit(&ETH_InitStructure);

  /* Fill ETH_InitStructure parametrs */

  /*------------------------   MAC   -----------------------------------*/

  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable  ; 

  //ETH_InitStructure.ETH_Speed = ETH_Speed_100M;                                     

  ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;             

  //ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;                                                                                  

  ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;                                                                                 

  ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;                                                                                                                                                                       

  ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;                                                                                                      

  ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable;     

  ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;                                                            

  ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;     

  ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;                       

  /* Configure ETHERNET */

  ETH_Init(&ETH_InitStructure, PHY_ADDRESS);

  /* Initialize Tx Descriptors list: Chain Mode */

  ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);

  /* Initialize Rx Descriptors list: Chain Mode  */

  ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

  /* Enable DMA Receive interrupt (need to enable in this case Normal interrupt) */

  ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);

  /* Enable MAC and DMA transmission and reception */

  ETH_Start();

 

然后在以太网中断服务程序中采用邮箱的机制,即建立一个邮箱,当有以太网数据来的时候,通知相应的收邮件线程:

     rt_mb_send(&eth_rx_thread_mb,0);

这样系统中再建立一个收邮件线程:

void eth_rx_thread_entry(void* pr)

{

    int i;

    struct eth_device* device;

    struct timer periodic_timer, arp_timer;

    while(1) {

      if (rt_mb_recv(&eth_rx_thread_mb, (rt_uint32_t*)&device, RT_WAITING_FOREVER) == RT_EOK)

      {

         uip_len = ETH_HandleRxPkt(uip_buf);

         if(uip_len > 0) {

      if(BUF->type == htons(UIP_ETHTYPE_IP)) { //IP包,缓冲地址为[12][13]=0x0800

       uip_arp_ipin();

       uip_input();

       /* If the above function invocation resulted in data that

          should be sent out on the network, the global variable

          uip_len is set to a value > 0. */

       if(uip_len > 0) {

         uip_arp_out();

         TransmitPacket();

       }

      } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {//ARP包

       uip_arp_arpin();

       /* If the above function invocation resulted in data that

          should be sent out on the network, the global variable

          uip_len is set to a value > 0. */

       if(uip_len > 0) {

         TransmitPacket();

       }

      }

 

    } else if(timer_expired(&periodic_timer)) {//5s

      timer_reset(&periodic_timer);

      for(i = 0; i < UIP_CONNS; i++) {

       uip_periodic(i);

       /* If the above function invocation resulted in data that

          should be sent out on the network, the global variable

          uip_len is set to a value > 0. */

       if(uip_len > 0) {

         uip_arp_out();

         TransmitPacket();

       }

      }

 

#if UIP_UDP

      for(i = 0; i < UIP_UDP_CONNS; i++) {

       uip_udp_periodic(i);

       /* If the above function invocation resulted in data that

          should be sent out on the network, the global variable

          uip_len is set to a value > 0. */

       if(uip_len > 0) {

         uip_arp_out();

         TransmitPacket();

       }

      }

#endif /* UIP_UDP */

     

      /* Call the ARP timer function every 10 seconds. */

      if(timer_expired(&arp_timer)) {

       timer_reset(&arp_timer);

       uip_arp_timer();

      }

    }

      }

  }

}

然后在添加uIP系统应用程序 telnet ,编译成功之后,系统跑起来的结果:

工程包源码:

(654.86 K) 该附件被下载次数 9

最新回复

感觉RTT不如FREERTOS;不过两者相差不多;我更倾向后者;   详情 回复 发表于 2022-10-11 13:25
点赞 关注

回复
举报

32

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
木有附件
 
 

回复

16

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
额,是不是在rt_thread中移植很简单哪?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 

没有附件

 
 
 

回复

87

帖子

0

TA的资源

一粒金砂(中级)

5
 

感觉RTT不如FREERTOS;不过两者相差不多;我更倾向后者;

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表