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.

TMDS64EVM: Linker error: "pruabi"

Part Number: TMDS64EVM

When compiling and linking C code for the PRU, I am getting an undefined symbol linker error, missing definition for symbol "__pruabi_remu", caused by the conditional statement in the code block:

if(framecount % 1000 == 0)
{
        *PRU1_MINOR_FRAME_CNT = framecount;
}

From what I've seen, I am missing some library file that is required, "pruaib" or something similar, but can not find anythign like it in my installation or online. Any suggestions on where to find it?

  • Hi

    Can you please share the makefile, or the linker command you are using?

    Regards

    Dhaval

  • I am using a linker file from the SDK examples, and the makefile is autogenerated by CCS when I build, but here they are attached. (I changed the file extenstion so the E2E forum would let me upload them)

    ################################################################################
    # Automatically-generated file. Do not edit!
    ################################################################################
    
    SHELL = cmd.exe
    
    CG_TOOL_ROOT := C:/ti/ti_cgt_pru_2.3.3
    
    GEN_OPTS__FLAG := 
    GEN_CMDS__FLAG := 
    
    ORDERED_OBJS += \
    "./PRU_AFDX.obj" \
    "./PRU_Clocks.obj" \
    "./PRU_MDIO.obj" \
    "./PRU_PCFG.obj" \
    "./PRU_RGMII.obj" \
    "./PRU_RegisterConfig.obj" \
    "./PRU_Scheduler.obj" \
    "./PRU_TaskManager.obj" \
    "./PRU_Timer.obj" \
    "./boot.obj" \
    "./main.obj" \
    "../linker.cmd" \
    $(GEN_CMDS__FLAG) \
    
    -include ../makefile.init
    
    RM := DEL /F
    RMDIR := RMDIR /S/Q
    
    # All of the sources participating in the build are defined here
    -include sources.mk
    -include subdir_vars.mk
    -include subdir_rules.mk
    -include objects.mk
    
    ifneq ($(MAKECMDGOALS),clean)
    ifneq ($(strip $(C55_DEPS)),)
    -include $(C55_DEPS)
    endif
    ifneq ($(strip $(C_UPPER_DEPS)),)
    -include $(C_UPPER_DEPS)
    endif
    ifneq ($(strip $(S67_DEPS)),)
    -include $(S67_DEPS)
    endif
    ifneq ($(strip $(S62_DEPS)),)
    -include $(S62_DEPS)
    endif
    ifneq ($(strip $(S_DEPS)),)
    -include $(S_DEPS)
    endif
    ifneq ($(strip $(OPT_DEPS)),)
    -include $(OPT_DEPS)
    endif
    ifneq ($(strip $(C??_DEPS)),)
    -include $(C??_DEPS)
    endif
    ifneq ($(strip $(ASM_UPPER_DEPS)),)
    -include $(ASM_UPPER_DEPS)
    endif
    ifneq ($(strip $(S??_DEPS)),)
    -include $(S??_DEPS)
    endif
    ifneq ($(strip $(C64_DEPS)),)
    -include $(C64_DEPS)
    endif
    ifneq ($(strip $(CXX_DEPS)),)
    -include $(CXX_DEPS)
    endif
    ifneq ($(strip $(S64_DEPS)),)
    -include $(S64_DEPS)
    endif
    ifneq ($(strip $(INO_DEPS)),)
    -include $(INO_DEPS)
    endif
    ifneq ($(strip $(CLA_DEPS)),)
    -include $(CLA_DEPS)
    endif
    ifneq ($(strip $(S55_DEPS)),)
    -include $(S55_DEPS)
    endif
    ifneq ($(strip $(SV7A_DEPS)),)
    -include $(SV7A_DEPS)
    endif
    ifneq ($(strip $(C62_DEPS)),)
    -include $(C62_DEPS)
    endif
    ifneq ($(strip $(C67_DEPS)),)
    -include $(C67_DEPS)
    endif
    ifneq ($(strip $(PDE_DEPS)),)
    -include $(PDE_DEPS)
    endif
    ifneq ($(strip $(K_DEPS)),)
    -include $(K_DEPS)
    endif
    ifneq ($(strip $(C_DEPS)),)
    -include $(C_DEPS)
    endif
    ifneq ($(strip $(CC_DEPS)),)
    -include $(CC_DEPS)
    endif
    ifneq ($(strip $(C++_DEPS)),)
    -include $(C++_DEPS)
    endif
    ifneq ($(strip $(C43_DEPS)),)
    -include $(C43_DEPS)
    endif
    ifneq ($(strip $(S43_DEPS)),)
    -include $(S43_DEPS)
    endif
    ifneq ($(strip $(ASM_DEPS)),)
    -include $(ASM_DEPS)
    endif
    ifneq ($(strip $(S_UPPER_DEPS)),)
    -include $(S_UPPER_DEPS)
    endif
    ifneq ($(strip $(CPP_DEPS)),)
    -include $(CPP_DEPS)
    endif
    ifneq ($(strip $(SA_DEPS)),)
    -include $(SA_DEPS)
    endif
    endif
    
    -include ../makefile.defs
    
    # Add inputs and outputs from these tool invocations to the build variables 
    EXE_OUTPUTS += \
    ICSSG1_PRU0_AFDX.out 
    
    EXE_OUTPUTS__QUOTED += \
    "ICSSG1_PRU0_AFDX.out" 
    
    
    # All Target
    all: $(OBJS) $(CMD_SRCS) $(GEN_CMDS)
    	@$(MAKE) --no-print-directory -Onone "ICSSG1_PRU0_AFDX.out"
    
    # Tool invocations
    ICSSG1_PRU0_AFDX.out: $(OBJS) $(CMD_SRCS) $(GEN_CMDS)
    	@echo 'Building target: "$@"'
    	@echo 'Invoking: PRU Linker'
    	"C:/ti/ti_cgt_pru_2.3.3/bin/clpru" -v4 -O0 --define=SOC_AM64X --define=_DEBUG_=1 --define=PRU0 --define=SLICE1 -g --diag_warning=225 --diag_wrap=off --display_error_number --endian=little -z -m"abi=ti" --heap_size=0x100 --stack_size=0x200 --disable_auto_rts --diag_suppress=10063-D --diag_wrap=off --display_error_number --warn_sections --xml_link_info="ICSSG1_PRU0_AFDX_linkInfo.xml" --entry_point=_c_int00_noinit_noargs --ram_model -o "ICSSG1_PRU0_AFDX.out" $(ORDERED_OBJS)
    	@echo 'Finished building target: "$@"'
    	@echo ' '
    	@$(MAKE) --no-print-directory post-build
    
    # Other Targets
    clean:
    	-$(RM) $(EXE_OUTPUTS__QUOTED)
    	-$(RM) "PRU_AFDX.obj" "PRU_Clocks.obj" "PRU_MDIO.obj" "PRU_PCFG.obj" "PRU_RGMII.obj" "PRU_RegisterConfig.obj" "PRU_Scheduler.obj" "PRU_TaskManager.obj" "PRU_Timer.obj" "boot.obj" "main.obj" 
    	-$(RM) "PRU_AFDX.d" "PRU_Clocks.d" "PRU_MDIO.d" "PRU_PCFG.d" "PRU_RGMII.d" "PRU_RegisterConfig.d" "PRU_Scheduler.d" "PRU_TaskManager.d" "PRU_Timer.d" "boot.d" "main.d" 
    	-@echo 'Finished clean'
    	-@echo ' '
    
    post-build:
    	-$(CG_TOOL_ROOT)/bin/hexpru --diag_wrap=off --array --array:name_prefix=PRU1Firmware  -o pru1_load_bin.h ICSSG1_PRU0_AFDX.out
    	-if win32 == linux cat C:/ti/mcu_plus_sdk_am64x_11_02_00_24/source/pru_io/firmware/pru_load_bin_copyright.h pru1_load_bin.h > C:/Users/seth.appleman/workspace_v12/open-pru/examples/empty_c/firmware/am64x-evm/pru1_load_bin.h
    	-if win32 == linux rm pru1_load_bin.h
    	-if win32 == win32  $(CCS_INSTALL_DIR)/utils/cygwin/cat C:/ti/mcu_plus_sdk_am64x_11_02_00_24/source/pru_io/firmware/pru_load_bin_copyright.h pru1_load_bin.h > C:/Users/seth.appleman/workspace_v12/open-pru/examples/empty_c/firmware/am64x-evm/pru1_load_bin.h
    	-if win32 == win32  $(CCS_INSTALL_DIR)/utils/cygwin/rm pru1_load_bin.h
    	-@echo ' '
    
    .PHONY: all clean dependents
    .SECONDARY:
    
    -include ../makefile.targets
    
    

    /*
     * AM64x_PRU0.cmd
     *
     * Example Linker command file for linking programs built with the C compiler
     * on AM64x PRU0 cores
     */
    
    -cr		/* Link using C conventions */
    
    /* Specify the System Memory Map */
    MEMORY
    {
          PAGE 0:
    	/* 12 KB PRU Instruction RAM */
    	PRU_IMEM	: org = 0x00000000 len = 0x00003000
    
          PAGE 1:
    	/* Data RAMs */
    	/* 8 KB PRU Data RAM 0; use only the first 4 KB for PRU0 and reserve
    	 * the second 4 KB for RTU0 and Tx_PRU0 */
    	PRU0_DMEM_0	: org = 0x00000000 len = 0x00001000	CREGISTER=24
    	/* 8 KB PRU Data RAM 1; reserved completely for Slice1 cores - PRU1,
    	 * RTU1 and Tx_PRU1; do not use for any Slice0 cores */
    	PRU0_DMEM_1	: org = 0x00002000 len = 0x00001000	CREGISTER=25
    	/* NOTE: Custom split of the second 4 KB of ICSS Data RAMs 0 and 1
    	 * split equally between the corresponding RTU and Tx_PRU cores in
    	 * each slice */
    	RTU0_DMEM_0	: org = 0x00001000 len = 0x00000800
    	TX_PRU0_DMEM_0	: org = 0x00001800 len = 0x00000800
    	RTU0_DMEM_1	: org = 0x00003000 len = 0x00000800
    	TX_PRU0_DMEM_1	: org = 0x00003800 len = 0x00000800
    
          PAGE 2:
    	/* C28 needs to be programmed to point to SHAREDMEM, default is 0 */
    	/* 64 KB PRU Shared RAM */
    	PRU_SHAREDMEM	: org = 0x00010000 len = 0x00010000	CREGISTER=28
    
    	/* Internal Peripherals */
    	/* NOTE: Use full INTC length instead of 0x200 to match the pruIntc
    	 * structure definition in pru_intc.h, ignoring the second Constant
    	 * Register #6 that starts at 0x200 offset within INTC */
    	PRU_INTC	: org = 0x00020000 len = 0x00001504	CREGISTER=0
    	PRU_IEP1	: org = 0x0002F000 len = 0x00000100	CREGISTER=1
    	PRU_IEP1_0x100	: org = 0x0002F100 len = 0x0000021C	CREGISTER=2
    	PRU_ECAP	: org = 0x00030000 len = 0x00000060	CREGISTER=3
    	PRU_CFG		: org = 0x00026000 len = 0x00000100	CREGISTER=4
    	PRU_CFG_0x100	: org = 0x00026100 len = 0x00000098	CREGISTER=5
    	/* XXX: PRU_INTC_0x200 is part of INTC space, and is therefore commented
    	 * out as it conflicts with PRU_INTC size above. To use PRU_INTC_0x200,
    	 * split up the pruIntc structure and CT_INTC variable in
    	 * source/include/c_code/PROCESSOR/pru_intc.h */
    	/*PRU_INTC_0x200: org = 0x00020200 len = 0x00001304	CREGISTER=6*/
    	PRU_UART	: org = 0x00028000 len = 0x00000038	CREGISTER=7
    	PRU_IEP0_0x100	: org = 0x0002E100 len = 0x0000021C	CREGISTER=8
    	MII_G_RT	: org = 0x00033000 len = 0x00000F44	CREGISTER=9
    	TM_CFG_PRU0	: org = 0x0002A000 len = 0x0000004C	CREGISTER=10
    	PRU0_CTRL	: org = 0x00022000 len = 0x00000030	CREGISTER=11
    	PA_STATS_QRAM	: org = 0x00027000 len = 0x00001000	CREGISTER=12
    	PA_STATS_CRAM	: org = 0x0002C000 len = 0x00001000	CREGISTER=13
    	MII_MDIO	: org = 0x00032400 len = 0x00000088	CREGISTER=21
    	PRU_RTU_RAT0	: org = 0x00008000 len = 0x00000854	CREGISTER=22
    	PRU_IEP0	: org = 0x0002E000 len = 0x00000100	CREGISTER=26
    	MII_RT		: org = 0x00032000 len = 0x00000070	CREGISTER=27
    
    	/* External Regions */
    	/* Random length 0x100 assigned to the below regions */
    	RSVD14		: org = 0x00024800 len = 0x00000100	CREGISTER=14
    	RSVD15		: org = 0x60000000 len = 0x00000100	CREGISTER=15
    	RSVD16		: org = 0x70000000 len = 0x00000100	CREGISTER=16
    	RSVD17		: org = 0x80000000 len = 0x00000100	CREGISTER=17
    	RSVD18		: org = 0x90000000 len = 0x00000100	CREGISTER=18
    	RSVD19		: org = 0xA0000000 len = 0x00000100	CREGISTER=19
    	RSVD20		: org = 0xB0000000 len = 0x00000100	CREGISTER=20
    	RSVD23		: org = 0xC0000000 len = 0x00000100	CREGISTER=23
    	/* Random length 0x10000 (max len value) assigned to programmable C29-31*/
    	RSVD29		: org = 0xD0000000 len = 0x00010000	CREGISTER=29
    	RSVD30		: org = 0xE0000000 len = 0x00010000	CREGISTER=30
    	RSVD31		: org = 0xF0000000 len = 0x00010000	CREGISTER=31
    }
    
    /* 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
    }
    

  • Hi
    I apologize for the delayed response here.

    "--disable_auto_rts" flag prevents the linker from automatically pulling in the PRU runtime support library (libc.a), which contains __pruabi_remu and other arithmetic helper functions. Without this library, any C operation that requires runtime support will produce an undefined symbol error.

    Options for fixing:

    Option A — Remove --disable_auto_rts (simplest)

    In your CCS project's linker settings, remove the --disable_auto_rts flag unless, it is added for any specific reason. This lets the linker automatically find and link the correct runtime library from your PRU compiler installation.

    Option B — Manually link libc.a

    If you need --disable_auto_rts for other reasons, explicitly add the runtime library to your linker command by adding -llibc.a to the linker flags. Using the generic name libc.a allows the linker to automatically select the correct library variant for your build configuration.

    In CCS, you can add this under Project Properties → Build → PRU Linker → File Search Path → Include library file.

    Regards

    Dhaval

  • For future readers,

    This is a bug in the OpenPRU repo's older C projects that was fixed in v2026.1.0.

    On tag v2026.0.0, you can see that --disable_auto_rts was copied from the assembly projects into the C project settings that CCS imports:
    https://github.com/TexasInstruments/open-pru/blob/v2026.00.00/examples/empty_c/firmware/am64x-evm/icss_g0_pru0_fw/ti-pru-cgt/example.projectspec

    However, on tag v2026.1.0 I updated example.projectspec for all projects in the repo:
    https://github.com/TexasInstruments/open-pru/blob/v2026.01.00/examples/empty_c/firmware/am64x-evm/icss_g0_pru0_fw/ti-pru-cgt/example.projectspec

    If you see any other issues with importing projects into CCS, please let us know so we can take a look.

    Regards,

    Nick

  • I'm sorry but I unintentionally set this as "fixed my issue" but am only now just getting back around to trying, and neither Option A nor Option B worked.

    Nothing changes with my build errors when I try Option A:

    Building target: "ICSSG1_PRU0_AFDX.out"
    Invoking: PRU Linker
    "C:/ti/ti_cgt_pru_2.3.3/bin/clpru" -v4 -Ooff --define=SOC_AM64X --define=_DEBUG_=1 --define=PRU0 --define=SLICE1 -g --diag_warning=225 --diag_wrap=off --display_error_number --endian=little -z -m"abi=ti" --heap_size=0x100 --stack_size=0x200 --diag_suppress=10063-D --diag_wrap=off --display_error_number --warn_sections --xml_link_info="ICSSG1_PRU0_AFDX_linkInfo.xml" --entry_point=_c_int00_noinit_noargs --ram_model -o "ICSSG1_PRU0_AFDX.out" "./PRU_AFDX.obj" "./PRU_Clocks.obj" "./PRU_MDIO.obj" "./PRU_PCFG.obj" "./PRU_RGMII.obj" "./PRU_RegisterConfig.obj" "./PRU_Scheduler.obj" "./PRU_TaskManager.obj" "./PRU_Timer.obj" "./boot.obj" "./ethTxRx.obj" "./main.obj" "../linker.cmd"
    <Linking>

    undefined first referenced
    symbol in file
    --------- ----------------
    __pruabi_mpyi ./PRU_Scheduler.obj


    When I try option B, I get an additional build error that the linker can not find "libc.a":

    Building target: "ICSSG1_PRU0_AFDX.out"
    Invoking: PRU Linker
    "C:/ti/ti_cgt_pru_2.3.3/bin/clpru" -v4 -Ooff --define=SOC_AM64X --define=_DEBUG_=1 --define=PRU0 --define=SLICE1 -g --diag_warning=225 --diag_wrap=off --display_error_number --endian=little -z -m"abi=ti" --heap_size=0x100 --stack_size=0x200 --disable_auto_rts --diag_suppress=10063-D --diag_wrap=off --display_error_number --warn_sections --xml_link_info="ICSSG1_PRU0_AFDX_linkInfo.xml" --entry_point=_c_int00_noinit_noargs --ram_model -o "ICSSG1_PRU0_AFDX.out" "./PRU_AFDX.obj" "./PRU_Clocks.obj" "./PRU_MDIO.obj" "./PRU_PCFG.obj" "./PRU_RGMII.obj" "./PRU_RegisterConfig.obj" "./PRU_Scheduler.obj" "./PRU_TaskManager.obj" "./PRU_Timer.obj" "./boot.obj" "./ethTxRx.obj" "./main.obj" "../linker.cmd" -llibc.a
    <Linking>
    error #10008-D: cannot find file "libc.a"

    undefined first referenced
    symbol in file
    --------- ----------------
    __pruabi_mpyi ./PRU_Scheduler.obj

    To resolve, an additional step was required. Under Project Properties → Build → PRU Linker → File Search Path → Add <Dir> to library search pathI had to also add entries to:

    C:\ti\ti_cgt_pru_2.3.3\include

    C:\ti\ti_cgt_pru_2.3.3\lib

    These file path additions, paired with manually adding "libc.a" resolved the error. Thanks.