6

私たちには、メモリマップデバイスが接続され、ARM CPUがLinuxを実行する組み込みシステムがあります。デバイスはアドレス0x40400000にあり、メガバイトを占有しています(ほとんどの場合、実際のメモリにバックアップされていませんが、アドレススペースはデバイスにマップされています)。現在このデバイスのデバイスドライバを持っていないはありません。ユーザ空間のポインタに物理デバイスをマッピング

装置において特別な読み取り専用アドレス0x404f0704に(CIDと呼ばれる)レジスタがあります。このレジスタには値CID = 0x404が含まれています。私はARM上で動作するプログラムからこのレジスタを読み込もうとしています。私はおそらく私がユーザ空間から物理アドレスにアクセスすることができますmmap()機能について学んネットを検索

 

#include <sys/mman.h> 
#include <fcntl.h> 
#include <err.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    void   *pdev = (void *) 0x40400000; 
    size_t   ldev = (1024*1024); 
    int   *pu; 
    int volatile *pcid; 
    int volatile cid; 

    pu = mmap(pdev, ldev, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 
    if (pu == MAP_FAILED) 
     errx(1, "mmap failure"); 

    pcid = (int *) (((void *) pu) + 0xf0704); 

    printf("pu = %08p\n", pu); 
    printf("pcid = %08p\n", pcid); 

    cid = *pcid; 
    printf("CID = %x\n", cid); 

    munmap(pu, ldev); 

    return (EXIT_SUCCESS); 
} 
 

ARMクロスコンパイラでコンパイルする:

a-gcc -O0 -g3 -o mmap-test.elf mmap-test.c 

は私が期待した結果を得ることができないので、私が見つけた例のカップルを追跡しようと、私は次のテストを書きました。私が見るものということです:私は/ここに何が問題を

pu = 0x40400000 
pcid = 0x404f0704 
CID = 0 

代わりに期待

CID = 404 

のをやって行方不明ですか?


UPDATE:

私は別のデモプログラムを発見し、そのコードは以下の私は、私のコードの作業を取得することができました:

 

int main(void) 
{ 
    off_t   dev_base = 0x40400000; 
    size_t   ldev = (1024 * 1024); 
    unsigned long mask = (1024 * 1024)-1; 
    int   *pu; 
    void   *mapped_base; 
    void   *mapped_dev_base; 
    int volatile *pcid; 
    int volatile cid; 
    int   memfd; 

    memfd = open("/dev/mem", O_RDWR | O_SYNC); 
    mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK); 
    if (mapped_base == MAP_FAILED) 
     errx(1, "mmap failure"); 
    mapped_dev_base = mapped_base + (dev_base & MAP_MASK); 
    pu = mapped_dev_base; 

    pcid = (int *) (((void *) pu) + 0xf0704); 

    printf("pu = %08p\n", pu); 
    printf("pcid = %08p\n", pcid); 

    cid = *pcid; 
    printf("CID = %x\n", cid); 

    munmap(mapped_base, ldev); 
    close(memfd); 

    return (EXIT_SUCCESS); 
} 
 

はそれでも、私は、なぜ第一のでわかりませんバージョンは機能しませんでした。私が理解したところでは、一度MAP_ANONYMOUSを使用すると、マッピングのファイルハンドルは必要ありません。また、私は明らかにaddr引数(私の第1版ではpepi)を物理アドレスと誤解しています。今の場合、これは実際には仮想アドレスです。

答えて

5

Mmapは通常仮想アドレスで動作する関数です。 mmap(... MAP_ANONYMOUS)mmapのファイル/dev/zero)に電話すると、新しい仮想メモリをいくつか用意して、ゼロで埋め尽くします。返されるアドレスは、仮想メモリのアドレスになります。

あなたは(MAP_ANONYMOUSなし)いくつかのファイルをmmapさすることができ、その後のmmapは、いくつかの仮想メモリ範囲にファイルの内容をマップします。

デバイスは、アドレス0x40400000に配置され

デバイスMMIOが物理メモリに配置されています。どのプロセスも仮想アドレス0x40400000を使用できます。 MMU(メモリ管理ユニット)によって空き物理ページにマッピング(変換)されます。 OSに何らかの仮想メモリを求めるだけでは、それがデバイスの範囲(それは地獄の変種になります)にmmapedされると期待できません。

しかし、すべての物理メモリを含むファイルとして使用できる特別なデバイス/ dev/memがあります。 mmap/dev/memの場合、実際にOSに要求された物理的範囲にいくつかの仮想メモリの新しいマッピングを作成するよう求めています。 MMAPのあなたの呼び出しで

mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, 
    MAP_SHARED, memfd, dev_base & ~MAP_MASK); 

あなたは、物理メモリ範囲[0x40400000 .. 0x4050000-1](1メガバイト、バイト0x40500000は含まない)をマッピングするために頼む(その開始アドレスはmmapので返される)仮想メモリの一部メガバイトに。

関連する問題