【正点原子RV1126 AI Linux开发板】 字符设备驱动例程测试
[复制链接]
按照教程再来学习下字符设备驱动程序的开发,通过基础例程来学习下驱动框架。
一、字符设备驱动
字符设备是linux驱动程序中最基本的设备驱动,就是一个一个字节按照字节流进行读写操作的设备。
linux应用程序对驱动程序的调用流程
二、例程代码
2.1、驱动程序代码
chrdevbase.c
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
-
- #include <asm/io.h>
-
-
- #define CHRDEVBASE_MAJOR 200 /* 主设备号 */
- #define CHRDEVBASE_NAME "chrdevbase" /* 设备名 */
-
- static char readbuf[100];
- static char writebuf[100];
- static char kerneldata[] = {"RV1126 开发板字符设备驱动-内核数据!"};
-
-
-
- static int chrdevbase_open(struct inode *inode, struct file *filp)
- {
-
- return 0;
- }
-
-
- static ssize_t chrdevbase_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- int retvalue = 0;
-
-
- memcpy(readbuf, kerneldata, sizeof(kerneldata));
- retvalue = copy_to_user(buf, readbuf, cnt);
- if(retvalue == 0){
- printk("向内核发送数据完成!\r\n");
- }else{
- printk("kernel senddata failed!\r\n");
- }
-
-
- return 0;
- }
-
-
- static ssize_t chrdevbase_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
- {
- int retvalue = 0;
-
- retvalue = copy_from_user(writebuf, buf, cnt);
- if(retvalue == 0){
- printk("内核接收数据内容:%s\r\n", writebuf);
- }else{
- printk("kernel recevdata failed!\r\n");
- }
-
-
- return 0;
- }
-
-
- static int chrdevbase_release(struct inode *inode, struct file *filp)
- {
-
- return 0;
- }
-
-
- static struct file_operations chrdevbase_fops = {
- .owner = THIS_MODULE,
- .open = chrdevbase_open,
- .read = chrdevbase_read,
- .write = chrdevbase_write,
- .release = chrdevbase_release,
- };
-
-
- static int __init chrdevbase_init(void)
- {
- int retvalue = 0;
-
-
- retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);
- if(retvalue < 0){
- printk("chrdevbase driver register failed\r\n");
- }
- printk("chrdevbase init!\r\n");
- return 0;
- }
-
-
- static void __exit chrdevbase_exit(void)
- {
-
- unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);
- printk("chrdevbase exit!\r\n");
- }
-
-
- module_init(chrdevbase_init);
- module_exit(chrdevbase_exit);
-
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("ALIENTEK");
- MODULE_INFO(intree, "Y");
2.2、应用程序代码
chrdevbaseApp.c
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
-
- #include <asm/io.h>
-
-
- #define CHRDEVBASE_MAJOR 200 /* 主设备号 */
- #define CHRDEVBASE_NAME "chrdevbase" /* 设备名 */
-
- static char readbuf[100];
- static char writebuf[100];
- static char kerneldata[] = {"RV1126 开发板字符设备驱动-内核数据!"};
-
-
-
- static int chrdevbase_open(struct inode *inode, struct file *filp)
- {
-
- return 0;
- }
-
-
- static ssize_t chrdevbase_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- int retvalue = 0;
-
-
- memcpy(readbuf, kerneldata, sizeof(kerneldata));
- retvalue = copy_to_user(buf, readbuf, cnt);
- if(retvalue == 0){
- printk("向内核发送数据完成!\r\n");
- }else{
- printk("kernel senddata failed!\r\n");
- }
-
-
- return 0;
- }
-
-
- static ssize_t chrdevbase_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
- {
- int retvalue = 0;
-
- retvalue = copy_from_user(writebuf, buf, cnt);
- if(retvalue == 0){
- printk("内核接收数据内容:%s\r\n", writebuf);
- }else{
- printk("kernel recevdata failed!\r\n");
- }
-
-
- return 0;
- }
-
-
- static int chrdevbase_release(struct inode *inode, struct file *filp)
- {
-
- return 0;
- }
-
-
- static struct file_operations chrdevbase_fops = {
- .owner = THIS_MODULE,
- .open = chrdevbase_open,
- .read = chrdevbase_read,
- .write = chrdevbase_write,
- .release = chrdevbase_release,
- };
-
-
- static int __init chrdevbase_init(void)
- {
- int retvalue = 0;
-
-
- retvalue = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);
- if(retvalue < 0){
- printk("chrdevbase driver register failed\r\n");
- }
- printk("chrdevbase init!\r\n");
- return 0;
- }
-
-
- static void __exit chrdevbase_exit(void)
- {
-
- unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);
- printk("chrdevbase exit!\r\n");
- }
-
-
- module_init(chrdevbase_init);
- module_exit(chrdevbase_exit);
-
-
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("ALIENTEK");
- MODULE_INFO(intree, "Y");
三、编译程序及复制文件
3.1、编译内核
hui@ubuntu:/opt/atk-rv1126_app/01_chrdevbase$ sudo make ARCH=arm
3.2、编译应用程序
hui@ubuntu:/opt/atk-rv1126_app/01_chrdevbase$ sudo /opt/atk-dlrv1126-toolchain/bin/arm-linux-gnueabihf-gcc chrdevbaseApp.c -o chrdevbaseApp
3.3、复制文件到开发板
复制编译后的文件到开发板
hui@ubuntu:/opt/atk-rv1126_app/01_chrdevbase$ scp chrdevbase.ko root@192.168.1.106:/lib/modules/4.19.111
hui@ubuntu:/opt/atk-rv1126_app/01_chrdevbase$ scp chrdevbaseApp root@192.168.1.106:/lib/modules/4.19.111
四、测试
4.1、加载驱动模块
[root@ATK-DLRV1126:/lib/modules/4.19.111]# modprobe chrdevbase
加载后,查看已经加载的模块。
4.2、创建设备节点
[root@ATK-DLRV1126:/lib/modules/4.19.111]# mknod /dev/chrdevbase c 200 0
查看系统设备
上面添加的设备成功
4.3、应用程序测试
4.3.1、用户程序给内核写数据
[root@ATK-DLRV1126:/lib/modules/4.19.111]# ./chrdevbaseApp /dev/chrdevbase 2
内核接收到用户程序发送的数据
4.3.2、用户程序读内核数据
[root@ATK-DLRV1126:/lib/modules/4.19.111]# ./chrdevbaseApp /dev/chrdevbase 1
从内核读到的数据内容
|