This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM2634: PRU-ICSSM firmware generation for PRUICSS drivers - problem with _c_int00* function.

Part Number: AM2634
Other Parts Discussed in Thread: PRU-CGT

Hi,

I am trying to export compiled code in a c-array that I can flash from ARM-R5F on PRU-ICSSM with PRUICSS_writeMemory() function. For that, I am trying to use the hexpru.exe tool that is included in PRU-CGT.

I have facing an issue with the entry function _c_int00_noinit_noargs that is not included into my export using hexpru.exe. First, to explain my issue, let's start from the start. To link my firmware, I use the following sections definition (based on TI examples):

[...]

/* 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		>  PRU0_DMEM_0, PAGE 1
	.bss		>  PRU0_DMEM_0, PAGE 1
	.cio		>  PRU0_DMEM_0, PAGE 1
	.data		>  PRU0_DMEM_0, PAGE 1
	.switch		>  PRU0_DMEM_0, PAGE 1
	.sysmem		>  PRU0_DMEM_0, PAGE 1
	.cinit		>  PRU0_DMEM_0, PAGE 1
	.rodata		>  PRU0_DMEM_0, PAGE 1
	.rofardata	>  PRU0_DMEM_0, PAGE 1
	.farbss		>  PRU0_DMEM_0, PAGE 1
	.fardata	>  PRU0_DMEM_0, PAGE 1
}

So, the .text section starts with the entry c-function. Then, when I compile my program, I get the following section allocation map:

[...]

SECTION ALLOCATION MAP

 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
.text:_c_int00* 
*          0    00000000    0000001c     
                  00000000    0000001c     rtspruv1_le.lib : boot.c.obj (.text:_c_int00_noinit_noargs)

.text      0    0000001c    00001568     
                  0000001c    00000590     myObj.obj (.text:myObj_Exec)
                  000005ac    000001fc     myobj2.obj (.text:myobj2_Cfg)

[...]

So my code is correctly mapped with the entry function at address 0x0 and my own code starting at address 0x1c (as expected according to my linker script).

Then, I use hexpru.exe with following command: hexpru.exe myBuild.out -o myBuild_hex.out hexpru.cmd. hexpru.cmd is then (taken from MCU+SDK AM243x examples):

-b
-map=pru_project.map
SECTIONS {.text}

Unfortunately, hexpru does not detect .text:_c_int00*  as part of .text section and it will not be included into my hex file...

I tried the opposite in hexpru.cmd, instead of defining which section has to be exported, I say which one must not be exported and I ended up with that export command file:

-b
-map=pru_project.map
--exclude=.binit
--exclude=.cinit
--exclude=.data
--exclude=.fardata
--exclude=.init_array
--exclude=.ovly
--exclude=.rodata
--exclude=.rofardata

With this version of export command file, I can generate a hex-file that contains my whole code and then, I can export it to a header file with hex2header.exe that is included in MCU+SDK (and it works!).

Therefore, my question is how I can modify my linker script or my export script to get a working hex-file to flash from Cortex-R5F? I would prefer to list the sections I want to export than listing all sections I don't want to export (makes more sense).

Thank you for your help.

Regards, Nicolas

  • Hi Nicolas,

    I'm looking into this and will get back with you shortly.

    Regards,
    Frank

  • Hi Nicolas,

    Sorry for the delayed response.

    I experimented a bit with the AM243x example empty_am243x-evm_icssg0-pru0_fw_ti-pru-cgt.

    I verified your findings:

    • .text:_c_int00* is included in the .out file
    • .text:_c_int00* is not included in the .b00 file.

    Is your firmware written in C or assembly language?

    I notice the functions in.text:_c_int00* setup the C run-time environment and then call main(). For _c_int00_noinit_noargs(), the C stack pointer is setup and then main() is called:

    void _c_int00_noinit_noargs()
    {
        __SP = ((unsigned int)_symval(&__TI_STACK_END) - 4);
        main(0);
        exit(1);
    }
    

    However, the example assembly code doesn't use the C run-time environment. Hence, I don't see any actual dependence on the C boot code.

    When you say "that I can flash from ARM-R5F on PRU-ICSSM", I assume you mean you want R5F to download the firmware image data to ICSS-M PRU IMEM?

    What happens when you load the image data included in the .h file? How are you calling PRUICSS_writeMemory()?

    Regards,
    Frank

  • Hi Nicolas,

    I looked at one of the AM243x PRU-IO examples: https://software-dl.ti.com/mcu-plus-sdk/esd/AM243X/08_05_00_24/exports/docs/api_guide_am243x/EXAMPLES_PRU_ADC_ADS85x8.html

    The PRU linker command file for this example doesn't include .text:_c_int00*. Looking at the .map file, I notice the C boot code in linked after the .text section for main.obj. The R5F code simply loads the image for this firmware at IMEM offset 0. Once the PRU core is enabled, it starts execution at IMEM address 0. Hence, the C boot code isn't used even though it's included in the image.

    I modified the empty_am243x-evm_icssg0-pru0_fw_ti-pru-cgt linker command file (attached below) to explicitly link the C boot code after the .text section for main.obj. I wrote a simple R5F loader to initialize ICSSG on AM243x and load the PRU firmware to PRU using PRUICSS_writeMemory(). As with the other example, the code starts execution at main label, address 0x0.

    This all seems like a bit of hack, but it should work on AM263x. For assembly only code, there is no reason to include C boot code.

    Let me know if this helps.

    Regards,
    Frank

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/7534.linker.cmd

  • Hi Frank,

    Thank you very much for the time invested on my issue. 

    First, to answer your questions, my firmware is written in C and is made of multiple functions and I'm currently unlucky because the main() function starts at address 0x1340. Then, yes, I use PRUICSS_writeMemory() from MCU+SDK to write the code in the IRAM (and btw, the PRUICSS library works well and is easy to use. Thanks for that!).

    Thank you for the information. I will then test whether your linker (7534.linker.cmd) works out-of-the-box and otherwise, I will force the address of the main() function to be 0x0.

    I will keep you up-to-date in the next hours.

    Regards, Nicolas

  • Hi Frank,

    I tested your example and luckily it has worked out-of-box. I just had to change rtspru library in linker to match the one I'm using.

    Thank you very much again for your answer.

    Regards, Nicolas

  • Hi Nicolas,

    If your code is written in C, then I think you need the C run-time environment to be properly setup before entering main(). Please let me know if you encounter issues moving forward.

    Regards,
    Frank