tiny4412--linux驅動學習(2)

在ubuntu下編寫驗證字符設備驅動

並移植到arm開發板上

1,準備工做

  1.   uname -r  查看電腦版本信息
  2.        apt-get  install  linux-source  安裝相應版本的linux內核

 

2,編寫驅動程序

    Global CharDev.c

/* GlobalCharDev.c */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>

#include <asm/uaccess.h>


#define DEV_NAME "GlobalChar"

static ssize_t GlobalRead(struct file *, char *, size_t, loff_t *);
static ssize_t GlobalWrite(struct file *, const char *, size_t,loff_t *);

static int char_major = 0;
static int GlobalData = 0; /* "GlobalChar"設備的全局變量 */

/* 初始化字符設備驅動的 file_operations 結構體 */
struct file_operations globalchar_fops = 
{
    .read = GlobalRead,
    .write = GlobalWrite
};

/* 模塊初始化 */
static int __init GlobalChar_init(void)
{
    int ret;

    ret = register_chrdev(char_major, DEV_NAME, &globalchar_fops);/* 註冊設備驅動,_driver_char_misc.c 第290行參考  */
    if(ret < 0 )
        printk(KERN_ALERT "GlobalChar Reg Fail\n");
    else
        {
        printk(KERN_ALERT "GlobalChar Reg Success\n");
        char_major = ret;
        printk(KERN_ALERT "Major = %d\n", char_major);
        }
    return ret;
}

/* 模塊卸載函數 */
static void __exit GlobalChar_exit(void)
{
    unregister_chrdev(char_major, DEV_NAME); /* 註銷設備驅動 */
    return;
}

/* 模塊驅動讀函數 */
static ssize_t GlobalRead(struct file *file, char *buf, size_t len, loff_t *off)
{
    if (copy_to_user(buf, &GlobalData ,sizeof(int)))  
    {
        /* 從內核複製 GlobalData 到用戶空間*/
        return -EFAULT;
    }
    return sizeof(int);
}
/* 模塊驅動寫函數 */ static ssize_t GlobalWrite(struct file *file, const char *buf, size_t len, loff_t *off) { if (copy_from_user(&GlobalData, buf, sizeof(int))) { /* 從用戶複製 GlobalData 到內核 */ return -EFAULT; } return sizeof(int); } module_init(GlobalChar_init); module_exit(GlobalChar_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("dongjin");

 

  Makefile

ifneq ($(KERNELRELEASE),)    
    obj-m := GlobalCharDev.o
else
    
# KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)       //這兩個均可以

    PWD := $(shell pwd)

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

clean:
    rm -rf rm -rf *.ko *.mod* *.o* *.sy*
endif

   理解:linux

      pwd-->  驅動文件目錄shell

      kerneldir -->  內核源碼目錄ubuntu

      default -->  表示到內核源碼目錄中去編譯pwd下的驅動文件函數

——————————————————————————————————————————————————————工具

          make 編譯

root@ubuntu:/home/arm/data/char_driver# make
make -C /usr/src/linux-headers-4.4.0-31-generic M=/home/arm/data/char_driver modules
make[1]: 正在進入目錄 `/usr/src/linux-headers-4.4.0-31-generic'
  CC [M]  /home/arm/data/char_driver/GlobalCharDev.o
  Building modules, stage 2.
  MODPOST 1 modules
  LD [M]  /home/arm/data/char_driver/GlobalCharDev.ko
make[1]:正在離開目錄 `/usr/src/linux-headers-4.4.0-31-generic'

 

出現Global CharDev.ko文件

2,insmod Global CharDev.ko  將模塊加入內核

3,cat  /proc/devices  查看驅動設備

 

 

4,mknod  /dev/GlobalChar   c  247  0      根據相應的設備號,創建設備節點。

5,測試文件

/* GlobaiCharText.c 測試文件*/

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define DEV_NAME "/dev/GlobalChar"

int main()
{
     int fd, num;

     /* 打開設備文件 */
     fd = open(DEV_NAME, O_RDWR, S_IRUSR | S_IWUSR);
     if(fd < 0)
     {
     printf("Open Device Fail!\n");
          return -1;
     }

     /* 讀取當前設備數值 */
     read(fd, &num, sizeof(int));
     printf("The GlobalChar is %d\n", num);

     printf("Please input a numble written to GlobalChar: ");
     scanf("%d", &num);

     /* 寫入新的數值 */
     write(fd, &num, sizeof(int));

     /* 從新讀取數值 */
     read(fd, &num, sizeof(int));
     printf("The GlobalChar is %d\n", num);

     close(fd);
     return 0;

}

 

   gcc -o  GlobalCharText  GlobalCharText.c      編譯出可執行文件

   執行:

root@ubuntu:/home/arm/data/char_driver# ./a.out 
The GlobalChar is 0
Please input a numble written to GlobalChar: 111
The GlobalChar is 111

 

——————————————————————————————————————————————————————————————————————測試

經過NFS咱們能夠創建共享目錄,將編寫好的驅動加載到arm板,固然也須要配置環境變量。

1,驅動文件:須要將Make file中KERNLDIR 改爲 本身下載內核的地址,如:

    KERNELDIR ?= /home/arm/linux-4.4

 

 

 

2,測試文件:理所固然咱們須要使用交叉編譯去編譯出可執行文件。

注意:首先咱們要知道本身製做的作小系統是採用靜態編譯仍是動態編譯,個人採用靜態編譯

  1,靜態:

  2,動態:

須要在製做最小系統時,在  /lib  下加入所需的動態交叉編譯庫(所選交叉編譯工具目錄下的連接庫),可是我在製做randisk的過程當中,提示內存不足,暫沒查找其緣由。ui

 

若是在靜態根文件系統內使用動態編譯鏈所編譯的elf,會提示:-sh:./test:no found  (這裏 not found 指的是 連接庫)spa

 

測試:

 

卸載:.net

1,刪除  /dev  下的設備節點3d

  rm /dev/GlobalChar

2,卸載驅動

  rmmod  GlopbalCharDev.ko 

出現問題:

 

 

——————————————————————————————————————————————————————

參考:

http://tieba.baidu.com/p/3645403366

https://blog.csdn.net/Ultraman_hs/article/details/53239455

解決移植到arm上不兼容的問題

 

https://blog.csdn.net/zqj6893/article/details/48439711

解決驅動卸載問題

相關文章
相關標籤/搜索