S3C实现DMA驱动程序编写

发布者:DreamySunset最新更新时间:2024-08-05 来源: cnblogs关键字:S3C  DMA  驱动程序 手机看文章 扫描二维码
随时随地手机看文章

在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             }

 50             break;

 51         }

 52 

 53         case MEM_CPY_DMA :

[1] [2] [3]
关键字:S3C  DMA  驱动程序 引用地址:S3C实现DMA驱动程序编写

上一篇:S3C2440实现dm9000网卡驱动程序移植
下一篇:S3C2440 nand_flash驱动程序

推荐阅读最新更新时间:2024-11-05 13:15

nRF24L01 AVR 发送接收驱动程序
#include #include #include 12864.h 智芯锐电子技术社区:http://www.zhixinrui.com //------------------------------------------------------------------------------ //spi标志 #define DDR_SPI DDRB #define DD_MOSI 5 #define DD_MISO 6 #define DD_SCK 7 #define DD_SS 4 #define CE PB3 #define IRQ PB2 //----------
[单片机]
stm32F1 DMA
DMA,全称是Direct Memory Access,中文意思为直接存储器访问 DMA可用于实现外设与存储器之间或者存储器与存储器之间数据传输的高效性 DMA请求映像 各通道的DMA1请求: 各通道的DMA2请求: DMA配置步骤 1.使能DMA控制器时钟 2.初始化DMA通道,DMA_InitTypeDef 3.使能外设DMA功能 4.开启DMA的通道 5.查询DMA传输状态 举例 u8 txBuffer = {0}; u8 rxBuffer = {0}; void DMA_send(u32 num) { DMA_Cmd(DMA1_Channel4, DISABLE); DMA_SetCur
[单片机]
stm32F1 <font color='red'>DMA</font>
STM32使用DMA加串口空闲中断接收数据
STM32中,需要用串口接收数据,是使用串口中断来接收数据。但是用这种方法的话,就要频繁进入串口中断,然后处理,效率就比较低。于是就想到用DMA来接收串口数据,这个STM32也是支持的。但是关键的一点,怎么知道数据接收完毕了呢?如果接收的数据长度固定,那就好办,直接设置DMA的接收数据个数就行了。但是如果长度不固定了,那应该怎么办了? 这个时候,就要用到STM32在串口中提供的另一个好用的东西了,就是串口空闲中断。在STM32的串口控制器中,设置了有串口空闲中断,即如果串口空闲,又开启了串口空闲中断的话,就触发串口空闲中断,然后程序就会跳到串口中断去执行。有了这个,是不是可以判断什么时候串口数据接收完毕了呢?因为串口数据
[单片机]
STM32使用<font color='red'>DMA</font>加串口空闲中断接收数据
stm32的DMA空闲中断数据配置
对于串口2的示例: void USART2_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_AHBPeriphClockCmd(
[单片机]
STM32 | 串口空闲中断接收不定长数据(DMA方式)
在使用STM32的串口接收数据的时候,我们常常会使用接收中断的方式来接收数据,常用的是RXNE。这里分享另一种接收数据的方式——IDLE中断(PS:本文的例子运行在STM32F103ZET6上)。 一、IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。 二、RXNE中断和IDLE中断的区别? 当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。 三、IDLE中断如何配
[单片机]
STM32 | 串口空闲中断接收不定长数据(<font color='red'>DMA</font>方式)
基于Linux的MISC类设备AD7859L的驱动程序开发
1 引言 在嵌入式系统中基于ARM微核的嵌入式处理器已经成为市场主流。随着ARM技术的广泛应用,建立面向ARM构架的嵌入式操作系统成为测量行业的热点问题。在LINUX操作系统中添加新的外部设备时,只需为其添加对应的驱动程序即可。介绍另一种驱动程序的编写方式,即采用MISC类设备。其实质也是一个字符设备。可将用户各种不同的驱动设备类型合成到一种类型中,共用一个主设备号,通过不同的次设备号和设备节点名来区分。可方便管理这些驱动模块。字符型的驱动设备模块在挂载时都要分配主设备号、次设备号和创建设备节点名,在卸载驱动设备时还必须同时删掉设备节点名。通过采用MISC类设备,在挂载设备驱动时无须再用到mknod命令分配主设备号、次设备号和
[嵌入式]
stm32F4 串口DMA+环形缓冲区的实现
下面是串口DMA+环形缓冲区的实现,将读写接口抽象出来,实现不定长度的数据收发。 关于环形缓冲区参考: http://blog.csdn.net/jieffantfyan/article/details/53572103 /****************************************************************************** * Copyright (C) 2016, roger * All rights reserved. * * 文件名称: tty.h * 摘 要:控制台驱动 * * 当前版本: 3.0 * 作 者: roger *
[单片机]
OK6410按键驱动程序(改)亲测可以运行
#include linux/kernel.h #include linux/module.h #include linux/init.h #include linux/fs.h #include linux/gpio.h #include linux/types.h #include linux/cdev.h #include linux/interrupt.h #include linux/sched.h #include linux/device.h #include linux/poll.h #include linux/semaphore.h #include linux/
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved