原文http://blog.csdn.net/andy_wsj/article/details/8973818
软件环境: 笔记本一台,安装WindowsXP sp3 XP下软件:Source Insight 3.5;SecureCRT;VMware Workstation7.0 虚拟机中安装ubuntu10.04 ubuntu中软件:Vim;编译工具链 arm-none-eabi- 版本4.7.2 硬件环境:cubieboard,淘宝自带的串口线和电源线 microSD卡一只,读卡器一个 准备工作:U-boot实现SD卡启动,请参考另一篇文章 http://blog.csdn.net/andy_wsj/article/details/8515197 CB的原理图 A10用户手册
在XP下用Source Insight 3.5建立u-boot代码查阅工程。 SecureCRT就是超级终端,XP还需要USB转串口的驱动,网上很多例子。
直接就在u-boot代码查阅工程中搜索"LED",出来一大片结果,最后可以定位通用的LED控制代码在文件: /u-boot-sunxi-sunxi/drivers/misc/status_led.c
调用的函数有__led_init,__led_toggle,__led_set,搜索这几个函数,定位在文件:
/u-boot-sunxi-sunxi/drivers/misc/gpio_led.c
如果需要实现LED控制,则将这两个文件修改成适合cubieboard即可。
1、编译细节处理
以上两个文件需要编译到u-boot里面去,看一下目录/u-boot-sunxi-sunxi/drivers/misc/的Makefile文件内容: .......
COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
COBJS-$(CONFIG_NS87308) += ns87308.o
COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
COBJS-$(CONFIG_STATUS_LED) += status_led.o
....... 可以看出,编译这两个文件需要定义两个宏 CONFIG_GPIO_LED CONFIG_STATUS_LED
2、函数调用细节 阅读gpio_led.c代码,调用了gpio_direction_output,gpio_set_value,gpio_get_value三个函数,在工程内搜索一下,找到相关文件就是/u-boot-sunxi-sunxi/arch/arm/cpu/armv7/sunxi/gpio.c 再来看看status_led.c内函数的调用情况,要实现LED闪烁,只要调用status_led_tick函数 搜索status_led_tick函数,可以看见其他平台的实现,都是在定时器中断中调用。如果不使用中断,最好的莫过于使用命令来控制了。到目录/u-boot-sunxi-sunxi/common看一下, 发现已经存在一个文件cmd_led.c,打开看看头文件和宏定义,如果想直接使用这个文件,再看看目录下的Makefile,那么需要定义 CONFIG_CMD_LED CONFIG_BOARD_SPECIFIC_LED 如此一来,在/u-boot-sunxi-sunxi/include/configs/sunxi-common.h最后加上下面这几行: /*LED*/ #define CONFIG_CMD_LED //使用LED命令,即编译cmd_led.c
#define CONFIG_BOARD_SPECIFIC_LED //板载特别LED
#define CONFIG_GPIO_LED //LED的IO操作,即编译../driver/misc/gpio_led.c
#define CONFIG_STATUS_LED //LED的状态控制操作,即编译../driver/misc/status_led.c, 实际上./driver/misc/status_led.c这个文件没有使用到。
这样编译会报错,因为还有一些LED相关的宏没有定义,定义在何处呢? 经过观察,我发现其他开发板都定义在status_led.h内,因此我也打算这样做 进入status_led.h,发现正好使用了CONFIG_BOARD_SPECIFIC_LED这个宏做条件编译 偷一下懒,status_led.h文件内如下定义之: #elif defined(CONFIG_BOARD_SPECIFIC_LED) #define STATUS_LED_BIT ((7 << 5) + 20) /*PH20, gpio group 7*/ #define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 10) #define STATUS_LED_STATE STATUS_LED_BLINKING
#define STATUS_LED_BIT1 ((7 << 5) + 21) /*PH21*/ #define STATUS_LED_PERIOD1 (CONFIG_SYS_HZ / 10) #define STATUS_LED_STATE1 STATUS_LED_BLINKING
解释一下这个宏: #define STATUS_LED_BIT ((7 << 5) + 20) /*PH20, gpio group 7*/ 7左移5表示:7乘以32 看看原理图,LED画在PH20和PH21上,同过IO控制三极管导通,进而控制LED状态 这时候需要看看A10的用户手册,“Port Controller”那一节,若要获得PH的控制寄存器首地址,需要 n*0x24 + 0x00 而PH是第7组IO,0x24就是十进制32,因此需要 7 << 5 加20表示是第PH20,如果是PH21就加21,当使用这个宏的时候,代码是反过来解析使用的, 阅读/u-boot-sunxi-sunxi/arch/arm/cpu/armv7/sunxi/gpio.c,就可以看到这个数据使用的方法了。 最后发现是初始化没有调用,在文件cmd_led.c里面还需要调用一下初始化,在函数 do_led 中加入
static int led_init_flag = 0;
if( led_init_flag == 0)
{
for(i=0; led_commands.mask; i++){
__led_init(led_commands.mask, 0);
}
led_init_flag = 1;
}
3、测试
编译,按SD卡启动方式写入SD卡,上电之后输入命令 led 0 on led 0 off
led 1 on led 1 off led all toggle 就可以控制两个LED了
|