小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Uip + Stm32移植問題總結(jié)

 細(xì)寒 2014-04-22

作者:Changing發(fā)表時(shí)間:07-26 21:37分類:電子相關(guān)3 Comments

uIP 由瑞典計(jì)算機(jī)科學(xué)學(xué)院(網(wǎng)絡(luò)嵌入式系統(tǒng)小組)的Adam Dunkels (http:///adam/uip/)開發(fā)。其源代碼由C 語言編寫,并完全公開,有了這個(gè)TCP/IP協(xié)議棧,讓嵌入式可以實(shí)現(xiàn)的功能更為豐富。可以作為WebClient 向指定網(wǎng)站提交數(shù)據(jù),可以作為WebServer作為網(wǎng)頁服務(wù)器,提供一個(gè)小型的動(dòng)態(tài)頁面訪問功能。由于是開源的免費(fèi)協(xié)議棧,據(jù)說Uip沒有考慮協(xié)議安全的問題。
首先介紹下移植的環(huán)境: stm32 + ENC28J60網(wǎng)絡(luò)模塊 
IMG_20100101_103506.jpg
Enc28j60是帶SPI 接口的獨(dú)立以太網(wǎng)控制器,可以用mcu控制spi來實(shí)現(xiàn)tcp/ip數(shù)據(jù)流的收發(fā),所以要先完成Enc28j60的驅(qū)動(dòng)程序,再整合Uip。Uip是用標(biāo)準(zhǔn)的C語言實(shí)現(xiàn),所以移植Uip在51單片機(jī)和stm32上類似。
經(jīng)過幾天的琢磨,已經(jīng)將Uip的幾個(gè)示例穩(wěn)定運(yùn)行。Uip中apps下的例子相互之間存在沖突,源程序中也有一些Error 要修改,我將Uip的文件結(jié)構(gòu)做了一些調(diào)整。


Uip文件結(jié)構(gòu)
先介紹下Uip下各個(gè)目錄文件的功能:
├─apps                               apps目錄 下為uip提供的一些應(yīng)用示例
│  ├─dhcpc
│  ├─hello-world
│  ├─resolv
│  ├─smtp
│  ├─telnetd
│  ├─webclient
│  └─webserver
│      └─httpd-fs
├─doc                              doc下放置的為說明文檔,程序中用不上  
│  └─html
├─lib                                lib下為內(nèi)存塊管理函數(shù)源碼
├─uip                               uip下為uip和核心實(shí)現(xiàn)源碼 
└─unix                              unix環(huán)境里的uip應(yīng)用例子,可以參照這個(gè)例子實(shí)現(xiàn)應(yīng)用
Uip+stm32 MDK下工程建立
QQ截圖20120726204704.png
stm32的目錄結(jié)構(gòu)建立可以參考 stm32 開發(fā)環(huán)境MDK+庫文件配置 
User 放置 stm32 SPI配置以及Uip配置和Enc28j60和Uip的接口函數(shù)
uip下為uip的核心實(shí)現(xiàn)源碼以及內(nèi)存管理源碼(即為Uip/uip+Uip/lib)
dev下為Enc28j60的驅(qū)動(dòng)函數(shù)源碼
apps為uip的各個(gè)示例應(yīng)用源碼(Uip/apps下的文件)包括smtp,rsolve,dhcp,telnetd,以及webclient
webserver 的文件結(jié)構(gòu)較為復(fù)雜,獨(dú)立一個(gè)文件夾
Uip移
Uip的移植可以參考uip的unix的文件結(jié)構(gòu)。
1. Uip的數(shù)據(jù)通過網(wǎng)卡Enc28j60從物理層剝離,所以需要先配置Uip和Enc28j60的數(shù)據(jù)交互。這個(gè)部分在tapdev.c文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "uip.h"
#include "ENC28J60.h"
/*---------------------------------------------------------------------------*/
void
tapdev_init(unsigned char *my_mac)
{
    enc28j60Init(my_mac);
}
/*---------------------------------------------------------------------------*/
unsigned int
tapdev_read(void)
{
    return enc28j60PacketReceive(UIP_CONF_BUFFER_SIZE,uip_buf);
}
/*---------------------------------------------------------------------------*/
void
tapdev_send(void)
{
    enc28j60PacketSend(uip_len,uip_buf);
}
/*---------------------------------------------------------------------------*/
寫網(wǎng)卡驅(qū)動(dòng)程序,與具體硬件相關(guān)。這一步比較費(fèi)點(diǎn)時(shí)間,不過好在大部分網(wǎng)卡芯片的驅(qū)動(dòng)程序都有代碼借鑒或移植。驅(qū)動(dòng)需要提供三個(gè)函數(shù),以Enc28j60 驅(qū)動(dòng)為例。
tapdev_init():網(wǎng)卡初始化函數(shù),初始化網(wǎng)卡的工作模式。
tapdev_read(void):讀包函數(shù)。將網(wǎng)卡收到的數(shù)據(jù)放入全局緩存區(qū)uip_buf 中,返回包的長度,賦給uip_len。
void tapdev_send(void):發(fā)包函數(shù)。將全局緩存區(qū)uip_buf 里的數(shù)據(jù)(長度放在uip_len 中)發(fā)送出去。
2.由于uIP 協(xié)議棧需要使用時(shí)鐘,為TCP 和ARP 的定時(shí)器服務(wù)。因此使用單片機(jī)的定時(shí)器或是stm32的滴答定時(shí)器用作時(shí)鐘,每20ms 讓計(jì)數(shù)tick_cnt 加1,這樣,25 次計(jì)數(shù)(0.5S)滿了后可以調(diào)用TCP 的定時(shí)處理程序。10S 后可以調(diào)用ARP 老化程序。uIP1.0 版本,增加了timer.c/timer.h,專門用來管理時(shí)鐘,修改clock-arch.c如下:
1
2
3
4
5
6
7
8
9
10
11
#include "clock-arch.h"
#include "stm32f10x.h"
extern __IO int32_t g_RunTime;
/*---------------------------------------------------------------------------*/
clock_time_t
clock_time(void)
{
    return g_RunTime;
}
/*---------------------------------------------------------------------------*/
使用stm32 滴答定時(shí)器中斷代碼:
User/stm32f10x_it.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__IO int32_t g_RunTime = 0;
void SysTick_Handler(void)
{
    static uint8_t s_count = 0;
    if (++s_count >= 10)
    {
        s_count = 0;
        g_RunTime++;    /* 全局運(yùn)行時(shí)間每10ms增1 */
        if (g_RunTime == 0x80000000)
        {
            g_RunTime = 0;
        }      
    }
}
3.uipopt.h/uip-conf.h 是配置文件,用來設(shè)置本地的IP 地址、網(wǎng)關(guān)地址、MAC 地址、全局緩沖區(qū)的大小、支持的最大連接數(shù)、偵聽數(shù)、ARP 表大小等。可以根據(jù)需要配置。
#define UIP_FIXEDADDR 1
決定uIP是否使用一個(gè)固定的IP地址。
如果uIP使用一個(gè)固定的IP地址,應(yīng)該置位(set)這些uipopt.h中的選項(xiàng)。如果不的話,則應(yīng)該使用宏uip_sethostaddr(),uip_setdraddr() 和 uip_setnetmask()。
#define UIP_PINGADDRCONF 0            Ping IP地址賦值。
#define UIP_FIXEDETHADDR 0            指明uIP ARP模塊是否在編譯時(shí)使用一個(gè)固定的以太網(wǎng)MAC地址。
#define UIP_TTL 255                           uIP發(fā)送的IP packets的IP TTL (time to live)。
#define UIP_REASSEMBLY 0                uIP支持IP packets的分片和重組。
#define UIP_REASS_MAXAGE 40          一個(gè)IP fragment在被丟棄之前可以在重組緩沖區(qū)中存在的最大時(shí)間。
#define UIP_UDP 0                              是否編譯UDP的開關(guān)。
#define UIP_ACTIVE_OPEN 1                決定是否支持uIP打開一個(gè)連接。
#define UIP_CONNS 10                        同時(shí)可以打開的TCP連接的最大數(shù)目。由于TCP連接是靜態(tài)分配的,減小這個(gè)數(shù)目將占用更少的RAM。每一個(gè)TCP連接需要大約30字節(jié)的內(nèi)存。
#define UIP_LISTENPORTS 10                同時(shí)監(jiān)聽的TCP端口的最大數(shù)目。每一個(gè)TCP監(jiān)聽端口需要2個(gè)字節(jié)的內(nèi)存。
#define UIP_RECEIVE_WINDOW 32768   建議的接收窗口的大小。如果應(yīng)用程序處理到來的數(shù)據(jù)比較慢,那么應(yīng)該設(shè)置的小一點(diǎn)(即,相對(duì)與uip_buf緩沖區(qū)的大小來說),相反如果應(yīng)用程序處理數(shù)據(jù)很快,可以設(shè)置的大一點(diǎn)(32768字節(jié))。
#define UIP_URGDATA 1                       決定是否支持TCP urgent data notification。
#define UIP_RTO 3                                The initial retransmission timeout counted in timer pulses.不要改變
#define UIP_MAXRTX 8                         在中止連接之前,應(yīng)該重發(fā)一個(gè)段的最大次數(shù)。不要改變
#define UIP_TCP_MSS (UIP_BUFSIZE – UIP_LLH_LEN – 40)             TCP段的最大長度。它不能大于UIP_BUFSIZE – UIP_LLH_LEN – 40.
#define UIP_TIME_WAIT_TIMEOUT 120    一個(gè)連接應(yīng)該在TIME_WAIT狀態(tài)等待多長。不要改變
#define UIP_ARPTAB_SIZE 8                    ARP表的大小。如果本地網(wǎng)絡(luò)中有許多到這個(gè)uIP節(jié)點(diǎn)的連接,那么這個(gè)選項(xiàng)應(yīng)該設(shè)置為一個(gè)比較大的值。
#define UIP_BUFSIZE 1500                        uIP packet緩沖區(qū)不能小于60字節(jié),但也不必大于1500字節(jié)。
#define UIP_STATISTICS 1                        決定是否支持統(tǒng)計(jì)數(shù)字。統(tǒng)計(jì)數(shù)字對(duì)調(diào)試很有幫助,并展示給用戶。
#define UIP_LOGGING 0                        輸出uIP登陸信息。
#define UIP_LLH_LEN 14                        鏈接層頭部長度。對(duì)于SLIP,應(yīng)該設(shè)置成0。
uip-conf.h 中增加幾個(gè)主要結(jié)構(gòu)體定義,不include任何應(yīng)用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define UIP_CONF_LOGGING         0                //logging off
typedef int uip_tcp_appstate_t;         //出錯(cuò)可注釋
typedef int uip_udp_appstate_t;         //出錯(cuò)可注釋
/*#include "smtp.h"*/
/*#include "hello-world.h"*/
/*#include "telnetd.h"*/
/*#include "webserver.h"*/
/*#include "dhcpc.h"*/
/*#include "resolv.h"*/
/*#include "webclient.h"*/
#include "app_call.h"                    //加入一個(gè)Uip的數(shù)據(jù)接口文件
uIP 在接受到底層傳來的數(shù)據(jù)包后,調(diào)用UIP_APPCALL( ),將數(shù)據(jù)送到上層應(yīng)用程序處理。
User/app_call.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "stm32f10x.h"
#ifndef UIP_APPCALL
    #define UIP_APPCALL                 Uip_Appcall
#endif
#ifndef UIP_UDP_APPCALL
    #define UIP_UDP_APPCALL             Udp_Appcall
#endif
void Uip_Appcall(void);
void Udp_Appcall(void);
void Uip_Appcall(void)
{
     
}
void Udp_Appcall(void)
{
     
}
4.加入uIP 的的主循環(huán)代碼架構(gòu)
User/main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"
#include "uip.h"
#include "uip_arp.h"
#include "tapdev.h"
#include "timer.h"
#include "ENC28J60.h"
#include "SPI.h"
#define  PRINTF_ON  1
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
#ifndef NULL
#define NULL (void *)0
#endif /* NULL */
static unsigned char mymac[6] = {0x04,0x02,0x35,0x00,0x00,0x01};
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
int main(void)
{
    int i;
    uip_ipaddr_t ipaddr;
    struct timer periodic_timer, arp_timer;
    RCC_Configuration();
    GPIO_Configuration();
    USART_Configuration();
    SPInet_Init();
    timer_set(&periodic_timer, CLOCK_SECOND / 2);
    timer_set(&arp_timer, CLOCK_SECOND * 10);
    SysTick_Config(72000);          //配置滴答計(jì)時(shí)器
    //以太網(wǎng)控制器驅(qū)動(dòng)初始化
    tapdev_init(mymac);
   
    //Uip 協(xié)議棧初始化
    uip_init();
    uip_ipaddr(ipaddr, 192, 168, 1, 15);     //配置Ip
    uip_sethostaddr(ipaddr);
    uip_ipaddr(ipaddr, 192, 168, 1, 1);     //配置網(wǎng)關(guān)
    uip_setdraddr(ipaddr);
    uip_ipaddr(ipaddr, 255, 255, 255, 0);   //配置子網(wǎng)掩碼
    uip_setnetmask(ipaddr);
    while(1){
   
        uip_len = tapdev_read();                                //從網(wǎng)卡讀取數(shù)據(jù)
         
        if(uip_len > 0)
        {                                                       //如果數(shù)據(jù)存在則按協(xié)議處理
            if(BUF->type == htons(UIP_ETHTYPE_IP)) {         //如果收到的是IP數(shù)據(jù),調(diào)用uip_input()處理
                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();
                  tapdev_send();
                }
            }else if(BUF->type == htons(UIP_ETHTYPE_ARP)){    //如果收到的是ARP數(shù)據(jù),調(diào)用uip_arp_arpin處理
                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)
                {
                  tapdev_send();
                }
            }
     
        }else if(timer_expired(&periodic_timer)){           //查看0.5s是否到了,調(diào)用uip_periodic處理TCP超時(shí)程序
              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();
                      tapdev_send();
                    }
              }
                                 
              for(i = 0; i < UIP_UDP_CONNS; i++)
              {
     
                    uip_udp_periodic(i);                                //處理udp超時(shí)程序
     
                    /* 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();
                      tapdev_send();
                    }
              }
           
              /* Call the ARP timer function every 10 seconds. */            //10s到了就處理ARP
              if(timer_expired(&arp_timer))
              {
                    timer_reset(&arp_timer);
                    uip_arp_timer();
              }
        }
    }
}
/*******************************Stm32 Set***************************************/
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;                                                                                                                                                                                                                                                       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        
    GPIO_Init(GPIOA , &GPIO_InitStructure);
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;          
    GPIO_Init(GPIOA , &GPIO_InitStructure);
}
void RCC_Configuration(void)
{
    /* 定義枚舉類型變量 HSEStartUpStatus */
    ErrorStatus HSEStartUpStatus;
    /* 復(fù)位系統(tǒng)時(shí)鐘設(shè)置*/
    RCC_DeInit();
    /* 開啟HSE*/
    RCC_HSEConfig(RCC_HSE_ON);
    /* 等待HSE起振并穩(wěn)定*/
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
    /* 判斷HSE起是否振成功,是則進(jìn)入if()內(nèi)部 */
    if(HSEStartUpStatus == SUCCESS)
    {
        /* 選擇HCLK(AHB)時(shí)鐘源為SYSCLK 1分頻 */
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        /* 選擇PCLK2時(shí)鐘源為 HCLK(AHB) 1分頻 */
        RCC_PCLK2Config(RCC_HCLK_Div1);
        /* 選擇PCLK1時(shí)鐘源為 HCLK(AHB) 2分頻 */
        RCC_PCLK1Config(RCC_HCLK_Div2);
        /* 設(shè)置FLASH延時(shí)周期數(shù)為2 */
        FLASH_SetLatency(FLASH_Latency_2);
        /* 使能FLASH預(yù)取緩存 */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        /* 選擇鎖相環(huán)(PLL)時(shí)鐘源為HSE 1分頻,倍頻數(shù)為9,則PLL輸出頻率為 8MHz * 9 = 72MHz */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
        /* 使能PLL */
        RCC_PLLCmd(ENABLE);
        /* 等待PLL輸出穩(wěn)定 */
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
        /* 選擇SYSCLK時(shí)鐘源為PLL */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        /* 等待PLL成為SYSCLK時(shí)鐘源 */
        while(RCC_GetSYSCLKSource() != 0x08);
    }
    /* 打開APB2總線上的GPIOA時(shí)鐘*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
         
}
  
void USART_Configuration(void)
{
    USART_InitTypeDef USART_InitStructure;
    USART_ClockInitTypeDef USART_ClockInitStructure;
    USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;                                                                                                                                                     
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
    USART_ClockInit(USART1 , &USART_ClockInitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
    USART_Init(USART1,&USART_InitStructure);
    USART_Cmd(USART1,ENABLE);
}
#if  PRINTF_ON
int fputc(int ch,FILE *f)
{
    USART_SendData(USART1,(u8) ch);
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
    return ch;
}
#endif
5.解決編譯過程中的錯(cuò)誤。歸總?cè)缦拢?
  • Uip/uip-split.c  注釋所有的 tcpip_output()函數(shù)  消除uip_fw_output()函數(shù)的注釋
  • Uip/memb.c 中 memb_free()函數(shù) 返回值 return -1 改為 return 1
  • 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.png

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多