任务 : 基于platform驱动模型完成LED驱动的编写,实现三盏灯的点亮
应用层程序
#include
#include
#include
#include
#include
#include
#include
#include
#define LED_ON 1
#define LED_OFF 0
int main(int argc, char const *argv[])
{
// 打开第一个设备文件
int fd1 = open("/dev/myled0", O_RDWR);
if (fd1 < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
// 打开第二个设备文件
int fd2 = open("/dev/myled1", O_RDWR);
if (fd2 < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
// 打开第三个设备文件
int fd3 = open("/dev/myled2", O_RDWR);
if (fd3 < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
while (1)
{
int a, b;
// 从终端读取
printf("请输入字符\n");
printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");
scanf("%d", &a);
printf("第二个字符:0(关灯) 1(开灯)\n");
printf("请输入>");
scanf("%d", &b);
// 向设备文件中写
switch (b)
{
case 1:
switch (a)
{
case 1: // LED1
printf("LED1_ON\n");
ioctl(fd1, LED_ON,&a);
break;
case 2: // LED2
printf("LED2_ON\n");
ioctl(fd2, LED_ON,&a);
break;
case 3: // LED3
printf("LED3_ON\n");
ioctl(fd3, LED_ON,&a);
break;
}
break;
case 0:
switch (a)
{
case 1: // LED1
printf("LED1_OFF\n");
ioctl(fd1, LED_OFF,&a);
break;
case 2: // LED2
printf("LED2_OFF\n");
ioctl(fd2, LED_OFF,&a);
break;
case 3: // LED3
printf("LED3_OFF\n");
ioctl(fd3, LED_OFF,&a);
break;
}
break;
}
}
close(fd1);
close(fd2);
close(fd3);
return 0;
}
驱动代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LED_ON 1
#define LED_OFF 0
struct resource *res;
int irqnum;
struct gpio_desc *gpionum1;
struct gpio_desc *gpionum2;
struct gpio_desc *gpionum3;
struct device *dev;
int major;
struct class *cls;
struct of_device_id of_tab[] =
{
{
.compatible = "hqyj,myplatform",
},
{
.compatible = "hqyj,myplatform1",
},
{},
};
// 打开文件函数
int myopen(struct inode *inode, struct file *file)
{
return 0;
}
// 关闭文件函数
int myclose(struct inode *inode, struct file *file)
{
int i;
for(i = 0;i < 3;i++)
{
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
unregister_chrdev(major,"mychrdev");
return 0;
}
// io控制函数
long myioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
printk("__ioctrl__");
int which;
int ret = copy_from_user(&which, (void *)arg, 4);
if (ret)
{
printk("copy_from_user failed\n");
return -EIO;
}
printk("copy_from_user success : [%d]\n",which);
switch (cmd)
{
case LED_ON:
switch (which)
{
case 1:
printk("[1] : LED_ON\n");
gpiod_set_value(gpionum1, 1);
break;
case 2:
printk("[2] : LED_ON\n");
gpiod_set_value(gpionum2, 1);
break;
case 3:
printk("[3] : LED_ON\n");
gpiod_set_value(gpionum3, 1);
break;
}
break;
case LED_OFF:
switch (which)
{
case 1:
printk("[1] : LED_OFF\n");
gpiod_set_value(gpionum1, 0);
break;
case 2:
printk("[2] : LED_OFF\n");
gpiod_set_value(gpionum2, 0);
break;
case 3:
printk("[3] : LED_OFF\n");
gpiod_set_value(gpionum3, 0);
break;
}
break;
}
return 0;
}
// 操作方法结构体
struct file_operations fops = {
.open = myopen,
.unlocked_ioctl = myioctl,
.release = myclose,
};
// 匹配成功函数
int pdri_probe(struct platform_device *pdev)
{
printk("%s : %s : %d\n", __FILE__, __func__, __LINE__);
// 字符设备注册
major = register_chrdev(0, "mychrdev", &fops);
if (major < 0)
{
printk("register_chrdev failed\n");
return -1;
}
printk("register_chrdev success\n");
// 提交上级目录
cls = class_create(THIS_MODULE, "mychrdev");
if (IS_ERR(cls))
{
printk("class_create failed\n");
return -PTR_ERR(cls);
}
printk("class_create success\n");
// 向上提交三次节点信息
int i;
for (i = 0; i < 3; i++)
{
dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
if (IS_ERR(dev))
{
printk("[%d] : device_create failed\n", i);
return -PTR_ERR(dev);
}
}
printk("device_create success\n");
// 获取设备信息
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL)
{
printk("MEM : platform_get_resource failed\n");
return -1;
}
printk("MEN : %x\n", res->start);
// 获取中断号信息
irqnum = platform_get_irq(pdev, 0);
if (irqnum < 0)
{
printk("IRQ : platform_get_irq failed\n");
return -1;
}
printk("IRQ : %d\n", irqnum);
// 获取LED1gpio信息
gpionum1 = gpiod_get_from_of_node(pdev->dev.of_node, "led1-gpioe", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpionum1))
{
printk("gpiod_get_from_of_node failed\n");
return PTR_ERR(gpionum1);
}
printk("gpiod_get_from_of_node success\n");
// 获取LED2gpio信息
gpionum2 = gpiod_get_from_of_node(pdev->dev.of_node, "led2-gpiof", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpionum2))
{
printk("gpiod_get_from_of_node failed\n");
return PTR_ERR(gpionum2);
}
printk("gpiod_get_from_of_node success\n");
// 获取LED3gpio信息
gpionum3 = gpiod_get_from_of_node(pdev->dev.of_node, "led3-gpioe", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpionum3))
{
printk("gpiod_get_from_of_node failed\n");
return PTR_ERR(gpionum3);
}
printk("gpiod_get_from_of_node success\n");
return 0;
}
// 分离函数
int pdri_remove(struct platform_device *pdev)
{
gpiod_set_value(gpionum1, 0);
gpiod_set_value(gpionum2, 0);
gpiod_set_value(gpionum3, 0);
gpiod_put(gpionum1);
gpiod_put(gpionum2);
gpiod_put(gpionum3);
printk("%s : %s : %d\n", __FILE__, __func__, __LINE__);
return 0;
}
// 给驱动对象分配空间
struct platform_driver pdri = {
.probe = pdri_probe,
.remove = pdri_remove,
.driver.name = "a",
.driver.of_match_table = of_tab,
};
module_platform_driver(pdri);
MODULE_LICENSE("GPL");