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.

Compiler/TM4C123GH6PM: Some unused functions not removed even with the --unused_section_elimination=on option

Part Number: TM4C123GH6PM

Tool/software: TI C/C++ Compiler

I just removed from my source code a function that was never called and was surprised to find that the amount of flash used decreased (per the *.map file); I had assumed that the linker would drop such unused functions so the result would be identical.  CCS is configured for the TM4C123GH6PM.  The compiler version is "TI v18.12.3.LTS" and the output format is eabi (ELF).  

I have not been using the --unused_section_elimination option (1) since it defaults on.  If I explicitly turn it on, the results are the same.  If I turn it off, the code size balloons as expected.  If I modify the source code to eliminate the function, the flash usage drops and that function disappears from the *.map file.  I would like to automatically drop it and any other unused functions from the output file to free up flash memory.

Is there something I can do to make the linker drop such unused functions?  It is apparently dropping some (based on the size ballooning when the option is turned off), but in this case it seems that the function remains unless I eliminate it from the source code.  The function is shown below in case it is relevant (2).  I saw this happen with another function earlier (and didn't think much about it at the time), so I don't think this is an isolated case.

Steve

(1) I am controlling the --unused_section_elimination option from CCS using Project Properties > CCS Build > ARM Linker > Advanced Options > Miscellaneous > Eliminate sections not needed in the executable (--unused_section_elimination), then checking the build console to make sure the change is having the desired effect on the options passed to the linker.  With that option turned off, the linker command (with some *.obj filenames snipped) is as follows (with that option turned on or left as default, that option is the only thing that changes in the command):

"C:/ti/ccs901/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --define=ccs="ccs" --define=PART_TM4C123GH6PM -g --relaxed_ansi --gcc --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --check_misra="2.3,3,4,5.3,5.4,6.5,7.1,8.2,8.6,8.7,8.8,8.11,9.1,10.4,11.1,11.2,12.3,12.8,12.9,13.1,13.2,13.3,13.4,13.6,14.1,14.2,14.3,14.8,14.9,14.10,15.4,15.5,16.4,16.5,16.8,17.5,17.6,18.1,19.2,19.3,19.5,19.8,19.9,19.11,19.12,19.14,19.16,19.17,20.4,20.5,20.6,20.7,20.8,20.11,20.12" -z -m"SystemControl.map" --heap_size=0 --stack_size=2048 -i"C:/ti/ccs901/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/lib" -i"C:/ti/ccs901/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/include" --reread_libs --diag_wrap=off --display_error_number --warn_sections --xml_link_info="SystemControl_linkInfo.xml" --rom_model --unused_section_elimination=off -o "SystemControl.out" [  snip  ] "./ds1372.obj" [  snip  ] "./grlib/string.obj" "./i18n/LifterTranslationStringTable.obj" "./i18n/fontcmss_i18n_18pt.obj" [  snip  ] "../tm4c123gh6pm.cmd"  -llibc.a -l"C:/ti/TivaWare_C_Series-2.1.4.178/grlib/ccs/Debug/grlib.lib" -l"C:/ti/TivaWare_C_Series-2.1.4.178/driverlib/ccs/Debug/driverlib.lib"  

(2) The function is in file ds1372.c.  Changing the "#if" from 0 to 1 and back changes the flash usage by 168 bytes.

#if 0	// Not currently used.
void printDS1372Time( DS1372Time_t timeReadAtStartup )
{
	UARTprintf("\n" "DS1372:  Overflow %d, Reset count %d, Minutes since last RTC reset %d",
		timeReadAtStartup.clockResetCountOverflow, timeReadAtStartup.clockResetCount,
		timeReadAtStartup.minutesSinceClockReset );
	UARTprintf_float( " (%f days)", ((float)timeReadAtStartup.minutesSinceClockReset/60.0/24.0) );
}
#endif

The command used to build ds1372.c is:

"C:/ti/ccs901/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/ti/ccs901/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/include" --include_path="C:/ti/TivaWare_C_Series-2.1.4.178" --include_path="C:/ti/TivaWare_C_Series-2.1.4.178" --define=ccs="ccs" --define=PART_TM4C123GH6PM -g --relaxed_ansi --gcc --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --check_misra="2.3,3,4,5.3,5.4,6.5,7.1,8.2,8.6,8.7,8.8,8.11,9.1,10.4,11.1,11.2,12.3,12.8,12.9,13.1,13.2,13.3,13.4,13.6,14.1,14.2,14.3,14.8,14.9,14.10,15.4,15.5,16.4,16.5,16.8,17.5,17.6,18.1,19.2,19.3,19.5,19.8,19.9,19.11,19.12,19.14,19.16,19.17,20.4,20.5,20.6,20.7,20.8,20.11,20.12" --preproc_with_compile --preproc_dependency="ds1372.d_raw" "../ds1372.c"

  • Please add the compiler option --gen_func_subsections.  That tells the compiler to put each function in its own section, which makes it easier for the linker to remove them.  Please search for this option in the ARM compiler manual.

    Thanks and regards,

    -George

  • I found the --gen_func_subsections option in Project Properties > CCS Build > ARM Compiler > Advanced Options > Runtime Model Options and turned it on, then did a clean build.  It saved me 5.5K of flash and 88 bytes of SRAM, which is rather nice since I am bumping up against the limits.  Thanks!  Removing the printDS1372Time() function I asked about from the source code no longer changes the amount of flash used, so it now works like I originally expected it would by default.  

    It would be interesting to know if it saves or costs memory (due to aligning every function) on the average project.  If it generally saves memory, perhaps it should be enabled by default.  Even better, if the linker could avoid the overhead of the extra alignments, there would be no drawbacks (that I am aware of) of using it all of the time and the option of turning it off could be eliminated.

    Steve