linux驱动学习笔记---s5pv210(一)

1,解压内核源码
tar -xvf linux-3.0.8.tar.bz2

2,内核的编译步骤:
    a,设置交叉工具链--目标文件运行在arm处理上, 修改Makefile
         195 ARCH            ?= arm
         196 CROSS_COMPILE   ?= arm-none-linux-gnueabi-
        
    
    b,选择当前开发的soc:内核源码兼容性比较强:s3c2410, s3c6410, s5pv210
        make s5pv210_defconfig   // 原理: arch/arm/configs/s5pv210_defconfig ==》拷贝到当前目录: .config (控制源码编译)
        
        
    c, 进一步选择内核模块(裁剪) //如果出现编译报错,需要安装'make menuconfig' requires the ncurses libraries.
                                //解决: sudo apt-get install libncurses5-dev
        make menuconfig     //产生一个图形界面,选择自己需要的东西
    
    d, make zImage  -j2 //编译内核. -j2表示双线程编译

    最原始的内核是不能直接运行成功, 需要做移植:
    D:\Linux驱动课程-fs210_1804\驱动参考代码和资料\1st_搭建环境\实验\系统环境搭建移植文档.doc
    
    
    
    编译完成之后:自动生成
    arch/arm/boot/zImage 
    
    
3, 启动内核:
    cp  arch/arm/boot/zImage   /tftpboot
    uboot设置:
    FS210 #     set bootcmd tftp 0x40008000 zImage \; bootm 0x40008000
        // bootcmd变量作用: uboot倒计时自动要做的事情
    FS210 #  save
        
4, 挂载根文件系统
    D:\Linux驱动课程-fs210_1804\source\rootfs_fs210.tgz ==》  /opt
        
    Ubuntu中配置    
     sudo tar -xvf rootfs_fs210.tgz  ==>      /opt/rootfs
     
     
     配置nfs服务器:
         sudo vim /etc/exports
             /opt/rootfs             *(subtree_check,rw,no_root_squash,async)
             
            
     重启nfs服务器:
      sudo service nfs-kernel-server restart

    
    uboot配置:bootargs: uboot传递给内核的参数,告诉内核挂载哪里的根文件系统
    FS210 # set bootargs  root=/dev/nfs nfsroot=192.168.7.108:/opt/rootfs_fs210 ip=192.168.7.168  console=ttySAC0,115200 init=/linuxrc
    FS210 # save
        
        // root=/dev/nfs   /dev/nfs只是一个字符串,内核需要通过nfs挂载根系统
        // nfsroot=192.168.7.3:/opt/rootfs  : 指定挂载机器的ip和路径, 路径一定要和/etc/exports中的路径保持一致
        //console=ttySAC0,115200 : 指定串口com1,波特率
        //init=/linuxrc :指定祖先进程--init进程
====================================================================================================
编写驱动代码
  

// 1, 添加头文件
#include <linux/init.h>
#include <linux/module.h>

// 3,实现驱动模块加载/卸载入口函数
static int hello_drv_init(void)
{
        printk("--------^_*  %s-------\n", __FUNCTION__);
        return 0;
}

static void hello_drv_exit(void)
{

        printk("--------^_*  %s-------\n", __FUCNTION__);

}

// 2,声明驱动模块加载/卸载入口函数
module_init(hello_drv_init);
module_exit(hello_drv_exit);

// 4, 添加gpl认证
MODULE_LICENSE("GPL");
============================================================================


Makefile的写法:
#指定内核所在路径
KERNEL_DIR = /home/farsight/s5pv210/kernel/linux-3.0.8

#获取当前路径
CURRENT_DIR = $(shell pwd)

all:
        #进入到内核源码中,执行内核Makefile, 告诉内核将当前目录中的源码编译成模块
        make -C $(KERNEL_DIR)  M=$(CURRENT_DIR) modules

clean :
        make -C $(KERNEL_DIR)  M=$(CURRENT_DIR) clean

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

#指定编译哪个模块
obj-m += hello_drv.o


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

运行:
[root@farsight /drv_module]# insmod hello_drv.ko
--------^_*  hello_drv_init-------
[root@farsight /drv_module]# lsmod
hello_drv 877 0 - Live 0x7f004000
[root@farsight /drv_module]# rmmod hello_drv
--------^_*  hello_drv_exit-------
    

=====================================================
编写驱动代码的时候,不会用vim去编写, 一般都是用source insight


1, 解压内核源码--windows某个位置

2, 将D:\Linux驱动课程-fs210_1804\source\si_linux308-ori.tgz,解压到内核linux3.0.8源码目录下

3,打开linux308-ori.PR

申请设备号:
    // 参数1---指定的主设备号--就是一个整数,选255以上
    //参数2--设备的描述--自定义的字符串
    //参数3--设备驱动的文件操作对象
    //返回值: 错误为负数,正确为0
    ret = register_chrdev(dev_major, "hello_device",  &hello_fops);

注销设备号:
    // 参数1---指定的主设备号--就是一个整数,选255以上
    //参数2--设备的描述--自定义的字符串
    unregister_chrdev(dev_major, "hello_device");


[root@farsight /drv_module]# cat /proc/devices
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
265 hello_device


ARM时钟


        
 c语言与汇编交叉代码

.text
.global _start

_start:

    @ init sp c函数中有栈的概念,汇编代码在调用c中的函数时,需要初始化栈才能使用,栈指针是从上往下走的,bl led_main
    ldr sp, =0x30008000

    @ pass args
    ldr r0, =0x100000

    bl led_main

loop:
    b loop
#define GPC0CON  *((volatile unsigned long *)0xE0200060)
#define GPC0DAT  *((volatile unsigned long *)0xE0200064)

int led_main(int delay)
{
    // c程序中对led进行控制

    // 配置 输出功能
    GPC0CON &= ~(0xff<<12);
    GPC0CON |= (0x11<<12);

    int i;
     
    while(1)
    {
	GPC0DAT |= (0x3<<3);
	for(i=delay; i>0; i--);
	GPC0DAT &= ~(0x3<<3);
	for(i=delay; i>0; i--);
    }
    
    return 0;
}

ledasm.bin : start.S 
	arm-none-linux-gnueabi-gcc -c start.S -o start.o
	arm-none-linux-gnueabi-gcc -c main.c -o main.o
	arm-none-linux-gnueabi-ld -Ttext 0x40008000   start.o main.o -o led_asm.elf
	arm-none-linux-gnueabi-objcopy -O binary led_asm.elf  ledasm.bin
	arm-none-linux-gnueabi-objdump -D led_asm.elf  > led.dis

clean:
	rm -rf *.o *.elf *.dis *.bin


install:
	cp -raf *.bin /tftpboot

       
        
        
        
        
        
        
        
        

猜你喜欢

转载自blog.csdn.net/weixin_42471952/article/details/81457890