Hi guys, after a deep dive, I’ve found how to program to PRU in C (instead of Assembly). Here’s my contribution:
http://catch22.eu/omnirobot/beaglebone-pru-c/
Feel free to comment on this forum!
Hi guys, after a deep dive, I’ve found how to program to PRU in C (instead of Assembly). Here’s my contribution:
http://catch22.eu/omnirobot/beaglebone-pru-c/
Feel free to comment on this forum!
Excellent! I did a couple of projects with PRU and C code, and this type of tutorial is sorely needed.
I would add a link to this:
https://training.ti.com/pru-compiler-tips-tricks
So I wonder how common it is to use a C union and bit selector?
When I first encountered this in the PRU header files, I didn’t even think it was C code!
In fact, in the information provided by TI in the video and slides, they say it is really warped C code.
Regards,
Greg
I have a Mac and the videos work just fine for me on the Chrome browser.
Regards,
John
Updated link: http://catch22.eu/beaglebone/beaglebone-pru-c/
Hi Joseph
Nice writeup. You did a good job of explaining a complex topic…at least it seems complex to me. I have however found a possible error.
Shouldn’t you be referring to the DEFAULT_INC value rather than the CMP_INC value in your description?
Updated link: http://catch22.eu/beaglebone/beaglebone-pru-c/
I may have mentioned this before, but I think blinking a USR LED would be
far more useful. Nothing to hook up, and worry about blowing the pins on
the processor, etc. However, then we're talking about involving the L3
interconnect, which might be what you did not want to do ?
A point of contention that I have with the article however, is: How does
the GPIO bank + DATA_OUT register get into the PRU's _R30 register ? This
also has to be dynamic somehow. I can't imagine all registers r0-r31 are
each dedicated to a single control register of *something*. Then yes, I do
know that some PRU registers are reserved, I just do not know which anymore.
In another part of the article:
The issue faced here is that one has to deep-dive into the workings of the
header files, and make the relation to the defined variables in those
header files and the PRU registers defined in the Reference Manual.
Fortunately the header files and the reference manual closely match each
other. *Unfortunately, you have to do the footwork to figure it out for
each common or less common usage of the registers. For instance, here’s a
relevant section of the pru_iep.h header file for the IEP example above:*
Then you go on to show some "pictures" from various sources, most notably
the applicable registers from the TRM. My point here is, I'm not sure what
your point is. This is pretty much standard procedure when working with any
hardware on this level. That is, *IF* you really need to know for sure,
what you're doing.
So, do not get me wrong, I'm not bashing what you've done there at all.
It's a lot more than I've done in demonstrating the PRU's to the public.
Mostly due to the fact that I do not know how to use the PRU's very well at
all.
Also very glad you chose to demonstrate this using UIO, instead of remote_proc.
Hi Clark,
That’s a good catch - I’ve corrected this.
Thanks!
Updated link: http://catch22.eu/beaglebone/beaglebone-pru-c/
I may have mentioned this before, but I think blinking a USR LED would be far more useful. Nothing to hook up, and worry about blowing the pins on the processor, etc. However, then we’re talking about involving the L3 interconnect, which might be what you did not want to do ?
A point of contention that I have with the article however, is: How does the GPIO bank + DATA_OUT register get into the PRU’s _R30 register ? This also has to be dynamic somehow. I can’t imagine all registers r0-r31 are each dedicated to a single control register of something. Then yes, I do know that some PRU registers are reserved, I just do not know which anymore.
I don’t know yet either at the moment. The way I use it in the example seems to work magically per default. Risk is that is breaks though. An explanation would be helpful.
In another part of the article:
The issue faced here is that one has to deep-dive into the workings of the header files, and make the relation to the defined variables in those header files and the PRU registers defined in the Reference Manual. Fortunately the header files and the reference manual closely match each other. Unfortunately, you have to do the footwork to figure it out for each common or less common usage of the registers. For instance, here’s a relevant section of the pru_iep.h header file for the IEP example above:
Then you go on to show some “pictures” from various sources, most notably the applicable registers from the TRM. My point here is, I’m not sure what your point is. This is pretty much standard procedure when working with any hardware on this level. That is, IF you really need to know for sure, what you’re doing.
So, do not get me wrong, I’m not bashing what you’ve done there at all. It’s a lot more than I’ve done in demonstrating the PRU’s to the public. Mostly due to the fact that I do not know how to use the PRU’s very well at all.
Okay, I’ve rephrased that part a bit. Thanks for the feedback.
Ah, ok, I was afraid of that. I do know the gpio registers fairly well, so
maybe at some point I could figure that out. If I do I'll try to relay the
info to you. One thing I'm thinking could be an obstetrical, is that there
is GPIO that the PRU has direct access to, and then GPIO that has to be
accessed over the L3 interconnect. Then I noticed from your article that
the GPIO that you're using is mode 0x05, which is obviously PRU mux mode
for GPO I suppose if you're controlling an LED. So yeah . . . will be a bit
different.
lol dahm text correction got me good that time “obstacle”
Thanks Joseph for sharing your code.
I am working on a project involving real-time closed loop control with the adc of the beaglebone, using the PRUs in c:
https://github.com/l4m4re/SoakageTester
I found a pretty nice base for programming the adc’s and some other examples, which I forked and updated the adc example:
https://github.com/l4m4re/bbb-pru
Currently, that example uses a dual buffer strategy, but one can also implement a ring buffer (as I have done in my project above). I will probably add that to these examples at some point, too. With this code, I can sample two channels at 800 kS/s each and hopefully do some control processing on the PRU, too.
So far, I have only used one PRU for sampling, and the next step is to move the GPIO controls to the PRU(s) as well. When searching for examples on how to do this, how to do interrupts between the PRUs and/or how to work with the IEP timer, I found your code, and thus I found out about the header files in the pru software support package (in /opt).
So, all in all the info you shared will surely help a lot.
Best regards and thanks again for sharing,
Arend.