DMA基本概念及linux2440下DMA驱动程序编写与测试

Linux驱动开发--linux下的DMA编程 DMA编程 DMA是一种无需要CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率 DMA方式的数据传输由DMA控制器控制,在传输期间,CPU可以并发地执行其他任务,当DMA结束后,DMA控制器通过中断通知CPU数据传输已经结束,然后由CPU执行相应的中断服务程序进行后序处理.DMA可以用做内 阅读详情
 
分类: linux 6410驱动   1063人阅读  评论(5)  收藏  举报

转自:http://blog.techbulo.com/tech/artical/1462.html

1、基本概念

DMA即Direct Memory Access(直接存储器存取),那么为什么要引入这么个东东呢?它的作用又是什么呢?我们通过一个例子来说明:
比 如当我们要往内存里面拷贝一块很大的数据时,由于CPU同一时间只能做一件事情,这样在一段很长的时间里就不能再处理其它事情了,这样就造成了浪费。于是 引入了DMA的概念,所谓DMA就是直接存储器访问,可以不通过CPU而在DMA控制器的控制下,高速地与I/O设备和存储器交换数据。CPU除了在数据 传输开始和结束时做一些处理外,在传输过程中,CPU可以进行其它工作。这样,在大部分的时间里,CPU和输入/输出都处于并行操作状态,大大提高了效 率。
我们需要做的就是将源、目的、长度告诉DMA,然后设置DMA参数,并启动DMA就可以了。
2、DMA工作过程
那么DMA的具体工作过程是怎样的呢?我们也有必要来说一下:
(1)外设向DMA发出请求
(2)DMA通过HOLD向CPU发出总线请求
(3)CPU响应释放三总线,并且发应答HLDA
(4)DMA向外设发DMA应答
(5)DMA发出地址、控制信号,为外设传输数据
(6)传送完规定的数据后,DMA撤销HOLD信号,CPU也撤销HOLD信号,并且恢复对三总线的控制
3、s3c2440的DMA
s3c2440支持4个DMA通道,每个DMA通道支持多个请求源,详见下表:
DMA基本概念 - 小白 - 小白的博客
每个DMA通道能处理下面四种情况的数据传输:
(1)源器件和目的器件都在系统总线
(2)源器件在系统总线,目的器件在外设总线
(3)源器件在外设总线,目的器件在系统总线
(4)源器件和目的器件都在外设总线
1、驱动程序编写

在本驱动程序中,我们打算在内存中开辟两个空间,分别作为源和目的。我们用两个方法将源中的数据写到目的中,一种方法是让cpu去做,另外一种发放是让DMA去做!好的,闲话少说,直接分析代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>
#include <linux/dma-mapping.h>

#define MEM_CPY_NO_DMA  0
#define MEM_CPY_DMA     1

#define BUF_SIZE  (512*1024)

#define DMA0_BASE_ADDR  0x4B000000
#define DMA1_BASE_ADDR  0x4B000040
#define DMA2_BASE_ADDR  0x4B000080
#define DMA3_BASE_ADDR  0x4B0000C0

struct s3c_dma_regs {
unsigned long disrc;
unsigned long disrcc;
unsigned long didst;
unsigned long didstc;
unsigned long dcon;
unsigned long dstat;
unsigned long dcsrc;
unsigned long dcdst;
unsigned long dmasktrig;
};


static int major = 0;

static char *src;
static u32 src_phys;

static char *dst;
static u32 dst_phys;

static struct class *cls;

static volatile struct s3c_dma_regs *dma_regs;

static DECLARE_WAIT_QUEUE_HEAD(dma_waitq);
/* 中断事件标志, 中断服务程序将它置1,ioctl将它清0 */
static volatile int ev_dma = 0;

static int s3c_dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int i;

