Reducing Code Size For Lpc11xx With Lpcxpresso
Reducing Code Size For Lpc11xx With Lpcxpresso
Reducing Code Size For Lpc11xx With Lpcxpresso
Application note
Document information
Info
Content
Keywords
Abstract
This application note will cover some basic techniques which can be used
to reduce the size of your programs binary image. This is an important
step in the design process when targeting LPC11XX parts with small
memory footprints.
AN10963
NXP Semiconductors
Revision history
Rev
Date
Description
Initial version.
20100802
Contact information
For additional information, please visit: http://www.nxp.com
For sales office addresses, please send an email to: [email protected]
AN10963
Application note
2 of 22
AN10963
NXP Semiconductors
1. Introduction
The LPC11XX part family offers a wide granularity of flash densities which enable
designers to reduce overall system costs by targeting optimally sized devices. When
targeting parts with the lowest available memory sizes, it becomes critical that a
programs binary image does not exceed the parts resources. Many strategies exist to
reduce an embedded programs footprint, and this application note will detail a general
purpose set of recommendations which if followed properly will allow designers to target
lower density microcontrollers with minimal effort.
It should be noted that a typical case of development may involve the use of an
evaluation board loaded with a microcontroller featuring more memory than the intended
target hardware. Often larger part variants in a family will inherit the memory map of the
lower end part variants. By adjusting the projects settings to target the lowest end part
early in the development process, the designer will have a better feel for the constraints
they will be working with in their final implementation.
AN10963
Application note
3 of 22
AN10963
NXP Semiconductors
If the use of printf() cannot be avoided, consider defining the preprocessor symbol
CR_INTEGER_PRINTF in LPCXpressos compiler settings, to limit formatting when
using the REDLIB libraries as it alleviates the need for double precision floating point
routines, thus saving space.
This section has focused on printf() as it is a commonly used library function that will
typically harvest many other functions, however it is not the only library routine that does
this. A recommended practice is to always analyze a projects symbol table to ensure
only those symbols which are required are included in the program image.
Fig 1.
AN10963
Application note
4 of 22
AN10963
NXP Semiconductors
Fig 2.
Coding style can also affect code size. For instance consider the following two routines to
increment and bound a value:
Table 1.
Coding style comparison
C Source
Note
No division required
2.2 Target a larger (or virtual) device in the case of link failure
When a programs image exceeds the resources of the target device, the linker will stop
and issue an error, preventing further analysis by the developer. Without a fully linked
image, it is difficult to detect unintentionally included libraries. Analysis of a properly
linked image enables developers to efficiently improve the largest sections of a project,
rather than attempting to reduce the size of every single function. It is therefore
recommended as a first step that developers work around linker failures in order to better
reduce their code size, rather than enabling optimizations straight away.
LPCXpresso allows designers to easily adjust their target devices in the MCU Settings
dialog. As an example, when a project targeting an LPC1111 fails, selecting the
LPC1114 instead may be a sufficient means to link the project. Be aware that changing
the target device may allow the build to complete, but you will not be able to debug the
device in LPCXpresso as the device ID will not match.
Should the project be too large for even the LPC1114, by manually managing the linkers
configuration file inside LPCXpresso, you can configure the toolchain into thinking your
target device has more memory than it actually does. As the topic of generating custom
linker scripts is slightly lengthy, it has been included later in the document as Appendix A.
When using a custom linker script, just as when selecting a larger device debugging and
execution will not be possible.
AN10963
Application note
5 of 22
AN10963
NXP Semiconductors
Fig 3.
AN10963
Application note
6 of 22
AN10963
NXP Semiconductors
Table 2.
Flag
-ffunction-sections
Compiler
-fdata-sections
Compiler
--gc-sections
Linker
--cref
Linker
Fig 4.
Compiler options
Fig 5.
Linker options
AN10963
Application note
7 of 22
AN10963
NXP Semiconductors
routines which, if deemed to be too large for the functionality they offer, can either be
replaced or removed.
Take the function SystemInit() as an example. Without compiler optimization enabled,
this function requires up to 224 bytes of .text (as well as 4 bytes of RAM for the
SystemCoreClock variable). If your application runs at a fixed clock rate (which is
common in many applications) you should consider replacing this routine with a focused
initialization routine to configure your clock(s) as required.
The example project LPC1114_Blinky makes use of a routine GPIOSetDir(). By including
a post build action arm-none-eabi-nm --size-sort ${BuildArtifactFileName} it can be
seen that GPIOSetDir() occupies over 500 bytes. Some applications do not need to
adjust the directionality of peripheral pins at runtime because they are dedicated on the
PCB. In these scenarios substantial amounts of code can be recovered by using fixed pin
input/output routines at the start of execution.
Another example involves the SYSAHBCLKCTRL register. Many of the routines included
with LPCXpresso will set or clear bits in SYSAHBCLKCTRL, but in some applications
(typically those without power consumption constraints) peripherals are powered up at
system startup and remain enabled indefinitely. In such a situation, it may make more
sense to simply configure SYSAHBCLKCTRL once at start up by setting multiple bits in
the mask. Doing this will prevent additional code associated with inline read/modify/write
cycles being included.
There is no universal rule as to which library functions should be replaced, therefore
doing so is recommended only in the event that implementing the application specific
routine can be accomplished with relative ease and in cases where prior analysis shows
that space savings warrant the development of application specific routines.
1.
AN10963
Application note
http://www.nxp.com/redirect/en.wikipedia.org/wiki/Volatile_variable
All information provided in this document is subject to legal disclaimers.
8 of 22
AN10963
NXP Semiconductors
3. Advanced topics
This section will cover several advanced topics. They are:
Utilities
Structure alignment
Disassembly
Vector table modification
3.1 Utilities
LPCXpresso offers several tools to assess a programs code size right out of the box. A
command prompt with an automatically configured environment can be quickly opened
by CTRL+Clicking on the active projects name in the LPCXpresso status bar.
Additionally, these utilities can be added to pre/post build actions, as seen in some of the
included example code.
The first of these utilities is the size program. The arm-none-eabi-size tool is part of the
GNU toolchain included with LPCXpresso. It can be accessed via an ELF binarys
context menu (Binary Utilities->Size) or can be invoked as a part of a custom build script
or manually from the command line. In Fig 6 it can be seen that the example Blinky
project when built without any optimization takes up nearly the entire 8 kB of flash offered
by an LPC1111.
Fig 6.
Application note
9 of 22
AN10963
NXP Semiconductors
knowing which symbols are the largest will aid in reducing the size of code without
wasting effort on optimizing insignificant routines.
This can be assessed by reading the toolchains map report. Adding the command line
switch "--cref" will append a Cross Reference Table to the map report which
alphabetically lists all symbols and the modules in which they are referenced.
Sometimes it can be more convenient to sort the list of symbols by their size rather than
alphabetically. The GNU toolchain included in LPCXpresso comes with a copy of the
utility arm-none-eabi-nm which lists symbols from ELF object files. Invoking the
command with the --size-sort option will result in output being sorted size. Including the
following line in a list of post build actions will display the size of all symbols after each
build: arm-none-eabi-nm --size-sort ${BuildArtifactFileName};
AN10963
Application note
10 of 22
AN10963
NXP Semiconductors
AN10963
Application note
Fig 7.
Fig 8.
11 of 22
AN10963
NXP Semiconductors
Fig 9.
3.3 Disassembly
Oftentimes it is useful to inspect the inner workings of a function which is suspiciously
large. This is easily done with the GNU objdump utility. By invoking objdump with the
--source and --syms switches will display the final object files symbol table as well as
disassembly intermixed with original C source. Note that LPCXpresso has an option to
view disassembly, but it does not invoke the inline source option. Below is a portion of
the disassembly of an application specific clock initialization routine.
AN10963
Application note
12 of 22
AN10963
NXP Semiconductors
AN10963
Application note
13 of 22
AN10963
NXP Semiconductors
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
&_vStackTop,
// The initial stack pointer
ResetISR,
// The reset handler
NMI_Handler,
// The NMI handler
HardFault_Handler,
// The hard fault handler
0,
// Reserved
0,
// Reserved
0,
// Reserved
0,
// Reserved
0,
// Reserved
0,
// Reserved
0,
// Reserved
SVCall_Handler,
// SVCall handler
0,
// Reserved
0,
// Reserved
PendSV_Handler,
// The PendSV handler
SysTick_Handler
// The SysTick handler
};
Fig 11. Redefined vector table (no peripheral interrupts)
If peripheral interrupts are required for an application, manually configuring the linker as
seen in Appendix A will allow a developer to reclaim some of the space normally
occupied by the vector table as well. The general process of doing this first requires
function and constant-data size analysis to make sure there are symbols which will fit
contiguously in the space to be freed. In the case of the included example project
LPCXpresso1114_blinky_tiny there is a look up table of 0x30 bytes used for GPIO
routines. After determining that savings can be had, two additional sections must be
added to the linker. The example uses .reset_vector and .vector_const as the names.
The vector table is split into two arrays, one of M0 core related handlers, the other of
peripheral handlers; the middle section of wakeup handlers is removed.
Complications in modifying the exception vector can be difficult to debug, as such the
recommendation is that developers first allocate space for additional functions and
variables by splitting the vector array into two parts and test their applications. After the
design is verified with the previous change define functions and constants with attributes
to place them in the .vector_const section.
AN10963
Application note
14 of 22
AN10963
NXP Semiconductors
.text :
{
KEEP(*(.reset_vector))
to M0
KEEP(*(.vector_const))
. = 0x7C;
KEEP(*(.isr_vector))
. = 0xC0;
*(.text*)
*(.rodata*)
} > MFlash32
Fig 12. Example linker configuration adding two new sections
Stock
25,772
314%
79%
Tiny
2,870
35%
9%
The second project is even more simplistic, it simply blinks an on board LED. The tiny
version of this project makes use of several advanced concepts covered in this
document, please be aware that it has custom linker configuration and startup routines.
Table 4.
Type
AN10963
Application note
Stock
1,448
18%
4%
Tiny
516
6%
2%
15 of 22
AN10963
NXP Semiconductors
5. Conclusion
The strategies and tools covered in this application note should give developers the
ability to ensure their programs will fit into their target hardware with minimal effort. By
analyzing their code, they will be better suited to meet product requirements using
devices with limited program storage. While this application note has been LPC11XX
centric, the recommendations made here can largely be applied to any NXP device.
6. Appendix A
Several steps are required to specify a custom linker script set. 2 First make a new folder
in the project named custom_ld. This will store the customized script files. Next copy
the automatically generated linker scripts with .ld extensions from the active target
folder (typically Debug or Release) into the custom_ld folder. Fig 13 illustrates where
the automatically generated scripts are stored in the project. Rename the file as per
Table 5. Before you modify the content of the scripts, you need to ensure that the
toolchain is configured to use them as seen in Fig 14. To redefine the memory map of
the virtual target device, manually edit Custom_mem.ld to suit your needs; in the
example shown in Fig 15 the flash section has been expanded to 1 MB. Finally update
Custom.ld to point to the Custom_mem.ld and Custom_lib.ld scripts in the newly created
custom_ld folder. An example of this is shown in Fig 16.
Table 5.
Renamed linker scripts
Original name
Renamed copy
PROJECTNAME_Debug.ld
Custom.ld
PROJECTNAME_Debug_mem.ld
Custom_mem.ld
PROJECTNAME_Debug_lib.ld
Custom_lib.ld
2.
AN10963
Application note
http://www.nxp.com/redirect/lpcxpresso.code-red-tech.com/LPCXpresso/node/31
All information provided in this document is subject to legal disclaimers.
16 of 22
AN10963
NXP Semiconductors
MEMORY
{
/* Define each memory region */
MFlash32 (rx) : ORIGIN = 0x0, LENGTH = 0x100000 /* 1M */
RamLoc8 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x2000 /* 8k */
}
/* Define a symbol for the top of each memory region */
__top_MFlash32 = 0x0 + 0x100000;
__top_RamLoc8 = 0x10000000 + 0x2000;
Underline indicates changes from original file
AN10963
Application note
17 of 22
AN10963
NXP Semiconductors
/*
* GENERATED FILE - DO NOT EDIT
* (C) Code Red Technologies Ltd,
* Generated C linker script file for LPC1114
*/
INCLUDE "../custom_ld / Custom_lib.ld "
INCLUDE "../custom_ld /Custom_mem.ld "
ENTRY(ResetISR)
Underline indicates changes from original file
AN10963
Application note
18 of 22
AN10963
NXP Semiconductors
7. Legal information
NXP Semiconductors products in such equipment or applications and
therefore such inclusion and/or use is at the customers own risk.
7.1 Definitions
Draft The document is a draft version only. The content is still under
internal review and subject to formal approval, which may result in
modifications or additions. NXP Semiconductors does not give any
representations or warranties as to the accuracy or completeness of
information included herein and shall have no liability for the consequences
of use of such information.
7.2 Disclaimers
Limited warranty and liability Information in this document is believed to
be accurate and reliable. However, NXP Semiconductors does not give any
representations or warranties, expressed or implied, as to the accuracy or
completeness of such information and shall have no liability for the
consequences of use of such information.
In no event shall NXP Semiconductors be liable for any indirect, incidental,
punitive, special or consequential damages (including - without limitation lost profits, lost savings, business interruption, costs related to the removal
or replacement of any products or rework charges) whether or not such
damages are based on tort (including negligence), warranty, breach of
contract or any other legal theory.
Notwithstanding any damages that customer might incur for any reason
whatsoever, NXP Semiconductors aggregate and cumulative liability
towards customer for the products described herein shall be limited in
accordance with the Terms and conditions of commercial sale of NXP
Semiconductors.
Right to make changes NXP Semiconductors reserves the right to make
changes to information published in this document, including without
limitation specifications and product descriptions, at any time and without
notice. This document supersedes and replaces all information supplied prior
to the publication hereof.
7.3 Trademarks
Notice: All referenced brands, product names, service names and
trademarks are property of their respective owners.
AN10963
Application note
19 of 22
AN10963
NXP Semiconductors
8. List of figures
Fig 1.
Fig 2.
Fig 3.
Fig 4.
Fig 5.
Fig 6.
Fig 7.
Fig 8.
Fig 9.
Fig 10.
Fig 11.
Fig 12.
Fig 13.
Fig 14.
Fig 15.
Fig 16.
AN10963
Application note
20 of 22
AN10963
NXP Semiconductors
9. List of tables
Table 1.
Table 2.
Table 3.
Table 4.
Table 5.
AN10963
Application note
21 of 22
AN10963
NXP Semiconductors
10. Contents
1.
2.
2.1
2.2
2.3
2.4
2.5
3.
3.1
3.2
3.3
3.4
4.
5.
6.
7.
7.1
7.2
7.3
8.
9.
10.
Introduction .........................................................3
Code size reduction strategies ..........................3
Avoid the use of high level library routines .........3
Target a larger (or virtual) device in the case of
link failure ...........................................................5
Configure linker options to remove unreferenced
sections ..............................................................6
Replace generic routines with application specific
ones ...................................................................7
Enable compiler optimization for code size ........8
Advanced topics..................................................9
Utilities................................................................9
Structure alignment ..........................................10
Disassembly.....................................................12
Vector table modification ..................................13
Example software projects ...............................15
Conclusion.........................................................16
Appendix A ........................................................16
Legal information ..............................................19
Definitions ........................................................19
Disclaimers.......................................................19
Trademarks ......................................................19
List of figures.....................................................20
List of tables ......................................................21
Contents.............................................................22
Please be aware that important notices concerning this document and the product(s)
described herein, have been included in the section 'Legal information'.