文档章节

驱动移植过程中DMA内存相关接口替换

Baiqq
 Baiqq
发布于 2017/09/11 17:26
字数 2334
阅读 6
收藏 0
点赞 0
评论 0

1. 相关概念介绍及移植简介 
1.1 物理地址与总线地址 
        1)物理地址是与CPU相关的。在CPU的地址信号线上产生的就是物理地址,在程序指令中的的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。 
        2)总线地址,顾名思义,是与总线相关的,外设使用的就是总线地址。 
        在x86平台下,外设的I/O地址是独立的,即有专门的指令访问外设I/O,I/O地址就是所谓的“总线地址”。而“物理地址”就是RAM地址。 
        在ARM平台下,I/O和RAM统一编址,即“总线地址”就是“物理地址”。 
        Linux系统无论是在内核还是用户空间,都是直接使用“虚拟地址”访问内存或I/O空间,因此要访问外设I/O,必须将I/O地址转换成“虚拟地址”才能够进行访问。 
        MMU启动前程序中的地址为“物理地址”,和硬件手册中规定的地址一致。MMU启动后程序中的地址为“虚拟地址”,“虚拟地址”和“物理地址”之间的关系参照MMU地址映射表。 
1.2 移植介绍 
        在移植Linux驱动的过程中,会遇到很多非POSIX接口,这些接口是跟Linux系统相关的,而在SylixOS中并未提供兼容接口,因此在替换过程中,需要结合SylixOS本身提供的一些机制实现一套兼容接口,在替换过程中为了保持与linux接口的兼容性,将不改变函数的原型,而只是将内部实现替换成SylixOS接口实现。 
        本篇将介绍在移植Linux驱动过程中有关DMA内存操作的相关接口的替换方案,注意,本文档提供的替换方案仅适用于“物理地址”和“总线地址”相同的硬件平台。 
2. DMA内存相关接口介绍及替换 
        在移植过程中主要遇到的和DMA内存相关操作的接口如表 2-1所示。 
        表 2-1 Linux DMA内存相关操作接口

系统接口 接口功能
dma_alloc_coherent 分配一片DMA一致性的内存区域
dma_free_coherent 释放一片DMA一致性内存
dma_pool_create 创建一片DMA内存池
dma_pool_alloc 从DMA内存池中分配一块DMA内存
dma_pool_free 释放DMA内存到DMA内存池中
dma_pool_destroy 销毁DMA内存池

2.1 一致性内存相关接口介绍及替换 
2.1.1 分配一致性内存 
        1)Linux接口介绍 
        Linux内核提供相应接口用于分配一个DMA一致性的内存区域。

void *dma_alloc_coherent(struct device  *dev, 
                          size_t         size, 
                          dma_addr_t    *handle, 
                          gfp_t          gfp)

        函数dma_alloc_coherent原型分析: 
        此函数成功时返回分配的缓冲区地址,失败时返回NULL; 
        参数dev为设备结构,SylixOS没有提供该结构,因此在实际替换中,对该参数进行了修改; 
        参数size为分配的DMA内存大小; 
        参数handle为分配的DMA内存的地址; 
        参数gfp为分配内存标志。 
        2)SylixOS接口替换 
        在SylixOS内核中提供分配DMA内存的接口,且DMA内存是一致性内存,因此为保持兼容,dma_alloc_coherent接口在SylixOS中的实现如程序清单 2-1所示。 
                                            程序清单 2-1 dma_alloc_coherent接口实现

void *dma_alloc_coherent(void *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
    *handle = (dma_addr_t )API_VmmDmaAllocAlign(size, size);
    if(0 == *handle) {
        *handle = ~0;
        return NULL;
    }
    return (void *)(*handle);
}

        主要调用了API_VmmDmaAllocAlign分配DMA物理内存并将DMA地址返回。与Linux中的不同点在于该替换接口返回的是DMA内存地址,而Linux返回的是handle所对应的虚拟地址,提供给用户使用。 
2.1.2 释放一致性内存 
        1)Linux接口介绍 
        Linux内核提供相应接口用于释放DMA一致性的内存区域。

