2016-09-19 11 views
0

Я пытаюсь получить доступ к GPIO-устройствам MT7620n через настройки регистра. Пока я могу получить к ним доступ, используя/sys/class/gpio/... но для меня это недостаточно быстро.Как использовать mmap для devmemon MT7620n

В руководстве по программированию на MT7620 стр. 84 вы можете видеть, что базовый адрес GPIO равен 0x10000600, а одиночные регистры имеют смещение 4 байта.

MT7620 Programming Guide

Что-то вроде: devmem 0x10000600 из оболочки работает абсолютно нормально, но я не могу получить доступ к нему из внутри гр 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 

Что я должен заботиться? Должен ли я сделать доступ к памяти раньше? Я бегу как корень.

Благодаря

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 «s файл аргумент смещения должен быть страница выровнены, и это one of the documented reasons для ттар, чтобы потерпеть неудачу с EINVAL ,

0x10000600 не является кратным 4k, или даже 1k, так что это почти наверняка ваша проблема. Я не думаю, что в каких-либо системах есть страницы размером 512B.

mmap целую страницу, которая включает адрес, который вы хотите, и доступ к регистрам MMIO со смещением на этой странице.

Либо код жесткого кода, либо, возможно, сделать что-то вроде GPIOCHIP_0_ADDDRESS & ~(page_size-1), чтобы округлить адрес до границы, выровненной по страницам. Вы должны иметь возможность делать то, что получает размер страницы как константу времени компиляции, поэтому она все еще эффективно компилируется.

+0

Ницца;) Большое спасибо – user3000289