新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > TFTP協議在嵌入式系統中的實現

        TFTP協議在嵌入式系統中的實現

        作者: 時間:2011-07-13 來源:網絡 收藏

        3.硬件實現
          

        系統使用了RTL8019AS 10M ISA網卡芯片接入以太網。RTL8019AS是一款性價比很高的網卡芯片:NE2000兼容,軟件移植性好;接口簡單不用轉換芯片如PCI-ISA橋;價格便宜、帶寬充裕、較長一段時間內不會停產。8019有3種配置模式:跳線方式、即插即用PP方式、串行Flash配置方式。串行模式不與NE2000兼容,PP模式用在PC機中,這里用不上。只剩下跳線配置模式可用。系統的MCU選擇的三星公司的S3C44B0X芯片,S3C44B0x是基于ARM7TDMI核的處理器,沒有MMU,可以源代碼級跟蹤調試。44B0與RTL8019的電路設計相對來說比較簡單,只需要連接數據線、地址選通、中斷等信號線。簡略電路圖如圖(3):            

        圖3 RTL8019與S3C440X的接口電路

        4.軟件設計

        a.RTL8019驅動程序
          RTL8019驅動程序主要包括3個函數 :
          i..RTL8019 初始化函數。要對網卡的工作參數進行設置.以使網卡開始工作。
          其主要工作包括:復位網絡芯片,設置MAC地址,設置組播地址,設置DMA傳輸參數等等。
          ii.收包函數:從網絡中接收數據到緩沖區。
          iii.發包函數:從緩沖區向網絡中發送數據。
        b.協議棧的實現
          TFTP的實現其實就是根據各種協議,對數據打包(當發送數據時)和解包(當接收數據時)。主函數主要部分如下

        eth_init();//其主要是清空ARP緩沖區.其中調用了一個功能函數[2]
        arp_init();//清零
        Mac_init();//設置MAC地址
        ip_init(ip); //主要功能:設置ip地址
        udp_init(); //初始化UDP協議
        while (1) net_handle();//處理函數
          

        前5個函數主要是初始化工作接下來的int net_handle(void)就要開始進入網絡傳輸了,這里就是協議棧的核心了:

        skb = alloc_skb(ETH_FRAME_LEN);//選擇一個 SKB
        if (eth_rcv(skb) != -1) {
        eth_hdr = (struct ethhdr *)(skb->data);
        skb_pull(skb, ETH_HLEN);
        if (ntohs(eth_hdr->h_proto) == ETH_P_ARP)//是否為ARP包
        arp_rcv_packet(skb); //是則進行ARP包應答
        else if(ntohs(eth_hdr->h_proto) == ETH_P_IP) //是否為IP包
        ip_rcv_packet(skb);//是則進行IP包處理
          

        如果從MAC層收到一個以太網幀,先把收到的以太網幀轉變為相應的幀結構再去掉其以太網偵頭部, 其中skb_pop(skb, ETH_HLEN)把數據指針往后移動ETH_HLEN個字節,而且真正的數據長度也做相應的變化..然后根據幀中的協議字段判斷其上層為什么協議.這里幀格式采用的是RFC894,如果其上層為arp協議,將去掉以太網頭部的數據交由ARP處理,同樣如果其上層協議為IP,也做類似的處理. arp_rcv_packet(skb)只處理的ARP請求消息,如果發現其為ARP請求,則發送ARP應答. 接下來就是把這個ARP應答包發出去,發送了ARP應答后把剛才請求的者的MAC地址和其IP保存在本機中,其實現采用了簡單循環區,利用數組.首先檢查緩沖區中有無此項,如果有則直接用該項的索引,如果沒有則重新分配索引, 把傳進來的MAC 和IP 賦給新分配的索引 i,。
          

        如果MAC層發現收到的包上層協議為IP,則執行[1]:
        if(ntohs(eth_hdr->h_proto) == ETH_P_IP)
        ip_rcv_packet(skb);
          

        首先檢查接受者是不是本機IP,通過檢查后,去掉IP頭部,再檢查其上層協議類型,如果為UDP,則將包轉交給上層的UDP協議處理其中udp_rcv_packet(skb)先去掉UDP頭部,再檢查其對應的上層協議,這里只實現了,對應語句為skb_pop(skb, sizeof(struct udphdr));
        if (ntohs(udp_hdr->dest) == TFTP)
        tftp_rcv_packet(skb);

        其中tftp_rcv_packet(skb)根據TFTP頭部中操作類型而采取不同的動作.對應代碼為:
        switch (ntohs(tftp_hdr->th_opcode)) {
        /* 只處理寫請求和DATA */
        case WRQ:
        tftp_rcv_wrq(skb); break;
        case DATA:
        tftp_rcv_data(skb); break;
        …}
          

        其中tftp_rcv_wrq(skb)先得到請求者的IP和PORT,再發送塊編號為0的ACK包.然后為數據傳輸做些初始化工作,具體為設置接受緩沖區和接受數據長度。:因為TFTP是包裝在UDP里面的,所以首先欲留出UDP頭部的空間,這里要注意的是在UDP層除了為自己留空間外其又會欲留出IP頭的空間,而在IP層除了為自己留空間外其又會欲留出MAC頭的空間.如此便留出了整個協議棧所要求的頭部空間.調用關系為
          udp_skb_reserve(skb)—ip_skb_reserve(skb)—eth_skb_reserve(skb);
          

        然后該函數按照ACK包的格式(在TCP/IP祥解 I 協議>160)賦相應的值.最后將此包交由下層的UDP協議處理.那么此時UDP層是怎么處理的呢?udp_send(skb, client_ip, TFTP, client_port);和TFTP層處理有些類似,先加入自己的頭部信息并賦相應的值.然后再交由下層處理, 在IP層其處理的思路也大致差不多,其中ip_send(skb, ip, UDP)定義在ip/_ip.c.其先查看ARP緩沖區中有無此項,如無則返回錯誤.對應代碼為,然后先加入自己的頭部信息并賦相應的值.然后再交由下層處理。
          

        tftp_rcv_data(skb)首先判斷接受到的包的目的IP和PORT是不是本機的,通過判斷后,再看接受到的包的確認序列號是不是和本機TFTP要求的一致,即看是不是發生了丟包.如果沒有則當前接受到的包有效,存入緩沖區,并發送確認序號對應代碼為:
        if (client_block == ntohs(tftp_hdr->th_block)) {
        /* 接受一個數據分組 */
        len = skb->len - sizeof(struct tftphdr);
        memcpy(buf + data_len, tftp_hdr->th_data, len);
        data_len += len;
        tftp_send_ack(tftp_hdr, client_block);
        client_block++;

        如果當前接受到的數據小于512字節,則說明傳送完畢,但是當發生丟包時,就要求對方重傳.采用的機制很簡單,就是要求重傳確認序號小的分組。

        5.結束語
          

        本文對S3C44B0X+RTL8019開發,實現了系統通過網絡與PC機通信,充分滿足嵌入式小系統網絡通信需要,改善了了一般通過串口通信速度慢、可靠性低的弊端。并且適當調整程序,可實現基于UDP的其它上層協議。


        上一頁 1 2 下一頁

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 永春县| 汉沽区| 厦门市| 玉树县| 东阳市| 石景山区| 罗定市| 云梦县| 华阴市| 余姚市| 德令哈市| 虎林市| 福州市| 平湖市| 康马县| 三亚市| 商南县| 安岳县| 林芝县| 南雄市| 宁远县| 威海市| 大安市| 黔东| 井研县| 南昌市| 花莲县| 通许县| 永吉县| 龙山县| 清苑县| 鹰潭市| 贵阳市| 凌海市| 成武县| 沙坪坝区| 宁津县| 罗江县| 清水县| 西城区| 建平县|