繁体   English   中英

映射大小和mmap无效参数错误

[英]Map size and mmap Invalid argument error

我正在尝试使用mmap访问我ARM( https://4donline.ihs.com/images/VipMasterIC/IC/ATML/ATML-S-A0001248554/ATML-S-A0001248554-1.pdf )上的物理地址寄存器,但是我不知道要放多长。
例如,如果我在地址0xFFFFFCE8处有一个寄存器,可以访问32位。
我应该在mmap size_t什么?

谢谢你的帮助 !

编辑:
在这里这里,我们可以看到它们放置了4096,第一个是与我的SAM9几乎相同的SAM9。
那么,为什么他们放4096?
也许是因为如果我这样做:

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

答案是4096 ...

编辑2:
根据这篇文章,我可以这样写:

#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(由于此线程 ): 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)

我不再有错误,但是什么也没发生...

任何想法 ?

阅读作为链接提供的数据表的第5章。 它描述了此设备的各种内存和内存映射。 您提供的地址是32位,但是您需要确保其映射。 那就是p上的图表的位置。 18进来-如果您真的想对这些SAM设备进行低级编程,还可以熟悉整个1200页的数据表。

您提供的地址似乎也用于PMC(电源管理控制器)内存空间(根据地图),因此我将在第21章中对该部分进行回顾。

谢谢@vlk和他在python中的 ,我可以使它工作! 这是一个切换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 Bank的值( 0xA00 )而不是0xFFFFFA00添加到地址中,因为它导致了mmap: Invalid argument 不知道为什么..

编辑:
通过mmap示例找到了解决方案:

#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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM