Skip to content
Dimitar Dimitrov edited this page Sep 22, 2019 · 3 revisions

Overview

ABI Compatibility Between GCC And TI

PRU GCC nowadays is mostly (but not 100%) ABI compatible with the TI toolchain. When mixing GCC and TI CLPRU object files, users are required to pass the -mabi=ti option to GCC. This option guarantees that the resulting GCC code is 100% ABI compatible. If the source code contains a not yet supported code structure (e.g. function pointers), GCC will emit an error. This is in constrast to the default -mabi=gnu option, which implements all C language features but breaks a few ABI rules.

The TI PRU C ABI is described in http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf , section 6 "Run-Time Environment". Below are pointed only the differences between GCC PRU and TI PRU C.

ABI Item TI PRU C PRU-GCC Mitigation
Pointers to text segment. Pointer size is 16-bit. All pointers, including function pointers, are 32-bit. User may pass -mabi=ti to prevent GCC from emitting code using function pointers.
Return of a large (>64bit) value. Caller may optionally pass NULL pointer for the return value storage. Caller must always pass a valid data pointer for the return value storage. User may pass -mabi=ti to prevent GCC from emitting code for functions returning large values.
ELF text start address. Both text and data start at address 0. Data addresses start from 0. Whereas PMEM addresses are mapped to text address 0x20000000. Patch the remoteproc kernel driver (see below).
DWARF debug info. Not tested against TI debuggers. Currently cannot relocate TI-generated debug sections. No mitigation available for the moment.

Some examples use the old UIO pru loader. Remoteproc kernel driver requires a small patch in order to load binutils PRU ELF firmware images. See examples' issue #2 for more information.

Other Differences

There are a few other differences between GCC and TI CGT, regarding syntax and support of features:

Item TI PRU C PRU-GCC
Optional label operand marker. `
Text labels in assembler. $CODE(text_label) Assembler programmers must mark all text labels with %pmem(__label__). Internally linker uses byte-addressing for text segment, so this explicit macro is needed to convert the byte-address to word-address.
Near/far data pointers. Supported. Not applicable. Symbols are loaded with LDI32, which can be relaxed by linker.
Intrinsics, e.g. __xin,__xout,. Supported. Planned to be supported, either via __builtin or inline assembly macros.
C++ Supported. Preliminary support. Not tested much.
Endianness. Both supported. Only little endianness supported.
PRU core versions. All supported. Only silicon version 3 is supported. AM33xx has been tested, but AM437x and AM572x and AM65x should also work.
__R30/__R31 builtin variables. Supported. Similar functionality available via read_r30/write_r30/read_r31/write_r31 macros from <pru/io.h>.
Data variables initialization. Both --rom_model and --ram_model supported. PRU GCC/Newlib CRT supports only load-time variable initialization (equivalent of TI's --ram_model)
cinit ELF section. . Supported. N/A because --rom_model is not supported.
fardata ELF section. Supported. Not supported. Not needed since GNU LD supports LDI32 relaxation.
C++ exceptions. Supported. Not supported.
C++ RTTI. Supported. Not supported.

PRU ELF file format

GNU LD places the DATA segment at offset 0x0. TEXT segment is put by LD at offset 0x20000000. The PMEM byte address can be calculated by masking bits 29-31 of the TEXT segment address. This is in contrast to the TI linker which places both DATA and TEXT at offset 0x0.

Other Notes

PRU ELF machine code previously was arbitrarily chosen to be EM_PRU=0xfebc. Now both PRU-GCC and TI toolchain use 0x90.

TI ELF PRU Relocations

Binutils mostly follows the TI ELF relocations. Binutils implement a few more relocations to allow ELF file relaxation.

Current Binutils/GCC equivalent TI ID example generator for this relocation
???? 1 Debug REL relocation.
PRU_16_PMEM 5 .2byte %pmem(text_label)
PRU_U16_PMEMIMM 6 jmp text_label; ldi r0, %pmem(text_label)
BFD_RELOC_16 8 .ushort data_label ; 2 bytes
PRU_U16 9 ldi r0, data_label
PRU_32_PMEM a .4byte %pmem(text_label)
BFD_RELOC_32 b .uint data_label ; 4 bytes
PRU_S10_PCREL e qbeq text_label, r1,r2
PRU_U8_PCREL f loop text_label, r0
PRU_LDI32 12 ldi32 r0, data_label
---------------------------------- ------- -------------------------------------------
BFD_RELOC_8 64 .byte data_label_1
PRU_GNU_DIFF8 65 .byte data_label_1 - data_label_2
PRU_GNU_DIFF16 66 .2byte data_label_1 - data_label_2
PRU_GNU_DIFF32 67 .4byte data_label_1 - data_label_2
PRU_GNU_DIFF16_PMEM 68 .2byte %pmem(text_label_1 - text_label_2)
PRU_GNU_DIFF32_PMEM 69 .4byte %pmem(text_label_1 - text_label_2)