字符设备驱动基础中-作业
led--- GPX2_7 --- GPX2CON ==0x11000C40 GPX2DAT ==0x11000C44 将0x11000C40映射成虚拟地址 对虚拟地址中到[32:28] = 0x1
代码展示:
//------------------chr_drv.c------------------ //驱动程序代码 #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/uaccess.h> #include <asm/io.h> #define GPX2CON_ADDR 0x11000c40 #define GPX2CON_SIZE 8 unsigned int major_id = 502; const char major_name[] = "test"; struct class* pmyclass = NULL; struct device* pmydevice =NULL; volatile unsigned int* GPX2CON; volatile unsigned int* GPX2DAT; int chr_drv_open (struct inode *inode, struct file *filp) { printk("------------%s----------\n",__FUNCTION__); return 0; } ssize_t chr_drv_read (struct file * filp, char __user *buf, size_t count, loff_t *fpos) { int buf_read = 666; int ret; ret = copy_to_user(buf,&buf_read,count); if(ret == 0) { printk("------------%s----------\n",__FUNCTION__); } else { printk("KERN:Error to read\n"); return -EFAULT; } return 0; } ssize_t chr_drv_write (struct file *filp, const char __user *buf, size_t count, loff_t *fpos) { int buf_write = 0; int ret; ret = copy_from_user(&buf_write,buf,count); if(ret == 0) { printk("__KERN__:%d\n",buf_write); if(buf_write == 0){ *GPX2DAT &= ~(0x1<<7); } else{ *GPX2DAT |= (0x1<<7); } } else { printk("KERN:Error to read\n"); return -EFAULT; } return 0; } int chr_drv_close (struct inode *inode, struct file *filp) { printk("------------%s----------\n",__FUNCTION__); return 0; } const struct file_operations major_fops = { .open = chr_drv_open, .read = chr_drv_read, .write = chr_drv_write, .release = chr_drv_close, }; static int __init my_chrdrv_init(void) { //一般都是申请资源 //申请设备号 int ret = register_chrdev(major_id, major_name, &major_fops); if (ret == 0){ printk("register ok\n"); } else{ printk("register failed"); return -EFAULT; } pmyclass = class_create(THIS_MODULE,"TEST1"); pmydevice = device_create(pmyclass,NULL,MKDEV(502, 0),NULL,"mychr0"); GPX2CON = (unsigned int*)ioremap(GPX2CON_ADDR,GPX2CON_SIZE) ; GPX2DAT = GPX2CON + 1; *GPX2CON &= ~(0xf << 28); *GPX2CON |= (0x1 << 28); return 0; } static void __exit my_chrdrv_exit(void) { //一般都是释放资源 //释放设备号资源 unregister_chrdev(major_id, major_name); device_destroy(pmyclass,MKDEV(502, 0)); class_destroy(pmyclass); iounmap(GPX2CON); } MODULE_LICENSE("GPL"); module_init(my_chrdrv_init); module_exit(my_chrdrv_exit);
//--------------drvtest.c------------------- //APP 代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { int fd; int buf = 233; fd = open("/dev/mychr0",O_RDWR); if(fd < 0) { perror("open"); exit(1); } while(1){ buf = 0; write(fd, &buf, 4); sleep(1); buf = 1; write(fd, &buf, 4); sleep(1); } read(fd, &buf, 4); close(fd); return 0; }
Makefile代码
ROOTFS_DIR = /home/linux/Level11 APP_NAME = drvtest CROSS_COMPILE = arm-none-linux-gnueabi- CC = $(CROSS_COMPILE)gcc ifeq ($(KERNELRELEASE), ) KERNEL_DIR = /home/linux/Level10/day6/linux-5.4.79 CUR_DIR = $(shell pwd) all : make -C $(KERNEL_DIR) M=$(CUR_DIR) modules -j6 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- $(CC) $(APP_NAME).c -o $(APP_NAME) clean : make -C $(KERNEL_DIR) M=$(CUR_DIR) clean install: cp -raf *.ko $(APP_NAME) $(ROOTFS_DIR)/drv_module else obj-m += chr_drv.o endif
[root@farsight ]# insmod chr_drv.ko
[ 287.317368] register ok
[root@farsight ]# ./drvtest
[ 291.632356] ------------chr_drv_open----------
[ 291.635357] __KERN__:0
[ 292.638023] __KERN__:1
[ 293.639042] __KERN__:0
[ 294.640062] __KERN__:1
[ 295.641081] __KERN__:0
[ 296.642106] __KERN__:1
[ 297.643127] __KERN__:0
[ 298.644145] __KERN__:1
[ 299.645167] __KERN__:0
[ 300.646187] __KERN__:1
[ 301.647281] __KERN__:0
[ 302.648296] __KERN__:1
[ 302.732408] ------------chr_drv_close----------
开发板上灯一闪一灭。