0
votes

Scenario:

  • Raspberry Pi 3 Model B
  • Adaptronic Modular ECU connected via USB (presents itself as a mass storage device, well 2 actually, sda and sdb in this case)

I'm simply using fopen() to open /dev/sda for reading, I seek to the position I want to read and I read 2048 bytes. I then re-seek to the position I seek'ed before and read that data again.

On my first read, I get fresh, correct data. On each subsequent read I get the same data over and over again. It does not attempt to poll the device again (because it has an activity light) after the first read, however when I kill my app (ctrl+c) I see the activity light flashing madly and then stop.

I thought it was a buffering issue with my code (I started with ifstream, and have tried fopen() and open(), all the same) and tried the various different methods of disabling the buffing (ie. setvbuf()) but I'm still not getting fresh data.

If I close and open the file again then I get new data but this is a very slow process (I only get about 10-12 samples/sec).

Keep in mind, this is not a mounted device, it simply presents as a storage device and I read from its block device directly.

I ported the same code to Windows and it works, so I don't believe it is my code, but rather something within Linux.

Any help would be greatly appreciated.

1
I've also tried doing int fd = fileno(fp); ioctl(fd, BLKFLSBUF, 0); which does work but is very slow, possibly as slow or slower than closing and opening the file again.Josh Finlay
To clear - echo 3 > /proc/sys/vm/drop_cacheShaibal
To disable caching completely, I think you can refer to - superuser.com/questions/242928/…Shaibal
I've used echo 3 > /proc/sys/vm/drop_cache and this works but with severe performance degradation (similar to that of closing/opening the file again)Josh Finlay
Could you please see if the solution in super user is useful to you?Shaibal

1 Answers

2
votes

This was solved in my question on the stackexchange site: unix.stackexchange.com/questions/372452/disable-read-cache-buffer-for-usb-mass-storage-device-in-linux

To summarise, the issue was that I needed to use O_DIRECT but ensure that I was reading (and seeking) full blocks of data. In my case, the device was in 512byte blocks so I needed to fetch that amount.

#define NUM_VARS 1024
#define PAGE 4096
#define STARTBYTE (272384/PAGE*PAGE) // must align
#define OFFSET (272384-STARTBYTE)
#define ITEMSIZE (sizeof(*liveBuffer))
#define LIVEBUFSIZE ((OFFSET+NUM_VARS*ITEMSIZE+PAGE-1)/PAGE*PAGE)

signed short *liveBuffer;
FILE *input = fopen("/dev/sda", "r+");
if(posix_memalign((void**)&liveBuffer, PAGE, LIVEBUFSIZE)!=0)
   exit(5);
if (fcntl(fileno(input), F_SETFL, O_DIRECT) == -1)
   exit(6);
fseek(input, OFFSET, SEEK_SET);
fread(liveBuffer, ITEMSIZE, LIVEBUFSIZE, input);
fclose(input);