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.

GPMC bus randomly does not work

Dear all,

I am using the GPMC bus to read data from an FPGA FIFO. I use async read of 16-bit data. In particular, when a fraction of a long-long FIFO is full, I send a signal (active high) to the ARM. This signal goes to a GPIO pin which is monitored by the ARM. When the ARM see that signal high, it starts a read cycle. In Fig.A, it is possible to see how it works: the yellow signal is the signal sent from the FPGA to the ARM to say that a fraction of the FIFO is full. After a while, the ARM starts a read cycle (which is the green line). The time-length of the read cycle is decided by me using:

if (gpio_get_value(gpio))  {   memcpy(p,extbus,256);  }

where:

-> gpio_get_value(gpio) is the function monitoring the GPIO state

-> memcpy(p,extbus,256) is the function coping the GPMC bus on a variable p and 256 is the length of the copy (which is fixed).

Normally it works and if a try to do several read cycles, I obtain something shown in Fig. A :

1) a fraction of the FIFO is filled (e.g. one third)

2) a signal is sent to the ARM to say that a fraction of the FIFO is filled (yellow goes high)

3) the ARM see that signal and starts to read

4) in the meanwhile, the signal coming from the FIFO (yellow) goes down because now the fraction of the FIFO filled is less than one third.

Sometimes happens something like FIG. B : the read cycle (which should be fixed: it is the number -256- written in the memcpy) randomly stops to work after a few reads (see the green path which stops after a few reads). Only after a while, it finishes the read cycle doing the remaining reads. Summarizing:

1) a fraction of the FIFO is filled (e.g. one third)

2) a signal is sent to the ARM to say that a fraction of the FIFO is filled

3) the ARM see that signal and starts to read

4) in the meanwhile, the signal coming from the FIFO goes down because now the fraction of the FIFO filled is less than one third

5) the ARM stops the read cycle for a while (for a reason that I do not understand)

6) in the meanwhile the FIFO is filled for one third again

6) the ARM starts again to read doing the remaining reads

If I try to sum the reads of the Fig. B I obtain 256, which means that it does the full read cycle.

Now, I know that there are better solution in terms of starting the read cycle (I could use a GPIO interrupt etc..etc) but this is not a problem for me. I would like to understand why it stops to read.

Possible question:

-> Are you sure that the FIFO is working correctly?

Yes: I did several tries to check it and it seems to work.

I thing it to be a problem coming from the ARM.

Do you have any ideas?

Thanks a lot.

Alberto

N.B : GPMC clock = 100 MHz

  • Hi Alberto,
     
    What software are you using? Where is the FIFO signal connected? Have you considered, on the FPGA side, to drive the FIFO signal low after 256 reads have been done?
  • Hi Biser,

    as always, thanks for your reply.

    1) Software : I am using a C software written by me.

    2) The FIFO signal is connected to the GPIO 30.

    3) The FIFO signal goes low automatically when the location filled in the FIFO are less than a given number.

    We can suppose to have a FIFO with N locations. The signal goes high when M locations of those N locations are filled. When the first M locations are filled, the signal goes high. In the meanwhile, the FPGA goes on filling the FIFO.  After a while the ARM see that GPIO signal and starts to read: the FPGA is writing on one side and the ARM is reading on the other. The reading side is faster than the writing side (I decided to write slower to avoid to have the FIFO full at some point). I said to the ARM to read M locations (and I am pretty sure that when it works, it reads exactly M locations).

    As soon as the FIFO locations filled are M-1, the signal coming from the FIFO goes down automatically: I do not need to drive it. In the meanwhile, the ARM should goes on doing the M reads. As it is possible to see in the Fig. B of the previous post, there is a stop in the read cycle after T reads (which are much less than M -> see the red circle in the picture). As a consequence, the FIFO signal goes again high (because the FPGA is going on writing the FIFO and M locations are filled again). Only after a dead time, the read cycle re-starts doing the remaining M - T reads.

    The software part is:

     while(j){                                                                     // while cycle to do a decided number of reads cycle (j);
                 if (gpio_get_value(gpio) ){                                // if condition to check the GPIO 30 value:
                     my_memcpy(p[k],extbus,256);                   // when the if condition is ok is starts a 256 long read.
                     k++;                                                        // As soon as that condition is passed, it should  
                     j--;                                                           // do a 256 long read, no matter what.
                 }                                                                 //  What I see on the oscilloscope is that the if condition
        }                                                                         // is passed because it starts a read but it does not do                                                                                            //  a full read but only a "partial" read which is complited                                                                                       //  only after a while.                                        

    Alberto

  • I can't very well say what's happening. You may need to do some debugging. It seems that your program is interrupted by something, but I don't think this is the GPMC itself.
  • Hi Biser,

    Maybe I got it: when I use the function

      if (gpio_get_value(gpio) ) {......}, I am doing (by using C) something like /sys/class/gpio/gpio30/value 

    and it seems to be really expensive in terms of %CPU. By doing "top" in a linux shell, I see 97.2% CPU only for my C program which is quite a lot.I cannot go on in that way.

    So, now I am trying to map the memory to check that GPIO pin. But here I have another problem (if I have to open a new thread for that, just ask):

    I open the GPIO communication in read mode and I try to map that pin by using:

    base GPIO0 address        -> 0x44e07000;

    DataIn address   offset      -> 0x138

    Then I am doing a cycle checking that pin:

    while(j){
                printf("Register = %x \n",*(0x44e07000 + 0x138) );

    }

    Now, it takes only the first value and it prints always it. If the voltage of the pin changes, it does not see it.

    e.g.:

    Real Value                     Printed Value

    A                                         A

    A                                         A

    B                                         A

    A                                         A

    B                                         A

    B                                         A

    B                                          A

    If I try to do:

    while(j){
                printf("Register = %x \n",*(0x44e07000 + 0x138) );

                sleep(1);

    }

    it sees the correct value when it changes.

    e.g. :

    Real Value                     Printed Value

    A                                         A

    A                                         A

    B                                         B

    A                                         A

    B                                         B

    B                                        B

    B                                         B

    Where I am wrong?

    Alberto

  • Hi Alberto,
     
    The high CPU usage you are seeing can be explained by the while (j) cycle. The MPU is constantly cycling in this loop and checking the condition. I think the best approach would be to implement a GPIO interrupt for the FPGA FIFO signal, which can be configured to be edge sensitive. Then you can use this interrupt to trigger the 256 bytes read.
  • Hi Biser,

    bad news: it seems that does not change so much in terms of %CPU by doing:

    while(j){
                if(*(gpio_interrupt) != 0) {
                                                                    printf("Transistion \n");
                                                                    j--;
                                                   }
                 }

    where gpio_interrupt is a pointer to the memory address containing the interrupt information...

    The %CPU is again 99% . If I have to do just one "256 reads" cycle, the %CPU is negligible, but if I want to do more cycles (by using a while cycle..I have no other ideas about how to do that...), I obtain 99%CPU.

    Now I really have no idea about how to fix it....

    Alberto

  • Hi Alberto,
     
    I am afraid that I can't help with structuring your program. Maybe you should move the 256 reads cycle and j++ in an ISR that is fired by the GPIO interrupt.