sysconfig配置系统,作为一个通用的软件平台,还希望通过它,可以适应用户不同的方案。通过给出一个对应的配置,用户的方案就可以自动运行,而不需要修改系统里面的代码,或者重新给出参数。
一、 sysconfig1.fex简述
配置脚本的本意是给系统传递参数。作为一个稳定的系统,本身应该和方案无关, 不管不同方案的差别有多大,系统都不应该重新编译才能运行。这里所说的系统,不单单指操作系统,也包括其中的驱动,模块,等等。
不同方案的差别,通常体现在:
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端的一个文本文件,通过一个固定的格式形成可以被我们使用的文件,里面保存了大量的配置信息。在图一中,可以看到,PC端的一个数据文件如何变成了小机端可以用到的文件。
图一 小机端配置文件生成
图一中可以看出,当用户生成一个配置文件之后,不需要做额外的操作,只要按照正常的打包,烧写过程,配置文件的数据就自动被嵌入到boot相关的数据中了。
3.2 系统启动的数据传递
在小机端,系统启动之后存在数据传递的过程,这个过程主要是数据从boot中读出,然后存放到操作系统指定的位置。然后操作系统可以自己搬移这块数据,或者直接使用这块和配置有关的数据。相关的处理过程可以参见图二。
图二 配置系统在系统中的流程
从图二中可以看出,boot阶段把数据从boot1.bin中读出,然后传递给了操作系统。操作系统拿到数据之后,做一次初始化动作,然后就一直等待用户进行操作。当系统关机的时候,操作系统需要调用一次配置管理的退出函数,然后,整个配置系统的运行就结束。
3.3 用户调用配置系统的数据传递
当用户调用配置系统的时候,里面存在数据传递。图三表示了用户的数据如何传递到系统,以及系统如何做出相应的。
图三 配置系统使用中数据传递流程
通过图三,用户可以看出,当调用配置相关的函数的时候,系统中以及配置管理模块如何管理用户传入的数据。
三、 关键函数分析
在系统中,提供了如下的几个函数,提供给用户在系统中读取配置信息的数据。
函数原型: 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的值,可以写成
|
在这个函数中,获取到的值存放在整型变量value中,正常情况下,函数调用的结果是 value = 406
如果要获取一个配置的GPIO信息,比如twi_para的twi_scl可以使用如下的形式
|
这个函数将把获取到的GPIO信息存放到结构体gpio_info中。用户可以使用这个结果,来调用GPIO管理模块提供的函数。
用户也可以使用脚本函数来获取一个字符串。
比如,存在如下的一个主键和子键项目
[string_test]
string_demo = string:abcdefghijklmn
现在,可以用这个函数来获取出主键string_test的子键string_demo的值。正常情况下,调用如下的函数之后,string_info中保存的值将是“abcdefghijklmn”(没有引号)。
|
获取子键个数
函数原型:int Script_parser_subkey_count(char *main_name); 参数: main_name 主键名称,即配置脚本中的主键名称,字符串形式
返回值: 成功返回 主键下的子键个数 失败返回 -1 |
这个函数返回的是一个主键下所有的子键的个数,通常用户不会关心它。这个函数更大的用途还在于做检查。
|
调用如上的函数,将获取到主键target下的所有子键的个数,即得到数值4。
获取主键个数
函数原型:int Script_parser_mainkey_count(void);
参数:无 返回值: 成功返回 配置脚本中主键的总的个数 失败返回 -1 |
这个函数将获取所有主键的个数,和Script_parser_subkey_count一样,主要用途还是做检查使用。
|
调用如上的函数,将获取到配置脚本中主键的个数。
函数原型:int Script_parser_mainkey_get_gpio_count(char *main_name);
参数:main_name 配置脚本中主键的名称,字符串形式 返回值: 成功返回 配置脚本中主键下的,数据GPIO类型的子键个数 失败返回 -1 |
获取主键下GPIO个数
这个函数的调用将得到主键下的子键中,值属于GPIO类型的子键个数。
比如,当获取twi_para下的子键中的GPIO类型时,将获取到数值2。
|
如果把上面函数的参数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); 参数:main_name 主键名称,即配置脚本中的主键名称,字符串形式 gpio_cfg 用于存放GPIO信息的地址,应该是属于user_gpio_set_t的数据结构 gpio_coumt 用户传进的结构体的个数 返回值: 成功返回0 失败返回-1 |
调用这个函数,将把配置脚本中匹配主键名称的,属于GPIO类型的子键的个数。
|
调用这个函数,将获取配置脚本里,twi_para的子键中,属于GPIO类型的描述信息。
本文大致地将sysconfig1.fex简单介绍一下,主要是为了后面分析驱动的过程做准备,大部分SUN4I平台的驱动都是采用这种方式来管理配置的,我们不妨也用这种方式.