sysconfig配置系統,作為一個通用的軟體平台,還希望通過它,可以适應使用者不同的方案。通過給出一個對應的配置,使用者的方案就可以自動運作,而不需要修改系統裡面的代碼,或者重新給出參數。
配置腳本的本意是給系統傳遞參數。作為一個穩定的系統,本身應該和方案無關, 不管不同方案的差别有多大,系統都不應該重新編譯才能運作。這裡所說的系統,不單單指作業系統,也包括其中的驅動,子產品,等等。
不同方案的差别,通常展現在:
1) 使用的硬體子產品不同,比如使用了不同的NAND FLASH,RTC子產品,等等。
2) 相同子產品使用的參數不同,其中包括GPIO不同,比如卡檢測腳不同,SPI的引
腳不同,等等;包括執行的頻率不同,如DRAM的頻率,CPU的頻率,等等。
3) 走線的方式不同。
4) 沒有列舉出的差别。
通常說來,上面列舉的方案差别中,(3)和(4)對于一個系統來說沒有任何差别,隻
有(1)和(2),才可能導緻一個系統需要重新編譯。
例如:
[uart_para0]
uart_used = 1
uart_port = 0
uart_type = 2
uart_tx = port:PB22<2><1><default><default>
uart_rx = port:PB23<2><1><default><default>
uart_para0是主鍵 uart_used uart_port uart_type uart_tx uart_rx 分别是uart_para0的子鍵,而uart_tx uart_rx對應着A10的GPIO
; 說明: 腳本中的字元串區分大小寫,使用者可以修改"="後面的數值,但是不要修改前面的字元串
; 描述gpio的形式:Port:端口+組内序号<功能配置設定><内部電阻狀态><驅動能力><輸出電平狀态>
這是一種典型的管理配置的方式,簡單地歸納特點如下
1) 配置獨立于代碼,用檔案的方式存儲、可讀寫
2) 集中管理,具有一定的規範,多種子產品遵循同一種配置規則
3) 有專門一套代碼去管理配置,讀取相應的配置提供給程式
端配置資料的生成
配置腳本本質上是PC端的一個文本檔案,通過一個固定的格式形成可以被我們使用的檔案,裡面儲存了大量的配置資訊。在圖一中,可以看到,PC端的一個資料檔案如何變成了小機端可以用到的檔案。
圖一 小機端配置檔案生成
圖一中可以看出,當使用者生成一個配置檔案之後,不需要做額外的操作,隻要按照正常的打包,燒寫過程,配置檔案的資料就自動被嵌入到boot相關的資料中了。
系統啟動的資料傳遞
在小機端,系統啟動之後存在資料傳遞的過程,這個過程主要是資料從boot中讀出,然後存放到作業系統指定的位置。然後作業系統可以自己搬移這塊資料,或者直接使用這塊和配置有關的資料。相關的處理過程可以參見圖二。
圖二 配置系統在系統中的流程
從圖二中可以看出,boot階段把資料從boot1.bin中讀出,然後傳遞給了作業系統。作業系統拿到資料之後,做一次初始化動作,然後就一直等待使用者進行操作。當系統關機的時候,作業系統需要調用一次配置管理的退出函數,然後,整個配置系統的運作就結束。
使用者調用配置系統的資料傳遞
當使用者調用配置系統的時候,裡面存在資料傳遞。圖三表示了使用者的資料如何傳遞到系統,以及系統如何做出相應的。
圖三 配置系統使用中資料傳遞流程
通過圖三,使用者可以看出,當調用配置相關的函數的時候,系統中以及配置管理子產品如何管理使用者傳入的資料。
在系統中,提供了如下的幾個函數,提供給使用者在系統中讀取配置資訊的資料。
函數原型: int Script_parser_fetch(char *main_name,
char *sub_name, int value[], int count);
參數:main_name 主鍵名稱,即配置腳本中的主鍵名稱,字元串形式
sub_name 子鍵名稱,配置腳本中的子鍵名稱,字元串形式
value 資料指針,用于存放使用者擷取的資料
count 使用者傳進的資料空間的最大word個數
傳回值: 成功傳回0
失敗傳回-1
這個函數的功能很強大,可以擷取配置腳本中任意一項的值。
比如,使用者需要擷取配置腳本中,主鍵target下的子鍵boot_clock的值,可以寫成
{
int value;
int ret;
ret = Script_parser_fetch(“target”, “boot_clock”, &value, 1);
if(ret < 0)
printf(“fetch script data fail\n”);
else
printf(“fetch script data ok, value = %d\n”, value);
return ret;
}
在這個函數中,擷取到的值存放在整型變量value中,正常情況下,函數調用的結果是 value
= 406
如果要擷取一個配置的GPIO資訊,比如twi_para的twi_scl可以使用如下的形式
user_gpio_set_t gpio_info[1];
ret = Script_parser_fetch(“twi_para”, “twi_scl”, gpio_info, sizeof(user_gpio_set_t)/sizeof(int));
printf(“fetch script gpio infomation fail\n”);
printf(“fetch script gpio infomation ok \n”);
這個函數将把擷取到的GPIO資訊存放到結構體gpio_info中。使用者可以使用這個結果,來調用GPIO管理子產品提供的函數。
使用者也可以使用腳本函數來擷取一個字元串。
比如,存在如下的一個主鍵和子鍵項目
[string_test]
string_demo = string:abcdefghijklmn
現在,可以用這個函數來擷取出主鍵string_test的子鍵string_demo的值。正常情況下,調用如下的函數之後,string_info中儲存的值将是“abcdefghijklmn”(沒有引号)。
char string_info[128];
memset(string_info, 0, 128);
ret = Script_parser_fetch(“string_test”, “string_demo”, string_info, 128/sizeof(int));
printf(“fetch script string infomation fail\n”);
printf(“fetch script string infomation ok \n”);
擷取子鍵個數
函數原型:int Script_parser_subkey_count(char *main_name);
參數: main_name 主鍵名稱,即配置腳本中的主鍵名稱,字元串形式
傳回值: 成功傳回 主鍵下的子鍵個數
失敗傳回 -1
這個函數傳回的是一個主鍵下所有的子鍵的個數,通常使用者不會關心它。這個函數更大的用途還在于做檢查。
int sub_key_count;
sub_key_count = Script_parser_subkey_count (“target”);
if(sub_key_count < 0)
printf(“fetch script sub key count fail\n”);
printf(“fetch script sub key count ok , sub_key_count = %d\n”, sub_key_count);
return sub_key_count;
調用如上的函數,将擷取到主鍵target下的所有子鍵的個數,即得到數值4。
擷取主鍵個數
函數原型:int Script_parser_mainkey_count(void);
參數:無
傳回值: 成功傳回 配置腳本中主鍵的總的個數
這個函數将擷取所有主鍵的個數,和Script_parser_subkey_count一樣,主要用途還是做檢查使用。
int main_key_count;
main_key_count = Script_parser_mainkey_count();
if(main_key_count < 0)
printf(“fetch script main key count ok , main_key_count = %d\n”, main_key_count);
return main_key_count;
調用如上的函數,将擷取到配置腳本中主鍵的個數。
函數原型:int Script_parser_mainkey_get_gpio_count(char
*main_name);
參數:main_name 配置腳本中主鍵的名稱,字元串形式
傳回值: 成功傳回 配置腳本中主鍵下的,資料GPIO類型的子鍵個數
擷取主鍵下GPIO個數
這個函數的調用将得到主鍵下的子鍵中,值屬于GPIO類型的子鍵個數。
比如,當擷取twi_para下的子鍵中的GPIO類型時,将擷取到數值2。
int gpio_key_count;
gpio_key_count = Script_parser_mainkey_get_gpio_count (“twi_para”);
if(gpio_key_count < 0)
printf(“fetch script gpio key count ok , gpio_key_count = %d\n”, gpio_key_count);
return gpio_key_count;
如果把上面函數的參數twi_para替換成target,則得到的将是0。如果把上面函數的參數twi_para替換成nand_para,則得到的将是23。
擷取主鍵下GPIO配置
這個函數将擷取一個主鍵下,所有屬于GPIO的子鍵的GPIO描述值。
函數原型:int Script_parser_mainkey_get_gpio_cfg(char
*main_name, void *gpio_cfg, int gpio_count);
gpio_cfg 用于存放GPIO資訊的位址,應該是屬于user_gpio_set_t的資料結構
gpio_coumt 使用者傳進的結構體的個數
傳回值: 成功傳回0
失敗傳回-1
調用這個函數,将把配置腳本中比對主鍵名稱的,屬于GPIO類型的子鍵的個數。
user_gpio_set_t gpio_info[2];
ret = Script_parser_mainkey_get_gpio_cfg(“twi_para”,gpio_info, 2);
調用這個函數,将擷取配置腳本裡,twi_para的子鍵中,屬于GPIO類型的描述資訊。
本文大緻地将sysconfig1.fex簡單介紹一下,主要是為了後面分析驅動的過程做準備,大部分SUN4I平台的驅動都是采用這種方式來管理配置的,我們不妨也用這種方式.