Forum Discussion
It appears that the read has a few clocks of latency. Maybe that's why reading in a loop doesn't work. Does a burst read operate properly?
Is everything working now other than the read-back?
Yeah. Everything appears to be working apart from being able to read only 1 FIR II coef after an mmap().
The reads in a user-space loop are spread very far out in time (relatively), so I don't think? its a burst issue.
Half of me thinks its a linux c programming issues, but identically programmed loop reads on other LW peripherals behave just fine.
I can loop write all the coefficients just fine and then read them back successfully one by one.
I am attaching a full poke application. The problem FIR II read loop is at the bottom. That won't ever run. The single offset read in the middle will run, but seemingly only if I investigate another LW peripheral before that.
I'll continue to play with this in my extra time, but for now it will deliver. The most important feature is coeffecient write which works great now. I bet if I study the LW Axi before and after a freeze I might come up with something.
I MASSIVELY appreciate the help on the problem JCox. I diffed the FIR II IP from 18.0 with the latest 19.1 release. No differences! This is HIGHLY alarming.
// The start address and length of the Lightweight bridge
#define HPS_TO_FPGA_LW_BASE 0xFF200000
#define HPS_TO_FPGA_LW_SPAN 0x0020000
#define HPS_TO_FPGA_HW_BASE 0xC0000000
#define HPS_TO_FPGA_HW_SPAN 0x04000000
#define GEN_INTERRUPT 0x20C0
#define DUMMYREG 0x2000
#define FIR_OFFSET 0x0000
volatile uint32_t *fir2base = 0;
volatile uint32_t *genint = 0;
volatile uint32_t *dummyreg = 0;
volatile uint32_t *gen_interupt = 0;
void * lw_bridge_map = 0;
int main(int argc, char ** argv)
{
int devmem_fd = 0;
int result = 0;
int offset = 0;
int write_enable = 0;
int read_loop_enable = 0;
int dummy_value = 0;
if (argc < 4)
{
printf("Please supply offset and writeover option\n");
}
else
{
offset = atoi(argv[1]);
printf("Offset is: %d \n",offset);
write_enable = atoi(argv[2]);
printf("Write enable is: %d \n",write_enable);
read_loop_enable = atoi(argv[3]);
printf("Read loop enable is: %d \n",read_loop_enable);
}
// Open up the /dev/mem device (aka, RAM)
devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if(devmem_fd < 0) {
perror("devmem open");
exit(EXIT_FAILURE);
}
// mmap() the entire address space of the Lightweight bridge so we can access our custom module
lw_bridge_map = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ | PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE);
if(lw_bridge_map == MAP_FAILED) {
perror("devmem mmap");
close(devmem_fd);
exit(EXIT_FAILURE);
}
fir2base = (uint32_t*)((void*)lw_bridge_map + FIR_OFFSET);
dummyreg = (uint32_t*)((void*)lw_bridge_map + DUMMYREG);
genint = (uint32_t*)((void*)lw_bridge_map + GEN_INTERRUPT);
printf("About to write DUMMYREG\n");
for(int i = 0; i<16; i++)
{
printf("ADDRESS IS %x ",dummyreg + i);
printf("DUMMYREG: %x \n", *(dummyreg + i));
// printf("ADDRESS IS %x ",dummyreg + i);
// printf("DUMMYREG: %x \n", *(dummyreg + i));
}
//You can only right to half the space, the coeffecients are symmetric.
if (write_enable)
{
printf("About to read FIRBASE\n");
for(int i = 0; i<16; i++)
{
printf("ADDRESS IS %x \n",fir2base + i);
printf("Writing %x \n",i);
*(fir2base + i) = i;
usleep(100);
}
}
printf("About to read FIRBASE\n");
printf("ADDRESS IS %x \n",fir2base + offset);
int value = *(fir2base + offset);
printf("Readback is %x::%d\n",value,value);
uint32_t *cur_addr = 0;
if (read_loop_enable)
{
printf("About to read FIRBASE\n");
for(int i = 0; i<16; i++)
{
printf("ADDRESS IS %x \n",fir2base + i);
// cur_addr = dummyreg + i;
// printf("DUMMYREG: %x \n", *(cur_addr));
// value = *(cur_addr);
// printf("Value is: %x \n", value);
// printf("ADDRESS IS %x \n",fir2base + i);
cur_addr = fir2base + i;
value = *(cur_addr);
// //printf("Readback is %x::%d\n",*(fir2base + offset),*(fir2base + offset));
printf("Fir_Reg value: %x \n", (value));
// dummy_value = *(dummyreg + 15);
// usleep(100);
}
}