S3C实现DMA驱动程序编写

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

 55 {

 56     int i;

 57 

 58     memset(src, 0xAA, BUF_SIZE);

 59     memset(dst, 0x55, BUF_SIZE);

 60     

 61     switch (cmd)

 62     {

 63         case MEM_CPY_NO_DMA :

 64         {

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

 66                 dst[i] = src[i];

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

 68             {

 69                 printk('MEM_CPY_NO_DMA OKn');

 70             }

 71             else

 72             {

 73                 printk('MEM_CPY_DMA ERRORn');

 74             }

 75             break;

 76         }

 77 

 78         case MEM_CPY_DMA :

 79         {

 80             ev_dma = 0;

 81             

 82             /* 把源,目的,长度告诉DMA */

 83             dma_regs->disrc      = src_phys;        /* 源的物理地址 */

 84             dma_regs->disrcc     = (0<<1) | (0<<0); /* 源位于AHB总线, 源地址递增 */

 85             dma_regs->didst      = dst_phys;        /* 目的的物理地址 */

 86             dma_regs->didstc     = (0<<2) | (0<<1) | (0<<0); /* 目的位于AHB总线, 目的地址递增 */

 87             dma_regs->dcon       = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(BUF_SIZE<<0);  /* 使能中断,单个传输,软件触发, */

 88 

 89             /* 启动DMA */

 90             dma_regs->dmasktrig  = (1<<1) | (1<<0);

 91 

 92             /* 如何知道DMA什么时候完成? */

 93             /* 休眠 */

 94             wait_event_interruptible(dma_waitq, ev_dma);

 95 

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

 97             {

 98                 printk('MEM_CPY_DMA OKn');

 99             }

100             else

101             {

102                 printk('MEM_CPY_DMA ERRORn');

103             }

104             

105             break;

106         }

107     }

108 

109     return 0;

110 }

111 

112 static struct file_operations dma_fops = {

113     .owner  = THIS_MODULE,

114     .ioctl  = s3c_dma_ioctl,

115 };

116 

117 static irqreturn_t s3c_dma_irq(int irq, void *devid)

118 {

119     /* 唤醒 */

120     ev_dma = 1;

121     wake_up_interruptible(&dma_waitq);   /* 唤醒休眠的进程 */

122     return IRQ_HANDLED;

123 }

124 

125 static int s3c_dma_init(void)