void dma_free_coherent(struct device    *dev, 
                        size_t           size, 
                        void            *cpu_addr, 
                        dma_addr_t       handle)

        函数dma_free_coherent原型分析: 
        参数dev为设备结构,SylixOS没有提供该结构,因此在实际替换中,对该参数进行了修改; 
        参数size为分配的DMA内存大小; 
        参数cpu_addr为待释放的缓冲区地址; 
        参数handle为DMA地址的值。 
        2)SylixOS接口替换 
        在SylixOS中提供释放DMA内存的接口,因此为了兼容,释放DMA内存实现如程序清单 2-2所示。 
                                            程序清单 2-2 dma_free_coherent接口实现

void dma_free_coherent(void *dev, size_t size, void *cpu_addr, dma_addr_t handle)
{
    API_VmmDmaFree ((void *)handle);
}

        由于在SylixOS中DMA内存的物理地址和虚拟地址是一一对应的,因此cpu_addr和handle在数值上是相同的。 
2.2 DMA内存池相关接口介绍及替换 
2.2.1 创建DMA内存池 
        1)Linux接口介绍 
        Linux内核提供相应接口用于创建DMA内存池。

struct dma_pool *dma_pool_create(const char     *name, 
                                  struct device *dev,
                                  size_t         size, 
                                  size_t         align, 
                                  size_t         boundary)

        函数dma_pool_create原型分析: 
        此函数成功时返回DMA池的结构指针,由于SylixOS没有提供该结构,因此在替换过程中接口返回值做了修改。失败时返回NULL; 
        参数name为DMA池的名字; 
        参数dev为设备结构,SylixOS没有提供该结构,因此在实际替换中,对该参数进行了修改; 
        参数size为从该DMA池中分配的缓冲区的大小; 
        参数align为从该池分配时所遵循的对齐原则; 
        参数boundary表示从该DMA池返回的内存不能越过2的boundary次方的边界。 
        2)SylixOS接口替换 
        SylixOS提供定长内存管理机制,因此创建DMA内存池接口实现如程序清单 2-3所示。 
                                            程序清单 2-3 dma_pool_create接口实现

void *dma_pool_create(LW_OBJECT_HANDLE  *ulId, void *dev,
                 size_t size, size_t align, size_t boundary)
{
    PVOID pucDMAPool = NULL;
    pucDMAPool = API_VmmDmaAllocAlign(size, align);
    if (pucDMAPool == NULL) {
        return NULL;
    }    
    *ulId = Lw_Partition_Create("my_partition",
                                 pucDMAPool,
                                 size *2,
                                 4096/64,
                                 LW_OPTION_OBJECT_GLOBAL,
                                 LW_NULL);
    return pucDMAPool;
}

        主要实现过程是通过调用API_VmmDmaAllocAlign分配一片DMA内存,调用Lw_Partition_Create对该DMA内存进行管理。此接口成功返回DMA内存池的地址,失败返回NULL。 
2.2.2 从DMA内存池获取内存块 
        1)Linux接口介绍 
        Linux内核提供相应接口用于从DMA内存池中获取内存块。

void *dma_pool_alloc(struct dma_pool    *pool, 
                      gfp_t                  mem_flags,
                      dma_addr_t        *handle)

        函数dma_pool_alloc原型分析: 
        此函数成功时返回从DMA池中获取的内存块的地址,失败时返回NULL; 
        参数pool为创建DMA池时返回的结构体指针,由于SylixOS没有提供该结构,因此在替换过程中接口返回值做了修改; 
        参数mem_flags为分配内存标志; 
        参数handle为获取的内存块的DMA地址。 
        2)SylixOS接口替换 
        SylixOS提供从创建的定长内存中获取内存块,因此从DMA内存池中获取内存块的实现如程序清单 2-4所示。 
                                            程序清单 2-4 dma_pool_alloc接口实现

void *dma_pool_alloc(LW_OBJECT_HANDLE  ulId, gfp_t mem_flags,
             dma_addr_t *handle)
{
    void *alloc;
    alloc = Lw_Partition_Allocate(ulId);

    /*
     * 由于内存是直接从dma内存中分配,因此,物理地址和虚拟地址一样,
     * 不需要调用API_VmmVirtualToPhysical((addr_t)alloc, handle);进行转换。
     */
    *handle = (dma_addr_t)alloc;

    return alloc;
}

        主要调用定长内存分配接口从定长内存中获取内存块,其中ulId是创建内存池成功时产生的句柄,通过该句柄可以从指定的内存池中获取内存块。 
2.2.3 释放内存块到内存池中 
        1)Linux接口介绍 
        Linux内核提供相应接口用于释放内存块到DMA内存池中。

