具体代码
1.驱动代码
#include
#include
#include
#include
#include "mycled.h"
#include
#include
#define Cname "mycled"
char kbuf[128] = {0};
unsigned int *rcc_gpio;
unsigned int *gpioe_moder;
unsigned int *gpioe_odr;
unsigned int *gpiof_moder;
unsigned int *gpiof_odr;
struct class *cls;
struct device *dev;
ssize_t my_read(struct file *file, char __user *ubuf, size_t t, loff_t *lt)
{
// int ret;
// printk("this is %s\n", __func__);
// if (t > sizeof(kbuf))
// t = sizeof(kbuf);
// ret = copy_to_user(ubuf, kbuf, t);
// if (ret)
// {
// printk("recive faild\n");
// return -EIO;
// }
return 0;
}
ssize_t my_write(struct file *file, const char __user *ubuf, size_t t, loff_t *lt)
{
// int ret;
// printk("this is %s\n", __func__);
// if (t <= sizeof(kbuf))
// {
// ret = copy_from_user(kbuf, ubuf, t);
// }
// else
// {
// ret = copy_from_user(kbuf, ubuf, sizeof(kbuf));
// }
// if (ret)
// {
// printk("recive faild\n");
// return -EIO;
// }
// if (kbuf[0] == '2')
// {
// *gpioe_odr &= (~(0x1 << 10));
// }
// else if (kbuf[0] == '1')
// {
// *gpioe_odr |= ((0x1 << 10));
// }
// else if (kbuf[0] == '3')
// {
// *gpiof_odr |= ((0x1 << 10));
// }
// else if (kbuf[0] == '4')
// {
// *gpiof_odr &= (~(0x1 << 10));
// }
// else if (kbuf[0] == '5')
// {
// *gpioe_odr |= ((0x1 << 8));
// }
// else if (kbuf[0] == '6')
// {
// *gpioe_odr &= (~(0x1 << 8));
// }
return 0;
}
int my_open(struct inode *inode, struct file *file)
{
//LED初始化
printk("this is %s\n", __func__);
rcc_gpio = ioremap(PHY_RCC_GPIO, 4);
if (rcc_gpio == NULL)
{
printk("rcc_gpio error\n");
return -ENOMEM;
}
gpioe_moder = ioremap(PHY_GPIOE_MODER, 4);
if (gpioe_moder == NULL)
{
printk("gpioe_moder error\n");
return -ENOMEM;
}
gpioe_odr = ioremap(PHY_GPIOE_ODR, 4);
if (gpioe_odr == NULL)
{
printk("gpioe_odr error\n");
return -ENOMEM;
}
gpiof_moder = ioremap(PHY_GPIOF_MODER, 4);
if (gpiof_moder == NULL)
{
printk("gpiof_moder error\n");
return -ENOMEM;
}
gpiof_odr = ioremap(PHY_GPIOF_ODR, 4);
if (gpiof_odr == NULL)
{
printk("gpiof_odr error\n");
return -ENOMEM;
}
*rcc_gpio |= (0x1 << 4);
*rcc_gpio |= (0x1 << 5);
*gpioe_moder &= (~(0x3 << 20));
*gpioe_moder |= (0x1 << 20);
*gpioe_moder &= (~(0x3 << 16));
*gpioe_moder |= (0x1 << 16);
*gpiof_moder &= (~(0x3 << 20));
*gpiof_moder |= (0x1 << 20);
*gpioe_odr &= (~(0x1 << 10));
*gpioe_odr &= (~(0x1 << 8));
*gpiof_odr &= (~(0x1 << 10));
return 0;
}
int my_close(struct inode *inode, struct file *file)
{
printk("this is %s\n", __func__);
return 0;
}
long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int data;
int ret;
switch (cmd)
{
case LED_ON:
ret = copy_from_user(&data, (int *)arg, sizeof(int));
if (ret)
{
printk("recive faild\n");
return -EIO;
}
switch (data)
{
case 0:
*gpioe_odr |= ((0x1 << 10));
break;
case 1:
*gpiof_odr |= ((0x1 << 10));
break;
case 2:
*gpioe_odr |= ((0x1 << 8));
break;
default:
break;
}
break;
case LED_OFF:
ret = copy_from_user(&data, (int *)arg, sizeof(int));
if (ret)
{
printk("recive faild\n");
return -EIO;
}
switch (data)
{
case 0:
*gpioe_odr &= (~(0x1 << 10));
break;
case 1:
*gpiof_odr &= (~(0x1 << 10));
break;
case 2:
*gpioe_odr &= (~(0x1 << 8));
break;
default:
break;
}
break;
default:
break;
}
return 0;
}
struct file_operations fops =
{
.open = my_open,
.release = my_close,
.read = my_read,
.write = my_write,
.unlocked_ioctl = my_ioctl,
};
int major; // 存放主设备号
static int __init mycdev_init(void)
{
major = register_chrdev(0, Cname, &fops); // 申请设备号
if (major > 0)
{
printk("major create sucess major= %d\n", major);
}
else
{
printk("major create fault\n");
return major;
}
cls = class_create(THIS_MODULE, "led");
if (IS_ERR(cls))
{
printk("class create error\n");
return PTR_ERR(cls);
}
printk("class create success\n");
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycled");
if (IS_ERR(dev))
{
printk("device create error\n");
return PTR_ERR(dev);
}
printk("device create success\n");
return 0;
}
static void __exit mycdev_exit(void)
{
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, Cname);
iounmap(rcc_gpio);
iounmap(gpioe_moder);
iounmap(gpioe_odr);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
1.2驱动头文件
#ifndef __MYCLED_H__
#define __MYCLED_H__
#define PHY_RCC_GPIO 0x50000A28
#define PHY_GPIOE_MODER 0x50006000
#define PHY_GPIOE_ODR 0x50006014
#define PHY_GPIOF_MODER 0x50007000
#define PHY_GPIOF_ODR 0x50007014
#define LED_ON _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)
#endif
1.3应用层测试代码
#include
#include
#include
#include
#include
#include
#include
#include
#include "mycled.h"
int fd;
char buf[128] = {0};
pthread_t thread;
int data=0;
void LED1_ON(void)
{
data=0;
ioctl(fd,LED_ON,&data);
}
void LED1_OFF(void)
{
data=0;
ioctl(fd,LED_OFF,&data);
}
void LED2_ON(void)
{
data=1;
ioctl(fd,LED_ON,&data);
}
void LED2_OFF(void)
{
data=1;
ioctl(fd,LED_OFF,&data);
}
void LED3_ON(void)
{
data=2;
ioctl(fd,LED_ON,&data);
}
void LED3_OFF(void)
{
data=2;
ioctl(fd,LED_OFF,&data);
}
void *callBack(void *arg)
{
while (1)
{
if (buf[0] == 'l')
{
data = data %3;
ioctl(fd,LED_ON,&data);
sleep(1);
ioctl(fd,LED_OFF,&data);
data++;
}
else if (buf[0] == 'q')
{
pthread_exit(NULL);
}
else if (buf[0]=='1')
{
LED1_ON();
}
else if (buf[0]=='2')
{
LED1_OFF();
}
else if (buf[0]=='3')
{
LED2_ON();
}
else if (buf[0]=='4')
{
LED2_OFF();
}
else if (buf[0]=='5')
{
LED3_ON();
}
else if (buf[0]=='6')
{
LED3_OFF();
}
}
return NULL;
}
int main(int argc, const char *argv[])
{
fd = open("/dev/mycled", O_RDWR);
if (fd < 0)
{
perror("open error");
}
pthread_create(&thread, NULL, callBack, NULL); //利用多线程
while (1)
{
printf("请输入--->: 1(led1开灯) 2(led1关灯) 3(led2开灯) 4(led2关灯) 5(led3开灯) 6(led3关灯)l(流水灯)\n");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = 0;
if(buf[0]=='q')
{
sleep(1);
break;
}
}
close(fd);
return 0;
}
实验结果