1. Driver code, install the LED light driver and register the device file, complete the mapping of the register address, and control the light on and off
#include "head.h"
#include "cdev.h"
int mycdev_open(struct inode *inode, struct file *file)
{
//1. Find the device number through struct inode
//2. Use the MINOR function to find the secondary device number according to the device number
//3. Put the secondary device number into private_date in the struct file
led_minor=MINOR(inode->i_rdev);
file->private_data=(void *)led_minor;
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__);
// read copy to user space
if (size > sizeof(kbuf)) // The size that the user space expects to read cannot be satisfied by the kernel, then give the maximum size supported by the kernel
size = sizeof(kbuf);
ret = copy_to_user(ubuf, kbuf, size);
if (ret) // copy failed
{
printk("copy_to_user filed\\
");
return ret;
}
return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
//Get the secondary device number stored in the private_data of the struct file
led_x=(unsigned int)file->private_data;
//Judge the device file of which LED light
switch(led_x)
{
//LED1 light
case 0:
switch(cmd)
{
case LED_ON:
vir_led1->ODR |=(1<<10);
break;
case LED_OFF:
vir_led1->ODR & amp;=(~(1<<10));
break;
}
break;
//LED2 lights
case 1:
switch(cmd)
{
case LED_ON:
vir_led2->ODR |=(1<<10);
break;
case LED_OFF:
vir_led2->ODR & amp;=(~(1<<10));
break;
}
break;
//LED3 lights
case 2:
switch(cmd)
{
case LED_ON:
vir_led3->ODR |=(1<<8);
break;
case LED_OFF:
vir_led3->ODR |=(~(1<<8));
break;
}
break;
}
return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\\
", __FILE__, __func__, __LINE__);
return 0;
}
int all_led_init(void)
{
// Mapping of register addresses
vir_led1 = ioremap(PHY_LED1_ADDR, sizeof(gpio_t));
if (vir_led1 == NULL)
{
printk("ioremap filed:%d\\
", __LINE__);
return -ENOMEM;
}
vir_led2 = ioremap(PHY_LED2_ADDR, sizeof(gpio_t));
if (vir_led2 == NULL)
{
printk("ioremap filed:%d\\
", __LINE__);
return -ENOMEM;
}
vir_led3 = vir_led1;
vir_rcc = ioremap(PHY_RCC_ADDR, 4);
if (vir_rcc == NULL)
{
printk("ioremap filed:%d\\
", __LINE__);
return -ENOMEM;
}
printk("Physical address mapping successful\\
");
// register initialization
// rcc
(*vir_rcc) |= (3 << 4);
//led1
vir_led1->MODER & amp;= (~(3 << 20));
vir_led1->MODER |= (1 << 20);
vir_led1->ODR &= (~(1 << 10));
// led2
vir_led2->MODER & amp;= (~(3 << 20));
vir_led2->MODER |= (1 << 20);
vir_led2->ODR &= (~(1 << 10));
// led3
vir_led3->MODER & amp;= (~(3 << 16));
vir_led1->MODER |= (1 << 16);
vir_led1->ODR &= (~(1 << 8));
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
unsigned long ret;
// read data from user space
if (size > sizeof(kbuf)) // The size that the user space expects to read cannot be satisfied by the kernel, then give the maximum size supported by the kernel
size = sizeof(kbuf);
ret = copy_from_user( & amp; sum, ubuf, size);
if (ret) // copy failed
{
printk("copy_to_user filed\\
");
return ret;
}
return 0;
}
// Define the operation method structure variable and assign it
struct file_operations fops = {
.open = mycdev_open,
.read = mycdev_read,
.write = mycdev_write,
.release = mycdev_close,
.unlocked_ioctl = mycdev_ioctl,
};
static int __init mycdev_init(void)
{
int i=-1;
/*****LED lamp driver installation process*****/
//1. Install the driver to obtain the mojor device number
printk("LED light driver installation\\
");
major=register_chrdev(0,"mychrdev", & amp;fops); //The system dynamically applies for the major equipment number
if(major<0)
{
printk("Major device number application failed\\
");
return major;
}
printk("Major device number application is successful: major=%d\\
",major);
//3. Submit directory up
cls=class_create(THIS_MODULE,"mychrdev");
if(IS_ERR(cls))
{
printk("Failed to submit directory up\\
");
return PTR_ERR(cls);
}
printk("submit directory successfully\\
");
/*
cls=class_create(THIS_MODULE,"mychrdev1");
cls=class_create(THIS_MODULE,"mychrdev2");
*/
//4. Submit device node information upwards, and create device files for each lamp
for(i=0;i<3;i ++ )
{
dev=device_create(cls,NULL,MKDEV(major,i),NULL,"mychrdev%d",i);
if(IS_ERR(dev))
{
printk("Upward submission of device information mychrdev%d failed\\
",i);
return PTR_ERR(dev);
}
printk("submit device information mychrdev%d successfully",i);
}
//Initialization of the LED lights
all_led_init();
return 0;
}
static void __exit mycdev_exit(void)
{
// Cancel address mapping
iounmap(vir_led1);
iounmap(vir_led2);
iounmap(vir_rcc);
// Destroy device information
device_destroy(cls, MKDEV(major, 0));
device_destroy(cls, MKDEV(major, 1));
device_destroy(cls, MKDEV(major, 2));
// destroy directory
class_destroy(cls);
// Unregister the character device driver
unregister_chrdev(major, "mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
2. Apply the code, open different device files, and control the corresponding LED lights to flash
#include "user.h"
#include "head.h"
int main(int argc, char const *argv[])
{
while (1)
{
my_select = -1;
key = -1;
fd = -1;
printf("Please choose the operation you want to perform 1<light on>, 2<light off>: ");
scanf("%d", &my_select);
switch (my_select)
{
// light up
case 1:
printf("Select the indicator light you want to operate 1<LED1>, 2<LED2>, 3<LED3>: ");
scanf("%d", & key);
switch (key)
{
// Operation LED1 lights up
case 1:
// Open the device file for the LED light
fd = open("/dev/mychrdev0", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_ON);
break;
// Operation LED2 lights up
case 2:
fd = open("/dev/mychrdev1", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_ON);
break;
// Operation LED3 lights up
case 3:
fd = open("/dev/mychrdev2", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_ON);
break;
}
break;
// lights out
case 2:
printf("Select the indicator light you want to operate 1<LED1>, 2<LED2>, 3<LED3>: ");
scanf("%d", & key);
switch (key)
{
// Operation LED1 lights off
case 1:
// Open the device file for the LED light
fd = open("/dev/mychrdev0", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_OFF);
break;
// Operation LED2 lights off
case 2:
fd = open("/dev/mychrdev1", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_OFF);
break;
// Operation LED3 lights off
case 3:
fd = open("/dev/mychrdev2", O_RDWR);
if (fd < 0)
{
printf("Failed to open device file\\
");
exit(-1);
}
ioctl(fd, LED_OFF);
break;
}
break;
default:
break;
}
}
close(fd);
return 0;
}