设备树及gpio子系统及ioctl控制及字符设备驱动及内核模块编程事项仨LED灯说点就点说灭就灭
设备树文件stm32mp157a-fsmp1a.dts
(主要是添加 leds 节点)
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (C) STMicroelectronics 2019 - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
/dts-v1/;
#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxac-pinctrl.dtsi"
#include "stm32mp15xx-fsmp1x.dtsi"
/ {
model = "HQYJ STM32MP157A-FSMP1A Discovery Board";
compatible = "st,stm32mp157a-fsmp1a", "st,stm32mp157";
aliases {
serial0 = &uart4;
};
chosen {
stdout-path = "serial0:115200n8";
};
reserved-memory {
gpu_reserved: gpu@da000000 {
reg = <0xda000000 0x4000000>;
no-map;
};
optee_memory: optee@0xde000000 {
reg = <0xde000000 0x02000000>;
no-map;
};
};
mynode@0x12345678{
compatible = "hqyj,mynode";
astring = "hello 24081";
uint = <0xaabbccdd 0x11223344>;
binarry=[00 0c 29 7b f9 be];
mixed = "helle", [11 22], <0x12345678>;
};
leds {
led1-gpio = <&gpioe 10 0>;
led2-gpio = <&gpiof 10 0>;
led3-gpio = <&gpioe 8 0>;
};
};
&optee {
status = "okay";
};
驱动文件dt_test.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include "det_led.h"
unsigned int major;
char kbuf[128] = {};
struct device_node *np;
int gpiono;
int myled_open(struct inode* inode , struct file * file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
ssize_t myled_read(struct file*file , char __user* ubuf , size_t size , loff_t * lft)
{
unsigned long ret;
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
if(size > sizeof(kbuf))
{
size = sizeof(kbuf);
}
ret = copy_to_user(ubuf ,kbuf, size);
if(ret)
{
printk("cpoy_to_user failed\n");
return ret;
}
return 0;
}
ssize_t myled_write(struct file*file , const char __user * ubuf , size_t size , loff_t *lft)
{
unsigned long ret;
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
if(size > sizeof(kbuf))
{
size = sizeof(kbuf);
}
ret = copy_from_user(kbuf ,ubuf, size);
if(ret)
{
printk("cpoy_from_user failed\n");
return ret;
}
return 0;
}
long myled_ioctl(struct file* file ,unsigned int cmd , unsigned long arg)
{
int ch;
unsigned long ret =copy_from_user(&ch , (int *)arg ,4);
if(ret){
printk("ch get error");
return ret;
}
switch (cmd)
{
case LED_ON:
switch (ch)
{
case 1:
gpiono = of_get_named_gpio(np, "led1-gpio", 0);
gpio_set_value(gpiono, 1);
break;
case 2:
gpiono = of_get_named_gpio(np, "led2-gpio", 0);
gpio_set_value(gpiono, 1);
break;
case 3:
gpiono = of_get_named_gpio(np, "led3-gpio", 0);
gpio_set_value(gpiono, 1);
break;
default:
break;
}
break;
case LED_OFF:
switch (ch)
{
case 1:
gpiono = of_get_named_gpio(np, "led1-gpio", 0);
gpio_set_value(gpiono, 0);
break;
case 2:
gpiono = of_get_named_gpio(np, "led2-gpio", 0);
gpio_set_value(gpiono, 0);
break;
case 3:
gpiono = of_get_named_gpio(np, "led3-gpio", 0);
gpio_set_value(gpiono, 0);
break;
default:
break;
}
break;
default:
break;
}
return 0;
}
int myled_close(struct inode*indoe , struct file* file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
struct file_operations fops={
.open=myled_open,
.read=myled_read,
.write=myled_write,
.unlocked_ioctl=myled_ioctl,
.release=myled_close,
};
static int __init mycdev_init(void)
{
int i = 0;//for循环参数变量
major = register_chrdev(0 ,"myled", &fops);
printk("%s:%s:%d\n", __FILE__, __func__, major);
if(major<0)
{
printk("register_chrdev error\n");
}
np = of_find_node_by_path("/leds");
if(np == NULL)
{
printk("find node failed\n");
return -1;
}
for(i=0 ; i<3 ; i++){
if(i==0){
gpiono = of_get_named_gpio(np, "led1-gpio", 0);
}
if(i==1){
gpiono = of_get_named_gpio(np, "led2-gpio", 0);
}
if(i==2){
gpiono = of_get_named_gpio(np, "led3-gpio", 0);
}
if(gpiono < 0)
{
printk("get gpiono failed \n");
return -1;
}
printk("get gpiono success \n");
if(gpio_request(gpiono , NULL))
{
printk("gpio requset failed\n");
}
printk("gpio requset success\n");
if (gpio_direction_output(gpiono , 0))
{
printk(" direction failed\n");
}
printk("gpio direction success\n");
}
return 0;
}
static void __exit mycdev_exit(void)
{
int i;
for(i=0;i<3;i++)
{
if(i==0){
gpiono = of_get_named_gpio(np, "led1-gpio", 0);
}
if(i==1){
gpiono = of_get_named_gpio(np, "led2-gpio", 0);
}
if(i==2){
gpiono = of_get_named_gpio(np, "led3-gpio", 0);
}
gpio_free (gpiono );
}
unregister_chrdev(major, "myled");
printk("gpio free success");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
应用文件头文件
led.h
#ifndef __LED_H__
#define __LED_H__
#define LED_ON _IOW('l', 1, int)
#define LED_OFF _IOW('l', 0, int)
#endif
应用文件 dpp.c(或许该叫他led.c)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "det_led.h"
#include <sys/ioctl.h>
#include<unistd.h>
int main(int argc,const char * argv[])
{
int fd = open("/dev/led" , O_RDWR);
if(fd<0)
{
printf("file open failed\n");
return fd;
}
printf("file open success\n");
int a , b;
while(1){
printf("选择要控制的灯 1-(LED1) 2-(LED2) 3-(LED3)\n");
scanf("%d", &a);
if(a!=1 && a!=2 && a!=3)
{
printf("选择有误请重新输入\n");
continue;
}
loop:
printf("控制灯的状态 1-(ON) 0-(OFF)\n");
scanf("%d", &b);
if(b!=1 && b!=0)
{
printf("选择有误请重新输入\n");
goto loop;
}
switch (b)
{
case 0:
ioctl(fd ,LED_OFF ,&a);
break;
case 1:
ioctl(fd ,LED_ON ,&a);
break;
default:
break;
}
}
close(fd);
return 0;
}