Browse Source

probe+字符设备驱动+应用程序编写

xuxinyi 1 year ago
parent
commit
f156ec5e28

BIN
开发笔记/img_15.png


BIN
开发笔记/img_16.png


+ 12 - 1
开发笔记/开发笔记.md

@@ -176,4 +176,15 @@
         ![img_12.png](img_12.png)
         ![img_13.png](img_13.png)
     测试结果
-        ![img_14.png](img_14.png)
+        ![img_14.png](img_14.png)
+
+25.probe + 字符设备驱动
+    1.注意: -static一定要加,否则在3566上运行不了
+        arm-linux-gnueabihf-gcc -o led led.c -static
+    2.adb push xxxx.ko /data/xxxx.ko
+    3.添加可执行权限
+        ![img_15.png](img_15.png)
+    4.执行
+        ./led
+    5.查看结果
+        ![img_16.png](img_16.png)

+ 3 - 2
设备树/tspi-rk3566-user-v10-linux.dts

@@ -65,8 +65,9 @@
     };
 
 	my_new_node{
-		compatible = "MYNEWNODE";
-	};
+    		compatible = "led-user";
+    		gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_LOW>;
+    	};
 
 	leds: leds {
 		compatible = "gpio-leds";

+ 49 - 0
驱动文件/2024-11-6/led.c

@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#define DEVICE_FILE "/dev/gpio_led"
+
+int main()
+{
+    int fd;
+    char write_buf[] = "Hello from user space!";
+    char read_buf[100];
+
+    // 打开设备文件
+    fd = open(DEVICE_FILE, O_RDWR);
+    if (fd < 0) {
+        perror("open");
+        return -1;
+    }
+
+    // 向设备写入数据
+    ssize_t written = write(fd, write_buf, strlen(write_buf));
+    if (written < 0) {
+        perror("write");
+        close(fd);
+        return -1;
+    } else {
+        printf("Wrote %zd bytes to the device.\n", written);
+    }
+
+    // 从设备读取数据
+    ssize_t read_bytes = read(fd, read_buf, sizeof(read_buf));
+    if (read_bytes < 0) {
+        perror("read");
+        close(fd);
+        return -1;
+    } else if (read_bytes == 0) {
+        printf("No data read from the device.\n");
+    } else {
+        read_buf[read_bytes] = '\0';
+        printf("Read from the device: %s\n", read_buf);
+    }
+
+    // 关闭设备文件
+    close(fd);
+
+    return 0;
+}

+ 135 - 0
驱动文件/2024-11-6/ledByMySelf.c

@@ -0,0 +1,135 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>  // for copy_to_user() and copy_from_user()
+const char *TAG = "MYNEWNODE";\
+
+static int major_number = 0;  // 默认自动分配主设备号
+static struct cdev my_cdev;
+static struct class *my_class;
+
+
+// 打开字符设备
+static int gpio_led_open(struct inode *inode, struct file *file)
+{
+    printk("%s:open!\n", TAG);
+    return 0;
+}
+
+// 关闭字符设备
+static int gpio_led_release(struct inode *inode, struct file *file)
+{
+    printk("%s:release!\n", TAG);
+    return 0;
+}
+
+// 读取数据(此示例没有实际硬件操作)
+static ssize_t gpio_led_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+    printk("%s:read!\n", TAG);
+    // 这里可以填充实际的读取逻辑,如果需要从硬件读取数据
+    return 0;
+}
+
+// 写入数据(此示例没有实际硬件操作)
+static ssize_t gpio_led_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)
+{
+    printk("%s:write!\n", TAG);
+    // 这里可以填充实际的写入逻辑,如果需要控制硬件
+    return len;  // 返回实际写入的字节数
+}
+
+// 字符设备操作结构体
+static const struct file_operations gpio_led_fops = {
+    .owner = THIS_MODULE,
+    .open = gpio_led_open,
+    .release = gpio_led_release,
+    .read = gpio_led_read,
+    .write = gpio_led_write,
+};
+
+static int gpio_led_probe(struct platform_device *pdev)
+{   int ret;
+    // 这里可以添加初始化代码
+    printk("%s:probe!\n",TAG);
+
+    ret = alloc_chrdev_region(&major_number,0,1,"gpio_led");
+    if(ret < 0){
+        printk("%s:alloc_chrdev_region failed!\n", TAG);
+        return ret;
+    }
+
+    // 注册字符设备
+    cdev_init(&my_cdev, &gpio_led_fops);
+    my_cdev.owner = THIS_MODULE;
+    ret = cdev_add(&my_cdev, major_number, 1);
+    if (ret) {
+        printk("%s:cdev_add failed!\n", TAG);
+        unregister_chrdev_region(major_number, 1);
+        return ret;
+    }
+
+    // 创建设备文件
+    my_class = class_create(THIS_MODULE, "gpio_led_class");
+    if (IS_ERR(my_class)) {
+        ret = PTR_ERR(my_class);
+        printk("%s:class_create failed!\n", TAG);
+        cdev_del(&my_cdev);
+        unregister_chrdev_region(major_number, 1);
+        return ret;
+    }
+
+    if (IS_ERR(device_create(my_class, NULL, major_number, NULL, "gpio_led"))) {
+        printk("%s:device_create failed!\n", TAG);
+        class_destroy(my_class);
+        cdev_del(&my_cdev);
+        unregister_chrdev_region(major_number, 1);
+        return -ENOMEM;
+    }
+
+    return 0; // 返回 0 表示成功
+}
+
+// 设备remove函数
+static int gpio_led_remove(struct platform_device *pdev)
+{
+    printk("%s:remove!\n", TAG);
+
+    // 注销字符设备
+    device_destroy(my_class, major_number);
+    class_destroy(my_class);
+    cdev_del(&my_cdev);
+    unregister_chrdev_region(major_number, 1);
+
+    return 0;
+}
+
+static void gpio_led_shutdown(struct platform_device *pdev)
+{
+    printk("%s:shutdown!\n", TAG);
+}
+
+static const struct of_device_id of_gpio_leds_match[] = {
+    { .compatible = "led-user", },
+    {}
+};
+
+MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
+
+static struct platform_driver gpio_led_driver = {
+    .probe      = gpio_led_probe,
+    .remove     = gpio_led_remove,
+    .shutdown   = gpio_led_shutdown,
+    .driver     = {
+        .name   = "led-user",
+        .of_match_table = of_gpio_leds_match,
+    },
+};
+
+module_platform_driver(gpio_led_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Your Name");
+MODULE_DESCRIPTION("Simple GPIO LEDs driver");

+ 2 - 1
驱动文件/Makefile

@@ -95,4 +95,5 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
 obj-y+= newchrled.o
 obj-m+= leds-user-defind.o
 obj-m+= charDevice.o
-obj-m+= platform.o
+obj-m+= platform.o
+obj-m+= ledByMySelf.o