乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       細(xì)寒 2014-04-22

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

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


      Uip文件結(jié)構(gòu)
      先介紹下Uip下各個目錄文件的功能:
      ├─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和核心實現(xiàn)源碼 
      └─unix                              unix環(huán)境里的uip應(yīng)用例子,可以參照這個例子實現(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的核心實現(xiàn)源碼以及內(nèi)存管理源碼(即為Uip/uip+Uip/lib)
      dev下為Enc28j60的驅(qū)動函數(shù)源碼
      apps為uip的各個示例應(yīng)用源碼(Uip/apps下的文件)包括smtp,rsolve,dhcp,telnetd,以及webclient
      webserver 的文件結(jié)構(gòu)較為復(fù)雜,獨立一個文件夾
      Uip移
      Uip的移植可以參考uip的unix的文件結(jié)構(gòu)。
      1. Uip的數(shù)據(jù)通過網(wǎng)卡Enc28j60從物理層剝離,所以需要先配置Uip和Enc28j60的數(shù)據(jù)交互。這個部分在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ū)動程序,與具體硬件相關(guān)。這一步比較費點時間,不過好在大部分網(wǎng)卡芯片的驅(qū)動程序都有代碼借鑒或移植。驅(qū)動需要提供三個函數(shù),以Enc28j60 驅(qū)動為例。
      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é)議棧需要使用時鐘,為TCP 和ARP 的定時器服務(wù)。因此使用單片機的定時器或是stm32的滴答定時器用作時鐘,每20ms 讓計數(shù)tick_cnt 加1,這樣,25 次計數(shù)(0.5S)滿了后可以調(diào)用TCP 的定時處理程序。10S 后可以調(diào)用ARP 老化程序。uIP1.0 版本,增加了timer.c/timer.h,專門用來管理時鐘,修改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 滴答定時器中斷代碼:
      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++;    /* 全局運行時間每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是否使用一個固定的IP地址。
      如果uIP使用一個固定的IP地址,應(yīng)該置位(set)這些uipopt.h中的選項。如果不的話,則應(yīng)該使用宏uip_sethostaddr(),uip_setdraddr() 和 uip_setnetmask()。
      #define UIP_PINGADDRCONF 0            Ping IP地址賦值。
      #define UIP_FIXEDETHADDR 0            指明uIP ARP模塊是否在編譯時使用一個固定的以太網(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          一個IP fragment在被丟棄之前可以在重組緩沖區(qū)中存在的最大時間。
      #define UIP_UDP 0                              是否編譯UDP的開關(guān)。
      #define UIP_ACTIVE_OPEN 1                決定是否支持uIP打開一個連接。
      #define UIP_CONNS 10                        同時可以打開的TCP連接的最大數(shù)目。由于TCP連接是靜態(tài)分配的,減小這個數(shù)目將占用更少的RAM。每一個TCP連接需要大約30字節(jié)的內(nèi)存。
      #define UIP_LISTENPORTS 10                同時監(jiān)聽的TCP端口的最大數(shù)目。每一個TCP監(jiān)聽端口需要2個字節(jié)的內(nèi)存。
      #define UIP_RECEIVE_WINDOW 32768   建議的接收窗口的大小。如果應(yīng)用程序處理到來的數(shù)據(jù)比較慢,那么應(yīng)該設(shè)置的小一點(即,相對與uip_buf緩沖區(qū)的大小來說),相反如果應(yīng)用程序處理數(shù)據(jù)很快,可以設(shè)置的大一點(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ā)一個段的最大次數(shù)。不要改變
      #define UIP_TCP_MSS (UIP_BUFSIZE – UIP_LLH_LEN – 40)             TCP段的最大長度。它不能大于UIP_BUFSIZE – UIP_LLH_LEN – 40.
      #define UIP_TIME_WAIT_TIMEOUT 120    一個連接應(yīng)該在TIME_WAIT狀態(tài)等待多長。不要改變
      #define UIP_ARPTAB_SIZE 8                    ARP表的大小。如果本地網(wǎng)絡(luò)中有許多到這個uIP節(jié)點的連接,那么這個選項應(yīng)該設(shè)置為一個比較大的值。
      #define UIP_BUFSIZE 1500                        uIP packet緩沖區(qū)不能小于60字節(jié),但也不必大于1500字節(jié)。
      #define UIP_STATISTICS 1                        決定是否支持統(tǒng)計數(shù)字。統(tǒng)計數(shù)字對調(diào)試很有幫助,并展示給用戶。
      #define UIP_LOGGING 0                        輸出uIP登陸信息。
      #define UIP_LLH_LEN 14                        鏈接層頭部長度。對于SLIP,應(yīng)該設(shè)置成0。
      uip-conf.h 中增加幾個主要結(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;         //出錯可注釋
      typedef int uip_udp_appstate_t;         //出錯可注釋
      /*#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"                    //加入一個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);          //配置滴答計時器
          //以太網(wǎng)控制器驅(qū)動初始化
          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超時程序
                    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超時程序
           
                          /* 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è)置*/
          RCC_DeInit();
          /* 開啟HSE*/
          RCC_HSEConfig(RCC_HSE_ON);
          /* 等待HSE起振并穩(wěn)定*/
          HSEStartUpStatus = RCC_WaitForHSEStartUp();
          /* 判斷HSE起是否振成功,是則進入if()內(nèi)部 */
          if(HSEStartUpStatus == SUCCESS)
          {
              /* 選擇HCLK(AHB)時鐘源為SYSCLK 1分頻 */
              RCC_HCLKConfig(RCC_SYSCLK_Div1);
              /* 選擇PCLK2時鐘源為 HCLK(AHB) 1分頻 */
              RCC_PCLK2Config(RCC_HCLK_Div1);
              /* 選擇PCLK1時鐘源為 HCLK(AHB) 2分頻 */
              RCC_PCLK1Config(RCC_HCLK_Div2);
              /* 設(shè)置FLASH延時周期數(shù)為2 */
              FLASH_SetLatency(FLASH_Latency_2);
              /* 使能FLASH預(yù)取緩存 */
              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
              /* 選擇鎖相環(huán)(PLL)時鐘源為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時鐘源為PLL */
              RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
              /* 等待PLL成為SYSCLK時鐘源 */
              while(RCC_GetSYSCLKSource() != 0x08);
          }
          /* 打開APB2總線上的GPIOA時鐘*/
          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.解決編譯過程中的錯誤。歸總?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

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多