tiny4412驱动开发

环境:

操作系统:ubuntu14.04

编译器:arm-linux-gcc-4.4.3

内核:linux-3.5

开发板:tiny4412

1安装编译工具链:

1)网上下载 arm-linux-gcc-4.4.3.tar.gz

2)解压

sudo tar -xvlf arm-linux-gcc-4.4.3.tar.gz

3)新建目录

sudo mkdir /usr/local/arm_4.4.3 arm-linux-gcc-4.4.3.tar.gz

4)移动文件到目录 arm_4.4.3

sudo mv ./opt/FriendlyARM/toolschain/4.4.3/* /usr/local/arm_4.4.3

5)配置环境变量PATH

sudo /etc/bash.bashrc

在这个文件后添加:

export PATH=$PATH:/usr/local/arm_4.4.3/bin
export PATH
source /etc/bash.bashrc

6)配置32bit的库

sudo apt-get install libc6:i386 
sudo apt-get install lib32ncurses5 
sudo apt-get install lib32z1
sudo apt-get install libstdc++6
sudo apt-get install lib32stdc++6

7)最后检查是否安装成功

arm-linux-gcc  -v

2将linux-3.5文件夹下tiny4412_linux_defconfig中的内容复制到.config中。

3编译内核

make ARCH=arm CROSS_COMPILE=arm-linux-

编译成功后:

4编写驱动程序和Makefile。

obj-m:=globalmem.o
globalmemmodule-objs:=module
	KDIR:=/home/pc/linux-3.5
	MAKE:=make
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

Globalmem.c:

#include  <linux/module.h>  
#include  <linux/types.h>  
#include  <linux/fs.h>  
#include  <linux/errno.h>  
#include  <linux/mm.h>  
#include  <linux/sched.h>  
#include  <linux/init.h>  
#include  <linux/cdev.h>  
#include  <asm/io.h>  
#include <linux/slab.h> 
#include  <linux/version.h>
#if  LINUX_VERSION_CODE  >  KERNEL_VERSION(3,  3,  0)
    #include  <asm/switch_to.h>
#else
    #include  <asm/system.h>
#endif
#include  <asm/uaccess.h>  
  
#define  GLOBALMEM_SIZE  0x1000    /*全局内存最大  4K  字节*/  
#define  MEM_CLEAR  0x1    /*清  0  全局内存*/  
#define  GLOBALMEM_MAJOR  150        /*预设的  globalmem  的主设备号*/  
  
static  int  globalmem_major  =  GLOBALMEM_MAJOR;  
/*globalmem  设备结构体*/  
struct  globalmem_dev  
{  
    struct  cdev  cdev;  /*cdev  结构体*/  
    unsigned  char  mem[GLOBALMEM_SIZE];  /*全局内存*/  
};  
  
struct  globalmem_dev  *globalmem_devp;  /*设备结构体指针*/  
  
int  globalmem_open(struct  inode  *inode,  struct  file  *filp)
{  
    filp->private_data  =  globalmem_devp;  
    return  0;
}  
int  globalmem_release(struct  inode  *inode,  struct  file  *filp)  
{  
    return  0;  
}  
  long globalmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 
{
  struct globalmem_dev *dev = filp->private_data;
/*
获得设备结构体指针
*/ 
  switch (cmd) 
  { 
    case MEM_CLEAR: 
      memset(dev->mem, 0, GLOBALMEM_SIZE); 
      printk(KERN_INFO "globalmem is set to zero\n"); 
     break; 
    default: 
      return  - EINVAL; 
  } 
  return 0; 
}
static  ssize_t  globalmem_read(struct  file  *filp,  char  __user  *buf,  size_t  size,  loff_t  *ppos)  
{  
    unsigned  long  p  =    *ppos;  
    unsigned  int  count  =  size;  
    int  ret  =  0;  
    struct  globalmem_dev  *dev  =  filp->private_data;  /*获得设备结构体指针*/  
  
    /*分析和获取有效的写长度*/  
    if  (p  >=  GLOBALMEM_SIZE)  
        return  count  ?    -  ENXIO:  0;  
    if  (count  >  GLOBALMEM_SIZE  -  p)  
        count  =  GLOBALMEM_SIZE  -  p;  
  
    /*内核空间->用户空间*/  
    if  (copy_to_user(buf,  (void*)(dev->mem  +  p),  count))  
    {  
        ret  =    -  EFAULT;  
    }  
    else  
    {  
        *ppos  +=  count;  
        ret  =  count;  
        printk(KERN_INFO  "read  %d  bytes(s)  from  %d\n",  count,  p);  
    }  
    return  ret;  
}  
  
