歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

tftp-nfs開發環境搭建 uboot環境變量設置

嵌入式開發通常使用主機-開發板的開發模式,在裸板開發中,我們通常使用串口調試工具傳遞文件,比如windows平台的超級終端,SecuCRT以及Linux平台的ckermit(題外話:ckermit比windows的那兩個快多了)。但在OS的開發環境中,由於程序復雜,規模巨大,串口的低速和易錯就不再適合我們開發了,而在這種環境下,基於網絡的開發環境由於高速和准確受到了大家的青睐。

結構說明

在有OS的嵌入式系統中,SoC的啟動過程有3個加載。

  1. 上電的第一個程序就是片上固化的啟動代碼,它負責把bootloader從Flash中加載到內存中並執行
  2. bootloader會從Flash中加載Linux內核以及設備樹文件到內存,並對兩者進行相關的配置。完成所有工作後跳轉到內核的首地址
  3. 內核接管bootloader配置好的硬件資源,內核啟動過程中非常重要的一件事就是掛載文件系統。

在開發過程中,由於bootloader通常都具有網絡功能,而linux內核,設備樹dts和文件系統fs都是不斷迭代的,所以我們自然希望通過配置bootloader的網絡功能使其直接通過服務器(開發主機)下載內核並進一步下載設備樹文件(tftp),甚至直接掛接網絡上的文件系統(nfs)。整個開發環境的結構框圖如下:

tftp的安裝和配置

tftp即tiny ftp,是一種輕型的ftp協議,Ubuntu下可以使用下面這個小腳本安裝並配置。

#!/bin/bash
echo "Please input tftpdir"
read tftpdir
sudo mkdir $tftpdir        #創建用於傳輸文件的目錄
sudo chmod 0777 $tftpdir
sudo apt-get install tftp-hpa tftpd-hpa xinetd -y
#sudo vi /etc/default/tftp-hpa
sudo touch /etc/default/tftpd-hpa
sudo chmod 0777 /etc/default/tftpd-hpa
sudo echo "TFTP_USERNAME=\"tftp\"" > /etc/default/tftpd-hpa
sudo echo "TFTP_DIRECTORY=\"$tftpdir\"" >> /etc/default/tftpd-hpa   #tftpd-hpa的服務目錄,這個想建立在哪裡都行
sudo echo "TFTP_ADDRESS=\"0.0.0.0:69\""     >> /etc/default/tftpd-hpa   #指定開發板地址,需要和主機的ip在同一個網段     
sudo echo "TFTP_OPTIONS=\"-l -c -s\""       >> /etc/default/tftpd-hpa   #-c是可以上傳文件的參數,-s是指定tftpd-hpa服務目錄,上面已指定

sudo service tftpd-hpa restart
echo -e '\n'

nfs的安裝和配置

nfs即network filesystem,可以使客戶端直接從服務器掛接文件系統,方便開發板直接訪問我們的程序或文件。nfs的安裝和配置腳本

#!/bin/bash
echo "nfs service"
echo "Please input nfs dir"
read nfsdir
sudo mkdir $nfsdir
sudo apt-get install nfs-kernel-server nfs-common portmap -y
#sudo vi /etc/exports
sudo touch /etc/exports
sudo chmod 0777 /etc/exports
sudo echo "$nfsdir  *(rw,sync,no_subtree_check,no_root_squash)" > /etc/exports
sudo service nfs-kernel-server restart
echo -e '\n'

export文件的屬性選項

ro      只讀訪問
rw      讀寫訪問
sync    所有數據在請求時寫入共享
async   nfs在寫入數據前可以響應請求
secure  nfs通過1024以下的安全TCP/IP端口發送
insecure    nfs通過1024以上的端口發送
wdelay      如果多個用戶要寫入nfs目錄,則歸組寫入(默認)
no_wdelay   如果多個用戶要寫入nfs目錄,則立即寫入,當使用async時,無需此設置
hide        在nfs共享目錄中不共享其子目錄
no_hide     共享nfs目錄的子目錄
subtree_check   如果共享/usr/bin之類的子目錄時,強制nfs檢查父目錄的權限(默認)
no_subtree_check    不檢查父目錄權限
all_squash      共享文件的UID和GID映射匿名用戶anonymous,適合公用目錄
no_all_squash   保留共享文件的UID和GID(默認)
root_squash     用戶的所有請求映射成如anonymous用戶一樣的權限(默認)
no_root_squash  root用戶具有根目錄的完全管理訪問權限
anonuid=xxx     指定nfs服務器/etc/passwd文件中匿名用戶的UID
anongid=xxx     指定nfs服務器/etc/passwd文件中匿名用戶的GID

安裝完畢可以使用下面的命令測試一下

$sudo mount -t nfs localhost:/home/jiang/nfs /mnt/  #localhost後面接的是nfs共享目錄
$ls /mnt/
1.txt       #如果能看到nfs裡面的1.txt就表示掛接成功了,nfs服務器沒有問題
$sudo unmount /mnt/

uboot環境配置

