How to use PRU constants table?

Hi,

the AM335x TRM specifies a constants table for PRU which can be used for easier access of memory addresses. As an example: for I2C1 registers which originally use base-address 0x4802A000 a constant 2 is defined.

What I do not understand: how can one use these constants? How does the mapping from a constant to a base-address work where I have to add an offset in order to access desired registers?

Or is this an assembler-thingy only which can’t be used out of PRU-C-Software?

Thanks!

On Fri, 15 Jul 2016 01:41:06 -0700 (PDT), Karl Karpfen
<karlkarpfen79@gmail.com> declaimed the
following:

Or is this an assembler-thingy only which can't be used out of
PRU-C-Software?

  Off-hand... "assembler-thingy"...

Appears to be just two opcodes that make use of the constant table: the
linked Load, and the following Store,

There is an example in the PRU support package:

http://git.ti.com/pru-software-support-package

Look in the examples folder for am335x.

Regards,
Greg

Thanks, I found it in the PRU support package. But I wonder if this really saves some time/code…

The support package is just examples of how to use RemoteProc/RPMSG. Remember to use V4.02 for the V4.1 Linux Kernel and V5 for the V4.4 Linux kernel. The V4.02 uses mailbox events and the V5 uses interrupt events. If you want ARM sample code which interacts with the PRU firmware, look in the Linux source code /samples/rpmsg.

Here is how to use the PRU support package:

http://processors.wiki.ti.com/index.php/PRU_Training:_Hands-on_Labs

Regards,
John

Hi Karl,

These constants allow the C compiler to produce more efficient code. Of course you can also use them in assembly programs by explicitly using lbco/sbco instructions.

Let me give you an example how pru-gcc uses the constant table. Consider this C code snippet:

`

define MYREG ( * (volatile uint32_t *)(0x4802A000 + 0x24))

MYREG = 42;

`

Normally pru-gcc would output the following:

`
ldi r14, %lo(1208131620)
ldi r14.w2, %hi_rlz(1208131620)
ldi r15, 42
sbbo r15, r14, 0, 4

`

But you can tell the compiler that this address base is special (btw, already defined for you in <pru/io.h>):

#pragma ctable_entry 2 0x4802a000
Then the compiler can produce a much shorter instruction sequence:

ldi r14, 42 sbco r14, 2, 36, 4

TI’s compiler uses a different syntax for the constants declarations, but essentially does the same optimization.

Regards,
Dimitar

What is the declaration syntax for TI’s clpru C/C++ compiler for declaring constant entries? I tried to find where it might be documented in the PRU Optimizing C/C++ Compiler doc (spruhv7c.pdf). But it didn’t seem to make any reference to the PRU constant table. But I’m assuming it needs to know what memory addresses are in there so it can know when it can optimize.

And what include-file would those declarations be supplied in that need to make sure to include on order to ensure the compiler uses the more efficient syntax?

Bueller?

Hey Chris. This might be a little late. However I had similar questions and I believe you will find these answers in the
PRU_C_USER_GUIDE.pdf

and specifically section 5.14.4 which states the following:

5.14.4 Type Attributes
The following type attributes are supported: aligned, cregister, deprecated, packed, transparent_union,
unused, and visibility.
The cregister attribute provides support for using the constant registers. If the cregister attribute is used,
the peripheral attribute can be used along with it. The syntax is:
int x __attribute__((cregister("MEM", [near|far]), peripheral));
The name "MEM" can be any name, although it will need to correspond to a memory range name in your
linker command file. The near or far parameter tells the compiler whether it can use the immediate
addressing mode (near) or register indirect addressing mode (far). If the data will be completely contained
within the first 256 bytes from the top of the constant register pointer then use near, otherwise use far. The
default is near.
The peripheral attribute can only be used with the cregister attribute and has two effects. First, it puts the
object in a section that will not be loaded onto the device. This prevents initialization of the peripheral at
runtime. Second, it allows the same object to be defined in multiple source files without a linker error. The
intent is that peripherals can be completely described in a header file.
The linker command file must be modified for the cregister attribute to work, otherwise relocation errors
occur. See the PRU Assembly Language Tools User's Guide for details about the linker command file.
The updated linker command file syntax is:
MEMORY
{
MEM: o=xxx l=xxx CREGISTER=4
}