memset(src, 0xAA, BUF_SIZE);
memset(dst, 0x55, BUF_SIZE);
switch (cmd)
{
                 //这是非DMA模式
case MEM_CPY_NO_DMA :
{
for (i = 0; i < BUF_SIZE; i++)
dst[i] = src[i];   //CPU直接将源拷贝到目的
if (memcmp(src, dst, BUF_SIZE) == 0) //这个函数见注释2
{
printk("MEM_CPY_NO_DMA OK\n");
}
else
{
printk("MEM_CPY_DMA ERROR\n");
}
break;
}

                 //这是DMA模式
case MEM_CPY_DMA :
{
ev_dma = 0;
/* 把源,目的,长度告诉DMA */
                        /* 关于下面寄存器的具体情况,我们在注释3里面来详细讲一下 */
dma_regs->disrc      = src_phys;         /* 源的物理地址 */
dma_regs->disrcc     = (0<<1) | (0<<0);  /* 源位于AHB总线, 源地址递增 */
dma_regs->didst      = dst_phys;         /* 目的的物理地址 */
dma_regs->didstc     = (0<<2) | (0<<1) | (0<<0);  /* 目的位于AHB总线, 目的地址递增 */
dma_regs->dcon       = (1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(0<<20)|(BUF_SIZE<<0);   /* 使能中断,单个传输,软件触发, */

/* 启动DMA */
dma_regs->dmasktrig  = (1<<1) | (1<<0);

/* 如何知道DMA什么时候完成? */
/* 休眠 */
wait_event_interruptible (dma_waitq, ev_dma );

if (memcmp(src, dst, BUF_SIZE) == 0)
{
printk("MEM_CPY_DMA OK\n");
}
else
{
printk("MEM_CPY_DMA ERROR\n");
}
break;
}
}

return 0;
}

static struct file_operations dma_fops = {
.owner  = THIS_MODULE,
.ioctl  = s3c_dma_ioctl,
};

static irqreturn_t s3c_dma_irq(int irq, void *devid)
{
/* 唤醒 */
ev_dma = 1;
    wake_up_interruptible (&dma_waitq);    /* 唤醒休眠的进程 */
return IRQ_HANDLED;
}

static int s3c_dma_init(void)
{
          /* 这里注册一个中断,当DMA数据传输完毕之后会发生此中断 */
if ( request_irq (IRQ_DMA3, s3c_dma_irq, 0, "s3c_dma", 1))
{
printk("can't request_irq for DMA\n");
return -EBUSY;
}
/* 分配SRC, DST对应的缓冲区,关于此函数详见注释1 */
src = dma_alloc_writecombine (NULL, BUF_SIZE, &src_phys, GFP_KERNEL); //源
if (NULL == src)
{
printk("can't alloc buffer for src\n");
free_irq(IRQ_DMA3, 1);
return -ENOMEM;
}
dst = dma_alloc_writecombine (NULL, BUF_SIZE, &dst_phys, GFP_KERNEL); //目的
if (NULL == dst)
{
free_irq(IRQ_DMA3, 1);
dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
printk("can't alloc buffer for dst\n");
return -ENOMEM;
}

major = register_chrdev(0, "s3c_dma", &dma_fops); //注册字符设备

/* 为了自动创建设备节点 */
cls = class_create(THIS_MODULE, "s3c_dma");
class_device_create(cls, NULL, MKDEV(major, 0), NULL, "dma"); /* /dev/dma */

dma_regs = ioremap(DMA3_BASE_ADDR, sizeof(struct s3c_dma_regs)); //这边是将DMA控制寄存器映射到内核空间
return 0;
}

static void s3c_dma_exit(void)
{
iounmap(dma_regs);
class_device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, "s3c_dma");
dma_free_writecombine(NULL, BUF_SIZE, src, src_phys);
dma_free_writecombine(NULL, BUF_SIZE, dst, dst_phys);
free_irq(IRQ_DMA3, 1);
}

module_init(s3c_dma_init);
module_exit(s3c_dma_exit);

MODULE_LICENSE("GPL");

注释1:
之前我们知道在内核中开辟空间可以用kmalloc函数,这里却用了dma_alloc_writecombine,这是为什么呢?这是因为kmalloc开辟的空间其逻辑地址虽然是连续的,但是其实际的物理地址可能不是连续的。而DMA传输数据时,要求物理地址是连续的,dma_alloc_writecombine就满足这一点,这个函数的原型是:
dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
其中size代表开辟的空间的大小,handle代表开辟的空间的物理地址,返回值是开辟的空间的逻辑地址。

注释2:
int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
return res;
}
我们看到这个函数的作用就是将第一个参数和第二个参数一位一位地比较,一旦不相等就返回,此时返回值为非零。比较的位数为第三个参数,如果前两个参数的前count为都是相等的,那么就会返回0
注释3:
我们先来解析一下上面几个寄存器:

 DISRCn bit Description Initial State
 S_ADDR [30:0] 源起始地址 0x00000000
 DISRCCn bit DescriptionInitial State
 LOC [1] 用于选择源的位置
