-
Notifications
You must be signed in to change notification settings - Fork 11
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.
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. |
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.
PRU ELF machine code previously was arbitrarily chosen to be EM_PRU=0xfebc. Now both PRU-GCC and TI toolchain use 0x90.
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) |