翻译:U-Boot programming: A tutorial Part II
0赞英文原文:http://xillybus.com/tutorials/uboot-hacking-howto-2
示例:添加GPIO支持
U-Boot在多个平台上都支持GPIO,但通常不启用。 我们将简要介绍为了一个新平台而启用此功能的过程。
查看common/目录,很容易发现cmd_gpio.c文件。 它包含处理U-Boot shell中“gpio”命令的代码。
最后几行如下:
U_BOOT_CMD(gpio, 3, 0, do_gpio, "input/set/clear/toggle gpio pins", "<input|set|clear|toggle> <pin>\n" " - input/set/clear/toggle the specified pin");
它声明了do_gpio()作为处理“gpio”命令的函数。 它还写明最多允许两个参数(数字3包括命令本身),并且不允许自动重复。 还有短的和长的帮助字符串。 U_BOOT_CMD宏在doc/README.commands中进行了解释。
do_gpio()函数本质上是一个argc/argv函数,有一些额外的参数在大多数实现中都没有使用。 因此,通常从一些驱动程序API解析参数并调用较低级别的函数。
详细介绍cmd_gpio.c是完全没有意义的,通过读取命令和其他cmd _ * .c文件,可以很容易地理解命令解释和执行的原理。 在大多数情况下,它比人们期望的更简单。
至于与构建系统的交互,它也很简单:在common/ Makefile文件中,有一行
COBJS-$(CONFIG_CMD_GPIO)+= cmd_gpio.o
在没有进入构建系统的纠结部分的情况下,这一行意味着如果在Config链中定义了CONFIG_CMD_GPIO,cmd_gpio.c将被编译为cmd_gpio.o,并链接到全局项目中。 U_BOOT_CMD()宏确保该命令在U-Boot shell解释器中登记。
但还没有完成。 例如,在cmd_gpio.c中,有一个地方写了
if (sub_cmd == GPIO_INPUT) {
gpio_direction_input(gpio);
value = gpio_get_value(gpio);
}函数gpio_direction_input()和gpio_get_value()未在cmd_gpio.c本身中定义。 相反,它预期它们将由一些其他文件(“驱动程序”)定义,该文件被编译并链接到全局可执行文件中。
正如人们所料,在drivers/gpio/中有许多候选C文件,每个文件都以它所针对的平台命名。 它们都以非常类似的方式实现或多或少相同的功能集。 当然,底层的实现方式各不相同。
当然,只能编译其中一个。 至于是哪一个,取决于CONFIG的定义(如果有的话)。
在drivers/gpio/中的Makefile也是类似的,makefile有些行如下:
[ ... ] COBJS-$(CONFIG_BCM2835_GPIO)+= bcm2835_gpio.o COBJS-$(CONFIG_S3C2440_GPIO)+= s3c2440_gpio.o COBJS-$(CONFIG_XILINX_GPIO)+= xilinx_gpio.o COBJS-$(CONFIG_ADI_GPIO2)+= adi_gpio2.o [ ... ]
总而言之,要使用Xilinx的GPIO,以下两行应出现在电路板的配置文件中:
#define CONFIG_CMD_GPIO #define CONFIG_XILINX_GPIO
请注意,有时需要其他配置变量。 通过阅读驱动程序的源代码,通常可以很容易的推断出需要哪些配置变量及其含义。
要为尚未支持的硬件添加驱动程序,建议查看现有的驱动程序,看看是否有一个几乎按期望要求工作的驱动程序。 有时可以使用#ifdef调整它以使其支持新的硬件。
如果不是这种情况,建议的做法是复制最接近所需功能的驱动程序,并根据需要进行更改。 为了在构建系统中包含新驱动程序,在同一目录的Makefile中添加COBJ-$()+= ...行,并在相应的(新)CONFIG文件中启用它。
可用的API
任何代码都可以访问U-Boot中的每个函数,但某些函数更常用。 查看其他驱动程序和cmd _ * .c文件通常会得到如何编写新代码的想法。即使在小型引导加载程序中,也支持许多经典的C API。
API中有一些值得一提的功能:
1.使用writel()和readl()等访问寄存器,就像在Linux中一样,如arch/arm/include/asm/io.h中所定义。
2.可以使用setenv(),setenv_ulong(),setenv_hex(),getenv(),getenv_ulong()和getenv_hex()等函数访问环境。common/cmd_nvedit.c中定义了这些函数和其他一些函数。
3.printf()和vprintf()可用,此外getc(),putc()和puts()也可用。
4.有用于解压缩数据的gunzip()和zunzip()。
5.lib/目录包含几个库函数,用于处理字符串,CRC,哈希表,排序,加密等。
6.对于一些基本的API函数,可以在include/common.h中查找。