0:源在系统总线上
1:源在外设总线上
 0
 INC [0] 用于选择地址是否自动增加
0:地址自动增加
1:地址固定不变(此时即便是burst 模式下,传输过程中地址自动增加,  但是一旦传输完这一次数据,地址又变为初值)
 0
 DIDSTn bit Description Initial State
 D_ADDR [30:0] 目的起始地址 0x00000000
 DIDSTCn Bit Description Initial State
 CHK_INT [2] 当设置为自动加载时,用来选择中断发生的时间
0:TC为0是产生中断
1:自动加载完成的时候产生中断
 0
 LOC [1] 用于选择目的设备的位置
0:目的设备在系统总线上
1:目的设备在外设总线上
 0
 INC [0] 用于选择地址是否自动增加
0:地址自动增加
1:地址固定不变(此时即便是burst模式下,传输过程中地址自动增加,但是一旦传输完这一次数据,地址又重新变为初值)
 0
 DCONn Bit Description Initial State
 DMD_HS [31] 选择为Demand模式或者是握手模式
0:选择为Demand模式
1:选择为握手模式
这 两种模式下都是当发生请求时,DMA控制器开始传输数据并且发出  应  答信号,不同点是握手模式下,当DMA控制器收到请求撤销信号,并且自  身发出应答撤销信号之后才能接收下一次请求。而在Demand模式下,并  不需要等待请求撤销信号,他只需要撤销自身的应答信号,然后等待下一  次的请求。
 0
 SYNC [30] 选择DREQ/DACK的同步
0:DREQ and DACK 与PCLK同步
1:DREQ and DACK 与HCLK同步
因此当设备在AHB系统总线时,这一位必须为1,而当设备在APB系统  时,它应该被设为0。当设备位于外部系统时,应根据具体情况而定。
 0
 INT [29] 是否使能中断
0:禁止中断,用户需要查看状态寄存器来判断传输是否完成
1:使能中断,所有的传输完成之后产生中断信号
 0
 TSZ [28] 选择一个原子传输的大小
0:单元传输(一次传输一个单元)
1:突发传输(一次传输四个单元)
 0
 SERVMODE [27] 选择是单服务模式还是整体服务模式
0:单服务模式,当一次原子传输完成后需要等待下一个DMA请求
1:整体服务模式,进行多次原子传输,知道传输计数值到达0
 0
 HWSRCSEL [26:24] 为每一个DMA选择DMA请求源
具体参见芯片手册
 000
 SWHW_SEL [23] 选择DMA源为软件请求模式还是硬件请求模式
0:软件请求模式,需要将寄存器DMASKTRIG的SW_TRIG置位
1:硬件请求模式
 0
 RELOAD [22] 是否自动重新装载
0:自动重装,当目前的传输计数值变为0时,自动重装
1:不自动重装
RELOAD[1]被设置为0以防无意识地进行新的DMA传输
 0
 DSZ [21:20] 要被传输的数据的大小
00 = Byte    01 = Half word
10 = Word   11 = reserved
 00
 TC [19:0] 初始化传输计数0000
这里我们需要注意了,里面有三个东东要分清楚:
DSZ   :代表数据的大小
TSZ   :一次传输多少个数据
TC     :一共传输多少次
所以实际传输的数据的大小为:DSZ * TSZ * TC   
我们本程序里面由于设置为数据大小为1个字节,一次传输1个数据,所以传输次数直接就是实际数据的大小了。
 DSTATn Bit Description Initial State
 STAT [21:20] DMA控制器的状态
00:DMA控制器已经准备好接收下一个DMA请求
01:DMA控制器正在处理DMA请求
 00
 CURR_TC [19:0] 传输计数的当前值
每个原子传输减1
 
 DCSRCn Bit Description Initial State
 CURR_SRC [30:0] 当前的源地址 0x00000000
 DCDSTn Bit Description Initial State
 CURR_DST [30:0] 当前的目的地址 0x00000000
 DMASKTRIGn Bit Description Initial State
 STOP [2] 停止DMA操作
1:当前的原子传输完成之后,就停止DMA操作。如果当前没有原子  传输正在进行,就立即结束。
 
 ON_OFF [1] DMA通道的开/闭
0:DMA通道关闭
1:DMA通道打开,并且处理DMA请求
 
 SW_TRIG [0] 1:在软件请求模式时触发DMA通道 
