例说uboot从命令到驱动

来源:互联网 发布:山东11选5最大遗漏数据 编辑:程序博客网 时间:2024/04/28 01:10

例说uboot从命令到驱动

本文转自:http://blog.csdn.net/zhouxinlin2009/article/details/45389987

我们知道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文件内容如下:

[cpp] view plain copy print?
  1. //drivers/gpio/sml2440_led_blink.c 
  2.  
  3. #include <common.h> 
  4. #include <asm/arch/s3c24x0_cpu.h> 
  5.  
  6. static void delay (unsignedlong loops) 
  7.     __asm__ volatile ("1:\n" 
  8.             "subs %0, %1, #1\n" 
  9.             "bne 1b":"=r" (loops):"0" (loops)); 
  10. int s3c24x0_led_init(void
  11.     struct s3c24x0_led *led = s3c24x0_get_base_led(); 
  12.     led->GPFCON = 0x55 ; 
  13.     led->GPFUP = 0xff ; 
  14.     led->GPFDAT = 0 ; 
  15.     return 0 ; 
  16. int s3c24x0_led_blink(void
  17.     int N = 10 ; 
  18.     struct s3c24x0_led *led = s3c24x0_get_base_led(); 
  19.     while(N--){ 
  20.         led->GPFDAT = 0xff ; 
  21.         delay(20000000); 
  22.         led->GPFDAT = 0x00 ; 
  23.         delay(20000000); 
  24.         } 
  25.     return 0 ; 
  26.      

分析:首先我们知道上层的指令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文件内添加:

[cpp] view plain copy print?
  1. COBJS-$(CONFIG_SML2440_LED)     += sml2440_led_blink.o 

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

[cpp] view plain copy print?
  1. LIB     := $(obj)libgpio.a 


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

[cpp] view plain copy print?
  1. COBJS-y += cmd_ledblink.o 
 


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

0 0
原创粉丝点击