cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Observer
Observer
654 Views
Registered: ‎07-23-2013

AR65444 Driver shared memory versus character device for user interface

The first version of our design used a Microblaze to control peripherals until we verified the XDMA interface worked (The FPGA is the peripheral to the Linux host). My intention was to eventually migrate everything to the host so there is only one software controller instead of managing the software for both Microblaze and the Linux user app.

 

While I was transitioning the code from a Microblaze solution to a Linux app I attempted to communicate between the host and the Microblaze using two AXI FIFO cores. One for each direction.

 

I experienced strange issues when, using the host, I read the status of the AXI FIFO from the Microblaze over and over again. I was looking for a change in the number of elements in the FIFO but it would never update unless I closed the app and restarted it. I couldn't spend too much time on that problem but it has gnawed on me. I'm curious if there is a cache coherence issue when reading small packets (like a single register) in the shared memory on the Linux host. It seemed as though once the shared memory was flushed (by closing my application) and then restarted the data was there.

 

I do not have much experience with the shared memory IPC mechanism but I did play around with msync to solve this problem but with no luck.

 

LET ME BE CLEAR I might have made another mistake somewhere in my design, this may not be related to shared memory.

 

I modified my code to use the AR65444 user interface as a character device instead of the shared memory interface but I needed to make a small modification to the xdma-core.c on line 366, specifically I changed the 'char_ctrl_llssek' to 'default_llseek' and removed the reference to the 'char_ctrl_llseek' function (it didn't do anything).

 

Now I can read and write to specific registers with the following:

 

void write_register(int fd, uint64_t addr, uint32_t data){
  uint8_t buf[4];
  buf[3] = (data >> 24) & 0xFF;
  buf[2] = (data >> 16) & 0xFF;
  buf[1] = (data >> 8) & 0xFF;
  buf[0] = (data >> 0) & 0xFF;
  lseek(fd, addr, SEEK_SET);
  write(fd, buf, 4);
}



uint32_t read_register (int fd, uint64_t addr){
  uint32_t result;
  uint8_t buf[4];
  lseek(fd, addr, SEEK_SET);
  read(fd, buf, 4);
  result = (((uint32_t) buf[3]) << 24) | (((uint32_t) buf[2]) << 16) | (((uint32_t)   buf[1]) << 8) | (((uint32_t) buf[0]) << 0);
  return result;
}

Has anyone else experienced this issue when continuously reading the same register?

 

I'm sorry for not providing a reproducible bug.

 

Dave

 

0 Kudos
0 Replies