OK!寄存器分析完毕,具体设置就不在写出来了!
在此我们在来总结一下DMA的操作流程:
我们首先设置DMA的工作方式,然后打开DMA通道,紧接着我们使进程休眠,进入等待队列。与此同时,在DMA控制器的作用下,从源向目的拷贝数据。一旦数据拷贝完成,就会触发中断,在中断函数里面,唤醒进程,从而程序继续运行,打印相关信息。
2、应用程序编写(测试用)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>

/* ./dma_test nodma
 * ./dma_test dma
 */
#define MEM_CPY_NO_DMA  0
#define MEM_CPY_DMA     1

void print_usage(char *name)
{
printf("Usage:\n");
printf("%s <nodma | dma>\n", name);
}


int main(int argc, char **argv)
{
int fd;
  if (argc != 2)
{
print_usage(argv[0]);
return -1;
}

fd = open("/dev/dma", O_RDWR);
if (fd < 0)
{
printf("can't open /dev/dma\n");
return -1;
}

if (strcmp(argv[1], "nodma") == 0)
{
while (1)
{
ioctl(fd, MEM_CPY_NO_DMA);
}
}
else if (strcmp(argv[1], "dma") == 0)
{
while (1)
{
ioctl(fd, MEM_CPY_DMA);
}
}
else
{
print_usage(argv[0]);
return -1;
}
return 0;
}

应用程序过于简单,不在分析!
3、测试
# insmod dma.ko       //加载驱动
# cat /proc/interrupts  //查看中断
           CPU0
 30:      52318         s3c  S3C2410 Timer Tick
 33:          0         s3c  s3c-mci
 34:          0         s3c  I2SSDI
 35:          0         s3c  I2SSDO
 36:          0         s3c  s3c_dma
 37:         12         s3c  s3c-mci
 42:          0         s3c  ohci_hcd:usb1
 43:          0         s3c  s3c2440-i2c
 51:       2725     s3c-ext  eth0
 60:          0     s3c-ext  s3c-mci
 70:         97   s3c-uart0  s3c2440-uart
 71:        100   s3c-uart0  s3c2440-uart
 83:          0           -  s3c2410-wdt
Err:          0

# ls /dev/dma      //查看设备
/dev/dma

# ./dmatest        //如此就会打印用法
Usage:
./dmatest <nodma | dma>

# ./dmatest dma      //以DMA方式拷贝,CPU可以做其他事情
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK

# ./dmatest nodma      //CPU拷贝,各种竞争CPU
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK
MEM_CPY_DMA OK



系统性能优化——Linux系统上运用DMA实现memcpy DMA(Direct Memory Access)是一种高效的数据传输方式,允许某些硬件子系统在不需要CPU介入的情况下直接访问系统内存。高效性:通过DMA,数据可以直接在内存和I/O设备之间传输,而不需要经过CPU。这样可以减少CPU的负担,使其可以处理其他任务。自主性:一旦CPU初始化了传输操作,DMA控制器就会接管总线控制权,自行完成数据传输任务。这意味着在传输过程中,CPU可以并行执行其他操作。高速性:DMA通常用于高速数据传输,特别是在大量数据的移动时,能够显著提高系统的吞吐量。硬件控制。 阅读详情

相关推荐

DMA驱动框架流程编写

本文主要是针对Xilinx DMA驱动流程框架编写 DMA驱动一致性和流式的基本认识 一致性DMA与流式DMA主要是内存的申请方式和访问控制权限不一样 一致性DMA内存申请: void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); 流式DMA内存申请: d

softwoker的专栏 1万+

linux之DMA使用

前言 对于长期从事嵌入式的开发人员来说,DMA是一个在实际中优化设备而老生常谈的问题,我们可以将它比喻为一个小机器人,长期重复与某一个动作的傻瓜式机器人,当我们设置好了出发添加,这个小机器人就会自动去执行相关的业务而不需要CPU的参与,从而大大的减轻了cpu的负载压力。 一、对于使用DMA控制器有什么内存上限制? dma的内存要求内存上是连续的一片虚拟内存空间, 1、我们不要使用vmalloc以及kmalloc这些通过get_free_page()函数来触发系统异常来分配在内存上可能是不连续的内存地址,而使

madannasf的博客 6446

S3C2440 UART串口驱动开发与优化指南

