head.h
#ifndef __HEAD_H__ #define __HEAD_H__ #define PHY_LED13_MODER 0x50006000 //[20 21]/[16 17] >01 #define PHY_LED13_ODR 0x50006014 // [10]/[8] #define PHY_LED2_MODER 0x50007000 //[20 21] >01 #define PHY_LED2_ODR 0x50007014 //10 #define PHY_RCC 0x50000A28 //4 5 bits #define LED_ON _IOW('l',1,int *) #define LED_OFF _IOW('l',0,int *) #endif
text.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include "head.h" int main(int argc,const char * argv[]) { int a; int b; while(1) { int fd; //Get the function we want to implement from the interrupt printf("Please select the lights to be controlled: 0-LED1, 1-LED2, 2-LED3\ "); scanf("%d", & amp;a); switch(a) { case 1: fd = open("/dev/mycdev0",O_RDWR); break; case 2: fd = open("/dev/mycdev1",O_RDWR); break; case 3: fd = open("/dev/mycdev2",O_RDWR); break; } if(fd<0) { printf("Failed to open device file\ "); return -1; } printf("Open device file successfully\ "); printf("Please enter the function you want to implement"); printf("0(lights off)1(lights on)\ "); printf("Please enter:"); scanf("%d", & amp;b); switch (b) { case 1: ioctl(fd,LED_ON, & amp;b); break; case 0: ioctl(fd,LED_OFF, & amp;b); break; } close(fd); } return 0; }
demo.c
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/slab.h> #include <linux/kdev_t.h> #include "head.h" struct class *cls; struct device *dev; unsigned int *vir_moder13; unsigned int *vir_moder2; unsigned int *vir_odr13; unsigned int *vir_odr2; unsigned int *vir_rcc; char kbuf[128]={}; //Encapsulation operation method int mycdev_open(struct inode * inode,struct file* file) { unsigned int min=MINOR(inode->i_rdev);//Get the minor device number of the opened file file->private_data=(void *)min; printk("%s:%s:%d\ ",__FILE__,__func__,__LINE__); return 0; } /* ssize_t mycdev_read(struct file * file,char *ubuf,size_t size,loff_t *lof) { printk("%s:%s:%d\ ",__FILE__,__func__,__LINE__); unsigned long ret; ret=copy_to_user(ubuf,kbuf,size); if(ret) { printk("copy to user filed\ "); return -EIO; } return 0; } ssize_t mycdev_write(struct file * file,const char *ubuf,size_t size,loff_t *lof) { printk("%s:%s:%d\ ",__FILE__,__func__,__LINE__); unsigned long ret; ret=copy_from_user(kbuf,ubuf,size); if(ret) { printk("copy from user filed\ "); return -EIO; } //Control LED lights if(kbuf[0]=='0')//Turn off the light { (*vir_odr13) & amp;=~(0x1<<10); (*vir_odr13) & amp;=~(0x1<<8); (*vir_odr2) & amp;=~(0x1<<10); } else if(kbuf[0]=='1')//Turn on LED1 { (*vir_odr13)|=(0x1<<10); } else if(kbuf[0]=='2')//Turn on LED2 { (*vir_odr2)|=(0x1<<10); } else if(kbuf[0]=='3')//Turn on LED3 { (*vir_odr13)|=(0x1<<8); } return 0; } */ int mycdev_close(struct inode * indode,struct file* file) { printk("%s:%s:%d\ ",__FILE__,__func__,__LINE__); return 0; } long mycdev_ioctl(struct file *file,unsigned int cmd,unsigned long arg) { int min=(int)file->private_data;//Get the minor device number of the file switch(min) { case 0://LED1 switch(cmd) { case LED_ON://turn on the light (*vir_odr13) |=(0x1<<10); break; case LED_OFF://turn off the light (*vir_odr13) & amp;=~(0x1<<10); break; } break; case 1://LED2 switch(cmd) { case LED_ON://turn on the light (*vir_odr2) |=(0x1<<10); break; case LED_OFF://turn off the light (*vir_odr2) & amp;=~(0x1<<10); break; } break; case 2://LED3 switch(cmd) { case LED_ON://turn on the light (*vir_odr13) |=(0x1<<8); break; case LED_OFF://turn off the light (*vir_odr13) & amp;=~(0x1<<8); break; } break; } return 0; } struct file_operations fops = { .open=mycdev_open, //.read=mycdev_read, //.write=mycdev_write, .unlocked_ioctl = mycdev_ioctl, .release=mycdev_close, }; struct cdev* cdev; unsigned int major=0; unsigned int minor=0; dev_t devno; static int __init mycdev_init(void) { int i; //Register character device driver //1. Apply for an object space cdev_alloc int ret; cdev=cdev_alloc(); if(cdev==NULL) { printk("Failed to apply for character device driver object space\ "); ret =-EFAULT; goto out1; } printk("Application for character device driver object space successful\ "); //2.Initialize object cdev_init cdev_init(cdev, & amp;fops); //3. Apply for device number register_chrdev_region()/alloc_chrdev_region() if(major==0)//Dynamic application { ret=alloc_chrdev_region( & amp;devno,minor,3,"mychrdev"); if(ret) { printk("Dynamic application for device number failed\ "); goto out2; } major=MAJOR(devno);//Get the major device number based on the device number minor=MINOR(devno);//Get the minor device number based on the device number } else//static application { ret=register_chrdev_region(MKDEV(major,minor),3,"mychrdev"); if(ret) { printk("Static application for device number failed\ "); goto out2; } } printk("Device number application successful\ "); //4. Register driver object cdev_add ret=cdev_add(cdev,MKDEV(major,minor),3); if(ret) { printk("Registration of character device driver object failed\ "); goto out3; } printk("Registration of character device driver object successful\ "); if(major<0) { printk("Character device driver registration failed\ "); return major; } printk("Character device driver successful major=%d\ ",major); //5. Submit the directory upward class_create cls=class_create(THIS_MODULE,"mychrdev"); if(IS_ERR(cls)) { printk("Failed to access the submission directory\ "); goto out4; } printk("I want to upload the submission directory successfully\ "); //6. Submit device node information upward device_create for(i=0;i<3;i + + ) { dev=device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i); if(IS_ERR(dev)) { printk("Failed to submit device node\ "); goto out5; } } printk("I want to submit the device node successfully\ "); //Perform register address mapping vir_moder13 = ioremap(PHY_LED13_MODER,4); if(vir_moder13 == NULL) { printk("Physical memory address mapping failed %d\ ",__LINE__); return -EFAULT; } vir_moder2 = ioremap(PHY_LED2_MODER,4); if(vir_moder13 == NULL) { printk("Physical memory address mapping failed %d\ ",__LINE__); return -EFAULT; } vir_odr13 = ioremap(PHY_LED13_ODR,4); if(vir_odr13 == NULL) { printk("Physical memory address mapping failed %d\ ",__LINE__); return -EFAULT; } vir_odr2 = ioremap(PHY_LED2_ODR,4); if(vir_odr2 == NULL) { printk("Physical memory address mapping failed %d\ ",__LINE__); return -EFAULT; } vir_rcc = ioremap(PHY_RCC,4); if(vir_rcc == NULL) { printk("Physical memory address mapping failed %d\ ",__LINE__); return -EFAULT; } printk("Register memory mapping successful\ "); //Register initialization //rcc initialization (*vir_rcc) |= (0x3<<4);//GPIOEF controller clock enable (*vir_moder13) & amp;= ~(0x3<<20); (*vir_moder13) |= (0x1<<20);//LED1 (*vir_moder13) & amp;= ~(0x3<<16); (*vir_moder13) |= (0x1<<16);//LED3 (*vir_moder2) & amp;= ~(0x3<<20); (*vir_moder2) |= (0x1<<20);//LED2 (*vir_odr13) & amp;=~(0x1<<10);//LED1 (*vir_odr13) & amp;=~(0x1<<8);//LED3 (*vir_odr2) & amp;=~(0x1<<10);//LED2 return 0; printk("Initialization of LED successful"); out5: //When submitting the device node fails, the successfully submitted node will be released. for(i--;i>=0;i--) { device_destroy(cls,MKDEV(major,i)); } //Destroy directory class_destroy(cls); out4: cdev_del(cdev); out3: unregister_chrdev_region(MKDEV(major,minor),3); out2: kfree(cdev); out1: return ret; } static void __exit mycdev_exit(void) { int i; //Cancel memory mapping iounmap(vir_moder13); iounmap(vir_moder2); iounmap(vir_odr13); iounmap(vir_odr2); iounmap(vir_rcc); //1. Destroy device node information for(i=0;i<3;i + + ) { device_destroy(cls,MKDEV(major,i)); } //2. Destroy the directory class_destroy(cls); //3. Unregister the character device driver object cdev_del(cdev); //4. Release the device number unregister_chrdev_region(MKDEV(major,minor),3); //5. Release the applied character device driver object space kfree(cdev); } module_init(mycdev_init); module_exit(mycdev_exit); MODULE_LICENSE("GPL");