linux内存学习笔记(三)——静态映射与DMA
来源:互联网 发布:淘宝服装质检标准 编辑:程序博客网 时间:2024/06/10 15:55
一、静态映射概述
在将linux移植到目标电路板时,通常会建立外设I/O内存到虚拟地址的静态映射。
能过在map_desc结构体添加新成员即可完成静态映射任务。
struct map_desc{
unsigned long virtual;
unsigned long pfn;
unsigned long length;
unsigned long type;
};
二、LPC3250相关
static struct map_desc lpc32xx_io_desc[] __initdata = {
{
.virtual = io_p2v(AHB0_START),
.pfn = __phys_to_pfn(AHB0_START),
.length = AHB0_SIZE,
.type = MT_DEVICE
},
{
.virtual = io_p2v(AHB1_START),
.pfn = __phys_to_pfn(AHB1_START),
.length = AHB1_SIZE,
.type = MT_DEVICE
},
{
.virtual = io_p2v(FABAPB_START),
.pfn = __phys_to_pfn(FABAPB_START),
.length = FABAPB_SIZE,
.type = MT_DEVICE
},
{
.virtual = io_p2v(IRAM_BASE),
.pfn = __phys_to_pfn(IRAM_BASE),
.length = (SZ_64K * 4),
.type = MT_DEVICE
},
};
void __init lpc32xx_map_io(void)
{
iotable_init (lpc32xx_io_desc, ARRAY_SIZE (lpc32xx_io_desc));
}
lpc32xx_io_desc[]数组指明要静态初始化的成员及其范围,实际的页面映射则是由lpc32xx_map_io()调用iotable_init()来完成的。lpc3250开发板静态映射分两步完成的
即有两个数组要进行静态映射,除了刚介绍的,还有就是smartarm3250_io_desc[]。当然映射的原理都是一样的。最后smartarm3250_map_io()函数由MACHIN_START,MACHINE_END宏赋值给map_io()函数。
static void __init smartarm3250_map_io(void)
{
lpc32xx_map_io();
iotable_init(smartarm3250_io_desc, ARRAY_SIZE(smartarm3250_io_desc));
}
static struct map_desc smartarm3250_io_desc[] __initdata = {
{ /* nCS2, CAN SJA1000 */
.virtual = io_p2v(EMC_CS2_BASE),
.pfn = __phys_to_pfn(EMC_CS2_BASE),
.length = SZ_1M,
.type = MT_DEVICE
},
{ /* nCS1, CF Card */
.virtual = io_p2v(EMC_CS1_BASE),
.pfn = __phys_to_pfn(EMC_CS1_BASE),
.length = SZ_1M,
.type = MT_DEVICE
}
};
MACHINE_START (LPC3XXX, "SmartARM3250 board with the LPC3250 Microcontroller")
/* Maintainer: Kevin Wells, NXP Semiconductors */
.phys_io = UART5_BASE,
.io_pg_offst = ((io_p2v (UART5_BASE))>>18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = smartarm3250_map_io,
.init_irq = lpc32xx_init_irq,
.timer = &lpc32xx_timer,
.init_machine = smartarm3250_board_init,
MACHINE_END
三、DMA
n 当DMA的目的地址与Cache所缓存的内存地址访问有重叠时,会发生Cache与内存之间数据“不一致”问题。
n 获得具备DMA能力的内存
__get_dma_pages(gfp_mask,order)
它的定义
#define __get_dma_pages(gfp_mask,order) __get_free_pages((gfp_mask) | GFP_DMA,(order))
n 虚拟地址:linux内核看到的地址
物理地址:CPU看到的地址
总线地址:设备看到的地址
n int dma_set_mask(struct device *dev, u64 mask);
如果,对于只能在24位地址上执行DMA操作的设备而言,就应该调用
dma_set_mask(dev,0xffffff)
n 一致性DMA缓冲区
一致性DMA缓冲区,首先内存要具有DMA能力,然后内存区域和Cache不会产生数据“不一致”问题。
void *dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t gfp)
dma_addr_t,代表总线地址
该函数返回申请到的DMA缓冲区的虚拟地址。
释放函数
void dma_free_coherent(struct device *dev,size_t size,void *cpu_addr,dma_addr_t handle);
n 流式DMA缓冲区
流式DMA缓冲区即缓冲区不是由驱动申请的,而是由内核上层使用kmalloc(),__get_free_pages()等方法实现。
流式DMA映射操作在本质上多数就是进行Cache的invalidate或flush操作,以解决Cache一致性问题。
dma_addr_t dma_map_single(struct device *dev,void *buffer,size_t size,
enum dma_data_direction direction);
dma_data_direction为DMA的方向
DMA_TO_DEVICE,DMA_FROM_DEVICE,
DMA_BIDIRECTIONAL,DMA_NONE
反函数
void dma_unmap_single(struct device *dev,dma_addr_t dma_addr,
size_t size,enum dma_data_direction direction);
如果支持SG(分散聚集)模式。
int dma_map_sg(struct device *dev,struct scatterlist *sg,int nents,
enum dma_data_direction direction);
nents,散列表(scatterlist)的入口数量
返回DMA缓冲区的数量。
dma_addr_t sg_dma_address(struct scatterlist *sg);
返回scatterlist对应缓冲区的总线地址
unsigned int sg_dma_len(struct scatterlist *sg)
返回scatterlist对应缓冲区的长度。
去映射
void dma_unmap_sg(struct device *dev,struct scatterlist *list,
int nents,enum dma_data_direction direction);
n 申请和释放DMA通道
int request_dma(unsigned int dmanr,const chat *device_id)
设备结构体指针可作为device_id的最佳参数。
void free_dma(unsigned int dmanr);
n DMA使用流程
request_dma()初始化DMAC
申请DMA缓冲区
进行DMA传输
中断处理
释放DMA缓冲区
free_dma()
- linux内存学习笔记(三)——静态映射与DMA
- linux内存学习笔记(三)——静态映射与DMA
- linux驱动学习--第二十天:第十一章:CPU 与内存和I/O(三):I/O 内存静态映射 和 DMA
- LDD3学习笔记(18):内存映射和DMA
- 内存映射与DMA
- [Linux内存]DMA学习笔记一
- Linux设备驱动程序学习(20)-内存映射和DMA-基本概念
- Linux设备驱动程序学习(21)-内存映射和DMA-数据结构
- linux 内存映射 PCI内存映射 DMA映射
- 《Linux Device Drivers》第十五章 内存映射和DMA——note
- 《Liunx设备驱动程序》——内存映射和DMA
- 内存映射和DMA
- 内存映射和DMA
- MyBatis学习笔记(三)——映射
- (学习笔记)stm32f429——DMA控制器
- stm32学习笔记——DMA
- TMS320F28335学习笔记——DMA
- Linux-2.6驱动开发 6 内存映射,DMA
- oracle with as
- linux学习笔记(六) linux关机命令
- google常用ip
- WCF配置文件注释
- C语言中a[3]和3[a]是一致的
- linux内存学习笔记(三)——静态映射与DMA
- 计算机的发展
- android 开机动画修改
- iPhone开发技巧之调试篇— 保存日志
- jquery,each的使用
- java Process类的使用
- c#让窗口最大化
- 博客开张了
- iPhone开发 - 内存泄露(不断更新)