2017-06-02 100 views
-1

我想通過mmap訪問我的ARM(https://4donline.ihs.com/images/VipMasterIC/IC/ATML/ATML-S-A0001248554/ATML-S-A0001248554-1.pdf)上的物理地址寄存器,但我不知道要放多長。
例如,如果我有一個地址爲0xFFFFFCE8的寄存器,其中我可以訪問32位。
我應該在mmap size_t中輸入什麼?

謝謝你的幫助!

編輯:
Herehere我們可以看到,他們把4096,並在第一個它是一個SAM9幾乎和我一樣。
那麼,他們爲什麼要放4096?
也許是因爲如果我這樣做:地圖大小和mmap無效的參數錯誤

#include <unistd.h> 
long sz = sysconf(_SC_PAGESIZE); 
printf("%ld",sz); 

釷的答案是4096 ...

編輯2:
基於this post我可以這樣寫:

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

#define handle_error(msg) \ 
      do { perror(msg); exit(EXIT_FAILURE); } while (0) 

#define PIOD_START_ADDR      0xFFFFFA00 
#define PIOD_STOP_ADDR      0xFFFFFC00 
#define PIOD_SIZE       (PIOD_STOP_ADDR-PIOD_START_ADDR) 

#define PIO_WPMR_OFFSET      0xE4 // PIO Write Protection Mode Register Bank D 

#define PIO_PUER_OFFSET      0x64 // PIO Pull-Up Enable Register Bank D 
#define PIO_PUSR_OFFSET      0x68 // PIO Pull-Up Status Register Bank D 

#define LED7_ON        0xFFDFFFFF // LED7 Mask ON 
#define LED7_OFF       0xFFFFFFFF // LED7 Mask OFF 
#define DESABLE_WRITE_PROTECTION_BANK_D  0x50494F00 // Desable write protection 

int main(void) { 
    volatile void *gpio_D_addr; 
    volatile unsigned int *gpio_pullup_enable_addr; 
    volatile unsigned int *gpio_pullup_status_addr; 
    volatile unsigned int *gpio_enable_write_addr; 

    int fd = open("/dev/mem", O_RDWR|O_SYNC); 
    if (fd < 0){ 
     fprintf(stderr, "Unable to open port\n\r"); 
     exit(fd); 
    } 

    gpio_D_addr = mmap(0, PIOD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR); 
    gpio_addr = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDR); 

    if(gpio_D_addr == MAP_FAILED){ 
     handle_error("mmap"); 
    } 

    gpio_enable_write_addr = gpio_D_addr + PIO_WPMR_OFFSET; 
    gpio_pullup_enable_addr = gpio_D_addr + PIO_PUER_OFFSET; 
    gpio_pullup_status_addr = gpio_D_addr + PIO_PUSR_OFFSET; 

    *gpio_enable_write_addr = DESABLE_WRITE_PROTECTION_BANK_D; 

    *gpio_pullup_enable_addr = *gpio_pullup_status_addr & LED7_ON; 

    return 0; 
} 

但是我有一個mmap: Invalid argument錯誤。 - >但是通過改變,像這樣的mmap(感謝這個thread):mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR & ~MAP_MASK);有:

#define MAP_SIZE       4096UL 
#define MAP_MASK       (MAP_SIZE - 1) 

我不再有錯誤,但什麼都沒有發生......

任何想法?

回答

1

謝謝@vlk和他python中的library我可以使它工作!下面是切換LED一個小例子:

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


#define handle_error(msg) \ 
      do { perror(msg); exit(EXIT_FAILURE); } while (0) 

#define _PIOD_BANK_D       0xA00 

#define _PIO_OFFSET        0xFFFFF000 

/* When executing this on the board : 
    long sz = sysconf(_SC_PAGESIZE); 
    printf("%ld\n\r",sz); 
    We have 4096. 
*/ 
#define _MAP_SIZE       0x1000 // 4096 

#define _WPMR_OFFSET      0x0E4 // PIO Write Protection Mode Register Bank D 

