From 7f1903ee7b50243a1c9d9ae925eafaea2235e0b4 Mon Sep 17 00:00:00 2001 From: sushe_Ubuntu Date: Sun, 31 Dec 2023 22:13:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=88=9A=E9=87=8D=E5=90=8D=E5=A5=BD?= =?UTF-8?q?=EF=BC=8C=E4=B8=8B=E9=9D=A2=E8=AF=A5=E6=94=B9=E5=8A=A8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=86=85=E5=AE=B9=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sushe_Ubuntu --- 08_spinlock/.vscode/c_cpp_properties.json | 21 +++ 08_spinlock/.vscode/settings.json | 21 +++ 08_spinlock/08_atomic.code-workspace | 11 ++ 08_spinlock/Makefile | 13 ++ 08_spinlock/spinlock.c | 169 ++++++++++++++++++++++ 08_spinlock/spinlockApp.c | 68 +++++++++ 6 files changed, 303 insertions(+) create mode 100644 08_spinlock/.vscode/c_cpp_properties.json create mode 100644 08_spinlock/.vscode/settings.json create mode 100644 08_spinlock/08_atomic.code-workspace create mode 100644 08_spinlock/Makefile create mode 100644 08_spinlock/spinlock.c create mode 100644 08_spinlock/spinlockApp.c diff --git a/08_spinlock/.vscode/c_cpp_properties.json b/08_spinlock/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..7ee3d5b --- /dev/null +++ b/08_spinlock/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/include/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated/**", + "/home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga/drivers/**" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} + diff --git a/08_spinlock/.vscode/settings.json b/08_spinlock/.vscode/settings.json new file mode 100644 index 0000000..1a2a04a --- /dev/null +++ b/08_spinlock/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.o":true, + "**/*.su":true, + "**/*.cmd":true, + "Documentation":true, + } +} \ No newline at end of file diff --git a/08_spinlock/08_atomic.code-workspace b/08_spinlock/08_atomic.code-workspace new file mode 100644 index 0000000..53a2b99 --- /dev/null +++ b/08_spinlock/08_atomic.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + + } + } +} \ No newline at end of file diff --git a/08_spinlock/Makefile b/08_spinlock/Makefile new file mode 100644 index 0000000..f3c5fa4 --- /dev/null +++ b/08_spinlock/Makefile @@ -0,0 +1,13 @@ +KERNELDIR := /home/youxiu/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga +CURRENT_PATH := $(shell pwd) +obj-m := spinlock.o + +build: kernel_modules + +kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean + + diff --git a/08_spinlock/spinlock.c b/08_spinlock/spinlock.c new file mode 100644 index 0000000..dbb2a35 --- /dev/null +++ b/08_spinlock/spinlock.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define GPIOLED_CNT 1 /* 设备号个数 */ +#define GPIOLED_NAME "gpioled" /* 名字 */ +#define LEDOFF 1 /* 关灯 */ +#define LEDON 0 /* 开灯 */ + + + +struct gpioled_dev +{ + dev_t devid; /* 设备号 */ + struct cdev cdev; /* cdev */ + struct class *class; /* 类 */ + struct device *device; /* 设备 */ + int major; /* 主设备号 */ + int minor; /* 次设备号 */ + struct device_node *nd; /* 设备节点 */ + int led_gpio; /* led所使用的GPIO编号 */ + atomic_t lock; /* 原子变量 */ +}; + +struct gpioled_dev gpioled; /* led设备 */ + + +static int led_open(struct inode *inode, struct file *filp) +{ + + if(atomic_read(&gpioled.lock)<1){ + return -EBUSY; + }else{ + atomic_dec(&gpioled.lock); + } + filp->private_data = &gpioled; + return 0; +} + +static ssize_t led_read(struct file *filp, const char __user *buf,size_t cnt,loff_t *offt) +{ + return 0; +} + + +static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt,loff_t *offt) +{ + int retval; + unsigned char databuf[1]; + unsigned char ledstate; + + struct gpioled_dev *dev = filp->private_data; + + retval = copy_from_user(databuf,buf,cnt); + + ledstate = databuf[0]; + + if(ledstate == LEDOFF){ + gpio_set_value(dev->led_gpio,0); + }else if(ledstate == LEDON){ + gpio_set_value(dev->led_gpio,1); + } + return retval; +} + +static int led_release(struct inode *inode, struct file *filp) +{ + struct gpioled_dev *dev = filp->private_data; + atomic_inc(&dev->lock); + return 0; +} + +/* 设备操作函数 */ +static struct file_operations gpioled_fops = { + .owner = THIS_MODULE, + .open = led_open, + .read = led_read, + .write = led_write, + .release = led_release +}; + +static int __init led_init(void) +{ + int ret = 0; + + atomic_set(&gpioled.lock, 1); + /* 设置LED所使用的GPIO */ + /* 1、获取设备节点 gpioled*/ + gpioled.nd = of_find_node_by_path("/gpioled"); + if (gpioled.nd != NULL) + { + printk("gpioled node has been found!\r\n"); + } + + /* 2、 */ + gpioled.led_gpio = of_get_named_gpio(gpioled.nd,"led-gpio",0); + ret = gpio_direction_output(gpioled.led_gpio,1); + + + /* 注册字符设备驱动 */ + /* 1、创建设备号 */ + if(gpioled.major){ + gpioled.devid = MKDEV(gpioled.major,0); + register_chrdev_region(gpioled.devid,GPIOLED_CNT,GPIOLED_NAME); + }else{ + alloc_chrdev_region(&gpioled.devid,0,GPIOLED_CNT,GPIOLED_NAME); /* 申请设备号 */ + gpioled.major = MAJOR(gpioled.devid); /* 获取分配的主设备号 */ + gpioled.minor = MINOR(gpioled.devid); /* 获取分配的次设备号 */ + } + + printk("gpioled major = %d, minor = %d \r\n",gpioled.major,gpioled.minor); + + + /* 2、初始化 */ + gpioled.cdev.owner = THIS_MODULE; + cdev_init(&gpioled.cdev,&gpioled_fops); + + /* 3、添加一个cdev */ + cdev_add(&gpioled.cdev,gpioled.devid,GPIOLED_CNT); + + /* 创建类 */ + gpioled.class = class_create(THIS_MODULE,GPIOLED_NAME); + if(IS_ERR(gpioled.class)){ + return PTR_ERR(gpioled.class); + } + + /* 5、创建设备 */ + gpioled.device = device_create(gpioled.class,NULL,gpioled.devid,NULL,GPIOLED_NAME); + + if(IS_ERR(gpioled.device)) { + return PTR_ERR(gpioled.device); + } + + return 0; +} + +static void __exit led_exit(void) +{ + /* 注销字符设备驱动 */ + cdev_del(&gpioled.cdev); + unregister_chrdev_region(gpioled.devid,GPIOLED_CNT); + + device_destroy(gpioled.class,gpioled.devid); + class_destroy(gpioled.class); +} + + + + + + +module_init(led_init); +module_exit(led_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("chaoliang"); diff --git a/08_spinlock/spinlockApp.c b/08_spinlock/spinlockApp.c new file mode 100644 index 0000000..90c1eb7 --- /dev/null +++ b/08_spinlock/spinlockApp.c @@ -0,0 +1,68 @@ +#include "stdio.h" +#include "unistd.h" +#include "sys/types.h" +#include "sys/stat.h" +#include "fcntl.h" +#include "string.h" +#include "stdlib.h" + +#define LEDOFF 0 /* LED关 */ +#define LEDPON 1 /* LED开 */ + +int main(int argc,char *argv[]) +{ + int fd,retvalue; + char *filename; + unsigned char ledstate[1]; + u_int8_t cnt = 0; + + if (argc !=3) + { + printf("Error Usage!\r\n"); + return -1; + } + + filename = argv[1]; + + /* 打开驱动文件 */ + fd = open(filename,O_RDWR); + if (fd < 0) + { + printf("Can't open file %s\r\n",filename); + return -1; + } + + ledstate[0] = atoi(argv[2]); + retvalue = write(fd,ledstate,sizeof(ledstate)); + if (retvalue < 0) + { + printf("LED Control failed!\r\n"); + close(fd); + return -1; + } + + + + while (1) + { + sleep(5); + cnt++; + printf("App runing times: %d\r\n",cnt); + if (cnt >=5) + { + break; + } + + } + printf("App runing finished!\r\n"); + retvalue = close(fd); + if (retvalue < 0) + { + printf("Can't close file %s \r\n",filename); + return -1; + } + + return 0; +} + + -- Gitee From 052607dbf5e741af2fa45a04995ffce0666f5d5e Mon Sep 17 00:00:00 2001 From: sushe_Ubuntu Date: Tue, 2 Jan 2024 21:50:35 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=87=AA=E6=97=8B=E9=94=81=E5=AE=9E?= =?UTF-8?q?=E9=AA=8C=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sushe_Ubuntu --- 08_spinlock/spinlock.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/08_spinlock/spinlock.c b/08_spinlock/spinlock.c index dbb2a35..8b840b6 100644 --- a/08_spinlock/spinlock.c +++ b/08_spinlock/spinlock.c @@ -33,20 +33,26 @@ struct gpioled_dev int minor; /* 次设备号 */ struct device_node *nd; /* 设备节点 */ int led_gpio; /* led所使用的GPIO编号 */ - atomic_t lock; /* 原子变量 */ + int dev_status; /* 设备状态,0:设备未使用;>0:设备已经被使用 */ + spinlock_t lock; /* 自旋锁 */ }; + struct gpioled_dev gpioled; /* led设备 */ static int led_open(struct inode *inode, struct file *filp) { - - if(atomic_read(&gpioled.lock)<1){ + unsigned long flags; + spin_lock_irqsave(&gpioled.lock,flags); /* 设置私有数据 */ + if (gpioled.dev_status) + { + spin_unlock_irqrestore(&gpioled.lock,flags); /* 解锁 */ return -EBUSY; - }else{ - atomic_dec(&gpioled.lock); } + gpioled.dev_status++; /* 如果设备没有被打开,那么就标记已经打开了 */ + spin_unlock_irqrestore(&gpioled.lock,flags); /* 解锁 */ + filp->private_data = &gpioled; return 0; } @@ -79,8 +85,15 @@ static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt,lo static int led_release(struct inode *inode, struct file *filp) { + unsigned long flags; struct gpioled_dev *dev = filp->private_data; - atomic_inc(&dev->lock); + spin_lock_irqsave(&dev->lock, flags); /* 上锁 */ + if (dev->dev_status) + { + dev->dev_status--; + } + spin_unlock_irqrestore(&dev->lock, flags); /* 解锁 */ + return 0; } @@ -97,7 +110,7 @@ static int __init led_init(void) { int ret = 0; - atomic_set(&gpioled.lock, 1); + spin_lock_init(&gpioled.lock); /* 设置LED所使用的GPIO */ /* 1、获取设备节点 gpioled*/ gpioled.nd = of_find_node_by_path("/gpioled"); -- Gitee