DMA(二) - DMA接口函数

本文介绍了DMA接口函数的主要功能,包括一致性DMA映射和流式DMA映射的不同应用场景及实现方式。详细对比了dma_alloc_coherent与dma_alloc_writecombine两种内存分配函数的特点,并通过示例代码展示了如何使用这些函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DMA接口函数

arch/arm/mm/dma-mapping.c 主要的作用是将虚拟地址映射到物理地址。
一致性DMA映射,分配指定大小的内存,并将物理地址映射到虚拟地址
dma_alloc_coherent
dma_mmap_coherent
dma_free_coherent
dma_alloc_writecombine
dma_mmap_writecombine
dma_free_writecombine
dma_alloc_coherent和dma_alloc_writecombine的区别是dma_alloc_coherent(cache disable,buffer disable),dma_alloc_writecombine(cache disable,buffer enable)

流式DMA映射,使用这个函数前需要事先分配连续物理内存,这个函数只是物理地址映射到虚拟地址
dma_map_single
dma_unmap_single

DMA池


DMA cache一致性问题

DMA如果使用cache,那么一定要考虑cache的一致性。解决DMA导致的一致性的方法最简单的就是禁止DMA目标地址范围内的cache功能。但是这样就会牺牲性能。

从dma_alloc_coherent和dma_alloc_writecombie源码可以看出,
Dma_alloc_coherent pgprot_noncached 禁止了页表项中的C(Cacheable)域和B(Bufferable)域
此时由于关闭了cache/buffer,性能自然比较低
dma_alloc_writecombie pgprot_writecombine 只禁止了C (Cacheable) 域


DMA接口函数使用实例

完整代码位置:dma映射函数

#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/device.h>

// int direction = PCI_DMA_TODEVICE ;
// int direction = PCI_DMA_FROMDEVICE ;
static int direction = PCI_DMA_BIDIRECTIONAL;
//int direction = PCI_DMA_NONE;

static char *kbuf;
static dma_addr_t handle;
static size_t size = (10 * PAGE_SIZE);
static struct dma_pool *mypool;
static size_t pool_size = 1024;
static size_t pool_align = 8;

static void my_release(struct device *dev)
{
	pr_info("releasing DMA device\n");
}

static struct device dev = {
	.release = my_release
};

static void output(char *kbuf, dma_addr_t handle, size_t size, char *string)
{
	unsigned long diff;
	diff = (unsigned long)kbuf - handle;
	pr_info("kbuf=%12p, handle=%12p, size = %d\n", kbuf,
		(unsigned long *)handle, (int)size);
	pr_info("(kbuf-handle)= %12p, %12lu, PAGE_OFFSET=%12lu, compare=%lu\n",
		(void *)diff, diff, PAGE_OFFSET, diff - PAGE_OFFSET);
	strcpy(kbuf, string);
	pr_info("string written was, %s\n", kbuf);
}

static int __init my_init(void)
{
	dev_set_name(&dev, "my0");
	device_register(&dev);

	/* dma_alloc_coherent method */

	pr_info("Loading DMA allocation test module\n");
	pr_info("\nTesting dma_alloc_coherent()..........\n\n");
	kbuf = dma_alloc_coherent(NULL, size, &handle, GFP_KERNEL);
	output(kbuf, handle, size, "This is the dma_alloc_coherent() string");
	dma_free_coherent(NULL, size, kbuf, handle);

	/* dma_map/unmap_single */

	pr_info("\nTesting dma_map_single()................\n\n");
	kbuf = kmalloc(size, GFP_KERNEL);
	handle = dma_map_single(&dev, kbuf, size, direction);
	output(kbuf, handle, size, "This is the dma_map_single() string");
	dma_unmap_single(&dev, handle, size, direction);
	kfree(kbuf);

	/* dma_pool method */

	pr_info("\nTesting dma_pool_alloc()..........\n\n");
	mypool = dma_pool_create("mypool", NULL, pool_size, pool_align, 0);
	kbuf = dma_pool_alloc(mypool, GFP_KERNEL, &handle);
	output(kbuf, handle, size, "This is the dma_pool_alloc() string");
	dma_pool_free(mypool, kbuf, handle);
	dma_pool_destroy(mypool);

	device_unregister(&dev);

	return 0;
}

static void __exit my_exit(void)
{
	pr_info("Module Unloading\n");
}

module_init(my_init);
module_exit(my_exit);

MODULE_AUTHOR("Jerry Cooperstein");
MODULE_DESCRIPTION("LDD:2.0 s_23/lab1_dma.c");
MODULE_LICENSE("GPL v2");
### 回答1: gd32f405是一款具有DMA功能的微控制器,可以通过串口与外部设备进行数据通信。串口通信是一种常用的数据传输方式,它通过数据线来传输数据,并且具有较好的适应性和广泛的应用场景。 gd32f405支持使用DMA(直接内存访问)来处理串口数据传输。DMA是一种硬件模块,可以在不需要CPU干预的情况下,直接从内存读取数据并将其传输到外部设备,或将外部设备的数据传输到内存。这样可以减轻CPU的负担,提高数据传输效率。 使用DMA进行串口数据传输有以下几个步骤: 1. 配置DMA通道:首先需要配置DMA通道用于串口数据传输的接口。在gd32f405中,可以使用多个DMA通道进行不同功能的数据传输。 2. 配置串口:需要配置串口相关参数,包括波特率、数据位数、校验位等。gd32f405的串口模块具有多个发送和接收缓冲区,可以通过调用相应的函数对串口进行配置。 3. 配置DMA传输方向和长度:根据具体需求,需要设置DMA的传输方向,即是从内存到外设还是从外设到内存。同时需要设置数据传输的长度。 4. 启动DMA传输:配置完成后,通过调用相应的函数启动DMA传输。DMA将自动从内存读取数据并进行串口传输,或从串口接收数据并写入内存,无需CPU干预。 通过使用DMA进行串口数据传输,可大大提高数据传输效率,减少CPU的负担。gd32f405的DMA功能使得串口通信更加可靠和高效。 ### 回答2: gd32f405是一款单片机芯片,而串口和DMA是其提供的两种功能。 串口是一种用于数据传输的接口,通过串行通信的方式可以实现将数据从一个设备传输到另一个设备。gd32f405内置了多个串口通道,可以通过配置相关寄存器和使用相应的引脚来实现与其他设备的串口通信。 而DMA(Direct Memory Access)是一种直接内存访问的技术,可以在不经过CPU的情况下,直接将数据从外设读取到内存或从内存写入到外设。在gd32f405中,通过配置DMA通道的相关寄存器,可以实现串口数据的DMA传输。 具体实现串口-DMA的步骤如下: 1. 配置串口:包括波特率、数据位、停止位、校验位等参数。 2. 配置DMA通道:包括传输方向、数据宽度、传输大小等参数。 3. 配置内存地址和外设地址:分别指定DMA传输的起始地址和目标地址。 4. 使能串口的DMA模式和DMA通道。 5. 当需要进行数据传输时,触发DMA传输请求。 6.DMA传输完成后,通过相应的中断或标志位进行处理。 通过串口-DMA的方式,可以实现高效的数据传输,减轻CPU负担。此外,gd32f405还支持多个DMA通道,可以同时进行多路数据传输,提高系统的数据处理效率。 总结来说,gd32f405芯片提供了串口和DMA功能,可以通过配置相关寄存器和引脚,实现串口数据的高效传输,并且支持多通道的DMA操作,提高系统的性能和效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckywang1103

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值