As mentioned, you can't really tell what a compiler is going to turn your C code into. As you discovered, the v2 code that is actually more suited to the PRU low-level assembly instructions turns into worse assembly because of the compiler. I suspect you have at least two problems with your code:

1) You are on the edge of having enough time to capture all the clocks even with the "better" assembly produced by v1 of the C code.

2) You may be encountering problems with noise or metastability with your code which looks for the clock edges. It's not at all uncommon to have an occasional glitch which could be why the v1 code isn't working reliably.

I *HIGHLY* recommend you code this in assembly, and add a small bit of filtering to the clock signal (eg: require the clock signal to be the same for two or more clocks before detecting the edge).

On 12/8/2018 3:11 PM, Fred Gomes wrote:
Hi Charles, thank you very much for your answer,

I followed your advice but something overly odd is happening.

First of all, let me contextualize you: the image sensor is always sending data through the CS, SCLK, and MOSI pins. The delay between each frame is about 10 ms. That said, I wrote the code in attachment "prog_pru_v1". In the first stage, I test it using the another PRU from beagle bone. So, I send some clocks from PRU 1 and count them on the PRU1; here I checked that the PRU can get all the pulses up to a frequency clock of 20 MHz (I only need 10 MHz). The problem comes when I shortened the delay time between frames, it stops catching all the clocks (in fact, it catches very few clocks) and I don't understand the reason since it should be in a loop (between the variation edges from the CS pin.

The other problem I did (prog_pru_v2.c) seems to work a bit better. It sometimes catches all the clocks from the sensor and fails another times. Surprisingly, the assembly code seems to be much uncluttered on this code.

I can't understand why is this happening, it doesn't seem to have much sense. I validate the code successfully, but the problem comes when I start sending much data spaced about 10 ms!

Find attached the code programs mentioned above, both the .c code and assembly.

Let me know if you have any other suggestion I should test,

Bets regards,
-- Fred Gomes



Charles Steinkuehler <[email protected] <mailto:[email protected]>> escreveu no dia sexta, 7/12/2018 à(s) 13:47:

    On 12/7/2018 3:52 AM, Fred Gomes wrote:
     >
     > Here's the code where I got the better results:
     >
     > while(__R31&cs); // CS = 1
     >
     > while(__R31&sclk){ //sclk = 1
     >
     > if(__R31&cs){
     > goto END;}
     > }
     > while(!(__R31&sclk)); //SCLK = 0
     > var =  (__R31&miso)? var |(0x01 << shift): var;
     >
     > k++;
     > shift--;
     >
     > if(shift == -1){
     > *(buffer_shared + cnt) = var;
     > cnt++;
     > shift=31;
     > var = 0;
     > }
     > END:
     > *(buffer_shared+2600) = k; // Here I am storing the value of the
    counter,
     > to check if all the clocks wre catched.
     >
     > I have only one small problem though, the sensor is sending data
    every
     > time, and sometimes it catches more than one frame. I don't
     > understand quite well why is it happening since the time between
    frames is
     > about 10 ms, and in that why it is difficult to have sure that I
    haven't
     > miss clocks in the frame. So, to have sure I am not missing
    clocks I add
     > the following line:
     >
     > LABEL:
     > if(k==79184)
     > goto END;
     >
     > And I noticed that sometimes I miss one clock (although here I am
     > introducing one extra instruction, which will make the program a
    bit slow).
     > If you have any suggestion I should implement to tackle this problem,
     > please let me know ...

    Again, please either write in assembly or post the assembly listing
    the compiler is generating.  You have 12 lines of C code above, and
    that doesn't even look like the entire loop (just the inner loop for
    one 32-bit word).  As mentioned previously, you have time for about 20
    PRU assembly instructions, which isn't many for 12 lines of C.

    Without the full code and seeing the assembly your compiler is
    generating, I can only make a few suggestions.  An optimizing compiler
    would probably do much of this for you, but it doesn't sound like your
    compiler is doing much optimization (again, let's see some listing
    files!):

    * Get rid of the count variable and create a dedicated buffer pointer,
    then increment that, ie:

       *(buffer_shared + cnt) = var;
       cnt++;

       ...turns into:

       // Initial setup
       uint32_t *buffer_ptr = buffer_shared

       // ...other code goes here...

       *(buffer_ptr) = var;
       buffer_ptr++;

    * Review the generated code for the var update.  The PRU has lots of
    bit test and shift instructions, so changing this calculation slightly
    could reduce the number of instructions needed.  If I was writing in
    assembly I would shift var first then conditionally or in a '1'
    depending on the state of the input pin.  In C it would look like this
    (but I don't know if this will generate the actual assembly I'm
    thinking of, it depends on your compiler):

       var >>= 1;
       if (__R31&miso) var |= 0x8000;

    * Review the code generated for the various bit test instructions (eg:
    __R31 & <val>).  These should be a single bit test instruction in PRU
    assembly, but that may not be what the compiler is generating.

    There are other "tricks" you can try (eg: get rid of the shift count
    and use a bit in var instead).  Without being able to see the
    generated assembly you can easily wind up making things much worse,
    but you can try it if you like.  Make sure to initialize var to 0x8000
    and set the buffer_ptr value in your setup code:

    while(!(__R31&sclk)); //SCLK = 0

    k++;  // I assume this is needed outside the loop

    // 1 in the LSB means this is the last bit of our 32-bit word
    if (var & 0x01)
    {
             // Shift in the last bit
             var >>= 1;
             if (__R31&miso) var |= 0x8000;

             // Store the value
             *(buffer_ptr) = var;

             // Setup for the next word
             buffer_ptr++;
             var = 0x8000;
    } else {
             // Shift in the next bit
             var >>= 1;
             if (__R31&miso) var |= 0x8000;
    }

-- Charles Steinkuehler
    [email protected] <mailto:[email protected]>

-- For more options, visit http://beagleboard.org/discuss
    ---
    You received this message because you are subscribed to a topic in
    the Google Groups "BeagleBoard" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/beagleboard/Vtw23FneFLk/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    [email protected]
    <mailto:beagleboard%[email protected]>.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/beagleboard/95d14956-6dad-f1c4-fe34-7074cb4e926d%40steinkuehler.net.
    For more options, visit https://groups.google.com/d/optout.

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <mailto:[email protected]>. To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/CAJHs20z_yfufDZ227vseD4zzUiE0kUAVBG0KBJcP6UnxgGYR1A%40mail.gmail.com <https://groups.google.com/d/msgid/beagleboard/CAJHs20z_yfufDZ227vseD4zzUiE0kUAVBG0KBJcP6UnxgGYR1A%40mail.gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

--
Charles Steinkuehler
[email protected]

--
For more options, visit http://beagleboard.org/discuss
--- You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/04c5f454-b5d8-d55a-5dd3-925a28fa370d%40steinkuehler.net.
For more options, visit https://groups.google.com/d/optout.

Reply via email to