2017-06-02 101 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