gdbserver shared library PRU loader

Hi All,

I'm running Arch Linux on my BBB, so no remoteproc for me :-( when working with the PRU.

In my setup I'm developing a shared library that loads a simple PRU program via a unittest to verify if it works. Because I work with prussdrv the program should be run with sudo. If that it is the case the shared library can't be found, so I have to export LD_LIBRARY=../lib/ for my super user. Now debugging works for unit test, but as soon as I have to step into the code of the shared library, it doesn't show the code, so I can't figure out where my program hangs.

If anybody knows how to load a PRU firmware with out being root it is much preferred.

I'm currently executing gdbserver with the following command:

su --command="export LD_LIBRARY_PATH=../lib && gdbserver localhost:8080 ./runTests"

My current code is one of the most basic pieces just to load a PRU program, which toggles a pin, to drive a steppermotor, but I can't see any a pattern on my scope, so I assume it doesn't get load, which I can't verify.

Fragment of the devicetree:

Hi!

Hi All,

I'm running Arch Linux on my BBB, so no remoteproc for me :-( when working with the PRU.

You’re lucky, you didn’t waste time for testing remoteproc.

Because I work with prussdrv the program should be run with sudo. If that it is the case the shared library can't be found, so I have to export LD_LIBRARY=../lib/ for my super user.

prussdrv doesn’t need root privileges, but the user needs at least read access to the interrupt handlers (/dev/uio[0-7]).

Regarding the linker issue: did you update the cache for the run-time linker (sudo ldconfig).

Fragment of the Shared library:


```
void BBB::loadPRUfirmware(const unsigned int &number, const std::string &firmwareLocation) {
    //Initialize structure used by prussdrv_pruintc_intc
    tpruss_intc_initdata pruss__intc_initdata = PRUSS_INTC_INITDATA;
    //Allocate and initialize memory
    prussdrv_init();
    prussdrv_open(PRU_EVTOUT0);
    //Map PRU's interrupts
    prussdrv_pruintc_init(&pruss__intc_initdata);
    //Load and execute the PRU program on the PRU
    prussdrv_exec_program(number, firmwareLocation.c_str());
    // Wait for event completion from PRU, returns PRU_EVTOUT_0 number
    //int n = prussdrv_pru_wait_event(PRU_EVTOUT0);
    //prussdrv_pru_disable(number);
    //prussdrv_exit();
}
```

All prussdrv functions return a value (zero in case of success). What return values do you get?

Regards

Just found another issue:

Hi TJF,

Thnx for your reply. I tried the following steps:

I added the /dev/uio[0…7] to the group bbb (of which my user is a member) and gave them read right for a group.
I changed the typo
`
prussdrv_open(PRU_EVTOUT_0);

`

When I run the test as a normal user and output the return values to the cout it returns

`

prussdrv_init returns: 0
prussdrv_open returns: -1
Segmentation fault (core dumped)

`

When I execute as sudo it gives the following output:

`

prussdrv_init returns: 0
prussdrv_open returns: 0
prussdrv_pruintc_init returns: 0
prussdrv_exec_program returns: -1

`

When I try to remote debug as sudo by running gdbserver as follows:

`
su --command="export LD_LIBRARY_PATH=…/lib && ldconfig && gdbserver localhost:8080 ./runTests

`

I still can’t step through my shared library code

When I run the test as a normal user and output the return values to the cout it returns

`

prussdrv_init returns: 0
prussdrv_open returns: -1
Segmentation fault (core dumped)

`

I’m not sure ATM. It may also need write access for the interrupt specified in function call prussdrv_open(). That's /dev/uio0 in your case. Just make them all writeable for the group, to be on the save side.

When I execute as sudo it gives the following output:

`

prussdrv_init returns: 0
prussdrv_open returns: 0
prussdrv_pruintc_init returns: 0
prussdrv_exec_program returns: -1

`

How did you generate the binary? Function prussdrv_exec_program()doesn’t handle ELF format (generated by C compilers). It only loads raw code (as generated by pasm assembler).

When I try to remote debug as sudo by running gdbserver as follows:

`
su --command="export LD_LIBRARY_PATH=…/lib && ldconfig && gdbserver localhost:8080 ./runTests

`

I still can’t step through my shared library code

Sorry, can’t help. I never used a debugger.

It seems that you installed libprussdrv local, so you don’t need ldconfig command here. (It’s used once in case of system wide installation.)

Regards

The PRU program is genereted in C with the CCS IDE, the compiler is TI V2.1.2 en the linker command file is AM335x_PRU.cmd

`

//
/
AM335x_PRU.cmd /
/
Copyright © 2015 Texas Instruments Incorporated /
/
/
/
Description: This file is a linker command file that can be used for /
/
linking PRU programs built with the C compiler and /
/
the resulting .out file on an AM335x device. /
/
/

-cr /* Link using C conventions */

/* Specify the System Memory Map /
MEMORY
{
PAGE 0:
PRU_IMEM : org = 0x00000000 len = 0x00002000 /
8kB PRU0 Instruction RAM */

PAGE 1:

/* RAM */

PRU_DMEM_0_1 : org = 0x00000000 len = 0x00002000 CREGISTER=24 /* 8kB PRU Data RAM 0_1 /
PRU_DMEM_1_0 : org = 0x00002000 len = 0x00002000 CREGISTER=25 /
8kB PRU Data RAM 1_0 */

PAGE 2:
PRU_SHAREDMEM : org = 0x00010000 len = 0x00003000 CREGISTER=28 /* 12kB Shared RAM */

DDR : org = 0x80000000 len = 0x00000100 CREGISTER=31
L3OCMC : org = 0x40000000 len = 0x00010000 CREGISTER=30

/* Peripherals */

PRU_CFG : org = 0x00026000 len = 0x00000044 CREGISTER=4
PRU_ECAP : org = 0x00030000 len = 0x00000060 CREGISTER=3
PRU_IEP : org = 0x0002E000 len = 0x0000031C CREGISTER=26
PRU_INTC : org = 0x00020000 len = 0x00001504 CREGISTER=0
PRU_UART : org = 0x00028000 len = 0x00000038 CREGISTER=7

DCAN0 : org = 0x481CC000 len = 0x000001E8 CREGISTER=14
DCAN1 : org = 0x481D0000 len = 0x000001E8 CREGISTER=15
DMTIMER2 : org = 0x48040000 len = 0x0000005C CREGISTER=1
PWMSS0 : org = 0x48300000 len = 0x000002C4 CREGISTER=18
PWMSS1 : org = 0x48302000 len = 0x000002C4 CREGISTER=19
PWMSS2 : org = 0x48304000 len = 0x000002C4 CREGISTER=20
GEMAC : org = 0x4A100000 len = 0x0000128C CREGISTER=9
I2C1 : org = 0x4802A000 len = 0x000000D8 CREGISTER=2
I2C2 : org = 0x4819C000 len = 0x000000D8 CREGISTER=17
MBX0 : org = 0x480C8000 len = 0x00000140 CREGISTER=22
MCASP0_DMA : org = 0x46000000 len = 0x00000100 CREGISTER=8
MCSPI0 : org = 0x48030000 len = 0x000001A4 CREGISTER=6
MCSPI1 : org = 0x481A0000 len = 0x000001A4 CREGISTER=16
MMCHS0 : org = 0x48060000 len = 0x00000300 CREGISTER=5
SPINLOCK : org = 0x480CA000 len = 0x00000880 CREGISTER=23
TPCC : org = 0x49000000 len = 0x00001098 CREGISTER=29
UART1 : org = 0x48022000 len = 0x00000088 CREGISTER=11
UART2 : org = 0x48024000 len = 0x00000088 CREGISTER=12

RSVD10 : org = 0x48318000 len = 0x00000100 CREGISTER=10
RSVD13 : org = 0x48310000 len = 0x00000100 CREGISTER=13
RSVD21 : org = 0x00032400 len = 0x00000100 CREGISTER=21
RSVD27 : org = 0x00032000 len = 0x00000100 CREGISTER=27

}

/* Specify the sections allocation into memory */
SECTIONS {

/* Forces _c_int00 to the start of PRU IRAM. Not necessary when /
/
loading an ELF file, but useful when loading a binary */

.text:_c_int00* > 0x0, PAGE 0
.text > PRU_IMEM, PAGE 0
.stack > PRU_DMEM_0_1, PAGE 1
.bss > PRU_DMEM_0_1, PAGE 1
.cio > PRU_DMEM_0_1, PAGE 1
.data > PRU_DMEM_0_1, PAGE 1
.switch > PRU_DMEM_0_1, PAGE 1
.sysmem > PRU_DMEM_0_1, PAGE 1
.cinit > PRU_DMEM_0_1, PAGE 1
.rodata > PRU_DMEM_0_1, PAGE 1
.rofardata > PRU_DMEM_0_1, PAGE 1
.farbss > PRU_DMEM_0_1, PAGE 1
.fardata > PRU_DMEM_0_1, PAGE 1
.resource_table > PRU_DMEM_0_1, PAGE 1
}

`

It generates an SonarArray.out see attachment.

SonarArray.out (28.2 KB)

That doesn’t work. You’d have to extract the .text section from that file and load only that data with function prussdrv_exec_program().

Better use pasm assembler. You won’t have to deal with all that overhead.

Regards