- #ifndef __HEAD_H__
- #define __HEAD_H__
-
- typedef struct
- {
- unsigned int MODER;
- unsigned int OTYPER;
- unsigned int OSPEEDR;
- unsigned int PUPDR;
- unsigned int IDR;
- unsigned int ODR;
- }gpio_t;
-
- //LED灯的寄存器地址
- #define LED1_ADDR 0X50006000
- #define LED2_ADDR 0X50007000
- #define LED3_ADDR 0X50006000
- #define RCC_ADDR 0X50000A28
-
- #endif
- #include
- #include
- #include
- #include
- #include
- #include "head.h"
- #include
-
- char kbuf[128] = {};
- unsigned int major;
- gpio_t *vir_led1;
- gpio_t *vir_led2;
- gpio_t *vir_led3;
- // 定义指针指向映射后的虚拟内存
- unsigned int *vir_rcc;
-
- // 封装操作方法
- int mycdev_open(struct inode *inode, struct file *file)
- {
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
- {
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- int ret;
- ret = copy_to_user(ubuf, kbuf, size);
- if (ret)
- {
- printk("copy_to_user filed\n");
- return -EIO;
- }
- return 0;
- }
- ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
- {
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- int ret;
- ret = copy_from_user(kbuf, ubuf, size);
- if (ret)
- {
- printk("copy_from_user filed\n");
- return -EIO;
- }
- switch (kbuf[0])
- {
- case '1':
- if (kbuf[1] == '1') // 开灯
- vir_led1->ODR |= (0x1 << 10);
- else if (kbuf[1] == '0') // 关灯
- vir_led1->ODR &= (~(0x1 << 10));
- break;
- case '2':
- if (kbuf[1] == '1') // 开灯
- vir_led2->ODR |= (0x1 << 10);
- else if (kbuf[1] == '0') // 关灯
- vir_led2->ODR &= (~(0x1 << 10));
- break;
- case '3':
- if (kbuf[1] == '1') // 开灯
- vir_led3->ODR |= (0x1 << 8);
- else if (kbuf[1] == '0') // 关灯
- vir_led3->ODR &= (~(0x1 << 8));
- break;
- default:
- printk("输入错误\n");
- }
- return 0;
- }
- int mycdev_close(struct inode *inode, struct file *file)
- {
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- // 定义操作方法结构体对象
- struct file_operations fops = {
- .open = mycdev_open,
- .read = mycdev_read,
- .write = mycdev_write,
- .release = mycdev_close,
- };
- static int __init mycdev_init(void)
- {
- // 注册字符设备驱动
- major = register_chrdev(0, "mychrdev", &fops);
- if (major < 0)
- {
- printk("字符设备驱动注册失败\n");
- return major;
- }
- printk("注册字符设备驱动成功major=%d\n", major);
- // 进行寄存器的地址映射
- vir_led1 = ioremap(LED1_ADDR, sizeof(gpio_t));
- if (vir_led1 == NULL)
- {
- printk("物理内存地址映射失败%d\n", __LINE__);
- return -EFAULT;
- }
- vir_led2 = ioremap(LED2_ADDR, sizeof(gpio_t));
- if (vir_led2 == NULL)
- {
- printk("物理内存地址映射失败%d\n", __LINE__);
- return -EFAULT;
- }
- vir_led3 = ioremap(LED3_ADDR, sizeof(gpio_t));
- if (vir_led3 == NULL)
- {
- printk("物理内存地址映射失败%d\n", __LINE__);
- return -EFAULT;
- }
- vir_rcc=ioremap(RCC_ADDR,4);
- if(vir_rcc == NULL)
- {
- printk("物理内存映射失败%d\n",__LINE__);
- return -EFAULT;
- }
- printk("寄存器内存映射成功\n");
-
- // 寄存器初始化
- (*vir_rcc) |= (0x3 << 4); // GPIOE控制器时钟使能
- // LED1
- vir_led1->MODER &= (~(0x3 << 20));
- vir_led1->MODER |= (0x1 << 20);
- vir_led1->ODR &= (~(0x1 << 10));
-
- // LED2
- vir_led2->MODER &= (~(0x3 << 20));
- vir_led2->MODER |= (0x1 << 20);
- vir_led2->ODR &= (~(0x1 << 10));
-
- // LED3
- vir_led3->MODER &= (~(0x3 << 16));
- vir_led3->MODER |= (0x1 << 16);
- vir_led3->ODR &= (~(0x1 << 8));
-
- printk("寄存器初始化成功\n");
- return 0;
- }
- static void __exit mycdev_exit(void)
- {
- // 取消内存映射
- iounmap(vir_led1);
- iounmap(vir_led2);
- iounmap(vir_rcc);
- // 注销字符设备驱动
- unregister_chrdev(major, "mychrdev");
- return 0;
- }
- module_init(mycdev_init);
- module_exit(mycdev_exit);
- MODULE_LICENSE("GPL");
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- int main(int argc, char const *argv[])
- {
- char buf[128] = {0};
- int fd = open("/dev/mychrdev", O_RDWR);
- if (fd < 0)
- {
- printf("打开设备文件失败\n");
- return -1;
- }
- printf("打开设备文件成功\n");
- while (1)
- {
- printf("请输入要控制的灯:1(LED1) 2(LED2) 3(LED3) >>>\n");
- printf("请输入您要进行的操作:1(开灯) 0(关灯) >>>\n");
- printf("请输入控制灯的两个字符 >>> ");
- fgets(buf, sizeof(buf), stdin); //在终端读一个字符串
- buf[strlen(buf) - 1] = '\0';
- write(fd, buf, sizeof(buf)); //将数据传递给内核
- }
- close(fd);
- return 0;
- }