void dma_pool_free(struct dma_pool *pool, 
                    void           *vaddr, 
                    dma_addr_t      dma)

        函数dma_pool_free原型分析: 
        参数pool为创建DMA池时返回的结构体指针,由于SylixOS没有提供该结构,因此在替换过程中接口返回值做了修改; 
        参数vaddr为从DMA池中获取的内存块的地址; 
        参数dma为DMA池中获取的内存块的地址对应的DMA地址。 
        2)SylixOS接口替换 
        通过调用定长内存释放函数可实现将分配的内存返还到定长内存中,具体实现如程序清单 2-5所示。 
                                            程序清单 2-5 dma_pool_free接口实现

void dma_pool_free(LW_OBJECT_HANDLE  ulId, void *vaddr, dma_addr_t dma)
{
    Lw_Partition_Free(ulId, vaddr);
}

2.2.4 销毁DMA内存池 
        1)Linux接口介绍 
        Linux内核提供相应接口用于销毁DMA内存池。

void dma_pool_destroy(struct dma_pool *pool)

        函数dma_pool_free原型分析: 
        参数pool为创建DMA池时返回的结构体指针,由于SylixOS没有提供该结构,因此在替换过程中接口返回值做了修改; 
        2)SylixOS接口替换 
        通过调用删除定长内存函数即可销毁DMA内存池,具体实现如程序清单 2-6所示。 
                                            程序清单 2-6 dma_pool_destroy接口实现

void dma_pool_destroy(LW_OBJECT_HANDLE   *pulId)
{
    Lw_Partition_Delete (pulId);
}

3. 总结 
        在移植过程中,经常会遇到平台相关的接口,虽然SylixOS没有直接提供相应的接口进行替换,但是如果理解该接口的实现目的,那么就可以通过SylixOS本身的机制实现相同的功能。当然需要对SylixOS本身提供的机制与方法有所了解,才能够轻松地进行接口替换。

© 著作权归作者所有

共有 人打赏支持
Baiqq
粉丝 2
博文 14
码字总数 22359
作品 0
合肥
驱动移植过程中DMA内存相关接口替换

1. 相关概念介绍及移植简介 1.1 物理地址与总线地址 1)物理地址是与CPU相关的。在CPU的地址信号线上产生的就是物理地址,在程序指令中的的虚拟地址经过段映射和页面映射后,就生成了物理地址...

炉yu ⋅ 2017/09/11 ⋅ 0

SylixOS音频驱动移植

1. 适用范围 本文档为实现Nuc970平台音频驱动的方法总结,以此提供一些SylixOS音频驱动移植方法的参考。 2. 原理概述 2.1 Codec编解码芯片 声音信号分为模拟信号和数字信号,Codec编解码芯片...

zhywxyy ⋅ 2017/04/21 ⋅ 0

linux中get_coherent_dma_mask函数中coherent_dma_mask 参数

最近在做一个关于HDMI驱动反面的移植,在给设备alloc framebuffer时,我追踪代码到getcoherentdmamask函数时,遇到问题,就是这个coherentdma_mask 变量,它是device结构体里的一个变量,我就...

fku ⋅ 2011/06/24 ⋅ 0

SylixOS USB Gadget层介绍

1. Gadget层介绍 由于SylixOS中没有Platform的概念,所以在笔者眼中Gadget层兼顾了Platform的功能,实现了UDC设备层和驱动层的连接。 Gadget层结构以及函数调用过于复杂,无法对每个函数做一...

Best_CC ⋅ 2017/10/25 ⋅ 0

浅谈 Linux 内核开发之网络设备驱动

网络设备介绍 网络设备是计算机体系结构中必不可少的一部分,处理器如果想与外界通信,通常都会选择网络设备作为通信接口。众所周知,在 OSI(Open Systems Interconnection,开放网际互连)...

小编辑 ⋅ 2010/07/20 ⋅ 0

【嵌入式开发板】迅为Exynos4412开发板 源码开放 功能强大

产品规格参数 屏幕 屏幕尺寸 9.7寸电容屏 分辨率 1024768 核心板参数 尺寸 6cm7cm 高度 连同连接器在内0.26cm CPU Exynos4412,四核Cortex-A9,主频为1.4GHz-1.6GHz 内存 2GB双通道 DDR3 存储...

topeet ⋅ 2013/12/05 ⋅ 0

RT-Thread 2.1.0 beta 发布,下一方向:物联网

