华清远见上海中心22071班
串口输入
echo 1 > /dev/myled0 ---->led1灯点亮
echo 0 > /dev/myled0 ---->led1灯熄灭
echo 1 > /dev/myled1 ---->led1灯点亮
echo 0 > /dev/myled1 ---->led1灯熄灭
echo 1 > /dev/myled2 ---->led1灯点亮
echo 0 > /dev/myled2 ---->led1灯熄灭
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- #include <linux/slab.h>
- #include <linux/io.h>
- #include "led.h"
-
- #if 0
- #define LED_MAJOR 500
- #else
- #define LED_MAJOR 0
- #endif
-
- #define COUNT 3
- #define SEQNUM 0
- #define DRIVERNAME "myled"
-
- struct cdev *ledcdev;
- struct class *cls;
- struct device *dce;
- volatile unsigned int *virt_RCC;
- volatile gpio_t *virt_gpioe;
- volatile gpio_t *virt_gpiof;
- int major = LED_MAJOR;
- int minor = 0;
-
- int mycdevopen(struct inode *inode, struct file *file)
- {
- int ledmajor, ledminor;
- ledmajor = MAJOR(inode->i_rdev);
- ledminor = MINOR(inode->i_rdev);
- printk("ledmajor=%d ledminor = %d\n", ledmajor, ledminor);
- printk("open success\n");
- file->private_data = (void *)(ledminor);
- return 0;
- }
-
- int mycdevrelease(struct inode *inode, struct file *file)
- {
- printk("release success\n");
- return 0;
- }
-
- ssize_t mycdevread(struct file *file, char __user *ubuf, size_t size, loff_t *loffs)
- {
- return 0;
- }
-
- ssize_t mycdevwrite(struct file *file, const char __user *ubuf, size_t size, loff_t *loffs)
- {
- int ledminor;
- unsigned long res;
- char kbuf[128] = "";
- ledminor = (int)file->private_data;
-
- switch (ledminor)
- {
-
- case 0:
- if (size > sizeof(kbuf))
- {
- size = sizeof(kbuf);
- }
-
- res = copy_from_user(kbuf, ubuf, size);
- if (res)
- {
- printk("copy_from_user failed (err %ld)", res);
- return res;
- }
- if ('0' == kbuf[0])
- {
- virt_gpioe->ODR &= (~(0x1 << 10));
- }
- else
- {
- virt_gpioe->ODR |= (0x1 << 10);
- }
- break;
- case 1:
- if (size > sizeof(kbuf))
- {
- size = sizeof(kbuf);
- }
-
- res = copy_from_user(kbuf, ubuf, size);
- if (res)
- {
- printk("copy_from_user failed (err %ld)", res);
- return res;
- }
- if ('0' == kbuf[0])
- {
- virt_gpiof->ODR &= (~(0x1 << 10));
- }
- else
- {
- virt_gpiof->ODR |= (0x1 << 10);
- }
- break;
- case 2:
- if (size > sizeof(kbuf))
- {
- size = sizeof(kbuf);
- }
-
- res = copy_from_user(kbuf, ubuf, size);
- if (res)
- {
- printk("copy_from_user failed (err %ld)", res);
- return res;
- }
- if ('0' == kbuf[0])
- {
- virt_gpioe->ODR &= (~(0x1 << 8));
- }
- else
- {
- virt_gpioe->ODR |= (0x1 << 8);
- }
- break;
- }
- return size;
- }
-
- struct file_operations fops = {
- .open = mycdevopen,
- .read = mycdevread,
- .write = mycdevwrite,
- .release = mycdevrelease};
-
- static int __init
- led_init(void)
- {
- int res, i;
- dev_t devt;
- // cdev的创建
- ledcdev = cdev_alloc();
- if (NULL == ledcdev)
- {
- printk("cdev alloc failed\n");
- res = -ENOMEM;
- goto ERR1;
- }
-
- // cdev的初始化
- cdev_init(ledcdev, &fops);
-
- // 条件判断是否动/静态注册设备号
- if (LED_MAJOR > 0)
- {
- res = register_chrdev_region(MKDEV(LED_MAJOR, SEQNUM), COUNT, DRIVERNAME);
- if (res)
- {
- printk("Unable to register char major %d\n", LED_MAJOR);
- goto ERR2;
- }
- major = LED_MAJOR;
- minor = SEQNUM;
- }
- else
- {
- res = alloc_chrdev_region(&devt, 0, COUNT, DRIVERNAME);
- if (res)
- {
- printk("Could not allocate chrdev region (err %d)\n", -res);
- goto ERR2;
- }
- major = MAJOR(devt);
- minor = MINOR(devt);
- }
-
- // 字符设备驱动添加至系统
- res = cdev_add(ledcdev, MKDEV(major, minor), COUNT);
- if (res)
- {
- printk("Unable register character device add (err %d)\n", -res);
- goto ERR3;
- }
-
- // 上传目录
- cls = class_create(THIS_MODULE, DRIVERNAME);
- if (IS_ERR(cls))
- {
- res = PTR_ERR(cls);
- printk("Class create failed (err %d)\n", -res);
- goto ERR4;
- }
-
- // 上传节点
- for (i = 0; i < COUNT; i++)
- {
- dce = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
- if (IS_ERR(dce))
- {
- res = PTR_ERR(dce);
- printk("Device create failed (err %d)\n", res);
- goto ERR5;
- }
- }
-
- //映射RCC_MP_AHB4ENSETR
- virt_RCC = (unsigned int *)ioremap(RCC, 4);
- if (NULL == virt_RCC)
- {
- printk("rcc ioremap failed\n");
- return -ENOMEM;
- }
-
- //映射gpioe的地址
- virt_gpioe = (gpio_t *)ioremap(GPIOE, sizeof(gpio_t));
- if (NULL == virt_gpioe)
- {
- printk("gpioe ioremap failed\n");
- return -ENOMEM;
- }
-
- //映射gpiof的地址
- virt_gpiof = (gpio_t *)ioremap(GPIOF, sizeof(gpio_t));
- if (NULL == virt_gpiof)
- {
- printk("gpiof ioremap failed\n");
- return -ENOMEM;
- }
-
- // RCC使能GPIOE,GPIOF
- *virt_RCC |= (0x1 << 4);
- *virt_RCC |= (0x1 << 5);
- // PE10,PE8设置为输出模式[21:20]=01 [17:16]=01
- virt_gpioe->MODER &= (~(0x3 << 20));
- virt_gpioe->MODER |= (0x1 << 20);
-
- virt_gpioe->MODER &= (~(0x3 << 16));
- virt_gpioe->MODER |= (0x1 << 16);
- // PF10设置为输出模式[21:20]=01
- virt_gpiof->MODER &= (~(0x3 << 20));
- virt_gpiof->MODER |= (0x1 << 20);
-
- //初始化PE10,PE8,PF10为熄灭状态
- virt_gpiof->ODR &= (~(0x1 << 10));
- virt_gpioe->ODR &= (~(0x1 << 10));
- virt_gpioe->ODR &= (~(0x1 << 8));
- return 0;
- ERR5:
- for (--i; i >= 0; i--)
- {
- device_destroy(cls, MKDEV(major, i));
- }
- class_destroy(cls);
- ERR4:
- cdev_del(ledcdev);
- ERR3:
- unregister_chrdev_region(MKDEV(major, minor), COUNT);
- ERR2:
- kfree(ledcdev);
- ERR1:
- return res;
- }
-
- static void __exit led_exit(void)
- {
- int i;
- iounmap(virt_RCC);
- iounmap(virt_gpioe);
- iounmap(virt_gpiof);
- for (i = 0; i < COUNT; i++)
- {
- device_destroy(cls, MKDEV(major, i));
- }
- class_destroy(cls);
- cdev_del(ledcdev);
- unregister_chrdev_region(MKDEV(major, minor), COUNT);
- kfree(ledcdev);
- }
-
- module_init(led_init);
- module_exit(led_exit);
- MODULE_LICENSE("GPL");