Thank you James, it works now! getpagesize() returns 4096, this matches the previous map_size which is a nice sanity check. I like that this would dynamically change with different modules as some are 1 or 2k.
The difference that made this work is casting the virtual address (pwm_addr in your code) as a uint8_t*. I do not understand why the pointer should change based on the type it is pointing to. To demonstrate this, the below code prints both addresses to the console to show the same result.
Also of note is that reading in this manner seems to take ~.36 us. Not PRU fast, but I presume this is as fast as we can get it in userspace land.
I apologize for the long code snipped but I wanted to post a complete solution here for anyone curious.
`
#include <stdio.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define QPOSCNT 0x0000
#define EQEP0_BASE 0x48300180
#define QREVID 0x005C
int main(){
int fd;
volatile unsigned long *map_base;
unsigned long target=EQEP0_BASE;
long eqep0_pos, revid;
struct timeval tv1, tv2;
unsigned long map_size = getpagesize();
unsigned long map_mask = map_size-1;
//O_SYNC makes the memory uncacheable
if ((fd = open("/dev/mem", O_RDWR | O_SYNC))==-1) {
printf(“Could not open /dev/mem\n”);
return 0;
}
printf(“opened /dev/mem\n”);
//&~map_mask truncates the address to the base of the 4K Page
map_base=(uint8_t*)mmap(0, map_size, PROT_READ|PROT_WRITE,MAP_SHARED,fd, target&~map_mask);
if(map_base == (void ) -1) {
printf(“Unable to mmap eqep\n”);
exit(-1);
}
//&map_mask adds the position within the page to the address, this is 0x180 for eEQP0
unsigned long eqep0_addr = (uint8_t *)map_base + (target&map_mask);
//time a read-loop to assess speed
int num_reads = 1000000;
int i;
gettimeofday(&tv1,NULL);
for(i=0;i<num_reads;i++){
eqep0_pos = *((uint8_t *)eqep0_addr + QPOSCNT);
}
gettimeofday(&tv2,NULL);
revid = *(uint32_t *)((uint8_t *)eqep0_addr+QREVID);
//find difference between start and end time
unsigned long dt_micros = (1000000 * tv2.tv_sec + tv2.tv_usec)-(1000000 * tv1.tv_sec + tv1.tv_usec);
float time_per_read = (float)dt_micros/num_reads;
printf(“last position %ld\n”, eqep0_pos);
printf(“micros per read %f\n”, time_per_read);
printf(“pagesize %d\n”, getpagesize());
printf(“map_base 0x%lX\n”,map_base);
printf("(uint8_t *)map_base 0x%lX\n", (uint8_t *)map_base);
printf(“target&map_mask 0x%lX\n”,target&map_mask);
printf(“revid 0x%lX (should read 44D31103)\n”,revid);
close(fd);
return 0;
}
`
output:
opened /dev/mem last position 71 micros per read 0.389692 pagesize 4096 map_base 0xB6FF1000 (uint8_t *)map_base 0xB6FF1000 target&map_mask 0x180 revid 0x44D31103 (should read 44D31103)