2016-09-19 3 views
0

私は、レジスタ設定によってMT7620nのGPIOにアクセスしようとしています。これまでのところ、私は/ sys/class/gpio /を使ってそれらにアクセスすることができますが、それは私にとっては十分速いものではありません。devmemonのためのmmapの使い方MT7620n

MT7620のプログラミングガイドページ84では、GPIOベースアドレスが0x10000600であり、単一レジスタのオフセットが4バイトであることがわかります。

MT7620 Programming Guide

ような何か:シェルから devmem 0x10000600 は絶対にうまく動作しますが、私はC言語のprogrammの内部からアクセスすることはできません。ここで

が私のコードです:

#define GPIOCHIP_0_ADDDRESS 0x10000600 // base address 
#define GPIO_BLOCK 4 

volatile unsigned long *gpiochip_0_Address; 
int gpioSetup() 
{ 
int m_mfd; 
if ((m_mfd = open("/dev/mem", O_RDWR)) < 0) 
{ 
    printf("ERROR open\n"); 
    return -1; 
} 
gpiochip_0_Address = (unsigned long*)mmap(NULL, GPIO_BLOCK, PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, GPIOCHIP_0_ADDDRESS); 

close(m_mfd); 

if(gpiochip_0_Address == MAP_FAILED) 
{ 
    printf("mmap() failed at phsical address:%d %s\n", GPIOCHIP_0_ADDDRESS, strerror(errno)); 
    return -2; 
} 

return 0; 
} 

私が手出力は次のとおりです。

mmap() failed at phsical address:268436992 Invalid argument 

私はの世話をするためには何がありますか?以前はメモリにアクセス可能にしなければなりませんか?私はrootとして実行しています。

おかげ

EDIT

ピーター・コルドが正しい、ありがとうございました。 )

#define GPIOCHIP_0_ADDDRESS 0x10000600 // base address 

volatile unsigned long *gpiochip_0_Address; 
int gpioSetup() 
{ 
const size_t pagesize = sysconf(_SC_PAGE_SIZE); 
unsigned long gpiochip_pageAddress = GPIOCHIP_0_ADDDRESS & ~(pagesize-1); //get the closest page-sized-address 
const unsigned long gpiochip_0_offset = GPIOCHIP_0_ADDDRESS - gpiochip_pageAddress; //calculate the offset between the physical address and the page-sized-address 

int m_mfd; 
if ((m_mfd = open("/dev/mem", O_RDWR)) < 0) 
{ 
    printf("ERROR open\n"); 
    return -1; 
} 
page_virtual_start_Address = (unsigned long*)mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, gpiochip_pageAddress); 


close(m_mfd); 

if(page_virtual_start_Address == MAP_FAILED) 
{ 
    printf("ERROR mmap\n"); 
    printf("mmap() failed at phsical address:%d %d\n", GPIOCHIP_0_ADDDRESS, strerror(errno)); 
    return -2; 
} 

gpiochip_0_Address = page_virtual_start_Address + (gpiochip_0_offset/sizeof(long)); 


return 0; 
} 

答えて

1

mmapのファイルオフセットの引数ページ揃えなければならない、そしてそれはEINVALで失敗するのmmapためone of the documented reasonsです。ここ

は、誰かがバグを見つけた場合、私に教えてくださいが、私の最終的な解決策であります。

0x10000600は、4k、または1kの倍数ではないため、ほぼ確実に問題になります。私は512Bほどの小さなページは持っていないと思います。

mmap必要なアドレスを含むページ全体をマップし、そのページ内のオフセットでMMIOレジスタにアクセスします。

ハードコーディングするか、またはアドレスをページ境界の境界に丸めるにはGPIOCHIP_0_ADDDRESS & ~(page_size-1)のようにします。ページサイズをコンパイル時定数として取得し、効率的にコンパイルできるようにする必要があります。

+0

ニース;)ありがとう – user3000289

関連する問題