UART串口通信是嵌入式系统中最基础的外设接口技术,通过异步串行协议实现设备间数据交换。其工作原理基于波特率同步和帧格式约定,具有硬件简单、可靠性高的特点。在ARM架构处理器如S3C2440中,UART控制器通常支持中断和DMA两种工作模式,能显著提升系统实时性和吞吐量。开发UART驱动需要深入理解线路控制、FIFO缓冲等硬件特性,通过正确配置UBRDIV等关键寄存器实现稳定通信。本文以S3C2440为例,详解从GPIO初始化到DMA模式优化的全流程实现,特别适合工业控制、智能硬件等需要可靠串口通信的场景。

weixin_42520909的博客 340

DMA基本概念及linux 2440下DMA驱动程序 编写与测试

本文是基于操作系统linux下的利用DMA的方式将

默默的努力 789

从MySQL到数据仓库:手把手教你用Airflow实现自动化ETL流水线

本文详细介绍了如何利用Airflow构建从MySQL到数据仓库的自动化ETL流水线,涵盖增量抽取策略、PySpark转换优化和数据质量监控等实战细节。特别适合中小规模企业构建高效数据仓库,提升数据处理效率和质量。

rnn9storyteller的博客 827

【LaTeX PPT模板集】Beamer主题与配色使用教程

【LaTeX PPT模板集】Beamer主题与配色使用教程

Xminyang的博客 1万+

linux usb dma,DMA基本概念及linux2440下DMA驱动程序编写与测试

37: 12 s3c s3c-mci42: 0 s3c ohci_hcd:usb143: 0 s3c s3c2440-i2c51: 2725 s3c-ext eth060: 0 s3c-ext s3c-mci70: 97 s...

weixin_42299679的博客 667

无耳科技 Solon v3.0.8 发布,Java 企业级应用开发框架

Solon 是新一代,Java 企业级应用开发框架。是杭州无耳科技有限公司的“根级”开源项目(最近“杭州六小龙”很火啊,我们也是杭州的哦)。从零开始构建(No Spring、No Java-EE、No Servlet),有灵活的接口规范与开放生态。采用对商用友好的 Apache 2.0 开源协议。

向往自由的少年!(我是一个少年!!!) 1696

DMA驱动程序编写

一.  DMA的引入

迷之月光的专栏 7116

C语言使用开源库libusb进行USB设备操作

https://libusb.info/libusb is a C library that provides generic access to USB devices. It is intended to be used by developers to facilitate the production of applications that communicate with USB hardware. It is portable: Using a single cross-platform AP

m0_60352504的博客 1554

使用IGV软件可视化染色质可及性

染色质可及性(chromatin accessibility)是指DNA序列在植物细胞核中的可访问程度。染色质是由DNA和蛋白质组成的复杂结构,它紧密地包裹在细胞核中,并影响基因的表达和功能。染色质可及性研究着重于理解染色质是否容易被转录因子和其他调控蛋白访问,从而影响基因的表达。文献中,常常会有下面这种图片来表示基因组上的一些区域或基因的染色质开放性强弱。一般情况下,我们可以使用IGV软件或GSA-man软件进行可视化,两者的操作相似。这里,以IGV软件为例,演示如何对染色质可及性进行可视化。

沉香best的博客 3724

DMA 驱动程序

DMA(Direct Memory Access) 即直接存储器访问, DMA 传输方式无需 CPU 直接控制传输,通过硬件为 RAM 、I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。 学了这么多驱动,不难推出DMA的编写套路: 1)注册DMA中断,分配缓冲区 2)注册字符设备,并提供文件操作集合fops -> 2.1)file_operation...

li5830的博客 2176

基于非接触式微波雷达设计的跌倒检测预警系统【短信报警】

本项目选择基于非接触式微波雷达的跌倒检测预警装置作为技术核心,采用云帆瑞达的R60AFD1跌倒检测模组。这一模组能够根据人体的运动变化,如速度、距离和姿态等特征,判断是否发生跌倒,并可以持续监控老年人是否处于危险状态。此外,本项目还结合4G通信技术,通过Air724UG模块实现短信报警功能,一旦检测到跌倒事故,系统将自动通过4G网络向紧急联系人发送短信报警,及时通知亲属或医护人员进行救援。

1755

jz2440_LCD驱动程序(非标准)

cfb_fillrect、cfb_copyarea、cfb_imageblit已经由内核实现好了,它们会根据fb_info中设置的fb_fix_screeninfo和fb_var_screeninfo两个结构体中的信息,帮助我们往LCD屏幕上绘制图像。上面我们就大致完成了fb_info的设置,下面是对S3C2440LCD控制器的设置,同时还有要配置一些GPIO引脚工作为LCD使用的引脚模式。然后还需要设置LCD的显存,是的LCDCDMA可以访问到我们的显存地址。......

