I want to write to a physical address to change the voltage of a pin using an ARM board- but in order to write to a physical address, I need to take a virtual address, and map it to the physical address using mmap. So I did that, in this way: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <signal.h> #include <fcntl.h> #include <ctype.h> #include <termios.h> #include <sys/types.h> #include <sys/mman.h> #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) int main(void) { int fd; int *map_base_c,*map_base_d, *map_base_p, *virt_addr; off_t target,control,data,pullup; control=0x56000050; if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; map_base_d = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,data & ~MAP_MASK); printf("Memory mapped at address %p.\n", map_base_d); virt_addr = map_base_d; //+ (data & MAP_MASK) *virt_addr = 0x00; //This is where it goes off. find out why!!! printf("Value at address 0x%X (%p): 0x%X\n", data, virt_addr,(*virt_addr)); close(fd); return 0; } But, The pin didn't get a high voltage as I'd expected. Is there something wrong with the way I'm changing the address? Also, is there a way to see the physical address which was mapped to the virtual address? Thanks!
Modifying registers from user space
Seems you want to write to the GPFCON register at the physical address 0x56000050. What about: static uint32_t read_reg32(const void *p) { const uint32_t *r = (const uint32_t*)p; return *r; } static void write_reg32(void *p, uint32_t v) { uint32_t *r = (uint32_t*)p; *r = v; } int main(....) uint32_t gpfcon: void *map_base_d; [...] gpfcon = read_reg32(map_base_d + 0x56000050); write_reg32(map_base_d + 0x56000050, gpfcon);
It is giving me a segmentation fault when I reach this particular line : gpfcon = read_reg32(map_base_d + 0x56000050); Why have you added 0x56000050 to the map_base_d? I am not getting any warnings or errors at compile time so I am not sure where the problem is.
The problem seems to be at this step : gpfcon = read_reg32(map_base_d + 0x56000050); This gives me a segfault when I run it What I had done in the previous code that didn't work was gpfcon = map_base_d + (0x56000050 & MAP_MASK) where MAP_MASK was 0xfff. Actually, I am not sure why this would even work. This doesn't give a segfault but it doesn't work either!
I got the GPIO access. Thanks! Here's the code if anyone is interested. I'm controlling port GPF0 and making it blink. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <signal.h> #include <fcntl.h> #include <ctype.h> #include <termios.h> #include <sys/types.h> #include <sys/mman.h> #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) #define USR1_LED (1<<22) int main(int argc, char *argv[]) { volatile void *gpio_addr_c = NULL; volatile void *gpio_addr_p = NULL; volatile void *gpio_addr_d = NULL; volatile unsigned int *gpio_oe_addr_c = NULL; volatile unsigned int *gpio_oe_addr_p = NULL; volatile unsigned int *gpio_oe_addr_d = NULL; unsigned int reg; off_t control,data,pullup; int fd = open("/dev/mem", O_RDWR); control = 0x56000050; data = 0x56000054; pullup = 0x56000058; printf("Mapping %x \n", control); gpio_addr_c = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (control& ~MAP_MASK)); gpio_oe_addr_c = gpio_addr_c + (control &MAP_MASK); if(gpio_addr_c == MAP_FAILED) { printf("Unable to map GPIO\n"); exit(1); } printf("GPIO mapped to %p\n", gpio_addr_c); printf("GPIO OE mapped to %p\n", gpio_oe_addr_c); reg = *gpio_oe_addr_c; printf("GPIO1 configuration: %X\n", reg); reg = reg & (0xFFFFFFFF - USR1_LED); *gpio_oe_addr_c = 0x5555; printf("GPIO1 configuration: %X\n", *gpio_oe_addr_c); gpio_addr_p = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (pullup & ~MAP_MASK)); gpio_oe_addr_p = gpio_addr_p + ( pullup &MAP_MASK); if(gpio_addr_p == MAP_FAILED) { printf("Unable to map GPIO\n"); exit(1); } printf("GPIO mapped to %p\n", gpio_addr_p); printf("GPIO OE mapped to %p\n", gpio_oe_addr_p); reg = *gpio_oe_addr_p; printf("GPIO1 configuration: %X\n", reg); reg = reg & (0xFFFFFFFF - USR1_LED); *gpio_oe_addr_p = 0xff; printf("GPIO1 configuration: %X\n", *gpio_oe_addr_p); gpio_addr_d = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ( data& ~MAP_MASK)); gpio_oe_addr_d = gpio_addr_d + ( data &MAP_MASK); if(gpio_addr_d == MAP_FAILED) { printf("Unable to map GPIO\n"); exit(1); } printf("GPIO mapped to %p\n", gpio_addr_d); printf("GPIO OE mapped to %p\n", gpio_oe_addr_d); reg = *gpio_oe_addr_d; printf("GPIO1 configuration: %X\n", reg); reg = reg & (0xFFFFFFFF - USR1_LED); *gpio_oe_addr_d = 0xfe; printf("GPIO1 configuration: %X\n", *gpio_oe_addr_d ); printf("Start blinking LED USR1\n"); while(1) { printf("ON\n"); *gpio_oe_addr_d= 0xfe; sleep(1); printf("OFF\n"); *gpio_oe_addr_d = 0xff; sleep(1); } close(fd); return 0; }