博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linuxドライバ_LDD3メモ_ハードウェアとの通信
阅读量:6903 次
发布时间:2019-06-27

本文共 3911 字,大约阅读时间需要 13 分钟。

ハードウェアとの通信            

1)、I/OポートとI/Oメモリ            
    各周辺デバイスは、そのレジスタを読み書きすることで制御されます。
    そのアドレスは、メモリアドレス空間か、I/Oアドレス空間の中に置かれています。        
    ①、I/Oレジスタとコンベンショナルメモリ        
        I/OレジスタとRAMの主な違いは、I/O操作には付帯的な影響があることです。
        I/O操作にとってはコンパイラの最適化(キャッシング、読み書きの並べ替え)が致命的なものになります。    
        ・ハードウェアキャッシングの対策  (対応不要)    
            既にLinuxの初期化コードが、ハードウェアのI/O領域(メモリまたはポート領域)にアクセスするときに、
            ハードウェアキャッシングを無効化にするように設定しています。
        ・コンパイラの最適化とハードウェアによる並べ替えの対策  (要対応)    
            特定の順序であることが見えなければならない操作の間に「メモリバリア」を置くことで対策します。
        一般メモリバリア (ハードウェアに影響しない): void barrier(void)    
        ハードウェアによるメモリバリア:    
            void rmb(void);
            void read_barrier_depends(void);
            void wmb(void);
            void mb(void);
        SMPシステム対応のハードウェアメモリバリア:    
            void smp_rmb(void);
            void smp_read_barrier_depends(void);
            void smp_wmb(void);
            void smp_mb(void);
        メモリバリア使用上の注意点:    
        ・メモリバリアは処理速度に影響します。    
        ・利用できるもののうち最も適したものを使います。    
        ・スピンロックやatomic_t操作など、同期を扱う他のカーネルプリミティブのほとんどは、メモリバリアのように機能します。    
        ・一部のペリフェラルバス(例えばPCIバス)にはそれ自体にキャッシュの問題がある点に注意してください。    
2)、I/Oポートの使い方            
    ①、I/Oポートの割り当て        
        I/Oポートを使う前に、ポートへの排他的なアクセスをまず獲得する必要があります。    
        関連関数:    
            struct resource *request_region(unsigned long first, unsigned long n, const char *name);
            void release_region(unsigned long start, unsigned long n);
    ②、I/Oポートの操作        
        ほとんどのハードウェアは、8ビット、16ビット、32ビットのポートを区別します。これらを混在させることはできません。    
        ・8ビットポートの読み書き:    
            unsigned inb(unsigned port);
            void outb(unsigned char byte, unsigned port);
        ・16ビットポートの読み書き:    
            unsigned inw(unsigned port);
            void outw(unsigned short word, unsigned port);
        ・32ビットポートの読み書き:    
            unsigned inl(unsigned port);
            void outl(unsigned longword, unsigned port);
    ③、ユーザ空間からのI/Oポートアクセス        
        略。    
    ④、ストリング操作        
        ・8ビットポート    
            void insb(unsigned port, void *addr, unsigned long count);
            void outsb(unsigned port, void *addr, unsigned long count);
        ・16ビットポート    
            void insw(unsigned port, void *addr, unsigned long count);
            void outsw(unsigned port, void *addr, unsigned long count);
        ・32ビットポート    
            void insl(unsigned port, void *addr, unsigned long count);
            void outsl(unsigned port, void *addr, unsigned long count);
    ⑤、I/O処理の休止        
        一部のプラットフォーム(特にi386)では、CPUとバスの間のデータ転送速度が速すぎて、問題が起きることがあります。    
        問題が発生するのは、CPUのクロックとペリフェラルバスに対して速すぎるためで、デバイスボードが遅すぎると追いつけないです。    
        解決するために各いI/O命令の間に短い遅延を挿入します。    
        ・「outb」命令    
        ・ビジー待ち    
        ・データ欠損の恐れがある場合は、通常の関数の代わりに休止(pause)付きの関数群を使います。    
    ⑥、プラットフォーム依存性
        互換性のなさ        
        ・データの型    (ARMのI/Oポートは「unsigned int」型、PowerPCは「unsigned char *」型です。)
        ・CPU構造の違い
