[day]__驱动基础01

 

1、u-boot的启动及基本烧写、挂载、设置 命令 

2、内核的裁剪、编译及错误处理(网卡驱动的添加)  

3、简单驱动代码的编写、Makefile模块文件编写、     ko文件的编译及在开发板中的运行
====================================================================

运行开发板:

1,uboot的用法:  FS210 # help nand  

nand info                  - show available NAND devices  

nand device [dev]       - show or set current device  

nand read[.jffs2]       - addr off|partition size  

nand write[.jffs2]      - addr off|partiton size - read/write `size' bytes starting   at offset `off' to/from memory address `addr'  

nand write[.yaffs[1]]   - addr off|partition size - write `size' byte yaffs image   starting at offset `off' from memory address `addr' (.yaffs1 for 512+16 NAND)  

nand erase [clean] [off size]   - erase `size' bytes from   offset `off' (entire device if not specified)  

nand bad       - show bad blocks

 nand dump[.oob] off   - dump page  

nand scrub     - really clean NAND erasing bad blocks (UNSAFE)  

nand markbad off   - mark bad block at offset (UNSAFE)  

nand biterr off   - make a bit error at offset (UNSAFE)  

nand lock [tight] [status]   - bring nand to lock state or display locked pages  

nand unlock [offset] [size]   - unlock section    

 

操作nandflash的命令:   

写nand:    

nand erase 0x100000 0x400000    

nand write 0x40008000 0x100000 0x400000       

读nand:    

nand read 0x40008000 0x100000 0x400000    

 

2,在uboot中去设置参数,能够启动内核并让内容挂载根文件系统:  

1,启动内核:  

 a,在ubuntu中,将uImage放在/tftpboot       

  E:\Linux驱动开发-s5pv210-george\source\image\uImage308     

b,在开发板uboot中:    bootcmd的作用:倒计时结束后uboot需要做什么    

  FS210 # set serverip 192.168.7.11 //ubuntu--tftp服务器的ip    

  FS210 # set ipaddr 192.168.7.7 //开发板ip--ubuntu ip + 60    

  FS210 # set bootcmd tftp 0x40008000 uImage \; bootm 0x40008000    

  FS210 # save

 2,挂载根文件系统:   

a,将rootfs放入到ubuntu-/opt    

E:\Linux驱动开发-s5pv210-george\source\rootfs_fs210.tgz       解压:    sudo tar -xvf rootfs_fs210.tgz      

b,设置nfs服务器--设置/opt/rootfs能够被挂载    

sudo vim /etc/exports      /opt/rootfs             *(subtree_check,rw,no_root_squash,async)        

重启nfs服务器:    sudo service nfs-kernel-server restart      

c,在开发板操作:   

 FS210 # set bootargs console=ttySAC0,115200 init=/linuxrc root=/dev/nfs nfsroot=192.168.7.11:/opt/rootfs ip=192.168.7.7    

FS210 # save

 

bootargs :传递给内核的参数      

console=xxx: 内核启动的调试信息通过什么设备输出      

init=xxx: 告诉内核整个系统的祖先进程是什么      

root=xxx: 告诉内核根文件系统在哪里       

root=/dev/nfs  告诉内核根文件系统在网络远端       

nfsroot=ip:path      ip=xx: 告诉内核开机为系统分配一个静态ip(开发板ip)   

 u-boot常用的环境变量:

环境变量

描述

bootdelay

执行自动启动的等候秒数

baudrate

串口控制台的波特率

netmask

以太网接口的掩码

ethaddr

以太网卡的网卡物理地址

bootfile

缺省的下载文件

bootargs

传递给内核的启动参数

bootcmd

自动启动时执行的命令

serverip

服务器端的ip地址

ipaddr

本地ip地址

stdin

标准输入设备

stdout

标准输出设备

stderr

标准出错设备

 

 

编译内核  

1,获取内核源码    www.kernel.org

  选择一个能够支持你的soc的内核   3.0.8 ==>android底层     

