首页资源分类嵌入式系统其他 > uip协议栈在stm32上移植

uip协议栈在stm32上移植

已有 445134个资源

下载专区

上传者其他资源

嵌入式系统热门资源

本周本月全部

文档信息举报收藏

标    签:UIP移植STM32

分    享:

文档简介

 uip stm32  ucos

文档预览

w 页码,1/6(W) AboutLinksInviteRss Home/ArchiveTripShareE-FactoryFindparkQuickweiboMr.YongLan here is siri ..  提交查询内容  逢人且说三分话,不可全拋一片心。 Uip + Stm32移植问题总结 作者:Changing发表时间:07-2621:37分类:电子相关4Comments 前一篇:stm32SPI通信[操作寄存器+库函数] 后一篇:UipWebClient实现 uIP由瑞典计算机科学学院(网络嵌入式系统小组)的AdamDunkels(http://dunkels.com/adam/uip/)开发。其源代码由C语言编写,并完全公开,有了这个TCP/IP协议栈,让嵌入式可以 实现的功能更为丰富。可以作为WebClient向指定网站提交数据,可以作为WebServer作为网页服务器,提供一个小型的动态页面访问功能。由于是开源的免费协议栈,据说Uip没有考虑协 议安全的问题。  首先介绍下移植的环境:stm32+ENC28J60网络模块    Enc28j60是带SPI接口的独立以太网控制器,可以用mcu控制spi来实现tcp/ip数据流的收发,所以要先完成Enc28j60的驱动程序,再整合Uip。Uip是用标准的C语言实现,所以移植Uip在51 单片机和stm32上类似。  经过几天的琢磨,已经将Uip的几个示例稳定运行。Uip中apps下的例子相互之间存在冲突,源程序中也有一些Error要修改,我将Uip的文件结构做了一些调整。  Uip文件结构  先介绍下Uip下各个目录文件的功能:  ├─appsapps目录下为uip提供的一些应用示例 │ ├─dhcpc │ ├─hello-world │ ├─resolv │ ├─smtp │ ├─telnetd │ ├─webclient │ └─webserver │ └─httpd-fs ├─docdoc下放置的为说明文档,程序中用不上 │ └─html ├─liblib下为内存块管理函数源码 ├─uipuip下为uip和核心实现源码 └─unixunix环境里的uip应用例子,可以参照这个例子实现应用  Uip+stm32 MDK下工程建立  QQ截图 20120726204704  stm32的目录结构建立可以参考stm32开发环境MDK+库文件配置  User放置stm32SPI配置以及Uip配置和Enc28j60和Uip的接口函数     uip下为uip的核心实现源码以及内存管理源码(即为Uip/uip+Uip/lib) dev下为Enc28j60的驱动函数源码 apps为uip的各个示例应用源码(Uip/apps下的文件)包括smtp,rsolve,dhcp,telnetd,以及webclient  webserver的文件结构较为复杂,独立一个文件夹   Uip移植  Uip的移植可以参考uip的unix的文件结构。  1.Uip的数据通过网卡Enc28j60从物理层剥离,所以需要先配置Uip和Enc28j60的数据交互。这个部分在tapdev.c文件中: 01 #include "uip.h" http://www.ichanging.org/uip-stm32.html 2013/7/16 w 页码,2/6(W) 02 #include "ENC28J60.h" 03 04 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 05 void 06 tapdev_init(unsigned char *my_mac) 07 { 08 enc28j60Init(my_mac); 09 } 10 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 11 unsigned int 12 tapdev_read(void) 13 { 14 return enc28j60PacketReceive(UIP_CONF_BUFFER_SIZE,uip_buf); 15 } 16 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 17 void 18 tapdev_send(void) 19 { 20 enc28j60PacketSend(uip_len,uip_buf); 21 } 22 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 写网卡驱动程序,与具体硬件相关。这一步比较费点时间,不过好在大部分网卡芯片的驱动程序都有代码借鉴或移植。驱动需要提供三个函数,以Enc28j60驱动为例。 tapdev_init():网卡初始化函数,初始化网卡的工作模式。 tapdev_read(void):读包函数。将网卡收到的数据放入全局缓存区uip_buf中,返回包的长度,赋给uip_len。 voidtapdev_send(void):发包函数。将全局缓存区uip_buf里的数据(长度放在uip_len中)发送出去。  2.由于uIP协议栈需要使用时钟,为TCP和ARP的定时器服务。因此使用单片机的定时器或是stm32的滴答定时器用作时钟,每20ms让计数tick_cnt加1,这样,25次计数(0.5S)满了后 可以调用TCP的定时处理程序。10S后可以调用ARP老化程序。uIP1.0版本,增加了timer.c/timer.h,专门用来管理时钟,修改clock-arch.c如下: 01 #include "clock‐arch.h" 02 #include "stm32f10x.h" 03 04 extern __IO int32_t g_RunTime; 05 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 06 clock_time_t 07 clock_time(void) 08 { 09 return g_RunTime; 10 } 11 /*‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/ 使用stm32滴答定时器中断代码:  User/stm32f10x_it.c 01 __IO int32_t g_RunTime = 0; 02 void SysTick_Handler(void) 03 { 04 static uint8_t s_count = 0; 05 if (++s_count >= 10) 06 { 07 s_count = 0; 08 09 g_RunTime++; /* 全局运行时间每10ms增1 */ 10 if (g_RunTime == 0x80000000) 11 { 12 g_RunTime = 0; 13 } 14 } 15 } 3.uipopt.h/uip-conf.h是配置文件,用来设置本地的IP地址、网关地址、MAC地址、全局缓冲区的大小、支持的最大连接数、侦听数、ARP表大小等。可以根据需要配置。  #defineUIP_FIXEDADDR1 决定uIP是否使用一个固定的IP地址。 如果uIP使用一个固定的IP地址,应该置位(set)这些uipopt.h中的选项。如果不的话,则应该使用宏uip_sethostaddr(),uip_setdraddr()和uip_setnetmask()。  #defineUIP_PINGADDRCONF0PingIP地址赋值。 #defineUIP_FIXEDETHADDR0指明uIPARP模块是否在编译时使用一个固定的以太网MAC地址。 #defineUIP_TTL255uIP发送的IPpackets的IPTTL(timetolive)。 #defineUIP_REASSEMBLY0uIP支持IPpackets的分片和重组。 #defineUIP_REASS_MAXAGE40一个IPfragment在被丢弃之前可以在重组缓冲区中存在的最大时间。 #defineUIP_UDP0是否编译UDP的开关。 #defineUIP_ACTIVE_OPEN1决定是否支持uIP打开一个连接。 #defineUIP_CONNS10同时可以打开的TCP连接的最大数目。由于TCP连接是静态分配的,减小这个数目将占用更少的RAM。每一个TCP连接需要大约30字节的内存。 #defineUIP_LISTENPORTS10同时监听的TCP端口的最大数目。每一个TCP监听端口需要2个字节的内存。 #defineUIP_RECEIVE_WINDOW32768建议的接收窗口的大小。如果应用程序处理到来的数据比较慢,那么应该设置的小一点(即,相对与uip_buf缓冲区的大小来说),相反如果应用 程序处理数据很快,可以设置的大一点(32768字节)。 #defineUIP_URGDATA1决定是否支持TCPurgentdatanotification。 #defineUIP_RTO3Theinitialretransmissiontimeoutcountedintimerpulses.不要改变 #defineUIP_MAXRTX8在中止连接之前,应该重发一个段的最大次数。不要改变 #defineUIP_TCP_MSS(UIP_BUFSIZE–UIP_LLH_LEN–40)TCP段的最大长度。它不能大于UIP_BUFSIZE–UIP_LLH_LEN–40. #defineUIP_TIME_WAIT_TIMEOUT120一个连接应该在TIME_WAIT状态等待多长。不要改变 #defineUIP_ARPTAB_SIZE8ARP表的大小。如果本地网络中有许多到这个uIP节点的连接,那么这个选项应该设置为一个比较大的值。 #defineUIP_BUFSIZE1500uIPpacket缓冲区不能小于60字节,但也不必大于1500字节。 #defineUIP_STATISTICS1决定是否支持统计数字。统计数字对调试很有帮助,并展示给用户。 #defineUIP_LOGGING0输出uIP登陆信息。 #defineUIP_LLH_LEN14链接层头部长度。对于SLIP,应该设置成0。  uip-conf.h中增加几个主要结构体定义,不include任何应用  01 #define UIP_CONF_LOGGING 0 02 03 typedef int uip_tcp_appstate_t; 04 typedef int uip_udp_appstate_t; 05 06 /*#include "smtp.h"*/ 07 /*#include "hello‐world.h"*/ 08 /*#include "telnetd.h"*/ 09 /*#include "webserver.h"*/ 10 /*#include "dhcpc.h"*/ //logging off //出错可注释 //出错可注释 http://www.ichanging.org/uip-stm32.html 2013/7/16 w 页码,3/6(W) 11 /*#include "resolv.h"*/ 12 /*#include "webclient.h"*/ 13 14 #include "app_call.h" //加入一个Uip的数据接口文件 uIP在接受到底层传来的数据包后,调用UIP_APPCALL(),将数据送到上层应用程序处理。 User/app_call.c 01 #include "stm32f10x.h" 02 03 #ifndef UIP_APPCALL 04 #define UIP_APPCALL 05 #endif 06 07 #ifndef UIP_UDP_APPCALL 08 #define UIP_UDP_APPCALL 09 #endif 10 11 void Uip_Appcall(void); 12 void Udp_Appcall(void); 13 14 15 void Uip_Appcall(void) 16 { 17 18 } 19 20 void Udp_Appcall(void) 21 { 22 23 } Uip_Appcall Udp_Appcall  4.加入uIP的的主循环代码架构 User/main.c 001 #include "stm32f10x.h" 002 #include "stdio.h" 003 #include "string.h" 004 005 #include "uip.h" 006 #include "uip_arp.h" 007 #include "tapdev.h" 008 #include "timer.h" 009 #include "ENC28J60.h" 010 #include "SPI.h" 011 012 #define PRINTF_ON 1 013 014 #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) 015 016 #ifndef NULL 017 #define NULL (void *)0 018 #endif /* NULL */ 019 020 static unsigned char mymac[6] = {0x04,0x02,0x35,0x00,0x00,0x01}; 021 022 void RCC_Configuration(void); 023 void GPIO_Configuration(void); 024 void USART_Configuration(void); 025 026 int main(void) 027 { 028 int i; 029 uip_ipaddr_t ipaddr; 030 struct timer periodic_timer, arp_timer; 031 032 RCC_Configuration(); 033 GPIO_Configuration(); 034 USART_Configuration(); 035 SPInet_Init(); 036 037 timer_set(&periodic_timer, CLOCK_SECOND / 2); 038 timer_set(&arp_timer, CLOCK_SECOND * 10); 039 040 SysTick_Config(72000); //配置滴答计时器 041 042 //以太网控制器驱动初始化 043 tapdev_init(mymac); 044 045 //Uip 协议栈初始化 046 uip_init(); 047 048 uip_ipaddr(ipaddr, 192, 168, 1, 15); //配置Ip 049 uip_sethostaddr(ipaddr); 050 uip_ipaddr(ipaddr, 192, 168, 1, 1); //配置网关 051 uip_setdraddr(ipaddr); 052 uip_ipaddr(ipaddr, 255, 255, 255, 0); //配置子网掩码 053 uip_setnetmask(ipaddr); 054 055 while(1){ 056 057 uip_len = tapdev_read(); //从网卡读取数据 058 059 if(uip_len > 0) 060 { //如果数据存在则按协议处理 061 if(BUF‐>type == htons(UIP_ETHTYPE_IP)) { //如果收到的是IP数据,调用uip_input()处理 062 063 uip_arp_ipin(); 064 uip_input(); 065 066 /* If the above function invocation resulted in data that 067 should be sent out on the network, the global variable uip_len is set to a value > 0. */ 068 069 if(uip_len > 0) 070 { 071 uip_arp_out(); 072 tapdev_send(); 073 } 074 075 }else if(BUF‐>type == htons(UIP_ETHTYPE_ARP)){ //如果收到的是ARP数据,调用uip_arp_arpin处理 076 http://www.ichanging.org/uip-stm32.html 2013/7/16 w 页码,4/6(W) 077 uip_arp_arpin(); 078 079 /* If the above function invocation resulted in data that 080 should be sent out on the network, the global variable uip_len is set to a value > 0. */ 081 082 if(uip_len > 0) 083 { 084 tapdev_send(); 085 } 086 } 087 088 }else if(timer_expired(&periodic_timer)){ //查看0.5s是否到了,调用uip_periodic处理TCP超时程序 089 090 timer_reset(&periodic_timer); 091 for(i = 0; i < UIP_CONNS; i++) { 092 093 uip_periodic(i); 094 095 /* If the above function invocation resulted in data that 096 should be sent out on the network, the global variable uip_len is set to a value > 0. */ 097 098 if(uip_len > 0) 099 { 100 uip_arp_out(); 101 tapdev_send(); 102 } 103 } 104 105 for(i = 0; i < UIP_UDP_CONNS; i++) 106 { 107 108 uip_udp_periodic(i); //处理udp超时程序 109 110 /* If the above function invocation resulted in data that 111 should be sent out on the network, the global variable uip_len is set to a value > 0. */ 112 113 if(uip_len > 0) 114 { 115 uip_arp_out(); 116 tapdev_send(); 117 } 118 } 119 120 /* Call the ARP timer function every 10 seconds. */ //10s到了就处理ARP 121 if(timer_expired(&arp_timer)) 122 { 123 timer_reset(&arp_timer); 124 uip_arp_timer(); 125 } 126 } 127 } 128 129 } 130 /*******************************Stm32 Set***************************************/ 131 132 void GPIO_Configuration(void) 133 { 134 GPIO_InitTypeDef GPIO_InitStructur e; 135 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 136 137 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 138 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 139 GPIO_Init(GPIOA , &GPIO_InitStructure); 140 141 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 142 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 143 GPIO_Init(GPIOA , &GPIO_InitStructure); 144 } 145 146 void RCC_Configuration(void) 147 { 148 /* 定义枚举类型变量 HSEStartUpStatus */ 149 ErrorStatus HSEStartUpStatus; 150 151 /* 复位系统时钟设置*/ 152 RCC_DeInit(); 153 /* 开启HSE*/ 154 RCC_HSEConfig(RCC_HSE_ON); 155 /* 等待HSE起振并稳定*/ 156 HSEStartUpStatus = RCC_WaitForHSEStartUp(); 157 /* 判断HSE起是否振成功,是则进入if()内部 */ 158 if(HSEStartUpStatus == SUCCESS) 159 { 160 /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */ 161 RCC_HCLKConfig(RCC_SYSCLK_Div1); 162 /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */ 163 RCC_PCLK2Config(RCC_HCLK_Div1); 164 /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */ 165 RCC_PCLK1Config(RCC_HCLK_Div2); 166 /* 设置FLASH延时周期数为2 */ 167 FLASH_SetLatency(FLASH_Latency_2); 168 /* 使能FLASH预取缓存 */ 169 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 170 /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */ 171 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 172 /* 使能PLL */ 173 RCC_PLLCmd(ENABLE); 174 /* 等待PLL输出稳定 */ 175 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); 176 /* 选择SYSCLK时钟源为PLL */ 177 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 178 /* 等待PLL成为SYSCLK时钟源 */ 179 while(RCC_GetSYSCLKSource() != 0x08); 180 } 181 /* 打开APB2总线上的GPIOA时钟*/ 182 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE); 183 184 } 185 186 187 void USART_Configuration(void) 188 { 189 USART_InitTypeDef USART_InitStructure; 190 USART_ClockInitTypeDef USART_ClockInitStructure; 191 http://www.ichanging.org/uip-stm32.html 2013/7/16 w 页码,5/6(W) 192 USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; 193 USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; 194 USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edg e; 195 USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; 196 USART_ClockInit(USART1 , &USART_ClockInitStructure); 197 198 USART_InitStructure.USART_BaudRate = 9600; 199 USART_InitStructure.USART_WordLength = USART_WordLength_8b; 200 USART_InitStructure.USART_StopBits = USART_StopBits_1; 201 USART_InitStructure.USART_Parity = USART_Parity_No; 202 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 203 USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; 204 USART_Init(USART1,&USART_InitStructure); 205 206 USART_Cmd(USART1,ENABLE); 207 } 208 209 #if PRINTF_ON 210 211 int fputc(int ch,FILE *f) 212 { 213 USART_SendData(USART1,(u8) ch); 214 while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET); 215 return ch; 216 } 217 218 #endif  5.解决编译过程中的错误。归总如下: Uip/uip-split.c注释所有的tcpip_output()函数消除uip_fw_output()函数的注释 Uip/memb.c中memb_free()函数返回值return-1改为return1 Apps/resolv.c中resolv_conf()中 //resolv_conn=uip_udp_new(dnsserver,HTONS(53)); resolv_conn=uip_udp_new((uip_ipaddr_t*)dnsserver,HTONS(53));  解决完所有问题后,编译成功后下载到stm32,ping测试。。  QQ截图 20120726201101    相关文章 stm32DA数模转换 stm32驱动触摸屏 stm32Fatfs读写SD卡 stm32最小系统 UipWebServer实现 转播到腾讯微博Tags:stm32,Uip,TCP/IP协议栈,嵌入式联网 前一篇:stm32SPI通信[操作寄存器+库函数] 后一篇:UipWebClient实现 Comments [4] Rming 在07-2915:02说:  很强大来学习了 写的比较匆忙讲了下大致的问题Uip的确很强大有问题话可以留言探讨下 h hoyo 在12-2220:51说:  你好,最近在学习这个UIP和STM32,不知可不可以把你上面的整个工厂文件打包发给我呢,谢谢! hou.wenbin@163.com Uip我只是做了下尝试如何移植我大概都写在博文里了你照着做如果不行在留言吧 P POWER 在01-0311:22说:  你好!我现在有一个项目,需要支持RS232和RS485,最重要是有电子邮件发送功能,我看了下STM32和uIP,实现这些应该没问题的,只是我没有在 单片机或嵌入式系统中实现过TCP/IP及SMTP协议,不知你有没有这方面的经验,可以分享下吗?非常感谢! 用Uip直接实现SMTP我不清楚如果是我我会使用另一种方法使用Uip实现webclient功能实现向网站提交数据然后通过网站的服务器端实现SM TP协议这样的实现方便的多 w wendy 在03-2815:38说:  你好,我们现在有个项目是需要在STM32中移植TCP/IP协议栈,如有兴趣,请发邮件给我.谢谢~~  Leave a Comment 昵称(必填*) 电邮(为保障隐私,将不被显示.[必填*]) 个人网站[要加上http://] http://www.ichanging.org/uip-stm32.html 2013/7/16 w  Copyright©2010-2013.AllRightsReserved. PoweredbyTypecho)))ThemebyPufen.NetHOSTBYSinaAppEngine赣ICP备10202164号 页码,6/6(W) http://www.ichanging.org/uip-stm32.html 2013/7/16

Top_arrow
回到顶部
EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高进,我们会尽快处理。