Forum Discussion
Thanks for the help. I greatly appreciate it.
Thanks of the heads up on the symmetric nature of the coeffs. I realized this.
Currently I'm at a 32 bit coefficient bus, having bumped my coefficients up to 17 bits wide.
The coeff_clock is tied to h2f_user0_clock from the HSP, set at 100mHz. All my other peripherals on the LW bus use this same clock and reset.
The coeff_reset is tied to the h2f_reset of the HPS.
I have found that I can write to all the symmetric coefficients just fine in a loop in linux.
I have used mmap and am pointer de-referencing on a uint32_t*;
I can also read all the coefficients if I do other bus transactions before I go to read the FIR II coefficient bus. I can also only do one. Doing reads in a loop do not work. So odd.
The address appears to be translating fine onto the offset. Addresses inside the FIR II coeffcient block show as 0,1,2,3,4. The address on the AXI bus and in linux count by +4 bytes from the FIR II base. I hope this makes sense. Incrementing on a *uint32_t maps to the offset I would expect and I see that.
- JC_FPGA5 years ago
New Contributor
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?
- CCase15 years ago
New Contributor
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); } }