天天看點

Lichee (五) sysconfig1.fex 配置系統

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端的一個資料檔案如何變成了小機端可以用到的檔案。

Lichee (五) sysconfig1.fex 配置系統

圖一 小機端配置檔案生成

圖一中可以看出,當使用者生成一個配置檔案之後,不需要做額外的操作,隻要按照正常的打包,燒寫過程,配置檔案的資料就自動被嵌入到boot相關的資料中了。

系統啟動的資料傳遞

在小機端,系統啟動之後存在資料傳遞的過程,這個過程主要是資料從boot中讀出,然後存放到作業系統指定的位置。然後作業系統可以自己搬移這塊資料,或者直接使用這塊和配置有關的資料。相關的處理過程可以參見圖二。

Lichee (五) sysconfig1.fex 配置系統

圖二 配置系統在系統中的流程

從圖二中可以看出,boot階段把資料從boot1.bin中讀出,然後傳遞給了作業系統。作業系統拿到資料之後,做一次初始化動作,然後就一直等待使用者進行操作。當系統關機的時候,作業系統需要調用一次配置管理的退出函數,然後,整個配置系統的運作就結束。

使用者調用配置系統的資料傳遞

當使用者調用配置系統的時候,裡面存在資料傳遞。圖三表示了使用者的資料如何傳遞到系統,以及系統如何做出相應的。

Lichee (五) sysconfig1.fex 配置系統

圖三  配置系統使用中資料傳遞流程

通過圖三,使用者可以看出,當調用配置相關的函數的時候,系統中以及配置管理子產品如何管理使用者傳入的資料。

在系統中,提供了如下的幾個函數,提供給使用者在系統中讀取配置資訊的資料。

函數原型: 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平台的驅動都是采用這種方式來管理配置的,我們不妨也用這種方式.

繼續閱讀