Hello,
We have a little program that runs in a PRU ICSS, it was working fine with SDK6 but when we moved to SDK8 it started to misbehave, even with the same binary. Funnier was that when booting with SDK6 through NFS, the firmware worked well, then rebooting (software) into SDK8, still working fine. But if the board was powered on and directly booted in SDK8, then everything stopped working. As I said, with the same binary in the PRU1_0.
We managed to debug and fix it, the problem was that there was a bunch of `static` variables that were not being init to 0. It took a few days to figure it out that, but after explicitly initing them to 0, the problem was fixed. However, according to ANSI C all statics should be init to 0 if not specified anything different, and that is also mentioned in "PRU Optimizing C/C++ Compiler" https://www.ti.com/lit/ug/spruhv7c/spruhv7c.pdf on page 119:
6.7.2.1 Zero Initializing Variables
In ANSI C, global and static variables that are not explicitly initialized must be set to 0 before program execution. The C/C++ compiler supports preinitialization of uninitialized variables by default. This can be turned off by specifying the linker option --zero_init=off.
I've checked that our Makefile doesn't have that zero_init flag, even tried passing --zero_init=on to the linker. But there is no change in the disassmebly. What could be going on here? My theory is that SDK6 (kernel v4.19) driver inits all PRU memory to zeroes, which makes it work, and while power is maintained booting into SDK8 keeps the zeroes there. And if SDK8 (kernel v5.10) doesn't init to zero, then it grabs wathever was in that memory section.
These are the disassembly excerpts regarding the "zero" variable that was supposed to be 0:
Original code (SDK6):
void main (void)
{
static uint32_t zero;
[...]
__xout (PRUSS_SCRATCH_PAD_BANK_1, R29, 0, zero);
}
This translated to this disassmebly (using ~/ti_processor_sdk_rtos_am57xx_08_01_00_09/ti-cgt-pru_2.3.3/bin/dispru ).
Here we can see that R0 is loaded with 6916 (0x1b04) and then R29 (and others) are loaded with that value, which, if I understand it correctly, is not even in the DATA section.
TEXT Section .text (Little Endian), 0x1b1c bytes at 0x0000001c 0x0000001c main: 0000001c 053ee2e2 SUB R2, R2, 62 00000020 e51482c3 SBBO &R3.b2, R2, 20, 42 00000024 241b04e0 LDI R0, 6916 # 6916 = 0x1b04 00000028 f100209b LBBO &R27.b0, R0, 0, 4 0000002c 2f05819b XOUT 11, &R27.b0, 4 00000030 10000000 AND R0.b0, R0.b0, R0.b0 00000034 f100209c LBBO &R28.b0, R0, 0, 4 00000038 2f05819c XOUT 11, &R28.b0, 4 0000003c 10000000 AND R0.b0, R0.b0, R0.b0 00000040 f100209d LBBO &R29.b0, R0, 0, 4 00000044 2f05819d XOUT 11, &R29.b0, 4 [...] # Notice that it's the same section, and that it's actually code!! 00001b04 6f00e0fc QBNE $C$L1, R0, 0 [...]
If I change the initialization in C code to zero = 0, the disassembly changes. Here are the excerpts:
TEXT Section .text (Little Endian), 0x1b1c bytes at 0x0000001c 0x0000001c main: 0000001c 053ee2e2 SUB R2, R2, 62 00000020 e51482c3 SBBO &R3.b2, R2, 20, 42 00000024 241df0e0 LDI R0, 7664 # 7664 = 0x1df0 00000028 f100209b LBBO &R27.b0, R0, 0, 4 0000002c 2f05819b XOUT 11, &R27.b0, 4 00000030 10000000 AND R0.b0, R0.b0, R0.b0 00000034 f100209c LBBO &R28.b0, R0, 0, 4 00000038 2f05819c XOUT 11, &R28.b0, 4 0000003c 10000000 AND R0.b0, R0.b0, R0.b0 00000040 f100209d LBBO &R29.b0, R0, 0, 4 00000044 2f05819d XOUT 11, &R29.b0, 4 [...] DATA Section .data (Little Endian), 0x90 bytes at 0x00001d64 [...] 0x00001df0 zero$15: 00001df0 00000000 .word 0x00000000
Here, R0 is loaded with 7664 (0x1DF0) which is referred as zero and in fact, has value 0 in the DATA section.
For now, we will stick to explicit initialization, but I am curious: Is this a linker/compiler bug? Is this a linux driver issue? Did we miss something in the configuration? Thank you very much!