ZBLOG

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

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

示例代码

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/fs.h>
  5. #include <linux/uaccess.h>
  6. #include <linux/dma-mapping.h>
  7. #define DEVICE_NAME "simple_dma_char"
  8. #define BUFFER_SIZE 1024
  9. struct simple_dma_device {
  10. char *cpu_addr; // CPU可访问的内存地址
  11. dma_addr_t dma_handle; // 设备可访问的DMA地址
  12. struct cdev cdev; // 字符设备结构体
  13. };
  14. static struct simple_dma_device *dma_dev;
  15. static int major_number;
  16. // 打开设备
  17. static int simple_dma_open(struct inode *inode, struct file *file) {
  18. return 0;
  19. }
  20. // 释放设备
  21. static int simple_dma_release(struct inode *inode, struct file *file) {
  22. return 0;
  23. }
  24. // 从设备读取数据
  25. static ssize_t simple_dma_read(struct file *file, char __user *buf, size_t count, loff_t *offset) {
  26. if (*offset >= BUFFER_SIZE) {
  27. return 0; // EOF
  28. }
  29. if (*offset + count > BUFFER_SIZE) {
  30. count = BUFFER_SIZE - *offset;
  31. }
  32. if (copy_to_user(buf, dma_dev->cpu_addr + *offset, count)) {
  33. return -EFAULT;
  34. }
  35. *offset += count;
  36. return count;
  37. }
  38. // 向设备写入数据
  39. static ssize_t simple_dma_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) {
  40. if (*offset >= BUFFER_SIZE) {
  41. return 0; // EOF
  42. }
  43. if (*offset + count > BUFFER_SIZE) {
  44. count = BUFFER_SIZE - *offset;
  45. }
  46. if (copy_from_user(dma_dev->cpu_addr + *offset, buf, count)) {
  47. return -EFAULT;
  48. }
  49. *offset += count;
  50. return count;
  51. }
  52. // 文件操作结构体
  53. static struct file_operations fops = {
  54. .owner = THIS_MODULE,
  55. .open = simple_dma_open,
  56. .release = simple_dma_release,
  57. .read = simple_dma_read,
  58. .write = simple_dma_write,
  59. };
  60. // 模块初始化函数
  61. static int __init simple_dma_init(void) {
  62. major_number = register_chrdev(0, DEVICE_NAME, &fops);
  63. if (major_number < 0) {
  64. printk(KERN_ALERT "Failed to register character device\n");
  65. return major_number;
  66. }
  67. dma_dev = kmalloc(sizeof(struct simple_dma_device), GFP_KERNEL);
  68. if (!dma_dev) {
  69. unregister_chrdev(major_number, DEVICE_NAME);
  70. printk(KERN_ALERT "Failed to allocate memory for device\n");
  71. return -ENOMEM;
  72. }
  73. // 分配一致性DMA内存
  74. dma_dev->cpu_addr = dma_alloc_coherent(NULL, BUFFER_SIZE, &dma_dev->dma_handle, GFP_KERNEL);
  75. if (!dma_dev->cpu_addr) {
  76. kfree(dma_dev);
  77. unregister_chrdev(major_number, DEVICE_NAME);
  78. printk(KERN_ALERT "Failed to allocate coherent DMA memory\n");
  79. return -ENOMEM;
  80. }
  81. memset(dma_dev->cpu_addr, 0, BUFFER_SIZE); // 初始化为零
  82. printk(KERN_INFO "Simple DMA driver initialized with major number %d\n", major_number);
  83. return 0;
  84. }
  85. // 模块退出函数
  86. static void __exit simple_dma_exit(void) {
  87. if (dma_dev && dma_dev->cpu_addr) {
  88. dma_free_coherent(NULL, BUFFER_SIZE, dma_dev->cpu_addr, dma_dev->dma_handle);
  89. kfree(dma_dev);
  90. }
  91. unregister_chrdev(major_number, DEVICE_NAME);
  92. }
  93. module_init(simple_dma_init);
  94. module_exit(simple_dma_exit);
  95. MODULE_LICENSE("GPL");
  96. MODULE_AUTHOR("Your Name");
  97. MODULE_DESCRIPTION("A Simple Character Device Driver using DMA Alloc Coherent");

编译与加载

  1. 将上述代码保存到文件 simple_dma_char.c 中。
  2. 创建一个 Makefile
  1. obj-m += simple_dma_char.o
  2. all:
  3. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  4. clean:
  5. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  1. 编译模块:
  1. make
  1. 加载模块:
  1. sudo insmod simple_dma_char.ko
  1. 查看日志以确认输出:
  1. dmesg | tail -n 20
  1. 创建设备节点:
  1. sudo mknod /dev/simple_dma_char c [major_number] 0 # 将 [major_number] 替换为实际的主设备号,如 'cat /proc/devices'
  1. 使用 echocat 命令进行读写测试:
  1. # 写入数据(例如:hello)
  2. echo "hello" > /dev/simple_dma_char
  3. # 从设备读取数据并打印出来
  4. cat /dev/simple_dma_char
  1. 卸载模块:
  1. sudo rmmod simple_dmа_char

注意事项

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


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

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?