PRU_ICSS vs PRU_ICSSG wrt GPIO and bi-directional communications

I have an extremely time-sensitive application that is perfect for a PRU…communicating on a memory bus. However it requires bi-directional communication. And it was my understanding when I researched this years ago with the PRU_ICSS that to do this correctly, each pin would have to be doubled…one for input, one for output. And because GPOs can’t be “disconnected”, an external device would be required to sever the GPO pin from the actual bus during times when the PRU isn’t transmitting on the bus.

The TI TXS0108E 8-Bit Bi-directional, Level-Shifting, Voltage Translator seemed perfect for this task since it can both level-shift between a 3.3v (BB) and 5v (the actual bus) domain as well as connect/sever the two via an enable-pin.

The downside is this takes up double the number of pins necessary to communicate on the bus. And given this bus is a parallel bus, there’s 8 lines that require bi-directional behavior (a number of other control lines also need to be monitored, but don’t require bi-directional control). Fortunately there’s enough pins on the BB headers to accommodate this. But this limits the other peripherals that can also be used since so many pins are consumed.

When I started reviewing the BBAI-64 and realized it has the upgraded PRU_ICSSG, I decided to educate myself on the differences. Document searches led to TI training videos…one suggests that when a PRU is configured for GPO output, it now has the ability to put the GPO into bi-directional mode and control the direction via the PRU’s DIGIO_DATA_OUT_EN register.
Youtube>Programmable real-time unit for gigabit industrial communication subsystem: cores, I/O & peripherals
The link should jump you right to ~3:30 (mm:ss) where this topic is discussed.

Is my interpretation correct that when using a PRU_ICSSG, GPIO pins intended for bi-directional COMs no longer need to consume 2 pins, and instead each GPO mapped to the PRU can be changed from output to input, on the fly, depending on whether the PRU intends to transmit or receive?

That certainly seems like what they are saying. But I thought maybe I better ask the question just to make sure there isn’t more to the story and possibly get some references to where this is discussed, in more detail, in documentation.

More importantly, has anybody actually done something similar to this with a PRU_ICSSG and thus can affirm that this is, indeed, the case that GPOs can now be bi-directional?

1 Like

Yes, PRU_ICSSG (as well as PRU_ICSS) can provide floating (bi-directional) GPIO by switching the DIGIO_DATA_OUT_EN register. This register is in GPIO-SS and doesn’t work on fast (direct) PRU-GPIO. The line has to get controlled by the GPIO-SS (via L3 bus), which means a latency of at least 3 cycles (depending on the L3 bus load).

Find an example in project, where a bidirectional line is used for one-wire communication.


Good to know.

And I’m surprised to hear that what you are describing is a feature of PRU_ICSS. The video on PRU_ICSSG was presenting it as though it was new functionality for the G version. Maybe that was just my wrongful interpretation of the video presentation?

So here are my followup questions:

-When you fiddle with the DIGIO_DATA_OUT_EN, can you select specifically which GPOs you want to float (i.e. leaving other GPOs active and driving their pins)?

Knowing that this register is in the GPIO_SS should help me to find more info about it in documentation. I was thinking it was a register of the PRUs.

Also good to know there’s that potential 3 cycle latency. For my purposes, 3 cycles is probably OK since the protocol does have “settling time” built into the timings when the direction of lines changes. But if that’s a minimum, I’d need to experiment with how loaded the L3 tends to get. I do expect to make relatively good use of the mailbox subsystem to pass Tx/Rx data-messages between the PRUs and the Processors. That traffic, I’m assuming would also be traversing the L3, and while it won’t be excessive, it will be present and thus adds some non-determinism to the system that will have to be tested for.

-The use of bi-directional leads me to assume that when GPOs are put into a floating state and are driven high/low by external means (i.e. other devices on the bus), the PRUs can READ the GPO pins for current state as though they are GPIs?

If the answer is YES to both of these, then I think this is something I can make use of to optimize my pin consumption. Unfortunately it doesn’t eliminate the need for the TXS0108E to perform level-shifting of the line voltages. But it might mean I don’t need to manage its Enable pin…another GPO I can reclaim.

I didn’t watch the video.

A floating line needs writing/reading registers in a GPIO-SS. This can be done by each cpu on the L3 bus (PRU, ARM, DSP, …).

Each GPIO-SS controls 32 lines. There’s one bit [0-31] for each line in the related read/write/data-out registers. So yes, some lines can float while others stay unchanged. You should take care that all lines are at the same GPIO-SS [0-3] (in order to control the paralel interface by a single register operation).

The rpmsg concept is not designed for real-time applications. Using UIO driver instead will speed up your development by making the timing in your application more predictable/reliable.


Meanwhile I watched the video. Here’s what I seem to understand:

