由于刚开始学习驱动开发方面的相关知识,在博客上也参考了大量的博文,但博文中的驱动代码编译过程大都相对简略一些。在这里,我根据自己电脑的工作环境,阐述一个关于字符设备驱动代码编译的详细流程,如果有不足或者需要纠正的地方,欢迎大佬们指出!
本文的运行代码见文章最后,例:chardrv_test。
如下例:
config CHARDRV_TEST
tristate "chardrv test program"
default n
help
Implements a shared memory based transport mechanism that allows
for a debugger running on a host PC to communicate with a remote
stub running on peripheral subsystems such as the ADSP, MODEM etc.
如下例:
在 obj-y += misc.o 后加 obj-$(CONFIG_CHARDRV_TEST) += chardrv_test.o
如下例,依次输入所列命令:
r >>> ls >>> cd android_5/LA.BR.1.2.3-10210-8x09.0/ >>> source build/envsetup.sh >>> lunch >>> msm8909-userdebug >>> (source build/envsetup.sh)make bootimage
如下例:
adb devices >>> adb root >>> adb remount >>> adb shell >>> exit >>>
接着在 C:\Users\Admin\Desktop> 路径下执行如下操作:
adb reboot bootloader >>> fast flash boot (+路径,例如:W:\android_5\LA.BR.1.2.3-10210-8x09.0\out\target\product\msm8909\boot.img) >>> fastboot reboot
文中所列代码:
#include
#include
#include
#include
#include
#include
#include
int dev1_registers[5]; //两个数组模拟两个字符型设备
int dev2_registers[5];
struct cdev cdev; //定义一个设备变量
dev_t devno; //定义一个设备号变量
struct class *cdev_class;
/*文件打开函数*/
int wumany_open(struct inode *inode, struct file *filp)
{
/*获取次设备号*/
int num = MINOR(inode->i_rdev);
pr_err("wumanyuan>>>%s: enter\n", __func__);
if (num==0)
filp->private_data = dev1_registers; //把设备地址赋值给filp->private_data
else if(num == 1)
filp->private_data = dev2_registers;
else
return -ENODEV; //无效的次设备号
return 0;
}
/*文件释放函数*/
int wumany_release(struct inode *inode, struct file *filp)
{
pr_err("wumanyuan>>>%s: enter\n", __func__);
return 0;
}
/*读函数*/
static ssize_t wumany_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
int *register_addr = filp->private_data; /*获取设备的寄存器基地址,//在open函数里,已经把设备的地址赋值给了filp->private_data*/
pr_err("wumanyuan>>>%s: enter\n", __func__);
/*判断读位置是否有效*/
if (p >= 5*sizeof(int))
return 0;
if (count > 5*sizeof(int) - p)
count = 5*sizeof(int) - p;
/*读数据到用户空间*/
if (copy_to_user(buf, register_addr+p, count))
{
ret = -EFAULT;
}
else
{
*ppos += count;
ret = count;
}
return ret;
}
/*写函数*/
static ssize_t wumany_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;
int *register_addr = filp->private_data; /*获取设备的寄存器地址*/
pr_err("wumanyuan>>>%s: enter\n", __func__);
/*分析和获取有效的写长度*/
if (p >= 5*sizeof(int))
return 0;
if (count > 5*sizeof(int) - p)
count = 5*sizeof(int) - p;
/*从用户空间写入数据*/
if (copy_from_user(register_addr + p, buf, count))
ret = -EFAULT;
else
{
*ppos += count;
ret = count;
}
return ret;
}
/* seek文件定位函数 */
static loff_t wumany_llseek(struct file *filp, loff_t offset, int whence)
{
loff_t newpos;
pr_err("wumanyuan>>>%s: enter\n", __func__);
switch(whence) {
case SEEK_SET:
newpos = offset;
break;
case SEEK_CUR:
newpos = filp->f_pos + offset;
break;
case SEEK_END:
newpos = 5*sizeof(int)-1 + offset;
break;
default:
return -EINVAL;
}
if ((newpos<0) || (newpos>5*sizeof(int)))
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
/*文件操作结构体*/
static const struct file_operations wumany_fops =
{
.owner = THIS_MODULE,
.llseek = wumany_llseek,
.read = wumany_read,
.write = wumany_write,
.open = wumany_open,
.release = wumany_release,
};
/*设备驱动模块加载函数*/
static int wumanydev_init(void)
{
pr_err("wumanyuan>>>%s: enter\n", __func__);
/*初始化cdev结构*/
cdev_init(&cdev, &wumany_fops);
pr_err("wumanyuan>>>%s: 1111111\n", __func__);
/* 注册字符设备 */
alloc_chrdev_region(&devno, 0, 2, "wumanyuan"); //注册两个设备,此设备号的起始值为0
pr_err("wumanyuan>>>%s: 2222222\n", __func__);
cdev_add(&cdev, devno, 2); //向系统添加设备
pr_err("wumanyuan>>>%s: 33333333\n", __func__);
cdev_class=class_create(THIS_MODULE,"wumanyuan");// /sys/class/wumanyuan
device_create(cdev_class,NULL,devno,0,"yuan");// /dev/yuan
return 0;
}
/*模块卸载函数*/
static void wumanydev_exit(void)
{
pr_err("wumanyuan>>>%s: enter\n", __func__);
cdev_del(&cdev); /*注销设备*/
device_destroy(cdev_class, devno);
class_destroy(cdev_class);
unregister_chrdev_region(devno, 2); /*释放设备号*/
}
module_init(wumanydev_init);
module_exit(wumanydev_exit);
MODULE_LICENSE("GPL");
【1】 https://blog.csdn.net/a201106107/article/details/36905159