zoukankan      html  css  js  c++  java
  • 例说uboot从命令到驱动

    我们知道uboot的最终目标是实现将OS内核由flash中复制到ram中,并跳到操作系统分内核的入口address,将处理器的控制权交给操作系统。U-boot的一个很重要的特点就是使用命令实现对底层的操作,通过执行指令我们就可以实现上述目标。这里以实现一个简单的led_blink硬件操作,解析uboot从命令执行到操作led的过程。依照这个example,我们可以对对包括NAND,USB,串口等驱动的执行过程以及uboot的移植有一个相对清晰的认识。

    在common目录下面是常用的命令文件,文件名格式为cmd_xxx.c。如图:



    在这个目录下建立我们的命令,以及命令指定的操作函数。操作函数调用drivers目录下的驱动程序,也就是直接操作硬件的代码。drivers目录下包含了各类具体设备的驱动程序,基本上是通用的,它们通过宏从外部引入与平台或者开发板相关的functions。如图:



    从单片机的角度,drivers目录下面的驱动文件由该驱动文件同目录的makefile文件指定预处理、编译、汇编生成静态库文件,链接器从库文件取得所需的代码,复制到生成的可执行文件中。所以我们需要将我们自己写的驱动文件和命令文件都要在makefile中指定编译规则。

    下面是led_blink具体实现过程。

    首先从功能的角度,我们要实现从上层的命令操作到底层的物理操作,需要建立两个文件,一个是在drivers/gpio/sml2440_led_blink.c文件;一个是在
    文件。这样我们就可以分别依照uboot的规则,在sml2440_led_blink.c文件中写驱动,在cmd_ledblink.c文件中写命令了。

    cmd_ledblink.c具体的内容如下:

    //common/cmd_ledblink.c
    #include <common.h>
    #include <command.h>
    
    int do_led(void)
    {
    	s3c24x0_led_blink();
    	return 0 ;
    }
    
    U_BOOT_CMD(
    	led, 2, 1,	do_led,
    	"ledblink, just for test",
    	"测试指令,让led闪烁"
    	"学习指令和驱动流程"
    );
    

    分析:

    U_BOOT_CMD();是建立指令的格式(宏),led是指令名称,2是指令的参数个数,1是指令可重复执行,do_led是指令执行的函数指针。所以我们再写了一个do_led的函数,其内容是调用底层驱动的s3c24x0_led_blink();函数。头文件自行分析。

    drivers/gpio/sml2440_led_blink.c文件内容如下:

    //drivers/gpio/sml2440_led_blink.c
    
    #include <common.h>
    #include <asm/arch/s3c24x0_cpu.h>
    
    static void delay (unsigned long loops)
    {
    	__asm__ volatile ("1:\n"
    			"subs %0, %1, #1\n"
    			"bne 1b":"=r" (loops):"0" (loops));
    }
    int s3c24x0_led_init(void)
    {
    	struct s3c24x0_led *led = s3c24x0_get_base_led();
    	led->GPFCON = 0x55 ;
    	led->GPFUP = 0xff ;
    	led->GPFDAT = 0 ;
    	return 0 ;
    }
    int s3c24x0_led_blink(void)
    {
    	int N = 10 ;
    	struct s3c24x0_led *led = s3c24x0_get_base_led();
    	while(N--){
    		led->GPFDAT = 0xff ;
    		delay(20000000);
    		led->GPFDAT = 0x00 ;
    		delay(20000000);
    		}
    	return 0 ;
    	
    }

    分析:首先我们知道上层的指令led将调用s3c24x0_led_blink()函数,我们在底层续写之。为了实现这个函数,满足对底层操作的要求,我们需要操作控制led的寄存器。相信程led闪烁的方式都看得懂,就是让io引脚延时拉高,延时拉低的结果。  struct s3c24x0_led *led = s3c24x0_get_base_led();在 http://blog.csdn.net/seek_0380/article/details/8764777这篇博文里已有说明,是取出一块首地址固定符合自定义寄存器要求的内存空间。我们在s3c24x0.h中定义一块连续的寄存器空间,具体实现方法请查看链接博文(这里只是一个实现的技巧)。然后对寄存器写数据即可。


    紧接着为了生成可执行文件,我们还需要对makefile进行modified,指定规则使source file被编译。对drivers/gpio下的makefile文件内添加:

    COBJS-$(CONFIG_SML2440_LED)		+= sml2440_led_blink.o

    然后就会被连接生成静态库

    LIB 	:= $(obj)libgpio.a


    对于common下面的makefile文件,添加如下code即可。

    COBJS-y += cmd_ledblink.o


    这样我们把编译生成的uboot镜像文件下载到flash中,在terminal输入help,就会看到led驱动及其说明。我们敲入led,就会看到led闪烁了十次后,terminal回到命令接受模式。这样led_blink的uboot下的实现就完成了。


  • 相关阅读:
    C#经典书籍推荐 [转]
    ubuntu的ADSL拨号上网(主要是无线网情况下) [转]
    2007元旦粤北山区:我的“多背1公斤”
    Javascript中给动态生成的表格添加样式,JavaScript里setAttribute的问题
    Asp.net2.0的AjaxPro中不能使用Server.HtmlEncode()函数?
    去了深圳出差,到了珠海泡温泉
    2007元旦粤北山区:翻山越岭到乳源,半途而废云门寺,风雨兼程向瑶山
    很好很强大的FLEX控件
    PHP生成PDF文档的FPDF类
    Flex,事件,绑定,机制
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3034404.html
Copyright © 2011-2022 走看看