Each PRU has fast GPIO lines (1 cycle latency) controlled by R30/R31.

In addition both PRUs can use the DIGIO block in the IEP module (constant 2 cycles latency). This block contains 8 digital lines controlled by data in/out registers (in a similar manner as in the GPIO-SS). In the new PRU_ICSSG hardware that block is extended by a further register named PRUSS_IEP_DIGIO_DATA_OUT_EN, in order to use those eight lines in floating mode.

So all PRUs can control floating lines by GPIO-SS with L3 latency, up to 32 lines simultaneously. In addition the new PRU_ICSSG can control eight floating lines with a fixed 2 cycle latency.


I did something similar to bit-bang a 4mhz three wire spi interface on the BBAI.
You need to clear the STANDBY_INIT on PRU startup;

then whenever you want to flip I/O, Change the MUXMODE & INPUTENABLE bits in the CTRL_CORE_PAD_XXXX_NN register for the pin you are trying to change.

for the BBAI I was changing pr1_pru1_gpx5 which connected to ball F5 and P8_18 on the BBAI header.
register CTRL_CORE_PAD_VIN2A_D8 on pg 4693 of the AM572x TRM
map the physical address shown in TRM of the register to a variable.

change the MUXmode register bits 0-3

0xC pr1_pru1_gpi5 input
0xD pr1_pru1_gpo5 output

toggle bit 18 VIN2A_D8_INPUTENABLE to set input or output
1 = recv enable
0 = recv_disable

Hope this helps

I’m looking through the code in this example, and I’m focusing on the PRU interaction code.

The two places that are of most interest to me are the pruw1 struct which seems like a quite competent struct for doing PRU interactions with. Is this something you invented for this project or is this part of some API for interfacing with PRUs?

And I’m also getting the feeling that this is not the actual C-code that’s running on the PRU, but rather the higher level processor code that interacts with the PRUs. If that’s correct, where is the PRU-code (asm or c)? I don’t see it as part of the code in this project or I don’t know what I’m looking for.

In the pruw1.h, there’s a declaration for what appears to be a prototype constructor & destructor declaration for these structs. However I’m not finding the actual implementation of these prototype declarations. The syntax used in the comments suggests this would be in C++…which also follows as these are described as constructors and destructors. But I don’t see any .cpp files in the project.

I’m thinking maybe there are library files you are linking against and possibly referencing in your cmake config files. But I’ve got very little experience with cmake so it doesn’t take much for me to get lost in those files and miss something.

I got TI’s CCS setup and I’m able to setup a PRU project which knows how to interact with the PRU cross-compiler right from within CCS (TI’s modified version of Eclipse). I tried to use vanilla Eclipse CDT, but it really didn’t like my trying to add a non-gcc compliant toolchain, and trying to call the clpru compiler as a gcc compiler generated a lot of warnings & errors AND it didn’t even recognize the .c file it was being given to compile and link. But CCS has TI-specific Eclipse configuration to understand a Project is targeting a PRU and to use the PRU compiler AND call it correctly. I did have to fool CCS into believing I’m compiling for a microcontroller that TI advertises has a PRU. The J7/TVA processors aren’t listed at all, even for C/C++ development, which I find a little annoying.

Once I get all my pre-requisite setup, maybe I can actually start typing out some starter code to run on the BBAI64.

I also got the ARM cross-compiler installed on the BBAI64 itself so if I need, I can make PRU code edits and recompiles right from the BB.

This leads me to yet another question. How do I single-step debug code running in the PRU? I’ll post this as a separate/new thread if I can’t find the answer searching.

In CCS when doing a new project can you not select “J7231E_DRA829_TDA4VM” from the second target type drop down ?

On my setup that lest me target any of the internal processors

Now that I’m back home, I’m trying it again, and at first, I still didn’t see that in the list.

However if I clear the 1st list OR set it to Auto, then I see that show up. Thanks for pointing that out, one so my post isn’t spreading misinformation, but also so I know. I’ve updated my project as you see above, so I should be good to go now.

1 Like

Searching around the forum, I found this post which contains C-code intended to execute on the PRU:
PRU DMA example w/ HUB75 matrix dithering

While my needs aren’t really similar enough for me to use this code outright, I found it exceptionally helpful since it made reference to various .h files that I was confident existed, I just didn’t know where to find them. I hope this info is documented somewhere, but there’s a LOT of documentation to have to go through and an example cuts to the chase a little easier than official documentation can. Once I knew the names of those files, I could navigate to them, review them, and start getting a feel for what the various configuration and command options are, and see how they are used.

Having examples like this saves so much time when it comes to overcoming the early boilerplate requirements of a new project and why contributors on forums like this are so valuable.

1 Like