2,tar -xvf linux-3.0.8.tar.bz2

 3,编译:具体操作参考---E:\Linux驱动开发-s5pv210-george\初级驱动\第一天\实验\系统环境搭建移植文档.doc     

0--设置交叉工具链:E:\Linux驱动开发-s5pv210-george\source\toolchain-4.5.1-farsight.tar.bz2    

解压到ubuntu:     

sudo mkdir /usr/local/arm          

sudo tar -xvf toolchain-4.5.1-farsight.tar.bz2  -C /usr/local/arm/        

设置环境PATH(直接快速的使用arm-none-linux-gnueabi-gcc):     

vim ~/.bashrc      

export PATH=$PATH:/usr/local/arm/toolchain-4.5.1-farsight/bin/     

保存后更新:      source ~/.bashrc       

 

a, 设置交叉工具链--arm的编译器--内核源码的Makefile    

195 ARCH            ?= arm    

196 CROSS_COMPILE   ?= arm-none-linux-gnueabi-

b,选择一个soc(挑出针对s5pv210相关代码)    

make s5pv210_defconfig      //内部中: cp -raf  arch/arm/configs/s5pv210_defconfig   .config      

c,make menuconfig --内核裁剪--选择你想要    

General setup  --->

         [*] Configure standard kernel features (expert users)  --->

   System Type  --->      
       (0) S3C UART to use for low-level messages            

   Kernel Features  --->

              Memory split (3G/1G user/kernel split)  --->

   [ * ] Networking support  --->

          Networking options  --->

         <*>Packet sockets      

     <*> Unix domain sockets       

    [*] TCP/IP networking         

     [*]   IP: multicasting          

     [*]IP: kernel level autoconfiguration          

    [*]     IP: DHCP support          

    [*]     IP: BOOTP support         

     [*]     IP: RARP support    

 Device Drivers  --->

      [*] Network device support  --->

         [*]   Ethernet (10 or 100Mbit)  --->

         <*>   DM9000 support    

  File systems  --->

       [*] Network File Systems (NEW)  --->

        <*>   NFS client support      

    [*]     NFS client support for NFS version 3     

     [*]       NFS client support for the NFSv3 ACL protocol extension      

    [*]   Root file system on NFS              

 

  注意:     除了以上选择,记得要做dm9000的移植

             (参考文档中“fs210之网卡驱动添加”,打开"arch/arm/mach-s5pv210/mach-smdkv210.c",需修改网卡的mac地址(即 smdkv210_dm9000_platdata结构体)、修改结构体数组smdkv210_dm9000_resources中的地址端口、修改函数smdkv210_dm9000_init参考手册进行时序配置(可看伟东山视频))     

   ============================================================    

如果make menuconfig报错:    

 lpf@ubuntu:/home/farsight/linux_source/linux-3.0.8$ make menuconfig     

*** Unable to find the ncurses libraries or the     

*** required header files.     

*** 'make menuconfig' requires the ncurses libraries.     

***     

*** Install ncurses (ncurses-devel) and try again.     

***     

解决:     sudo apt-get install libncurses5-dev

   ============================================================   

d,编译内核--make uImage    

make uImage


 备注:   

   编译内核:    

   make uImage  ==>生成zImage和uImage(需要mkimage的支持, 放入到ubuntu---/usr/bin/)       

   E:\Linux驱动开发-s5pv210-george\初级驱动\第一天\实验\mkimage              

     sudo mv  mkimage /usr/bin/       

    sudo chmod 777 /usr/bin/mkimage     

    make zImage  ==》只生成zImage      

e,使用自己编译的内核:    

cp arch/arm/boot/uImage  /tftpboot/   

 

编写代码:  .

c +  Makefile    

 

驱动代码编写:   

1, 头文件   

 #include <linux/init.h>   

 #include <linux/module.h>    

  2, 模块的装载和卸载入口函数的声明    

module_init(hello_drv_init);    

module_exit(hello_drv_exit);

  3, GPL的认证    