#define _PIO_ENABLE       0x000 
#define _PIO_DISABLE      0x004 
#define _PIO_STATUS       0x008 
#define _OUTPUT_ENABLE      0x010 
#define _OUTPUT_DISABLE      0x014 
#define _OUTPUT_STATUS      0x018 
#define _FILTER_ENABLE      0x020 
#define _FILTER_DISABLE      0x024 
#define _FILTER_STATUS      0x028 
#define _OUTPUT_DATA_SET     0x030 
#define _OUTPUT_DATA_CLEAR     0x034 
#define _OUTPUT_DATA_STATUS     0x038 
#define _PIN_DATA_STATUS     0x03c 
#define _MULTI_DRIVER_ENABLE    0x050 
#define _MULTI_DRIVER_DISABLE    0x054 
#define _MULTI_DRIVER_STATUS    0x058 
#define _PULL_UP_DISABLE     0x060 
#define _PULL_UP_ENABLE      0x064 
#define _PULL_UP_STATUS      0x068 
#define _PULL_DOWN_DISABLE     0x090 
#define _PULL_DOWN_ENABLE     0x094 
#define _PULL_DOWN_STATUS     0x098 

#define _DISABLE_WRITE_PROTECTION   0x50494F00 // Desable write protection 

#define LED_PIN         21 

int main(void) { 

    volatile void *gpio_addr; 
    volatile unsigned int *gpio_enable_addr; 
    volatile unsigned int *gpio_output_mode_addr; 
    volatile unsigned int *gpio_output_set_addr; 
    volatile unsigned int *gpio_output_clear_addr; 
    volatile unsigned int *gpio_data_status_addr; 
    volatile unsigned int *gpio_write_protection_addr; 

    int fd = open("/dev/mem", O_RDWR|O_SYNC); 
    if (fd < 0){ 
     fprintf(stderr, "Unable to open port\n\r"); 
     exit(fd); 
    } 


    gpio_addr = mmap(NULL, _MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PIO_OFFSET); 


    if(gpio_addr == MAP_FAILED){ 
     handle_error("mmap"); 
    } 


    gpio_write_protection_addr = gpio_addr + _PIOD_BANK_D + _WPMR_OFFSET; 

    gpio_enable_addr = gpio_addr + _PIOD_BANK_D + _PIO_ENABLE; 

    gpio_output_mode_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_ENABLE; 

    gpio_output_set_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_SET; 

    gpio_output_clear_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_CLEAR; 

    gpio_data_status_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_STATUS; 


    *gpio_write_protection_addr = _DISABLE_WRITE_PROTECTION; 

    *gpio_enable_addr = 1 << LED_PIN; 
    *gpio_output_mode_addr = 1 << LED_PIN; // Output 


    // If LED 
    if((*gpio_data_status_addr & (1<<LED_PIN)) > 0){ 
     *gpio_output_clear_addr = 1 << LED_PIN; 
    }else{ 
     *gpio_output_set_addr = 1 << LED_PIN; 
    } 

    return 0; 
} 

我只好把_PIO_OFFSET0xFFFFF000,並添加到地址d銀行(0xA00)的值,而不是0xFFFFFA00因爲它導致與mmap: Invalid argument。不知道爲什麼..

編輯:
找到與mmap example解決方案:

#define _PIO_OFFSET       0xFFFFFA00 // Instead of 0xFFFFF000 
#define _MAP_SIZE       0x1000 // 4096 
#define _MAP_MASK       (_MAP_SIZE - 1) 
#define _PA_OFFSET       _PIO_OFFSET & ~_MAP_MASK 

而且MMAP:

gpio_addr = mmap(NULL, _MAP_SIZE + _PIO_OFFSET - _PA_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PA_OFFSET); 

而對於分配:

gpio_enable_addr = gpio_addr + _PIO_OFFSET - (_PA_OFFSET) + _PIO_ENABLE; 
1

閱讀作爲鏈接提供的數據表的第5章。它描述了該設備的各種存儲器和存儲器映射。你給的地址是32位,但你需要確定它的映射。這就是p。中的圖表。如果您真的想在較​​低的水平上對這些SAM設備進行編程,那麼您可以熟悉整個1200頁的數據表。

你給我的地址,也似乎是對PMC(電源管理控制器)的存儲空間(根據地圖),所以我會審查部分,21章

+0

謝謝你的幫助。我已經看過這一章,但看到我的帖子上面編輯。 – Tagadac

+1

我不知道4096的價值..需要更多的研究來了解這一點。但現在,工作要求:( – TomServo

+1

通過這樣做'#包括 長SZ =的sysconf(_SC_PAGESIZE); \t的printf( 「%LD」,SZ),'我們'4096'所以頁面的大小。 4096。 – Tagadac