通過配置uboot讓它在啟動過程中從tftp獲取內核和設備樹,並從在加載內核之後把通過啟動參數將"從nfs掛載根文件系統"傳入內核。這個配置主要是通過uboot內建的"set 變量名 變量值+save"設置環境變量的方式進行配置,下面是我采用的uboot的環境變量,下面是我用的環境變量設置:

#pri                    #即printenv  
baudrate=115200
bootargs=root=/dev/nfs nfsroot=192.168.0.50:/nfs rw console=ttySAC2,115200n8 init=/linuxrc ip=192.168.0.55 loglevel=7 clk_ignore_unused
bootcmd=tftp 41000000 uImage;tftp 42000000 exynos4412-origen.dtb;bootm 41000000 - 42000000
bootdelay=4
ethact=dm9000
ethaddr=11:22:33:44:55:66
fileaddr=41000000
filesize=26D213
gatewayip=192.168.2.1
ipaddr=192.168.0.55
netmask=255.255.255.0
serverip=192.168.0.50
stderr=serial
stdin=serial
stdout=serial

baudrate就是波特率,習慣上就設成115200,根據硬件的不同可以相應的修改

bootargs啟動參數,這個參數除了uboot要用,啟動內核之後還會傳入內核。
其中,root=/dev/nfs表示開發板的根文件系統從nfs網絡設備中加載,nfsroot=192.168.0.55:/nfs表示從網絡中的ip是192.168.0.55的主機中的/nfs目錄加載根文件系統,rw表示可讀可寫,console=ttySAC2表示使用的中端,115200表示波特率,init=/linuxrc表示啟動的祖先進程的位置,顯然這是給linux內核用的,ip=192.168.0.55是開發板的ip,需要和主機在同一個網段,loglevel=7就是登錄等級,這個不設也行,clk_ignore_unused忽略時鐘。這個參數的實質是uboot傳入內核的,所以需要參考內核的啟動參數的相關文件,我在下面做了簡要的說明。除了啟動參數,uboot還需要做一些其他的准備工作,並不是這個參數准備好了內核就可以工作了,比如,關於arm平台的linux內核啟動條件,可以參考Linux內核源碼中的Documentation/arm/Booting ,這裡就不做說明了
bootcmd啟動命令,tftp 41000000 uImage表示從tftp網絡中下載uImage內核鏡像到41000000地址處,tftp 42000000 exynos4412-origen.dtb表示下載從tftp網絡中下載設備樹文件到42000000地址處,bootm 41000000 - 42000000表示從41000000啟動內核,我這沒有randisk,用-代替,不是從41000000到42000000的意思!!!此外,一旦填入了ramdisk地址,內核就會從ramdisk掛載根文件系統而忽略nfs。最後,把設備樹從42000000傳入內核。
注意:多個命令之間用;分隔,所以為了在設置變量的時候不立即執行,應該寫成set bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-origen.dtb\;bootm 41000000 - 42000000

bootdelay啟動倒計時的秒數

gatewayip表示網關

ipaddr表示開發板的ip

serverip表示主機的ip

netmask表示子網掩碼

stderrstdinstdout表示標准輸入輸出錯誤設備,基本都填串口serial

Linux內核啟動參數

內核需要的啟動參��在linux-4.8.5/Documentation/kernel-parameters.txt以及相應的文件中,這些參數就是uboot需要通過bootargs將他們准備好並傳給內核,當然,這些參數都是有缺省值的,我們只需要對需要的參數進行配置,這裡列出這裡用到的幾個

noinitrd    [RAM] Tells the kernel not to load any configured
            initial RAM disk.
            
root=       [KNL] Root filesystem
            See name_to_dev_t comment in init/do_mounts.c.

nfsroot=    [NFS] nfs root filesystem for disk-less boxes.
            See Documentation/filesystems/nfs/nfsroot.txt.

rw          [KNL] Mount root device read-write on boot

rootwait    [KNL] Wait (indefinitely) for root device to show up.
            Useful for devices that are detected asynchronously
            (e.g. USB and MMC devices).

ip=         [IP_PNP]
            See Documentation/filesystems/nfs/nfsroot.txt.

console=    [KNL] Output console device and options.
        。。。

init=       [KNL]
            Format: <full_path>
            Run specified binary instead of /sbin/init as init
            process.

loglevel=   All Kernel Messages with a loglevel smaller than the
            console loglevel will be printed to the console. 
            。。。
            
clk_ignore_unused
            [CLK]
            Prevents the clock framework from automatically gating
            clocks that have not been explicitly enabled by a Linux
            device driver but are enabled in hardware at reset or
            by the bootloader/firmware. 
            。。。
$grep ip=  Documentation/filesystems/nfs/nfsroot.txt -A 20
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>

  This parameter tells the kernel how to configure IP addresses of devices and also how to set up the IP routing table. It was originally called 'nfsaddrs', but now the boot-time IP configuration works independently of NFS, so it was renamed to 'ip' and the old name remained as an alias for compatibility reasons.
。。。。
$grep nfsroot=  Documentation/filesystems/nfs/nfsroot.txt -A 20
nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]

  If the 'nfsroot' parameter is NOT given on the command line,
  the default "/tftpboot/%s" will be used.
 。。。

搭建開發環境的細節很多,如有纰漏歡迎批評^-^交流

Copyright © Linux教程網 All Rights Reserved