ZBLOG

编写一个简易的dma_alloc_coherent驱动程序,不使用platform总线的方式来实现的驱动

下面是一个简易的 Linux 驱动程序示例,使用 dma_alloc_coherent() 分配 DMA 一致性内存,并不依赖于 platform 总线。这种情况下,我们可以使用字符设备驱动来实现。

示例代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/dma-mapping.h>

#define DEVICE_NAME "simple_dma_char"
#define BUFFER_SIZE 1024

struct simple_dma_device {
    char *cpu_addr;       // CPU可访问的内存地址
    dma_addr_t dma_handle; // 设备可访问的DMA地址
    struct cdev cdev;     // 字符设备结构体
};

static struct simple_dma_device *dma_dev;
static int major_number;

// 打开设备
static int simple_dma_open(struct inode *inode, struct file *file) {
    return 0;
}

// 释放设备
static int simple_dma_release(struct inode *inode, struct file *file) {
    return 0;
}

// 从设备读取数据
static ssize_t simple_dma_read(struct file *file, char __user *buf, size_t count, loff_t *offset) {
    if (*offset >= BUFFER_SIZE) {
        return 0; // EOF
    }

    if (*offset + count > BUFFER_SIZE) {
        count = BUFFER_SIZE - *offset;
    }

    if (copy_to_user(buf, dma_dev->cpu_addr + *offset, count)) {
        return -EFAULT;
    }

    *offset += count;
    return count;
}

// 向设备写入数据
static ssize_t simple_dma_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) {
    if (*offset >= BUFFER_SIZE) {
        return 0; // EOF
    }

    if (*offset + count > BUFFER_SIZE) {
        count = BUFFER_SIZE - *offset;
    }

    if (copy_from_user(dma_dev->cpu_addr + *offset, buf, count)) {
        return -EFAULT;
    }

    *offset += count;
    return count;
}

// 文件操作结构体
static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = simple_dma_open,
    .release = simple_dma_release,
    .read = simple_dma_read,
    .write = simple_dma_write,
};

// 模块初始化函数
static int __init simple_dma_init(void) {
   major_number = register_chrdev(0, DEVICE_NAME, &fops);
   if (major_number < 0) {
       printk(KERN_ALERT "Failed to register character device\n");
       return major_number;
   }
   
   dma_dev = kmalloc(sizeof(struct simple_dma_device), GFP_KERNEL);
   if (!dma_dev) {
       unregister_chrdev(major_number, DEVICE_NAME);
       printk(KERN_ALERT "Failed to allocate memory for device\n");
       return -ENOMEM;
   }

   // 分配一致性DMA内存
   dma_dev->cpu_addr = dma_alloc_coherent(NULL, BUFFER_SIZE, &dma_dev->dma_handle, GFP_KERNEL);
   if (!dma_dev->cpu_addr) {
       kfree(dma_dev);
       unregister_chrdev(major_number, DEVICE_NAME);
       printk(KERN_ALERT "Failed to allocate coherent DMA memory\n");
       return -ENOMEM;
   }

   memset(dma_dev->cpu_addr, 0, BUFFER_SIZE); // 初始化为零

   printk(KERN_INFO "Simple DMA driver initialized with major number %d\n", major_number);

   return 0;
}

// 模块退出函数
static void __exit simple_dma_exit(void) {
   if (dma_dev && dma_dev->cpu_addr) {  
       dma_free_coherent(NULL, BUFFER_SIZE, dma_dev->cpu_addr, dma_dev->dma_handle);
       kfree(dma_dev); 
   }
   
   unregister_chrdev(major_number, DEVICE_NAME); 
}

module_init(simple_dma_init);
module_exit(simple_dma_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A Simple Character Device Driver using DMA Alloc Coherent");

编译与加载

  1. 将上述代码保存到文件 simple_dma_char.c 中。
  2. 创建一个 Makefile
obj-m += simple_dma_char.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  1. 编译模块:
make
  1. 加载模块:
sudo insmod simple_dma_char.ko 
  1. 查看日志以确认输出:
dmesg | tail -n 20 
  1. 创建设备节点:
sudo mknod /dev/simple_dma_char c [major_number] 0 # 将 [major_number] 替换为实际的主设备号,如 'cat /proc/devices'
  1. 使用 echocat 命令进行读写测试:
# 写入数据(例如:hello)
echo "hello" > /dev/simple_dma_char 

# 从设备读取数据并打印出来 
cat /dev/simple_dma_char 
  1. 卸载模块:
sudo rmmod simple_dmа_char 

注意事项

  • 上述驱动是一个基本示例,演示了如何创建字符设备并使用 dma_alloc_coherent()
  • 请根据需要扩展和修改该驱动,以满足您的具体要求和硬件环境。
  • 确保处理好错误情况以及多线程环境下的数据安全。


    内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6142

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?