This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Kernel Buffer Cache Problem with self written McBSP Driver

Other Parts Discussed in Thread: ADS1278

Hi folks,

 

I've been quite busy writing an own kernel module to access the mcbsp bus. This Module enables McBSP in Master Receiver mode, and then fills the received data over DMA access into 5 Buffers in a circular manner. This works quit well, and when I do a "cat /dev/ads1278|hexdump -C" - ads1278 is my loaded McBSP kernel module - I can see the incoming data which I can verify with a scope.

Now my problem: when I try to read that data from an own Userprogram using "fread" or "read", I get some funny buffering behaviour, which gives me repeatedly the same values. It looks like linux knows of the 5 buffers arranged circularly and so the "fread" and "read" return the same 5 buffers for some iterations (sometimes only two times the exact same buffer contents, sometimes even 10 times), so it looks like the Kernel Buffer Cache mechanism that takes over control of the reading here.

Here's the code snipped where I try to read out my driver (remember: when reading out my driver with "cat...", this works wonderfully and never returns the same values for the same buffer twice). I denoted 2 approaches inside the code, one with "fopen" and an appropriate "setvbuf(...)" and one with "open" and "O_DIRECT". The one with "O_DIRECT" returns -1. I here quickly searched the kernel source and everywhere I found "O_DIRECT" there was a "return EINVAL" afterwards, so it looks like this kernel doesn't support "O_DIRECT".

 

int main()
{

    // 1. approach-----------------
    FILE *driver=NULL;

    //2. approach------------------

    int driver;

    //-----------------------------------
    char *chan1;
    char *chan2;
    char *chan3;
    char *chan4;
    int i;


    // 1. approach-----------------
    driver=fopen("/dev/ads1278","r+");
    i=setvbuf(driver,NULL,_IONBF,0);

    //2. approach------------------

    driver=open("/dev/ads1278",O_RDWR | O_DIRECT);
    //-----------------------------------

    // 1. approach-----------------
   
    if(driver)
    {

     //2. approach------------------


     if(driver!=-1)
    {

    //-----------------------------------

        chan1=(char*)memalign(2*4096,100+4096);
        chan1+=4096;
        chan2=(char*)memalign(2*4096,100+4096);
        chan2+=4096;
        chan3=(char*)memalign(2*4096,100+4096);
        chan3+=4096;
        chan4=(char*)memalign(2*4096,100+4096);
        chan4+=4096;
        while(1)
        {
            // 1. approach-----------------

     
            i=fread((char*)chan1,100,1,driver);


            //2. approach-----------------           

            i=read(driver,chan1,100);

            //-----------------------------------

            (here I print out the buffer with "printf(...")

        }

    }

}

My configuration: TAO-3530 Board from Technexion, "uname -a" gives me:

Linux taodemo 2.6.32 #1 Tue Jul 5 14:06:07 CEST 2011 armv7l unknown

It's an Angstrom Linux distribution.