编写LED灯的驱动,实现三盏灯的控制
mychrdev.c
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "head.h"unsigned int major; // 保存主设备号 char kbuf[128]={0}; unsigned int* rcc_gpio; gpio_t* gpioe_base; gpio_t* gpiof_base;// 封装操作方法 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) {int ret;ret=copy_to_user(ubuf,kbuf,size);if(ret){printk("copy_to_user err\n");return -EIO;}return 0; } ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof) {int ret;//从用户拷贝ret=copy_from_user(kbuf,ubuf,size);if(ret){printk("copy_from_user err\n");return -EIO;}printk("1111111111111111");switch (kbuf[0]){case '0':gpioe_base->ODR &= (~(0x1<<10));break;case '1':gpioe_base->ODR |= (0x1<<10);break;case '2':gpiof_base->ODR &= (~(0x1<<10));break;case '3':gpiof_base->ODR |= (0x1<<10);break;case '4':gpioe_base->ODR &= (~(0x1<<8));break;case '5':gpioe_base->ODR |= (0x1<<8);break;default:break;}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);//进行相关寄存器的内存映射rcc_gpio = ioremap(PHY_RCC_GPIO,4);if(rcc_gpio == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}gpioe_base = ioremap(PHY_GPIOE_BASE,sizeof(gpio_t));if(gpioe_base == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}gpiof_base = ioremap(PHY_GPIOF_BASE,sizeof(gpio_t));if(gpiof_base == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}printk("寄存器内存映射成功\n");//LED1寄存器的初始化*rcc_gpio |=(0x1<<4); //gpioe时钟使能gpioe_base->MODER &=(~(0x3<<20)); //清零moder 21-20bitgpioe_base->MODER |= (0x1<<20); //设置PE为输出gpioe_base->ODR &= (~(0x1<<10)); //LED灭//LED2寄存器的初始化*rcc_gpio |=(0x1<<5);gpiof_base->MODER &=(~(0x3<<20));gpiof_base->MODER |= (0x1<<20);gpiof_base->ODR &= (~(0x1<<10));//LED3寄存器的初始化*rcc_gpio |=(0x1<<4);gpioe_base->MODER &=(~(0x3<<16));gpioe_base->MODER |= (0x1<<16);gpioe_base->ODR &= (~(0x1<<8));return 0; } static void __exit mycdev_exit(void) {//取消物理内存映射iounmap(rcc_gpio);iounmap(gpioe_base);iounmap(gpiof_base);// 字符设备驱动注销unregister_chrdev(major, "mychrdev"); } module_init(mycdev_init); module_exit(mycdev_exit); MODULE_LICENSE("GPL");
head.h
#ifndef __HEAD_H__ #define __HEAD_H__typedef struct{volatile unsigned int MODER;volatile unsigned int OTYPER;volatile unsigned int OSPEEDR;volatile unsigned int PUPDR;volatile unsigned int IDR;volatile unsigned int ODR; }gpio_t;#define PHY_RCC_GPIO 0x50000A28 #define PHY_GPIOE_BASE 0x50006000 #define PHY_GPIOF_BASE 0x50007000#endif
test.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main(int argc, char const *argv[]) {char buf[128] = {0};int fd = open("/dev/mychrdev", O_RDWR);if (fd < 0){printf("设备文件打开失败\n");exit(-1);}while (1){printf("请输入对LED1/LED2/LED3的控制命令1(开灯)0(关灯)/3(开灯)2(关灯)/5(开灯)4(关灯)>\n");fgets(buf, sizeof(buf), stdin); // 在终端输入数据传递到bufbuf[strlen(buf) - 1] = '\0'; // 替换末尾的'\n'write(fd, buf, sizeof(buf));}close(fd);return 0; }