摘要:RT-Thread发布2.1.0 beta版本,这个版本包括了龙芯1C300 智龙v2开发板的移植;也第一次包括了ARM Cortex-M7的移植;在微处理器(MPU)上,RT-Thread也越加完善,POSIX接口兼容度进一步...

午夜熊 ⋅ 2015/10/20 ⋅ 12

android之ION内存储器管理器(1)- 简介

为什么需要ION 回顾2011年末[2],LWN审查了 android kernel patch[3],以期望将这些patch合并到kernel主线中。但是PMEM(android实现的 一个内存分配器)使这个愿望破灭了。为什么PMEM不被l...

sflfqx ⋅ 2014/11/11 ⋅ 0

RT-Thread 嵌入式操作系统 2.0.0 beta 发布

RT-Thread v2.0.0这个版本系列是RT-Thread嵌入式实时操作系统当前的开发分支,如果要上新项目,建议使用这个版本来进行,预计这个版本的正式版会在年底发布。欢迎对这个版本进行测试、并反馈...

午夜熊 ⋅ 2014/08/09 ⋅ 8

STM32之独立版USB(Host)驱动+MSC+Fatfs移植

写在前面 现在,网上关于STM32的USB的文章数不胜数。写这篇文章仅仅是对于自我学习的一个记录。主要是对实际学习中遇到的一些棘手问题做个备忘录。使用的芯片为STM32F407VG 。 目前,ST的USB...

zcshoucsdn ⋅ 01/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Boost库编译应用

版本:Boost 1.66.0 Windows库编译 官网指南:直接执行bootstrap.bat处理文件即可,可以我却遇到一堆的问题。 环境:Windows 10 + Visual Studio 2017 Boost编译出来库命名 boost库生成文件命...

水海云 ⋅ 14分钟前 ⋅ 0

解决Eclipse发布到Tomcat丢失依赖jar包的问题

如果jar文件是以外部依赖的形式导入的。Eclipse将web项目发布到Tomcat时,是不会自动发布这些依赖的。 可以通过Eclipse在项目上右击 - Propertics - Deployment Assembly,添加“Java Build ...

ArlenXu ⋅ 14分钟前 ⋅ 0

iview tree组件层级过多时可左右滚动

使用vue+iview的tree组件,iview官网iview的tree树形控件 问题描述:tree层级过多时左右不可滚动 问题解决:修改overflow属性值 .el-tree-node>.el-tree-node_children { overflow: vi...

YXMBetter ⋅ 16分钟前 ⋅ 0

分布式锁

1.通过数据库实现 http://www.weizijun.cn/2016/03/17/%E8%81%8A%E4%B8%80%E8%81%8A%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E8%AE%BE%E8%AE%A1/ 2.ZK实现:curator-recipes分布式锁的......

素雷 ⋅ 24分钟前 ⋅ 0

Sublime Text3 快捷键

选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本。 Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名...

AndyZhouX ⋅ 31分钟前 ⋅ 0

XamarinAndroid组件教程RecylerView自定义适配器动画

XamarinAndroid组件教程RecylerView自定义适配器动画 如果RecyclerViewAnimators.Adapters命名空间中没有所需要的适配器动画,开发者可以自定义动画。此时,需要让自定义的动画继承Animation...

大学霸 ⋅ 31分钟前 ⋅ 0

eureka 基础(二)

使用Eureka服务器进行身份验证 如果其中一个eureka.client.serviceUrl.defaultZone网址中包含一个凭据(如http://user:password@localhost:8761/eureka)),HTTP基本身份验证将自动添加到您...

明理萝 ⋅ 34分钟前 ⋅ 1

Kubernetes(五) - Service

Kubernetes解决的另外一个痛点就是服务发现,服务发现机制和容器开放访问都是通过Service来实现的,把Deployment和Service关联起来只需要Label标签相同就可以关联起来形成负载均衡,基于kuberne...

喵了_个咪 ⋅ 34分钟前 ⋅ 0

更新队友POM文件后报错

打开报错的地方的pom及其引用方法所在文件的pom,观察其版本号是否一致,不一致进行更改

森火 ⋅ 48分钟前 ⋅ 0

IDEA使用sonarLint

一、IDEA如何安装SonarLint插件 1.打开 Idea 2.点击【File】 3.点击【Settings】 4.点击【Plugins】 5.在搜索栏中输入“sonarlint”关键字 6.点击【Install】进行安装 7.重启Idea 二、IDEA如...

开源中国成都区源花 ⋅ 53分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部