Bin_Watson的博客 547

【Bug已解决】Codex Desktop 更新后无法启动/闪退解决方案

方案适用场景推荐指数清理本地缓存重启最常见、最应优先尝试的方案⭐⭐⭐⭐⭐完全卸载重装缓存清理无效时的进阶方案⭐⭐⭐⭐详细日志定位崩溃环节需要精确诊断问题原因⭐⭐⭐⭐锁定旧稳定版本确认是特定版本缺陷时的过渡方案⭐⭐⭐反馈官方支持团队自助方式无效时的最终途径⭐⭐⭐⭐Codex Desktop 更新后无法启动/闪退的本质通常是新版本程序在启动时读取到了旧版本遗留的、格式不兼容的本地缓存或配置数据,导致启动流程中途崩溃。

一键难忘的博客 6288

Python电商网站全站爬虫实战:以京东为例的数据采集与分析

随着电子商务的蓬勃发展,电商数据已成为市场研究、竞争分析和消费者行为研究的重要资源。本文详细介绍了如何使用Python最新技术栈构建一个高效的电商网站全站爬虫,以京东为例实现商品数据的自动化采集。文章涵盖了爬虫的法律与伦理考量、技术选型、反爬虫策略应对、分布式架构设计以及数据存储方案,并提供了完整的代码实现。本爬虫系统采用Scrapy-Redis分布式框架、Selenium动态渲染、智能代理轮换和机器学习验证码识别等先进技术,能够稳定高效地抓取京东全站商品数据,为电子商务研究提供数据支持。关键词。

2201_76125261的博客 414

mini2440 简单的dma工作原理实验

以驱动方式测试dma的工作原理,用户层程序不停调用ioctl触发驱动里面完成的dma操作,把内存

皓首不倦 不负少年 788

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

linux下基于S3C2440的PWM蜂鸣器移植以及驱动程序分析

========================================================================== 主机操作系统:Centos 6.7  交叉编译器环境:arm-linux-gcc-4.5.4 (可通过命令/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc -v查询) 开发板平台: f

qicheng777的博客 1617

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

嵌入式Linux驱动学习【13】—— DMA

1 DMA 1.1 概述   DMA(Direct Memory Access),不需要CPU控制,直接进行数据传输。S3C2440有4个DMA通道,源地址和目的地址可以是系统总线或外设总线,因此传输可以有4种情况:     系统总线/外设总线 <===> 系统总线/外设总线   请求源:   工作模式:   1)查询模式:当DMA请求XnXDREQ为低电平时,则DMA会一直传输数据,直到DMA请求拉高,才停止。   2)握手模式:如果 XnXDREQ 为高电平,DMA XnXDAC

chen06130的博客 432

linux设备树-LCD驱动程序

----------------------------------------------------------------------------------------------------------------------------内核版本:linux 5.2.8根文件系统:busybox 1.25.0u-boot:2016.05-------------------------...

Graceful_scenery的博客 238

DM9000C网卡驱动程序编写与测试

一般网卡驱动程序厂商会给我们提供一份模板驱动,我们的工作就是需要根据自己的需要更改这个模板驱动 1、DM9000C的硬件连接 硬件连接图如下所示:它接在S3C2440的BANK4内存控制器上,它只占用8个字节的长度,并且是16bit的位宽。 下面介绍一下DM9000C的主要引脚的功能:SD0-SD15位16bit的数据引脚接口;IOR为读使能信号,低电平有效;IOW为写使能...

weixin_30888413的博客 1554

个人总结日记:ltv350三星LCD并行接口接2440处理器的linux驱动程序移植

ltv350三星LCD并行接口接2440处理器的linux驱动程序移植 总体上分三步: 1> framebuffer_alloc函数分配一个fb_info类型的结构体 该结构体用于填充描述使用的液晶参数,比如像 像素类型,是否有硬件加速, 长宽,每个像素的位数,调色板等。 其中主要填充fix与var这两个成员结构体变量,这两个结构体在应用程序中 可以通过ioctl函数的命令字

伍宝哥的专栏 1049
上一篇: ADS + JLink + FL2440调试
下一篇: Linux内核多线程实现方法 —— kthread_create函数
shareCode
博客等级 码龄15年 125粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值