需求:
使用platform框架实现led流水灯和按键中断开启风扇
实现过程:
设备树文件:
/dts-v1/;
#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxac-pinctrl.dtsi"
#include "stm32mp15xx-fsmp1x.dtsi"
/ {
model = "HQYJ STM32MP157 FSMP1A Discovery Board";
compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
aliases {
serial0 = &uart4;
serial5 = &usart3;
};
chosen {
stdout-path = "serial0:115200n8";
};
reserved-memory {
gpu_reserved: gpu@d4000000 {
reg = <0xd4000000 0x4000000>;
no-map;
};
optee_memory: optee@0xde000000 {
reg = <0xde000000 0x02000000>;
no-map;
};
};
myplatform{ //添加的platform内容
compatible = "hqyj,platform";
reg = <0x12345678 0x14>;
interrupt-parent = <&gpiof>;
interrupts = <8 0>;
led1=<&gpioe 10 0>;
led2=<&gpiof 10 0>;
led3=<&gpioe 8 0>;
fan=<&gpioe 9 0>;
};
};
驱动源文件:
#include "pdrv.h"
//KEY3 PF8 中断处理函数
irqreturn_t irq1_handler(int irqno, void *arg)
{
gpiod_set_value(gpiono4, !gpiod_get_value(gpiono4));
return IRQ_HANDLED;
}
//ioctl
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{
int whitch;
int ret;
switch (cmd)
{
case LED_ON:
ret = copy_from_user(&whitch, (void *)args, sizeof(int));
if (ret)
{
printk("copy_from_user failed\n");
return -EIO;
}
switch (whitch)
{
case LED1:
gpiod_set_value(gpiono1, 1);
break;
case LED2:
gpiod_set_value(gpiono2, 1);
break;
case LED3:
gpiod_set_value(gpiono3, 1);
break;
}
break;
case LED_OFF:
ret = copy_from_user(&whitch, (void *)args, sizeof(int));
if (ret)
{
printk("copy from user is error\n");
return -EIO;
}
switch (whitch)
{
case LED1:
gpiod_set_value(gpiono1, 0);
break;
case LED2:
gpiod_set_value(gpiono2, 0);
break;
case LED3:
gpiod_set_value(gpiono3, 0);
break;
}
break;
}
return 0;
}
const struct file_operations fops = {
.unlocked_ioctl = mycdev_ioctl,
};
int pdrv_probe(struct platform_device *pdev)
{
int ret;
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (NULL == res)
{
printk("获取设备信息失败\n");
return -ENODATA;
}
printk("mem类型资源数值为:%x\n", res->start);
gpiono1 = gpiod_get_from_of_node(pdev->dev.of_node, "led1", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpiono1))
{
printk("解析gpio1编号失败\n");
return PTR_ERR(gpiono1);
}
printk("解析gpio1编号成功\n");
gpiono2 = gpiod_get_from_of_node(pdev->dev.of_node, "led2", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpiono2))
{
printk("解析gpio2编号失败\n");
return PTR_ERR(gpiono2);
}
printk("解析gpio2编号成功\n");
gpiono3 = gpiod_get_from_of_node(pdev->dev.of_node, "led3", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpiono3))
{
printk("解析gpio3编号失败\n");
return PTR_ERR(gpiono3);
}
printk("解析gpio3编号成功\n");
gpiono4 = gpiod_get_from_of_node(pdev->dev.of_node, "fan", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpiono4))
{
printk("解析gpio4编号失败\n");
return PTR_ERR(gpiono4);
}
printk("解析gpio4编号成功\n");
irqno = platform_get_irq(pdev, 0);
if (irqno < 0)
{
printk("获取中断类型资源失败\n");
return -ENODATA;
}
printk("中断类型的资源数值为%d\n", irqno);
request_irq(irqno, irq1_handler, IRQF_TRIGGER_FALLING, "myirq", 0);
// 1.分配对象
cdev = cdev_alloc();
if (NULL == cdev)
{
printk("分配对象空间失败\n");
ret = -ENOMEM;
goto ERR1;
}
printk("分配对象空间成功\n");
// 2.初始化驱动对象
cdev_init(cdev, &fops);
if (0 == major)
{
ret = alloc_chrdev_region(&devno, minor, 3, "mycdev");
if (ret)
{
printk("动态申请设备号失败\n");
goto ERR2;
}
major = MAJOR(devno);
minor = MINOR(devno);
}
else if (major > 0)
{
ret = register_chrdev_region(MKDEV(major, minor), 3, "mycdev");
if (ret)
{
printk("静态申请设备号失败\n");
goto ERR2;
}
}
// 3.注册对象
ret = cdev_add(cdev, MKDEV(major, minor), 3);
if (ret)
{
printk("驱动对象注册进内核失败\n");
goto ERR3;
}
printk("驱动对象注册进内核成功\n");
cls = class_create(THIS_MODULE, "mycdev");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
goto ERR4;
}
printk("向上提交目录成功\n");
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "mycdev0");
if (IS_ERR(dev))
{
printk("向上提交结点信息失败\n");
goto ERR5;
}
printk("向上提交结点信息成功\n");
printk("向上提交设备结点成功\n");
printk("major = %d\n", major);
return 0;
ERR5:
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
ERR4:
cdev_del(cdev);
ERR3:
unregister_chrdev_region(MKDEV(major, minor), 3);
ERR2:
kfree(cdev);
ERR1:
return ret;
return 0;
}
int pdrv_remove(struct platform_device *pdev)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
cdev_del(cdev);
unregister_chrdev_region(MKDEV(major, minor), 3);
kfree(cdev);
free_irq(irqno, NULL);
gpiod_set_value(gpiono1, 0);
gpiod_put(gpiono1);
gpiod_set_value(gpiono2, 0);
gpiod_put(gpiono2);
gpiod_set_value(gpiono3, 0);
gpiod_put(gpiono3);
gpiod_set_value(gpiono4, 0);
gpiod_put(gpiono4);
return 0;
}
struct of_device_id oftable[] =
{
{.compatible = "hqyj,platform"},
{},
};
struct platform_driver pdrv = {
.probe = pdrv_probe,
.remove = pdrv_remove,
.driver = {
.name = "aaaa",
.of_match_table = oftable,
},
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");
驱动头文件:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>
struct resource* res;
int irqno;
struct gpio_desc* gpiono1;
struct gpio_desc* gpiono2;
struct gpio_desc* gpiono3;
struct gpio_desc* gpiono4;
int irqno;
struct cdev* cdev;
dev_t devno;
#if 0
unsigned int major = 0;
#else
unsigned int major = 500;
#endif
unsigned int minor = 0;
struct class* cls;
struct device* dev;
#define LED_ON _IOW('a',1,int)
#define LED_OFF _IOW('a',0,int)
enum{
LED1,
LED2,
LED3,
};
测试文件:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#define LED_ON _IOW('a',1,int)
#define LED_OFF _IOW('a',0,int)
enum{
LED1,
LED2,
LED3,
};
int main(int argc,const char * argv[])
{
int cmd;
int fd = -1;
fd = open("/dev/mycdev0",O_RDWR);
if(fd == -1)
{
perror("open is error\n");
return -1;
}
int whitch;
while(1)
{
whitch = LED1;
ioctl(fd,LED_ON, &whitch);
sleep(1);
ioctl(fd,LED_OFF, &whitch);
sleep(1);
whitch = LED2;
ioctl(fd,LED_ON, &whitch);
sleep(1);
ioctl(fd,LED_OFF, &whitch);
sleep(1);
whitch = LED3;
ioctl(fd,LED_ON, &whitch);
sleep(1);
ioctl(fd,LED_OFF, &whitch);
sleep(1);
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)