Ver Fonte

cat,echo控制驱动程序的数据写入与读出

xuxinyi há 1 ano atrás
pai
commit
faa4c0599f

BIN
开发笔记/img_17.png


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

@@ -187,4 +187,8 @@
     4.执行
         ./led
     5.查看结果
-        ![img_16.png](img_16.png)
+        ![img_16.png](img_16.png)
+26.使用echo,cat 命令控制驱动写入和读出
+    这里并没有使用APP进行控制,而知直接使用echo,cat命令
+    APP有点bug,暂时没修复。
+    ![img_17.png](img_17.png)

+ 14 - 1
驱动文件/2024-11-6/led.c

@@ -9,7 +9,7 @@
 int main()
 {
     int fd;
-    char write_buf[] = "Hello from user space!";
+    char write_buf[100] = "Hello from user space!";
     char read_buf[100];
 
     // 打开设备文件
@@ -19,6 +19,19 @@ int main()
         return -1;
     }
 
+    // 从设备读取数据
+    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);
+    }
+
     // 向设备写入数据
     ssize_t written = write(fd, write_buf, strlen(write_buf));
     if (written < 0) {

+ 177 - 0
驱动文件/2024-11-7/ledUser.c

@@ -0,0 +1,177 @@
+#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;
+char data_buf[100] = "Hello from kernel space!      .";
+char write_buf[100 = "Hello from user space!";
+// 打开字符设备
+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;
+}
+
+// 读取数据(从内核空间的 data_buf[] 数组中读取数据)
+static ssize_t gpio_led_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
+{
+    ssize_t ret;
+    size_t to_read;
+
+    printk("%s: read!\n", TAG);
+
+    if (*offset >= sizeof(data_buf)) {
+        return 0;  // 没有更多数据可以读取
+    }
+
+    // 计算最多读取的数据长度,并确保不会越界
+    to_read = min(len, (size_t)(sizeof(data_buf) - *offset));  // 强制转换为 size_t 类型
+
+    // 从内核空间复制数据到用户空间
+    ret = copy_to_user(buf, data_buf + *offset, to_read);
+    if (ret != 0) {
+        printk("%s: copy_to_user failed!\n", TAG);
+        return -EFAULT;
+    }
+
+    // 更新偏移量
+    *offset += to_read;
+
+    return to_read;  // 返回实际读取的字节数
+}
+
+// 写入数据(将数据保存到内核空间的 data_buf[] 数组)
+static ssize_t gpio_led_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)
+{
+    ssize_t ret;
+
+    printk("%s: write!\n", TAG);
+
+    // 确保写入的数据大小不超过缓冲区
+    if (len > sizeof(data_buf)) {
+        printk("%s: write data_buf too large!\n", TAG);
+        return -EINVAL;
+    }
+
+    // 从用户空间复制数据到内核空间
+    ret = copy_from_user(data_buf, buf, len);
+    if (ret != 0) {
+        printk("%s: copy_from_user failed!\n", TAG);
+        return -EFAULT;
+    }
+
+    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,
+};
+
+// probe函数:设备初始化时调用
+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;
+}
+
+// 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;
+}
+
+// shutdown函数:设备关闭时调用
+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");

+ 62 - 0
驱动文件/2024-11-7/ledUserApp.c

@@ -0,0 +1,62 @@
+#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[100] = "Hello from user space!";
+    char read_buf[100] = "\0";
+
+    // 打开设备文件
+    fd = open(DEVICE_FILE, O_RDWR);
+    if (fd < 0) {
+        perror("open");
+        return -1;
+    }
+
+    // 从设备读取数据
+    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);
+        memset(read_buf, 0, sizeof(read_buf));  // 将 read_buf 数组的所有元素设置为 0
+    }
+
+    // 向设备写入数据
+    ssize_t written = write(fd, write_buf, sizeof(write_buf));
+    if (written < 0) {
+        perror("write");
+        close(fd);
+        return -1;
+    } else {
+        printf("Wrote %zd bytes to the device.\n", written);
+    }
+
+    // 从设备读取数据
+    ssize_t read_bytes1 = read(fd, read_buf, 40);  // 继续读取更多数据
+    if (read_bytes1 < 0) {
+        perror("read");
+        close(fd);
+        return -1;
+    } else if (read_bytes1 == 0) {
+        printf("No data read from the device.\n");
+    } else {
+        printf("Read from the device: %s\n", read_buf);
+    }
+
+    // 关闭设备文件
+    close(fd);
+
+    return 0;
+}