驱动控制LED灯
编写驱动代码,初步实现串口输入逻辑控制开发板的LED灯的亮灭
代码示例
head.h
#ifndef __HEAD_H__
#define __HEAD_H__typedef struct
{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPD;unsigned int IDR;unsigned int ODR;
}gpio_t;#define PHY_LED1_ADDR 0x50006000
#define PHY_LED2_ADDR 0x50007000
#define PHY_LED3_ADDR 0x50006000
#define PHY_RCC_ADDR 0x50000A28#endif
test.c
#include
#include
#include
#include
#include
#include
#include int main(int argc,const char * argv[])
{char buf[1024] = {0};int fd = open("/dev/mycdev0",O_RDWR); if(fd < 0){printf("打开设备失败\n");exit(-1);}while (1){printf("输入两个数,选择控制逻辑;第一个数控制灯,第二个数控制灯的状态 > \n");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';write(fd,buf,sizeof(buf));}close(fd);return 0;
}
Character_device.c
#include
#include
#include
#include
#include
#include
#include "head.h"unsigned int major;
char kbuf[1024] = {0};gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;unsigned int *vir_rcc;//
struct class *cls;
struct device *dev;// 封装操作方法
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__);long ret;ret = copy_to_user(ubuf, kbuf, size);if (ret){printk("copy_to_user failed\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__);long ret;ret = copy_from_user(kbuf, ubuf, size);if (ret){printk("copy_from_user failed\n");return -EIO;}switch (kbuf[0]){case '1': // LED1if (kbuf[1] == '0')vir_led1->ODR &= (~(0x1 << 10));elsevir_led1->ODR |= 0x1 << 10;break;case '2': // LED2if (kbuf[1] == '0')vir_led2->ODR &= (~(0x1 << 10));elsevir_led2->ODR |= 0x1 << 10;break;case '3': // LED3if (kbuf[1] == '0')vir_led3->ODR &= (~(0x1 << 8));elsevir_led3->ODR |= 0x1 << 8;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,.release = mycdev_close,.read = mycdev_read,.write = mycdev_write,
};// 寄存器地址映射
int all_led_init(void)
{vir_led1 = ioremap(PHY_LED1_ADDR, sizeof(gpio_t));if (vir_led1 == NULL){printk("物理内存映射失败%d\n", __LINE__);return -EFAULT;}vir_led2 = ioremap(PHY_LED2_ADDR,sizeof(gpio_t));if (vir_led2 == NULL){printk("物理内存映射失败%d\n", __LINE__);return -EFAULT;}vir_led3 = vir_led1;vir_rcc = ioremap(PHY_RCC_ADDR, 4);if (vir_rcc == NULL){printk("物理内存映射失败%d\n", __LINE__);return -EFAULT;}printk("物理内存映射成功\n");//rcc(*vir_rcc) |= 0x3 << 4;//LED1vir_led1->MODER &= (~(0x3 << 20));vir_led1->MODER |= 0x1 << 20;vir_led1->ODR &= (~(0x1 << 10));//LED2vir_led2->MODER &= (~(0x3 << 20));vir_led2->MODER |= 0x1 << 20;vir_led2->ODR &= (~(0x1 << 10));//LED3vir_led3->MODER &= (~(0x3 << 16));vir_led3->MODER |= 0x1 << 16;vir_led3->ODR &= (~(0x1 << 8));return 0;
}static int __init mycdev_init(void)
{int i;// 注册设备字符驱动major = register_chrdev(0, "mycdev", &fops);if (major < 0){printk("注册字符设备驱动失败\n");return major;}printk("注册字符设备驱动成功major=%d\n", major);all_led_init();// 向上提交目录信息cls = class_create(THIS_MODULE, "mycdev");if (IS_ERR(cls)){printk("向上提交目录信息失败\n");return -PTR_ERR(cls);}printk("向上提交目录信息成功\n");// 向上提交设备信息for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mycdev%d", i);if (IS_ERR(dev)){printk("向上提交设备节点失败\n");return -PTR_ERR(cls);}}printk("向上提交设备节点成功\n");return 0;
}static void __exit mycdev_exit(void)
{// 取消物理映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_rcc);// 销毁设备信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录信息class_destroy(cls);// 字符设备注销unregister_chrdev(major, "mycdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
运行结果


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
