映射大小和 mmap Invalid argument 错误
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
中输入什么?
谢谢你的帮助 !
编辑:
Here and here 我们可以看到他们放了 4096,第一个是 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(感谢这个 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)
我不再有错误,但什么也没发生...
有什么想法吗?
阅读您作为 link 提供的数据表的第 5 章。它描述了该设备的各种内存和内存映射。您提供的地址是 32 位的,但您需要确定其映射。这就是第 1 页上的图表所在的位置。 18 进来了——如果你真的想在低级别对这些 SAM 设备进行编程,还要熟悉整个 1200 页的数据表。
您提供的地址似乎也是用于 PMC(电源管理控制器)内存的 space(根据地图),所以我会复习第 21 章那一节。
感谢 python 中的 and his 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_OFFSET
放入 0xFFFFF000
,并将 D Bank (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;
我正在尝试使用 mmap
访问我的 ARM (https://4donline.ihs.com/images/VipMasterIC/IC/ATML/ATML-S-A0001248554/ATML-S-A0001248554-1.pdf) 上的物理地址寄存器,但我不知道要放多长时间。
例如,如果我在地址 0xFFFFFCE8
有一个寄存器,我可以在其中访问 32 位。
我应该在 mmap size_t
中输入什么?
谢谢你的帮助 !
编辑:
Here and here 我们可以看到他们放了 4096,第一个是 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(感谢这个 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)
我不再有错误,但什么也没发生...
有什么想法吗?
阅读您作为 link 提供的数据表的第 5 章。它描述了该设备的各种内存和内存映射。您提供的地址是 32 位的,但您需要确定其映射。这就是第 1 页上的图表所在的位置。 18 进来了——如果你真的想在低级别对这些 SAM 设备进行编程,还要熟悉整个 1200 页的数据表。
您提供的地址似乎也是用于 PMC(电源管理控制器)内存的 space(根据地图),所以我会复习第 21 章那一节。
感谢 python 中的
#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_OFFSET
放入 0xFFFFF000
,并将 D Bank (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;