126 {

127     if (request_irq(IRQ_DMA3, s3c_dma_irq, 0, 's3c_dma', 1))

128     {

129         printk('can't request_irq for DMAn');

130         return -EBUSY;

131     }

132     

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

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

135     if (NULL == src)

136     {

137         printk('can't alloc buffer for srcn');

138         free_irq(IRQ_DMA3, 1);

139         return -ENOMEM;

140     }

141     

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

143     if (NULL == dst)

144     {

145         free_irq(IRQ_DMA3, 1);

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

147         printk('can't alloc buffer for dstn');

148         return -ENOMEM;

149     }

150 

151     major = register_chrdev(0, 's3c_dma', &dma_fops);

152 

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

154     cls = class_create(THIS_MODULE, 's3c_dma');

155     class_device_create(cls, NULL, MKDEV(major, 0), NULL, 'dma'); /* /dev/dma */

156 

157     dma_regs = ioremap(DMA3_BASE_ADDR, sizeof(struct s3c_dma_regs));

158         

159     return 0;

160 }

161 

162 static void s3c_dma_exit(void)

163 {

164     iounmap(dma_regs);

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

166     class_destroy(cls);

167     unregister_chrdev(major, 's3c_dma');

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

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

170     free_irq(IRQ_DMA3, 1);

171 }

172 

173 module_init(s3c_dma_init);

174 module_exit(s3c_dma_exit);

175 

176 MODULE_LICENSE('GPL');


附上测试程序3:


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 

 8 /* ./dma_test nodma

 9  * ./dma_test dma

10  */

11 #define MEM_CPY_NO_DMA  0

12 #define MEM_CPY_DMA     1

13 

14 void print_usage(char *name)

15 {

16     printf('Usage:n');

17     printf('%s n', name);

18 }

19 

20 

21 int main(int argc, char **argv)

22 {

23     int fd;

24     

25      if (argc != 2)

26     {

27         print_usage(argv[0]);

28         return -1;

29     }

30 

31     fd = open('/dev/dma', O_RDWR);

32     if (fd < 0)

33     {

34         printf('can't open /dev/dman');

35         return -1;

36     }

37 

38     if (strcmp(argv[1], 'nodma') == 0)

39     {

40         while (1)

41         {

42             ioctl(fd, MEM_CPY_NO_DMA);

43         }

44     }

45     else if (strcmp(argv[1], 'dma') == 0)

46     {

47         while (1)

48         {

49             ioctl(fd, MEM_CPY_DMA);

50         }

51     }

52     else

53     {

54         print_usage(argv[0]);

55         return -1;

56     }

57     return 0;     

58 }


五.总结DMA工作流程.


简单来说,我觉得DMA编程总共分为配置和运行两个步骤.


配置:


①注册中断


②分配供模拟拷贝数据的源.目的地址的内存空间.


③注册字符设备


④映射ioremapDMA的IO空间


运行:


①应用程序调用ioctl(fd,MEM_CPY_DMA),进入case语句


②在case语句中配置号DMA传输数据所需要的源,目的,大小,便启动DMA传输.


③启动DMA传输后,程序进入可中断的休眠,让出CPU


④一旦DMA传输完毕,便会触发中断,再中断中唤醒,然后打印MEM_CPY_DMA OK告诉应用程序DMA传输成功了.


 


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

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

推荐阅读最新更新时间:2024-11-13 17:22

接近开关的51单片机驱动程序
今天用做了个小东西:数码管显示接近开关变化值接近开关通过外部中断0连接单片机;数码管示数增加到50后清零; #include reg51.h // 引用标准库的头文件 #include intrins.h #define uchar unsigned char #define uint unsigned int #define NoOp 0x00 // 空操作寄存器 #define Digit0 0x01 // 数码管1寄存器 #define Digit1 0x02 // 数码管2寄存器 #define Digit2 0x03 // 数码管3寄存器
[单片机]
stm32舵机驱动程序分享
  STM32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM Cortex-M3内核。按内核架构分为不同产品:   其中STM32F系列有:   STM32F103“增强型”系列   STM32F101“基本型”系列   STM32F105、STM32F107“互联型”系列   增强型系列时钟频率达到72MHz,是同类产品中性能最高的产品;基本型时钟频率为36MHz,以16位产品的价格得到比16位产品大幅提升的性能,是32位产品用户的最佳选择。两个系列都内置32K到128K的闪存,不同的是SRAM的最大容量和外设接口的组合。时钟频率72MHz时,从闪存执行代码,STM32功耗36mA,相当于0.5mA/MHz。
[单片机]
STM32F3的ADC使用DMA模式传输转换数据
本文使用ADC转换电位器输出的电压值,并用DMA模式传输转换的结果,每8次采样转换取平均值,做一个简单的数字滤波。 ADC的详细配置与使用 见之前的日记 STM32中ADC的使用 ,只是最后增加一步配置DMA: DMA for ADC channels features configuration  To enable the DMA mode for ADC channels group, use the ADC_DMACmd() function.  To configure the DMA transfer request, use ADC_DMAConfig() function. DMA的配置 (摘自STM32F3
[单片机]
micro2440 按键驱动程序
my_buttons.c文件: #include linux/fs.h #include linux/poll.h #include linux/irq.h #include linux/interrupt.h #include mach/regs-gpio.h #include mach/hardware.h #include linux/miscdevice.h #define DEVICE_NAME mybuttons struct button_irq_desc { int irq; int pin; int pin_setting; int number; char *na
[单片机]
关于STM32F107VCT6串口DMA接收数字控制LED亮灭的功能实现
主函数中代码如下: #include stm32f10x.h void GPIO_Config(void); void USART_Config(void); void DMA_Config(void); void NVIC_Config(void); void LED1_ON(void); void LED2_ON(void); void LED3_ON(void); void LED4_ON(void); void LED_ALL_OFF(void); void delay(void); uint8_t DMA_BUFFER ; int main() { GPIO_Config(); USART_Co
[单片机]
关于STM32F107VCT6串口<font color='red'>DMA</font>接收数字控制LED亮灭的功能实现
关于STM32 ADC DMA 使用心得(2)
(二)ADC循环采集六路电压,使用DMA. 这次实验真的很郁闷,对DMA的不了解让我深陷误区,明白之后,让我更加佩服DMA的强大。 误区就是:从实验的目标我们知道这次是用DMA把ADC转换的数据传送到内存中的一个数组里存起来,因为是采集6个通道,这里使能了ADC的扫描模式。一旦启动ADC,就会按顺序转换SQRX里选中的通道,问题就是我一开始以为ADC与DMA并不会协调工做,也就是ADC自己转自己的,DMA自己传自己的,这样的话内存里的数组就不是我想要的了,后来着实的研究了很长时间,在群里的一位兄弟的提醒下,我才知道,可能我想的复杂了,也许就可以在ADC转一次,然后DMA把数据传一次,Ok,经过实验得知,这个想法是正确的。
[单片机]
S3C内部中断和外部中断
1.中断分两大类:内部中断和外部中断。 2.外部中断。24个外部中断占用GPF0-GPF7(EINT0-EINT7),GPG0-GPG15(EINT8-EINT23)。用这些脚做中断输入,则必须配置引脚为中断,并且不要上拉。具体参考datesheet数据手册。 寄存器:EXTINT0-EXTINT2:三个寄存器设定EINT0-EINT23的触发方式。 EINTFLT0-EINTFLT3:控制滤波时钟和滤波宽度。 EINTPEND:这个是中断挂起寄存器,清除时要写1,后面还有几个是写1清除。当一个外部中断(EINT4-EINT23)发生后,那么相应的位会被置1。为什么没有EINT0-EINT3,呵呵,看
[单片机]
12.2440串口驱动程序设计
串口的功能就是接受数据跟发送数据的,在上一节已经了解串口的引脚信号。但是数据的收发需要一定的条件,也就是串口的初始化。所以所以今天的内容就会被划分为三个部分: 1.串口的初始化: 创建一个uart.c来对串口进行处理,然后把它加入到Makefile工程文件里: 接着就是串口处理程序的实现了。 程序的刚开始是对串口进行初始化,初始化的步骤: 配置引脚功能 设置数据模式 设置工作模式 设置波特率。 1)配置引脚功能: 在2440里的串口底板原理图: 上面的11 TXD0和12 RXD0就是串口的发送和接受引脚,对应的编号里的3,2口,5口是接地的。接下来在核心板原理图里找对应的共用引脚。在核心板原理图里搜
[单片机]
12.2440串口<font color='red'>驱动程序</font>设计
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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