MODULE_LICENSE("GPL");  

 4, 模块的装载和卸载入口函数的实现   

 static int __init hello_drv_init(void)    {

     return 0;    }

   static void __exit hello_drv_exit(void)    {

   }

 

 Makefile:  

 #KERNELRELEASE是内核源码中一个变量  

 ifeq ($(KERNELRELEASE),)   

#获取内核路径   

KERN_DIR = /home/farsight/linux_system/kernel/linux-3.0.8  

 #当前代码路径   

CUR_DIR = $(shell pwd)

 

  all :    

 #进入到内核目录,执行内核Makefile,并且告诉内核将当前的源码编译成模块     

make -C $(KERN_DIR) M=$(CUR_DIR) modules

  clean :     make -C $(KERN_DIR) M=$(CUR_DIR) clean

  install :     cp -raf  *.ko  /opt/rootfs/drv_module

 

  else   

#将当前的hello.c编译成hello.ko   

#指定编译哪个   

obj-m += hello.o

 

  endif

 

ifeq ($(KERNELRELEASE),) KERNELDIR ?= /home/linux/linux-2.6.22.6 PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules modules_install clean else obj-m := myhello.o endif

其中有一些是我们常见或是见过的,第一个ifeq ($(KERNELRELEASE),)目前,并无用处,它的由来是指在Linux源码根目录下的Makefile编译内核时,KERNELRELEASE宏会被定义,那么如果是从源码根目录开始的make则会将myhello.o模块编译进内核。

KERNELDIR ?= /home/linux/linux-2.6.22.6,这句是对KERNELDIR进行赋值,这个变量是后面我们用到的指代内核源码目录用的

PWD := $(shell pwd),这句是对PWD变量进行赋值,作用是将$(shell pwd)的返回结果既求得当前目录的路径赋值给PWD这个变量我们在后面指代我们要编译的驱动程序所在的位置

modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

这句是Makefile的规则:这里的$(MAKE)就相当于make-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。

modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

这个命令是模块的安装,在Makefile中搜索“lib\/modules”可以看到下面的语句,通过阅读你不难找到这个“MODLIB”的用处,它是用来指定安装路径的,而变量“INSTALL_MOD_PATH”往往为空。

MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) Export MODLIB

.PHONY: modules modules_install clean

这句话是的作用是保证modules,modules_install,clean这三个命令能正常完成。.PHONY 这是一个特殊目标名称,还有其它的,如:

.SUFFIXES,.DEFAULT,.PRECIOUS,.INTERMEDIATE,.SECONDARY,.SECONDEXPANSION,.DELETE_ON_ERROR,.IGNORE .LOW_RESOLUTION_TIME .SILENT .EXPORT_ALL_VARIABLES .NOTPARALLEL

它们的具体用法可以参考GNU手册中的Special Built-in Target Names章节。

.PHONY目标的具体意思是如果在Makefile的工作目录中有名如:modules,modules_install,clean等文件时命令会出错。它是防止这出错的方式。

 

运行ko:  

[root@farsight /drv_module]# insmod hello.ko  

--------^_^ hello_drv_init--------  

[root@farsight /drv_module]# rmmod hello  

--------^_^ hello_drv_exit--------  

[root@farsight /drv_module]# insmod hello.ko  

--------^_^ hello_drv_init--------  

[root@farsight /drv_module]# lsmod  

hello 755 0 - Live 0xbf004000

 

     

推荐大家使用source insight编写代码:  

E:\Linux驱动开发-s5pv210-george\source\si_linux308-ori.tgz(已经做好工程,一定解压到源码目录)

 

模块传递参数: insmod hello.ko 或者: insmod hello.ko myname="xxx" age=777
驱动中: module_param(myname,charp, 0644); module_param(age, int, 0644);

 

 

任务: 1,将开发板运行起来--用提供好的 2,编译内核--移植dm9000网卡--用自己编译的内核 3,编译最简单的驱动模块 4,编写Makefile 5,用sourceinsight去写参数传递 ==================================================

posted @ 2017-06-24 01:47  chengj001  阅读(93)  评论(0)    收藏  举报