Code Size Information with gcc for ARM/Kinetis

Working with the Freescale S08 and S12 build tools, there is something I really appreciated: that the linker reports on the console the code size of the application:

S08 Linker reporting the code size

S08 Linker in Eclipse reporting the code size

This is especially handy as it allows you to see the impact on code size immediately e.g. if I change a compiler option or do a source code change. Simple and easy. Yes, I could get that kind of information from the linker map file too. But this means I need to open that file, scroll down/etc: many steps just to find out the code size.

As with all good things: you learn to appreciate it even more if you do not have it any more. And this happens to me when I moved to ColdFire, PowerPC and Kinetis applications using CodeWarrior build tools. I would expect that this kind of simple thing would be there, but…. nada. I need to open the map file.

GNU gcc for Kinetis: arm-none-eabi-size

With the advent of gcc for Kinetis in CodeWarrior for MCU10.3 (see the Freedom board posts), there is finally some relief. GNU gcc is here the default compiler for the Kinetis L family. The KL25Z which is on the FRDM-KL25Z Freedom board has decent RAM and Flash, but the L series really is targeting the small and tiny microcontrollers. And here code and data size information right at link time is important, as it is e.g. for the S08. And with the move of Freescale to gcc, the arm-none-eabi-size is part of the tools: it is part of the GNU tools for ARM Cortex M0+. I can find that tool inside

<installationPath>\Cross_Tools\arm-none-eabi-gcc-4_6_2\bin\arm-none-eabi-size.exe

Command Line Interface

Executing that tool from the command prompt/DOS Shell with the option -help provides pretty much everything needed:

C:\Freescale\CW MCU v10.3\Cross_Tools\arm-none-eabi-gcc-4_6_2\bin>arm-none-eabi-size.exe -help
Usage: arm-none-eabi-size.exe [option(s)] [file(s)]
Displays the sizes of sections inside binary files
If no input file(s) are specified, a.out is assumed
The options are:
  -A|-B     --format={sysv|berkeley}  Select output style (default is berkeley)
  -o|-d|-x  --radix={8|10|16}         Display numbers in octal, decimal or hex
  -t        --totals                  Display the total sizes (Berkeley only)
  --common                  Display total size for *COM* syms
  --target=<bfdname>        Set the binary file format
  @<file>                   Read options from <file>
  -h        --help                    Display this information
  -v        --version                 Display the program's version

arm-none-eabi-size.exe: supported targets: elf32-littlearm elf32-bigarm elf32-little elf32-big srec symbolsrec verilog tekhex binary ihex

Executing the utility with

arm-none-eabi-size.exe c:\wsp_Freedom\Freedom_Accel\FLASH\Freedom_Accel.elf

gives

text    data     bss     dec     hex filename
6036      40    1120    7196    1c1c c:\wsp_Freedom\Freedom_Accel\FLASH\Freedom_Accel.elf

Here I have the code size (text), constant data (data) and global variables or statically allocated variables (bss), all in decimal. The sum of text+data+bss is shown in dec(imal) and hex(adecimal).

Printing Code Size for gcc in Eclipse/CodeWarrior

Now while using the command line tool is nice, I want it be part of the build in Eclipse/CodeWarrior. The good news is: as shown in “S-Record Generation with gcc for ARM/Kinetis” it can be done.

In the build tool settings, I enable the ‘Print Size’ option and press the Apply button:

Print Size Option

Print Size Option

This enables a ‘GNU Print Size’ option group:

GNU Print Size

GNU Print Size

Now if I build my application, I get code and data size information:

Kinetis ARM GNU gcc Code and Data Size Information with CodeWarrior

Kinetis ARM GNU gcc Code and Data Size Information with CodeWarrior

Happy Sizing 🙂

