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.