S3C实现DMA驱动程序编写

发布时间:2024-08-05  

在IMX257上只有SDMA,SDMA比DMA的功能更加强大,但是为了学习的目的,如果直接学习SDMA,可能会不能消化,


所以,此处,我们从简单到复杂,从S3C2440的DMA驱动程序开始学习,等学懂它之后,我们再进军IMX257的SDMA.


一.一个简单的程序框架


1.定义一些指针


 1 static int major = 0;

 2 

 3 #define MEM_CPY_NO_DMA  0

 4 #define MEM_CPY_DMA     1

 5 

 6 static char *src;

 7 static u32 src_phys;

 8 

 9 static char *dst;

10 static u32 dst_phys;

11 

12 static struct class *cls;

13 

14 #define BUF_SIZE  (512*1024)


上面代码中主要定义了主设备号,目的地址,源地址等.


2.定义字符设备的file_operation结构体


 1 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

 2 {

 3     switch (cmd)

 4     {

 5         case MEM_CPY_NO_DMA :

 6         {

 7             break;

 8         }

 9         case MEM_CPY_DMA :

10         {

11             break;

12         }

13     }

14     return 0;

15 }

16 

17 static struct file_operations dma_fops = {

18     .owner  = THIS_MODULE,

19     .ioctl  = s3c_dma_ioctl,

20 };


在case中,分别定义CPU拷贝数据和DMA拷贝数据两种情况.


3.入口函数


 1 static int s3c_dma_init(void)

 2 {

 3     /* 分配SRC, DST对应的缓冲区 */

 4     src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);

 5     if (NULL == src)

 6     {

 7         printk("can't alloc buffer for srcn");

 8         return -ENOMEM;

 9     }

10     

11     dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);

12     if (NULL == dst)

13     {

14         dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);

15         printk("can't alloc buffer for dstn");

16         return -ENOMEM;

17     }

18 

19     major = register_chrdev(0, "s3c_dma", &dma_fops);

20 

21     /* 为了自动创建设备节点 */

22     cls = class_create(THIS_MODULE, "s3c_dma");

23     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma"); /* /dev/dma */

24         

25     return 0;

26 }


上面代码中:首先分配了源.目的地址的内存缓冲区,接着就是申请字符设备,自动创建字符设备节点.


4.出口函数


1 static void s3c_dma_exit(void)

2 {

3     class_device_destroy(cls, MKDEV(major, 0));

4     class_destroy(cls);

5     unregister_chrdev(major, "s3c_dma");

6     dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);

7     dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);    

8 } 


销毁字符设备的类,卸载字符设备,接着就是释放前面申请的源.目的地址的内存.


附上驱动代码1:


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 #include

10 #include

11 #include

12 #include

13 

14 static int major = 0;

15 

16 #define MEM_CPY_NO_DMA  0

17 #define MEM_CPY_DMA     1

18 

19 static char *src;

20 static u32 src_phys;

21 

22 static char *dst;

23 static u32 dst_phys;

24 

25 static struct class *cls;

26 

27 #define BUF_SIZE  (512*1024)

28 

29 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

30 {

31     switch (cmd)

32     {

33         case MEM_CPY_NO_DMA :

34         {

35             break;

36         }

37 

38         case MEM_CPY_DMA :

39         {

40             break;

41         }

42     }

43 

44     return 0;

45 }

46 

47 static struct file_operations dma_fops = {

48     .owner  = THIS_MODULE,

49     .ioctl  = s3c_dma_ioctl,

50 };

51 

52 static int s3c_dma_init(void)

53 {

54     /* 分配SRC, DST对应的缓冲区 */

55     src = dma_alloc_writecombine(NULL, BUF_SIZE, &src_phys, GFP_KERNEL);

56     if (NULL == src)

57     {

58         printk("can't alloc buffer for srcn");

59         return -ENOMEM;

60     }

61     

62     dst = dma_alloc_writecombine(NULL, BUF_SIZE, &dst_phys, GFP_KERNEL);

63     if (NULL == dst)

64     {

65         dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);

66         printk("can't alloc buffer for dstn");

67         return -ENOMEM;

68     }

69 

70     major = register_chrdev(0, "s3c_dma", &dma_fops);

71 

72     /* 为了自动创建设备节点 */

73     cls = class_create(THIS_MODULE, "s3c_dma");

74     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma"); /* /dev/dma */

75         

76     return 0;

77 }

78 

79 static void s3c_dma_exit(void)

80 {

81     class_device_destroy(cls, MKDEV(major, 0));

82     class_destroy(cls);

83     unregister_chrdev(major, "s3c_dma");

84     dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);

85     dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);    

86 }

87 

88 module_init(s3c_dma_init);

89 module_exit(s3c_dma_exit);

90 

91 MODULE_LICENSE("GPL");


二.增加不使用DMA的内存拷贝功能.


 1 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

 2 {

 3     int i;

 4     memset(src, 0xAA, BUF_SIZE);

 5     memset(dst, 0x55, BUF_SIZE);

 6     

 7     switch (cmd)

 8     {

 9         case MEM_CPY_NO_DMA :

10         {

11             for (i = 0; i < BUF_SIZE; i++)

12                 dst[i] = src[i];

13             if (memcmp(src, dst, BUF_SIZE) == 0)

14             {

15                 printk("MEM_CPY_NO_DMA OKn");

16             }

17             else

18             {

19                 printk("MEM_CPY_DMA ERRORn");

20             }

21             break;

22         }

23         case MEM_CPY_DMA :

24         {

25             break;

26         }

27     }

28 

29     return 0;

30 }


如程序所示,再ioctl函数中不适用DMA的增加内存拷贝功能.


附上驱动程序2


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 

 14 static int major = 0;

 15 

 16 #define MEM_CPY_NO_DMA  0

 17 #define MEM_CPY_DMA     1

 18 

 19 static char *src;

 20 static u32 src_phys;

 21 

 22 static char *dst;

 23 static u32 dst_phys;

 24 

 25 static struct class *cls;

 26 

 27 #define BUF_SIZE  (512*1024)

 28 

 29 static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

 30 {

 31     int i;

 32 

 33     memset(src, 0xAA, BUF_SIZE);

 34     memset(dst, 0x55, BUF_SIZE);

 35     

 36     switch (cmd)

 37     {

 38         case MEM_CPY_NO_DMA :

 39         {

 40             for (i = 0; i < BUF_SIZE; i++)

 41                 dst[i] = src[i];

 42             if (memcmp(src, dst, BUF_SIZE) == 0)

 43             {

 44                 printk("MEM_CPY_NO_DMA OKn");

 45             }

 46             else

 47             {

 48                 printk("MEM_CPY_DMA ERRORn");

 49             }

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>