1. 程式人生 > >linux驅動學習筆記---s5pv210(一)

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


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

執行:
[[email protected] /drv_module]# insmod hello_drv.ko
--------^_*  hello_drv_init-------
[[email protected] /drv_module]# lsmod
hello_drv 877 0 - Live 0x7f004000
[[email protected] /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");


[[email protected] /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