49 thoughts on “Code Size Information with gcc for ARM/Kinetis

  1. Pingback: Tutorial: Freedom with FreeRTOS and Kinetis-L | MCU on Eclipse

  2. Pingback: Optimizing the Kinetis gcc Startup | MCU on Eclipse

  3. Pingback: Reducing Code Size with gcc and EWL | MCU on Eclipse

  4. Hi Erich,

    Your post is very useful. I’m using CodeWarrior 10.2 for Kinetis K60N512. How can I print code size with Codewarrior ARM toolchain?

    Like

        • I need to disappoint you: according to Freescale, the non-gcc ARM compiler is in maintenance mode. It is still present in MCU10.3, but I would not expect any new features or enhancements for it. ARM gcc is the future. I already switched over all my Kintetis project to gcc, and the code is not only faster, it is smaller too, and the compiler/build tools have more features. No reasons for me to stay with the non gcc compiler.

          Like

  5. Hi,

    The “Additional Tools” settings seem to be removed in CW 10.3 official version. Is there any way to enable the “Print Size” option in CW 10.3 official release?

    Thank you for your help.

    Like

    • Hi Joey,
      it is still there for me in my offical MCU10.3. Keep in mind that the setting is for gcc, and *not* for the other ARM compiler (from Freescale) in MCU10.3. Maybe this is the disconnect?

      Like

      • Hi Erich:

        Mmm… I can find it with projects that I created (and gcc was selected as compiler), but I can’t find “Additional Tools” in a MQX example project (created by selecting New MQX 3.8 project, and selected “hello” project from the example list). It seems MQX projects are still using ARM compiler, even we create it under CW 10.3.

        Thank you for your response. I will inform my customers to check code size from xMap file.

        PS: I am Freescale disty FAE and your blog does help me a lot. I would like to present my appreciation for your contributions on this blog.

        Like

        • Hi Joey,
          thanks :-). For MQX-Lite (Kinetis-L) projects, gcc is used. I think the next MQX version will finally support gcc as well for the other Kinetis parts.

          Like

  6. Hello:

    First of all thank you for your hard work on your blog, I really liked it and it has helped me a lot to learn about ARMs.

    I wanted to ask you about the data, bss and Text information. At the end, which one of them can tell me about FLASH and RAM usage? When I download a program to the board, what it downloads is the sum of text + data, so what is bss? I made a new barebones project and I have a huge bss data (2076).

    Also, how can I know the RAM the program will use?

    Thank you very much for your time,

    Ed.

    Like

  7. Pingback: text, data and bss: Code and Data Size Explained | MCU on Eclipse

  8. in case you want to reduce bss consumption, you can modify the linker script in the heap and stack area. Afaik heap can be chosen to zero, when no malloc is used.

    Like

  9. I had myself scratching my head and pawing my HP42S when you said “Here I have the code size (text), constant data (data) and global variables or statically allocated variables (bss), all in hexadecimal. The sum of text+data+bss is shown in dec(imal) and hex(adecimal).”

    Until I realized you meant *all in decimal*, when you said “all in hexadecimal”

    Like

      • No worries Erich.
        Your blog is so good, and this was such a minor thing.
        I’m just happy you are shedding so much light on the Freedom boards. At least for me, there is no other source of this information. I’m trying out the Freescale ARM Cortex chips after having been a Mot/Freescale person for decades, and more lately taken a few years out for other things. Just an observation about Freedom stuff, at least the K20D50 version: For a product that tries to be like Arduino….it is far from the ease of use of Arduino, and could use a lot more sample programs and drag and drop kind of applications for the un-itiated. I know this is a blog thread about finding the memory left in Codewarrior, but I wanted to get that off my chest!
        Tim
        Offgrid

        Like

        • Hi Tim,
          yeah, I know what you mean, and I felt the same, so I published my findings as much as possible. I think many companies (especially silicon companies) have not realized (yet?) that the best microcontrollers are nothing without good tools and software. I mean the Arduino and Raspberry Pi are not the best microcontrollers, but having an excellent software and tools environment. And especially an open source driven environment. I belive only vendors will survive which can adopt to that change. Will see.

          Like

        • Erich, You are really keen on Processor Expert, and I need some help, so I thought I would write.

          I’ve never used the tool, electing instead to handcraft code to get exactly what I want. Now with lots of RAM and Flash, and with the ability to use different variants easily, I find myself more interested in PE, and using it at least for startup code on different peripherals.

          My dillema is that I have spent far too much time on getting a real time timer running and I could use a hand; I literally cannot get the timer to start and run. I’m using the RealTime_LDD and it’s configured to use GetTimeSec function. The help window on this component gives me this Typical Usage:

          void main(void) { unsigned int i, time; float one_loop_us;

          RT1_Reset(); /* reset the counter */ for (i = 0; i < 60000; ++i); /* for-cycle */

          /* get measured time of whole for-cycle */ if(RT1_GetTimeUS(RT1_DeviceData,&time) == ERR_OK) { /* average time of one loop */ one_loop_us = time / 60000.0; } }

          1. First off, I cannot use the RT1_Reset() function as the gcc compiler gives me "undefined reference to `RT1_Reset'" in clock.c , which seem weird since this is defined in the PE modules, and referenced in my ProcessorExpert.c file. 2. Here is my clock routine (clock.c), when single stepping in debug mode, I see that it does actually go into the RT1_GetTimeUS() function.

          unsigned int seconds, minutes, hours, i; unsigned int msecTimer, time, RT1_DeviceData; //typedef uint32_t TU2_TValueType ; // Type for data parameters of methods. 32bit is maximum //long TU2_TValueType ; // Type for data parameters of methods. 32bit is maximum //int LDD_TDeviceData;

          int Clock(void) { #define TICKS1SEC 100 // there are 100 – 10msec ticks in one second

          if(RT1_GetTimeUS(RT1_DeviceData,&time) == 0){ msecTimer = time ; } else i = 0; //RT1_Reset(); //for (i = 0; i = TICKS1SEC){ msecTimer = 0; seconds ++; //RT1_Reset(); /* reset the real time counter */ } if (seconds >= 60) { seconds = 0; minutes ++; if (minutes >= 60) { minutes = 0; hours ++; if (hours >= 24) hours = 0; // hours go to 0 every day, 24 hours } } return (seconds); }

          I do see the RT1_GetTimeUS() routine wants to return ERR_OVERFLOW when called. I’ve got both the linked timer, TimerUnit_LDD (TU2) and this RealTime_LDD resultion set to 16 bits, and resultion set to 10msecs. Initialization for RealTime is yes in init code and yes for Auto initialization, and yes in init code for the TU2 timer.

          Anything you can do to get me moving again…would be most appreciated!!!

          Like

        • I apologize for my late response (to many things going on right now). I would need to try out the same thing you describe, but here are a few thoughts (blindly without trying it myself):
          – If RT1_Reset() is not defined, it could be that it is not enabled? Check if the method has a X on it in the Components view. If yes, it is disabled. Enable it with right mouse click.
          – If you are interested just in a realtime clock functionality (without the need for the RTC on the chip), you easily could use the GenericTimeDate component I have created. See https://mcuoneclipse.com/2012/07/26/there-is-a-time-and-date-for-both-worlds/. Simply import that component (see https://mcuoneclipse.com/2013/05/09/processor-expert-component-peupd-files-on-github/), then add a timer (e.g. 10 ms) and call the TmDt1_AddTick() from the timer interrupt. Then you have a realtime clock 🙂

          I hope this helps get moving.

          Like

        • Thanks Erich, your tip about enabling the Reset was right on, it was disabled, and I learned a new way to talk to PE. Unfortunately, that did not fix my problem. Moving the routine to main did solve the problem, so I need to see why the routines are not working in my clock file. I’ll take a look at your clock code, but since this part has it’s own RTC, it seems smart to use the on-chip resource.

          Thanks again,
          Tim

          Like

        • Hi Tim, yes, I agree using the onboard RTC is a good thing. In my projects I used the software RTC (GenericTimeDate) or an external RTC like a Maxim DS3232.

          Like

  10. Hi Erich,
    First of all, thanks for this post, it was helpful.
    After doing what you teach here, and enjoying it, I wonder if you ever had this issue:
    Sometimes, I do a Build All, and because it sometimes takes 1 or 2 minutes, I start to do other things: checking my mail, going to the bathroom, … sometimes I came back to the computer 15 minutes later, and then… Do I did the Build All ???? or not ??? I don’t remember !
    So, I need to go to the file .elf to check the hour/date.
    Do you think there might be an easy way to have the Date and Time in the console, in the last line ?
    Or, is there other place were this information is available ?

    Best Regards,
    Christian

    Like

  11. Hi Erich, a question that i think is in topic with the article:

    If i notice that the size of the used RAM is increasing more than expected,how can i check in detail the RAM size allocate by my globals and static allocated variables?
    Say that, somewhere ,i erroneously declared an array with [1000] elements instead of[100] as needed,is it possible to put it in evidence in some ordered list?

    Thanks for your useful work.
    Diego

    Like

    • Hi Diego,

      I suggest that you enable the linker map file (under the linker options). This creates a text file with that information.

      Unfortunately at least for GNU linker that map file is not that easy to read, but I’m sure you get to it 🙂

      Like

      • Erich thanks for the datailed answer on the same
        question(added by more data) on Freescale forum
        freescale community thread/321919
        ,unselecting the Print Link Map option everything works fine

        Diego

        Like

  12. Pingback: Printing Code Size Information in Eclipse | MCU on Eclipse

  13. Hi,
    Please let me know the option to enable the memory map summary like the one in the starting of this thread. I want to know what is the total size of the .text, total size of .bss and the total size of .data. Currently I use the option -Xlinker -Map=$(basename $(1)).map to generate the map file..with Arm gcc compiler.
    Best Regards
    Hari

    Like

    • See the last screenshot of this post (“Kinetis ARM GNU gcc Code and Data Size Information with CodeWarrior”) which shows the options. You do not get that from the linker, you need to call the size program.

      Like

  14. Hi Erich
    Had to deal with memory questions and noted, that the option to put the size information to the console has not worked for me. I don’t even see a call to the size program in the console. However, using Post-build steps in Project Properties > C/C++ Build > Settings > Build Steps has helped me out. I placed
    “${ARM_GNU_TOOLS_HOME}/bin/arm-none-eabi-size.exe” –format=sysv ${BuildLocation}/${BuildArtifactFileName} >> ${BuildLocation}/${BuildArtifactFileBaseName}.map
    in there and from now on I get a neat memory usage table at the end of my map file.
    Thought this might help some other people around here. Thank you and keep on going with this great blog!
    Adrian

    Like

  15. Took me a while to find the size option on KDS. It is in C/C++ Build -> Settings -> Toolchains instead of Tool Settings.

    Like

  16. hi Eric,

    I am genrating srecord file in my project and i have print size option selected in Kenetis Design Studio.
    I am trying to find the End of the Program Code.
    the End of program code address calculated by looking into console screen in KDS, from below is addr(33808)+ size(234296) = 268104

    section size addr
    .interrupts 1024 32768
    .flash_config 16 1024
    .text 234296 33808
    .ARM 8 268104
    .init_array 4 268112
    .data 5452 536806400
    .m_data_1FFF0000 53792 536811852
    .m_interrupts_ram 1024 536805376
    .bss 129660 536865792
    .stack 1024 537001984
    .ARM.attributes 55 0
    .debug_info 980501 0
    .debug_abbrev 79454 0
    .debug_aranges 17552 0
    .debug_ranges 14576 0
    .debug_macro 490179 0
    .debug_line 611590 0
    .debug_str 1977333 0
    .comment 112 0
    .debug_frame 56792 0
    .stab 156 0
    .stabstr 335 0
    Total 4654935

    Like

    • but when I check in srec file (below shown end of file)generated by KDS. I see end address diffreent which is higher than above print
      which is 0x4FEB0 -> in decimal 327344
      S21404FE900000000000000000000000000000000059
      S21404FEA00000000000000000000000000000000049
      S21404FEB00000000000000000000000000000000039

      is this generated srec is adding any dummy data in to Flash area

      Like

      • Hi Niranjan,
        this all depends on your linker file, maybe you are using some filling with zero bytes?
        Regardless, if you want to know the end of your code, then you can define a symbol in the linker file.
        For example

        ___ROM_AT = .;
        } > m_text
        the ___ROM_AT symbol is what you can use in your code to find out the end of the m_text segment.

        Like

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.