Is it possible with libpruio to prepare some data to be shifted out at multiple pins simultaneously? The way I see it currently is host preparing some bytes for each pin, sending them to the PRU, and then it starts shifting the data out at a predefined rate (or shifting the data in, then informing the host CPU about new input data available).
Or should I write custom PRU firmware for that?
Yes, that’s possible up to a certain degree.
When your GPIO pins are connected to multiple GPIO_SS, it’s not avoidable to face a latency between the settings.
But when all GPIO outputs (or inputs) are at the same GPIO_SS, they can get configured simultanuously. That’s up to 32 GPIO channels at once. That needs some expert understanding of the GPIO_SS internals.
In case of input you can check the GpioUdt::Raw(i)->Mix member variable to get all 32 input states at once.
In case of output you can either set the GpioUdt::DATAOUT member variable or better use the GpioUdt::SETDATAOUT and GpioUdt::CLEARDATAOUT member variables, and then transfer the new setting to the hardware registers, like it’s done in function GpioUdt::setGpioSs():
IF .DRam > PRUIO_MSG_IO_OK THEN EXIT SUB
PruReady(1) ' wait, if PRU is busy (should never happen)
.DRam = Conf(Indx)->OE
.DRam = Conf(Indx)->SETDATAOUT
.DRam = Conf(Indx)->CLEARDATAOUT
.DRam = Conf(Indx)->DeAd + &h100
.DRam = PRUIO_COM_GPIO_CONF SHL 24
In case of CLEAR/SET registers you’ll face one PRU cycle (1/200 MHz) between clearing and setting the states.
Edit: I should’ve mentioned that this is documented in the Tips and Tricks page at
Ok, thank you.
And is it possible with libpruio to preload a bit sequence to be shifted out at a certain bit rate?
Like, shift out 11011001111100… at a certain pin.
The PRUSS have such a feature (no reason to wrap it by libpruio).
Find details in the AM335x PRU-ICSS Reference Guide in chapter
188.8.131.52.4.2 Shift Out
In shift out mode, data is shifted out of pru_r30 (PRU_DATAOUT) on every rising edge of pru_r30 (PRU_CLOCK). The shift rate is controlled by the effective divisor of two cascaded dividers applied to the 200-MHz clock.
Yeah, but it seems I have to use only pru_r30 pin for that, whereas I’d like it to be configurable.
You cannot use GPIO_SS, since you’ll face unpredictable OCR port latency. So you’re limited to fast PRU-GPIO.
If you want hardware support you’re configurable between P9_31 and P8_45. Discuss details with the CPU manufacturer.
I’m fine with my options being limited to fast PRU GPIO. But hardware support on two pins only is quite restrictive in my opinion. Does libpruio support similar software-based mode of operation for other PRU GPIO pins?
libpruio supports pinmuxing for all fast PRU-GPIO pins. Handling the pins state is the task of custom firmware (which can get loaded and started by libpruio).
Could you please share an example of how this is going to work?
Libpruio description says:
libpruio software runs on the host (ARM) and in parallel on a Programmable Realtime Unit SubSystem and controls the CPU subsystems
If I overwrite libpruio part which runs on PRU with my custom firmware, how can libpruio keep working?
Or do you mean I should write my firmware for PRU and use libpruio only for loading it?
There’re two PRUSS, one for libpruio (if needed) and the other for your custom firmware.
In example pruss_toggle libpruio measures the pulse train generated by custom firmware on the other PRU.
In example pruss_add libpruio is only used for loading and starting firmware (its main loop isn’t running).
So write your firmware for any PRU, loading and starting it by libpruio (CTOR configured to the other PRU). If you need libpruio features then start its main loop by calling PruIo::config() (running on the other PRU).