您好,登錄后才能下訂單哦!
9、1、uboot的環境變量
1、環境變量的作用
(1)在我們不改變uboot源代碼的情況下,只需要改變環境變量的值就可以改變uboot運行時的數據和一些特性。比如說,通過修改bootdelay環境變量,就可以更改開機倒數的秒數。
2、環境變量的優先級
(1)uboot代碼當中有一個值,環境變量(DDR 環境變量的分區中)中也有一個值,uboot程序實際運行時,規則是,如果環境變量(DDR中環境變量的分區)為空,則使用代碼中的環境變量的值,如果環境變量不為空,優先使用環境變對應的值。
(2)比如說我們的machid(機器碼),我們uboot中,在x210_sd.h中,定義了一個機器碼2456,這個是寫死在程序中的,所以我們在開機的時候是可以看到這個環境變量的,用bdinfo來看。如果要修改uboot中配置的機器碼,可以修改x210_sd.h中的機器碼,但是修改源代碼后需要重新編譯燒錄,很麻煩,比較簡便的方法就是使用環境變量machid即可。把環境變量machid設置成別的 set machid xxx 設置好后,系統在啟動時,會優先使用machid環境變量中的值。
3、環境變量在uboot中的工作方式
(1)當一個uboot鏡像剛開始燒錄到一個SD卡上的時候,第一次燒錄的時候,SD卡上的環境變量分區是空的。所以將來重定位到了DDR中去運行的時候,DDR中的環境變量分區也是空的,所以這個時候會使用uboot代碼中默認的環境變量,當我們將改變環境變量后,在saveenv保存環境變量的時候,這個時候會將環境變量保存到了SD卡的環境變量的分區上去。當我們在此啟動的時候,在將sd卡的環境變量分區重定位到DDR中的時候,環境變量在內存就有了,所以就會使用內存中的這一份環境變量。
(2)默認環境變量在uboot/common/env_comon.c中的default_environment,這個東西就是一個字符數組,里面的內容就是很多個環境變量連續分布組成的,每個環境變量的末端用'\0'作為結束符。
(3)DDR中的環境變量,在default_environment中,實質是字符數組,在uboot中其實是一個全局變量,鏈接時在數據段的,重定位的時候就重定位到了DDR中的一個內存地址中去了。這個地址處放的就是我們uboot在運行的時候的環境變量了。
在重定位的時候,程序會去檢查SD卡的env分區中是否有環境變量,會進行CRC校驗,如果檢驗通過了,SD卡的env'分區有環境變量,那么就會將SD卡中的這一份環境變量會覆蓋default_environment中的環境變量,
9、2、環境變量相關命令的源碼分析1
1、printenv
(1)分析do_printenv函數
(2)在do_printenv函數中可以看出來,如果argc=1的話,就會打印出來所有的環境變量,如果argc不等于1就會只打印出來我們我要打印出來的環境變量。
(3)argc=1時,就會執行那個三重for循環,第一重for循環就是處理所有的環境變量,你有多少了個環境變量,那么第一重的for循環就會循環多少次。
(4)這個函數要看明白,首先要明白環境變量在內存中是怎么存儲的問題,根據代碼和上節課將到的default_enironment字符數組,知道,環境變量在內存中是以一個字符數組的形式存儲的,每個環境變量的名到他的值都是連續的字符,一個環境變量的名字和值結束后就會有一個'\0'來標志這第一個環境變量的字符結束了,接著要在內存中接著放第二個環境變量的字符一次挨著放的,每個環境變量的結束分割是'\0',所以代碼中,可以用'\0'這個標志,來區分我們在內存中讀取字符時,讀取到哪個位置表示一個環境變量讀取完了,可以接著讀取下一個了。
9、3、環境變量相關命令的源碼分析2
1、setenv
(1)_do_setenv (flag, argc, argv);//沒有下劃線的表示可以自己用的,一個下劃線表示系統自己用的,兩個下劃線的表示系統內部自己用的,三個下劃線開頭表示我們就不要碰了
}
(2)setenv的思路,先去DDR中去尋找有沒有這個環境變量,如果有,則覆蓋這個環境變量,如果沒有則在最后新增一個環境變量,
第一步:遍歷DDR中環境變量的字符數組,找到原來就有的那個環境變量對應的地址 168-174行
第二部:去擦除原來的環境變量在_do_setenv 259-265行
第三步:寫入新的環境變量 266-273行
本來setenv做完上面的就完事了,但是還要考慮一些附加的問題,
問題1、就是環境變量太多,超出了DDR中環境變量的分區,這時就溢出了,
問題2,有些環境變量,如bundrate,在gd中有對應的全局變量,這種環境變量在set的時候,還要對應的更新對應的全局變量,否則就會出現在本次運行中,環境變量和全局變量不一致的情況。
9、4、環境變量相關命令的源碼分析3
1、saveenv
(1)我們的uboot執行saveenv的函數是在env_aotu.c中那個do_saveenv函數,為什么是這個文件中的這個函數呢,是由在x210_sd.h中那個#define CFG_ENV_IS_IN_AUTO宏來配置的,aotu的意思就是自動適配的,在do_saveenv函數中開始的部分,有一個寄存器(這個寄存器是用戶自定的寄存器,是在start.S中往里面寫值的)來判斷我們是從哪個介質中啟動的,從哪個介質中啟動,就執行哪個對應的函數,我們的SD卡啟動的,所以對應的實際上應該是movinand(因為movinand就是inand,而inand的操作和SD卡的操作很像inand就是小版的sd卡可以這么理解,因為板子上的inand是是接在SD卡通道0的,SD通道2和3是接SD卡的,可以看出來其實兩者很像)。
(2)用戶自定義信息的寄存器E010_F00C,這個寄存器中實現在start.S中,開始時由一個寄存器判斷出了是從哪個啟動介質啟動,完了之后,我們相應的在這個用戶自定義信息的寄存器中存儲了我們從哪種介質啟動的信息標志,由于我們是SD卡啟動,我們無法從那個寄存器中知道我們是哪種啟動方式,我們只能通過實際來知道,因為那個寄存器三星給的數據手冊中沒有。由這個用戶自定寄存器中的值在我們的env_aotu.c中的do_saveenv函數中開始的部分去進行判斷執行哪個保存環境變量的函數,最后我們確定是調用的saveenv_movinand這個函數去保存我們的環境變量的。
(3)真正執行保存環境變量的函數是這個movi_write_env,將環境變量從DDR中寫入到,保存到SD/iNand中,實際上就是將內存中的那個default_enironment字符數組保存到了SD/iNand中,大小是16KB,剛好就是32個扇區(一個扇區512B)。
(4)raw_area_control是uboot中規劃inand/sd卡的原始分區表,env分區就記錄在這里,
9、5、uboot內部獲取環境變量
1、getenv
(1)getenv,應該是不可重入函數
(2)實現方式就是去遍歷default_enironment這個字符數組,也就是遍歷DDR中內存中放env的那部分內存里面的字符。
去和name相比較,如果找到了,就返回這個環境變量的首地址
2、getenv_r
(1)可重入函數。(你用的時候,沒有破壞原來的內存中那一份,別人用的時候,內存中的那一份還是好的)
(2)這個函數,是在DDR中找到那一個環境變量后,將他的值放到了一個buf中,而getenv函數是將那個環境變量的值在DDR中對應的內存地址返回回來,改的話,就直接改了DDR中環境變量的那一份,而getenv_r改的值的話,改的是buf中的那一份,為的是當發送中斷,或者在多線程的情況下,你getenv的話執行,在別人想用這個值的是,可是已經被你改掉了,有可能會無意的改動了內存中值,而放在了buf中的話,當發生這種情況的話,內存中的那一份的值還是好好的,當別人想用的時候還可以得到內存中完好的那一份的值。
總結:
功能是一樣的,但是可重入版本是安全一些的,建議應該使用這個、
有關于環境變量的所有操作,只要理解了環境變量在DDR中的存儲方法,理解了環境變量和我們gd全局變量的關聯,和優先級,理解了環境變量在存儲介質中的存儲方式(就是我們專用的分區),那么整個環境變量相關的就都清楚了。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。