分享

与硬件通信

 clover_xian 2012-11-30
匆匆忙忙又一年,  由于最近项目不忙,  对之前的工作做些总结,  本文主要描述与硬件通信相关.

与硬件通信不得不提IO端口与IO内存, 对于两者的定义与区别我在网上找了段描述, 感觉还可以, 如下:

这两者如何区分就涉及到硬件知识,X86体系中,具有两个地址空间:IO空间和内存空间,而RISC指令系统的CPU(如ARM、PowerPC等)通常只实现一个物理地址空间,即内存空间。
io端口: 当寄存器或内存位于IO空间时,称为IO端口。一般寄存器也俗称I/O端口,或者说I/O ports,这个I/O端口可以被映射在Memory Space,也可以被映射在I/O Space。

Io内存:当寄存器或内存位于内存空间时,称为IO内存


本文着重说明IO内存的操作:

首先需要说明的驱动访问I/O寄存器的主要目的是: 处理寄存器操作边际效应.

既:驱动程序必需确保不使用高速缓存(cache), 并且在访问的寄存器时不发生读写指令的重新排序.

关于cache引起的问题只需要将该段地址空间设置为NO CACHE类型即可. ioremap函数在映射的过程中就设置了对应空间的nocacke属性.

对于编译器优化或者硬件重新排序引起的问题,  需要使用内存屏障.  如下是一个内存屏障的例子, 便于理解其工作原理.

#define set_mb(var, value) do { var = value; mb(); } while (0)
#define mb() __asm__ __volatile__ ("" : : : "memory")

1)set_mb(),mb(),barrier()函数追踪到底,就是__asm__ __volatile__("":::"memory"),而这行代码就是内存屏障。
2)__asm__用于指示编译器在此插入汇编语句
3)__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
4)memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将 作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内 存。
5)"":::表示这是个空指令。barrier()不用在此插入一条串行化汇编指令。在后文将讨论什么叫串行化指令。
6)__asm__,__volatile__,memory在前面已经解释

借此说明对于DMA操作内存管理做个说明:

一般DMA内存会使用dma_alloc_coherent申请, 该函数在内存映射时就增加no cache属性, 该属性存在页表中.

wilson 
2012-02-02

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多