static  ssize_t  globalmem_write(struct  file  *filp,  const  char  __user  *buf,  size_t  size,  loff_t  *ppos)  
{  
    unsigned  long  p  =    *ppos;  
    unsigned  int  count  =  size;  
    int  ret  =  0;  
    struct  globalmem_dev  *dev  =  filp->private_data;  /*获得设备结构体指针*/  
      
    /*分析和获取有效的写长度*/  
    if  (p  >=  GLOBALMEM_SIZE)  
        return  count  ?    -  ENXIO:  0;  
    if  (count  >  GLOBALMEM_SIZE  -  p)  
        count  =  GLOBALMEM_SIZE  -  p;  
      
    /*用户空间->内核空间*/  
    if  (copy_from_user(dev->mem  +  p,  buf,  count))  
        ret  =  -  EFAULT;  
    else  
    {  
        *ppos  +=  count;  
        ret  =  count;  
        printk(KERN_INFO  "written  %d  bytes(s)  from  %d\n",  count,  p);  
    }  
    return  ret;  
}  

static  loff_t  globalmem_llseek(struct  file  *filp,  loff_t  offset,  int  orig)  
{  
    loff_t  ret  =  0;  
    switch  (orig)  
    {  
        case  0:        /*相对文件开始位置偏移*/  
            if  (offset  <  0)  
            {  
                ret  =    -  EINVAL;  
                break;  
            }  
            if  ((unsigned  int)offset  >  GLOBALMEM_SIZE)  
            {  
                ret  =    -  EINVAL;  
                break;  
            }  
            filp->f_pos  =  (unsigned  int)offset;  
            ret  =  filp->f_pos;  
            break;  
        case  1:        /*相对文件当前位置偏移*/  
            if  ((filp->f_pos  +  offset)  >  GLOBALMEM_SIZE)  
            {  
                ret  =    -  EINVAL;  
                break;  
            }  
            if  ((filp->f_pos  +  offset)  <  0)  
            {  
                ret  =    -  EINVAL;  
                break;  
            }  
            filp->f_pos  +=  offset;  
            ret  =  filp->f_pos;  
            break;  
        default:  
            ret  =    -  EINVAL;  
            break;  
    }  
    return  ret;  
}  
  
static  const  struct  file_operations  globalmem_fops  =  
{  
    .owner  =  THIS_MODULE,  
    .llseek  =  globalmem_llseek,  
    .read  =  globalmem_read,  
    .write  =  globalmem_write,  
    .unlocked_ioctl  =  globalmem_ioctl,  
    .open  =  globalmem_open,  
    .release  =  globalmem_release,  
};  
static  void  globalmem_setup_cdev(struct  globalmem_dev  *dev,  int  index)  
{  
    int  err,  devno  =  MKDEV(globalmem_major,  index);  
  
    cdev_init(&dev->cdev,  &globalmem_fops);  
    dev->cdev.owner  =  THIS_MODULE;  
    dev->cdev.ops  =  &globalmem_fops;  
    err  =  cdev_add(&dev->cdev,  devno,  1);  
    if  (err)  
        printk(KERN_NOTICE  "Error  %d  adding  LED%d",  err,  index);  
}  
int  globalmem_init(void)  
{  
    int  result;  
    dev_t  devno  =  MKDEV(globalmem_major,  0);  
  
    /*    申请设备号*/  
    if  (globalmem_major)  
        result  =  register_chrdev_region(devno,  1,  "globalmem");  
    else    /*    动态申请设备号    */  
    {  
        result  =  alloc_chrdev_region(&devno,  0,  1,  "globalmem");  
        globalmem_major  =  MAJOR(devno);  
    }      
    if  (result  <  0)  
        return  result;  
      
    /*    动态申请设备结构体的内存*/  
    globalmem_devp  =  kmalloc(sizeof(struct  globalmem_dev),  GFP_KERNEL);  
    if  (!globalmem_devp)        /*申请失败*/  
    {  
        result  =    -  ENOMEM;  
        goto  fail_malloc;  
    }  
    memset(globalmem_devp,  0,  sizeof(struct  globalmem_dev));  
    globalmem_setup_cdev(globalmem_devp,  0);  
    return  0;  
fail_malloc:  unregister_chrdev_region(devno,  1);  
    return  result;  
}  
  
void  globalmem_exit(void)  
{  
    cdev_del(&globalmem_devp->cdev);        /*注销  cdev*/  
    kfree(globalmem_devp);            /*释放设备结构体内存*/  
    unregister_chrdev_region(MKDEV(globalmem_major,  0),  1);  /*释放设备号*/  
}  
MODULE_AUTHOR("Song  Baohua");  
MODULE_LICENSE("Dual  BSD/GPL");  
module_param(globalmem_major,  int,  S_IRUGO);  
module_init(globalmem_init);  
module_exit(globalmem_exit);

5输入make:

 

6连接启动板子,将所需文件传送上去。

7输入insmod globalmem.ko命令将字符驱动设备加载进去。

然后输入cat /proc/devices命令查看驱动信息。

8验证

echo "hello world" > /dev/globalmem
cat /dev/globalmem

结果输出helloworld。

posted @ 2018-06-05 21:43  奇热行  阅读(435)  评论(0)    收藏  举报