华清远见上海中心22071班
linux流水灯点灯驱动,在用户层进行电灯操作
#include
#include
#include
#include
#include
#include "led.h"
#define CNAME "led"
char kbuf[128] = "";
volatile unsigned int *virt_RCC;
gpio_t *virt_gpioe;
gpio_t *virt_gpiof;
int mycdev_open(struct inode *inode, struct file *file)
{
printk("open success\n");
return 0;
}
ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *loffs)
{
int res;
if (size > sizeof(kbuf))
{
size = sizeof(kbuf);
}
res = copy_to_user(ubuf, kbuf, size);
if (res)
{
printk("copy to user failed\n");
return -EIO;
}
return size;
}
ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loffs)
{
int res;
if (size > sizeof(kbuf))
{
printk("copy from user failed\n");
return -EIO;
}
res = copy_from_user(kbuf, ubuf, size);
if (res)
{
printk("copy to user failed\n");
return -EIO;
}
printk("copy from user success.kbuf = %s\n", kbuf);
switch (kbuf[0])
{
case '1':
virt_gpioe->ODR |= (0x1 << 10);
break;
case '2':
virt_gpiof->ODR |= (0x1 << 10);
break;
case '3':
virt_gpioe->ODR |= (0x1 << 8);
break;
case '4':
virt_gpioe->ODR &= (~(0x1 << 10));
virt_gpioe->ODR &= (~(0x1 << 8));
virt_gpiof->ODR &= (~(0x1 << 10));
break;
default:
printk("ERROR KBUF\n");
break;
}
return size;
}
int mycdev_ralease(struct inode *inode, struct file *file)
{
printk("close success\n");
return 0;
}
struct file_operations fops = {
.open = mycdev_open,
.read = mycdev_read,
.write = mycdev_write,
.release = mycdev_ralease,
};
static int __init led_init(void)
{
int major;
major = register_chrdev(0, CNAME, &fops);
if (0 > major)
{
printk("register_chrdev failed\n");
return major;
}
printk("register_chrdev success.major = %d\n", major);
//映射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;
}
static void __exit led_exit(void)
{
iounmap(virt_gpioe);
iounmap(virt_gpiof);
iounmap(virt_RCC);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
#ifndef __LED_H__
#define __LED_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 RCC 0x50000A28
#define GPIOE 0x50006000
#define GPIOF 0x50007000
#endif
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
int fd = open("/dev/myled", O_RDWR);
if (-1 == fd)
{
perror("open");
return -1;
}
char buf[128] = "";
while (1)
{
buf[0] = '1';
write(fd, buf, sizeof(buf));
sleep(1);
buf[0] = '2';
write(fd, buf, sizeof(buf));
sleep(1);
buf[0] = '3';
write(fd, buf, sizeof(buf));
sleep(1);
buf[0] = '4';
write(fd, buf, sizeof(buf));
sleep(1);
}
close(fd);
return 0;
}