andy 发表于 2013-5-25 22:09:12

cubieboard上通过U-boot点亮板载LED

原文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_LEDCONFIG_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_LEDCONFIG_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卡,上电之后输入命令led0onled0off

led1onled1offled   all   toggle   就可以控制两个LED了

soloforce 发表于 2013-5-26 08:34:21

好贴!学习了

寒寒 发表于 2013-7-10 09:05:21

有没有不用打指令的方法,比如闪灯,把bin烧入sd,插卡后就可以看到灯闪

寒寒 发表于 2013-7-17 15:01:21

寒寒 发表于 2013-7-10 09:05 static/image/common/back.gif
有没有不用打指令的方法,比如闪灯,把bin烧入sd,插卡后就可以看到灯闪

读贴不精,再读一次就知道问题怎么解决了

tll 发表于 2013-10-6 21:58:06

本帖最后由 tll 于 2013-10-6 22:00 编辑

这个用gpio的命令去控制led就好了,实在没必要上传程序……

lknlfy 发表于 2013-11-13 09:19:11

不错哦。。

醉月 发表于 2013-11-15 09:01:37

LZ你好,我在A20的uboot.lds文件中发现是这样写的:OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
        . = 0x00000000;

        . = ALIGN(4);
        .text        :
        {
                arch/arm/cpu/armv7/start.o        (.text)
                *(.text)
        }

        . = ALIGN(4);
        .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

        . = ALIGN(4);
        .data : {
                *(.data)
        }

        . = ALIGN(4);

        . = .;
        __u_boot_cmd_start = .;
        .u_boot_cmd : { *(.u_boot_cmd) }
        __u_boot_cmd_end = .;

        . = ALIGN(4);

        __image_copy_end = .;

        .rel.dyn : {
                __rel_dyn_start = .;
                *(.rel*)
                __rel_dyn_end = .;
        }

        .dynsym : {
                __dynsym_start = .;
                *(.dynsym)
        }

        _end = .;

        .bss __rel_dyn_start (OVERLAY) : {
                __bss_start = .;
                *(.bss)
               . = ALIGN(4);
                __bss_end__ = .;
        }

        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
        /DISCARD/ : { *(.interp*) }
        /DISCARD/ : { *(.gnu*) }
}
也就是在它的前4kB中,就只有一个start.S文件,而没有从nand flsh拷贝到ram 的函数,请问这个是怎么回事...?莫非拷贝功能已经在 start.S中已经实现了?还是...?
页: [1]
查看完整版本: cubieboard上通过U-boot点亮板载LED