On Fri, Mar 24, 2017 at 9:34 AM, ags <alfred.g.schm...@gmail.com> wrote:

> @William Hermans I thought I'd share the result of my efforts to reliably
> stream data from ARM host (Linux userspace) to PRU.
>
> I instrumented the PRU ASM code to use the CYCLE register for very precise
> measurements. I ran tests that kept track of how many times, for how long,
> and the "worst offender" when the PRU was stalled waiting for data from the
> ARM host. I used this to test my current implementation using select(), and
> then replaced select() with usleep() (and nanosleep()), and then again a
> loop with no sleep, just a brute-force busy wait that never released the
> CPU. As it turns out, the results were surprising. Using usleep() (and
> similar related methods), the number of stalls, the overall stall time and
> the worst-case stall time were all significantly worse than the
> implementation using select(). Even the busy wait loop w/out sleep() was
> worse. I did a bit of research and sleep() and related methods are
> implemented using a syscall (sleep - used to use alarm in the olden-days
> (so I read)). So getting through the call gate and the context swap happens
> with sleep() just like with select(). My theory is that select() is more
> efficient precisely because of this: one call to select() incurs one system
> call/context swap per interrupt. The process is put on the NotRunning list,
> and the the OS continues on. When a trigger event happens, the OS returns
> the process to the Running list and then control back to user space. For
> the sleep() method, there are many calls per "interrupt", polling some
> memory location looking for the signal from the PRU. So what is handled by
> one userspace->kernelspace->userspace transition with select() could
> require dozens of these transitions using sleep().
>
> I don't claim to be an expert, and if there is a flaw in this theory I'm
> open to hearing what it is. But this is my theory at the current moment.
>

I've honestly no idea how you're implementing what I suggested, so I can't
really comment on what's going on. sleep() won't work though, and I'm not
sure how usleep() is implemented for your particular OS( Debian Linux ),
but usleep() on micro-controllers( bare metal ) is usually less than 10
lines of code. I want to say less than 6 lines of code, but it's been a
while since I've looked through an implementation.

Your findings are also surprising to me, but I can not help but feel that
you did not implement the busy wait loop how I expected. Or perhaps there
is something else going on that we haven't discussed. So, if you used
"interrupts" with the busy wait loop, then that's not how I intended it to
be used. The busy wait loop was to be in place of your interrupt code. But
that would explain why it could have been slower. To be sure, there are
potentially many other things that could have been culprit / co-culprit for
your given situation. It's not always easy to talk about these things at a
high level without making sure everything is understood on both sides of
the conversation. Without seeing your code, I can not really say any more,
with surety.

>
> So what I ended up doing is compress the data so that one "frame" can fit
> in PRU memory at once. The PRU needs to send a full "frame" out with
> precise timing (within microsecond timing) for all data in that frame.
> Between frames, there is slack. By compressing the data, I can load a full
> frame into the PRU0/1 DRAM and shared RAM, and then kick off writing out
> the frame. Now everything is (or appears to be) deterministic in the timing
> of all transfers between registers, scratch and PRU DRAM. So I've
> sidestepped the problem of unpredictable latency waiting for data from the
> ARM host.
>
> I hope this might help someone else with similar requirements.
>

Yeah, there is usually more way than one way to do the same thing. That's
why I mentioned data packing, as I had a feeling that it could at least be
useful for you.

-- 
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 beagleboard+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/CALHSORqqNp_JRjWBDDPKZX%2B8%2BDdnr-To5mn0R1EfRyHO-n-ktg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to