3)、I/Oメモリの使い方
    レジスタとデバイスメモリはソフトウェアにとっては等価的なので、どちらも「I/Oメモリ」と呼ばれます。
    I/Oメモリは、プロセッサがバス経由でデバイスにアクセスするためのものです。                        
    I/Oメモリの使い方はコンピュータアーキテクチャ、バス、使用するデバイスに依存します。(ページテーブルを使う使わない場合がある)
    ①、I/Oメモリ割り当てとマッピング
        I/Oメモリ領域を使う前に、割り当てを行います。全てのI/Oメモリ割り当ては「/proc/iomem」にリストされます。
        関連関数:                                                                                        
            struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);        
            void release_mem_region(unsigned long start, unsigned long len);                                 
        多くのシステムでは、I/Oメモリに直接アクセスできないです。即ち、まずマッピングを最初に設定する必要があります。
            /* ioremapから返されたアドレスは、そのままでは参照することができず、
            カーネルが提供する関数を使用する必要があります。  */
            void *ioremap(unsigned long phys_addr, unsigned long size);                    
            void *ioremap_nocache(unsigned long phys_addr, unsigned long size);        
            void iounmap(void * addr);                                                
    ②、I/Oメモリのアクセス                                                            
        I/Oメモリを正しく扱うには、その目的のために提供されている関数群(asm/io.h)を使います。
            unsigned int ioread8(void *addr);        
            unsigned int ioread16(void *addr);        
            unsigned int ioread32(void *addr);        
            void iowrite8(u8 value, void *addr);    
            void iowrite16(u16 value, void *addr);    
            void iowrite32(u32 value, void *addr);    
            void ioread8_rep(void *addr, void *buf, unsigned long count);                    
            void ioread16_rep(void *addr, void *buf, unsigned long count);                    
            void ioread32_rep(void *addr, void *buf, unsigned long count);                    
            void iowrite8_rep(void *addr, const void *buf, unsigned long count);                
            void iowrite16_rep(void *addr, const void *buf, unsigned long count);                
            void iowrite32_rep(void *addr, const void *buf, unsigned long count);                
            void memset_io(void *addr, u8 value, unsigned int count);                
            void memcpy_fromio(void *dest, void *source, unsigned int count);                
            void memcpy_toio(void *dest, void *source, unsigned int count);                
    ③、ポートをI/Oメモリとして扱う                        
        I/OポートをI/Oメモリとして扱うため、下記関数を使います。                    
            void *ioport_map(unsigned long port, unsigned int count);                 
            void ioport_unmap(void *addr);                 

转载于:https://www.cnblogs.com/nliao/archive/2013/01/06/2847737.html

你可能感兴趣的文章
Java线程安全和锁Synchronized概念
查看>>
mac app开发试玩(续)
查看>>
【译】提高 JavaScript 开发效率的高级 VSCode 扩展!
查看>>
npm script 钩子的使用
查看>>
产品经理爬取《人人都是产品经理》的5万篇文章,学习如何通过数据找到业务推进重点...
查看>>
基于Git生成开发周报或项目版本change log
查看>>
小程序自定义音频组件,带滚动条,IOS循环失效问题
查看>>
junit测试方法执行顺序
查看>>
Swift开发之粒子动画的实现
查看>>
我学Java我傲娇
查看>>
(十六)spring cloud微服务分布式云架构-集成项目简介
查看>>
挖矿蠕虫肆虐,详解云防火墙如何轻松“制敌”
查看>>
java类实例化内存过程与面向对象特征
查看>>
Linux -- Samba之客户端访问(Linux和windows)
查看>>
centos下的ssdb的安装和使用
查看>>
版本控制系统SVN的分支开发
查看>>
2010下半年网络工程师考证上下午试题【答案】
查看>>
八个Docker的真实应用场景
查看>>
××× Client通过公司GW连接连接internet
查看>>
iis5和Apache2.2共享80端口
查看>>