Please Note That Cypress Is An Infineon Technologies Company
Please Note That Cypress Is An Infineon Technologies Company
The document following this cover page is marked as “Cypress” document as this is the
company that originally developed the product. Please note that Infineon will continue
to offer the product to new and existing customers as part of the Infineon product
portfolio.
www.infineon.com
AN60486
If you have a question, or need help with this application note, contact msur@cypress.com.
AN60486 shows you how to optimize PSoC 1 C code to be faster and smaller and covers PSoC Designer project and
ImageCraft compiler settings that help you to do so. In addition, it offers several guidelines for efficient coding. This
application note assumes that you are familiar with PSoC 1, the PSoC Designer Integrated Design Environment (IDE),
and programming in C. For introductory information, refer to AN75320 – Getting Started with PSoC 1.
Contents Introduction
Introduction ....................................................................... 1 There are several ways to reduce the amount of flash
Project-Level Optimization ................................................ 2 (ROM) used in a PSoC Designer project. This can
Setting 1: Relocatable Code Start Address .................. 2 sometimes allow you to use a smaller PSoC device, which
reduces cost.
Setting 2: Configuration Initialization ............................ 3
Setting 3: Sublimation and Condensation .................... 4 The ImageCraft compiler Standard version is included with
Setting 4: Treat const as ROM Versus Treat const as PSoC Designer. You can also buy the Pro version, which
RAM ............................................................................. 6 offers more optimization, on the ImageCraft website. The
code snippets included in this application note can be
ImageCraft Pro Compiler Options ..................................... 6 used with both compilers. The examples shown were
Tips and Guidelines........................................................... 6 compiled with the Standard version; the additional
Guideline 1: Avoiding Function Calls in Interrupt optimizations that can be obtained using the Pro version
Service Routines .......................................................... 6 are also covered.
Guideline 2: Limiting Math Functions ........................... 8 To use the techniques explained in this document, you
Guideline 3: Using Array Indexing Versus Pointer ...... 10 should know how to develop and build PSoC Designer
Guideline 4: Using Switch Statement Versus If-Else projects and have a basic knowledge of C programming.
Statement ................................................................... 11 Refer to AN75320 to get started with PSoC 1.
Guideline 5: Writing Part of Code in Assembler ......... 12 While developing a PSoC Designer project, if you want to
Guideline 6: Manipulating Bits in PSoC 1 ................... 12 find out how much ROM space it is using, look at the
Guideline 7: Calculating C Code Flash Usage and Build tab in the Output status window, as shown in Figure
Execution Time ........................................................... 13 1. The code space used in this example is 543 bytes.
Conclusion ...................................................................... 15
Figure 1. PSoC Designer Build Message Showing ROM Figure 3. Relocatable Start Code Address Selection
and RAM Usage
The address you place in the text box is based on the size
Project-Level Optimization of the boot code, which you can find in the map file (.mp),
Several PSoC Designer code optimization settings are as shown in Figure 4.
available at Project > Settings. Figure 4. Map File in PSoC Designer
Setting 1: Relocatable Code Start Address
When a PSoC Designer project is built, the ImageCraft
compiler converts the C files into assembly files. The
assembler then converts them into relocatable object files.
Finally, the linker combines the relocatable object files to
produce the executable .hex file.
In addition to your code, the .hex file includes auto-
generated initialization code (boot code). This is followed
by a set of NOP instructions that act to reserve some flash
bytes for possible expansion of boot code. See Figure 2.
You can save flash by forcing your code to be located
immediately after the boot code.
BOOT
End
NOP
NOP
The map file shows the start and end addresses of
Start different areas of code, as shown in Figure 5. The boot
code is in area “TOP,” and your code is in area “lit.” You
PROGRAM can set the Relocatable code start address in Figure 3
CODE to the end address of the “TOP” area to use the flash
space most efficiently. For example, the default setting is
End 0x190 (start of “lit” area). If you change it to 0x151 (end of
“TOP” area), you can gain 63 (0x190 – 0x151 = 0x3F)
more bytes in ROM.
PSoC Designer lets you specify the start address of your
portion of the code by choosing Project > Settings. In the
window that pops up, select “Linker,” as shown in Figure
3.
Figure 5. “lit” and “TOP” Area in .mp File Figure 7. Configuration Initialization Selection
Setting 3: Sublimation and Condensation If all functions in all user module APIs are used in a
project, then a “no dead symbol found” message is
Sublimation and condensation are compression
displayed, as Figure 12 shows.
techniques provided by the ImageCraft Standard version.
These can be set by choosing Project > Settings and Figure 12. Sublimation with “no dead symbol found”
then selecting “Compiler” in the pop-up window, as shown Message
in Figure 9.
Condensation
When you select the Condensation option, a function is
formed for segments of code that are repeated in a
project, and each instance of that code is replaced with a
function call. In the simple example shown in Code 1, the
same code is repeated three times in various locations of
the project. When condensation is enabled, a single
instance of the code is converted into a function, and
Sublimation wherever the instance occurs, it is replaced by a function
When you select the Sublimation option, the compiler call to that function, as shown in Figure 13. All such
deletes the unused functions in the user module APIs created functions/procedures are placed at the end of the
(interface code), which saves space. code and below the label “<created procedures>,” as
shown in Figure 13. As you can see, the created
For example, you can place a PGA and a PWM user procedure for Code 1 starts at the label “<created
module in a project and call only the “Start” function for procedures>”; therefore, wherever the instance is used, it
both user modules. As shown in Figure 10 and Figure 11, is replaced with a call to the label “<created procedures>.”
you can save 142 bytes of flash by eliminating the other The functions at location “0520” and “052B” below
unused functions in those user module APIs. “<created procedures>” are other duplicate codes in the
project that are converted to callable functions.
Figure 10. ROM Usage Without Sublimation
Code 1
/* Instance one */
shadowRegs[PORT_2] |= 0x01;
PRT2DR = shadowRegs[PORT_2];
/* Instance two */
shadowRegs[PORT_2] |= 0x01;
PRT2DR = shadowRegs[PORT_2];
Figure 11. ROM Usage with Sublimation
/* Instance three */
shadowRegs[PORT_2] |= 0x01;
PRT2DR = shadowRegs[PORT_2];
Figure 13. Condensation for Code 1 in .lst File Figure 14. “text” Area in .mp File
Code 3
BYTE bVar1;
void TestFunc()
{
bVar1 = 1;
}
#pragma interrupt_handler
SleepTimerHandler;
void SleepTimerHandler(void)
{
TestFunc();
}
The floating-point math functions use the integer math Figure 24. ROM Usage for Code 7
libraries as the base. This means that the integer math
libraries are also required when using floating-point math.
Instead of using floating-point math, the variables can be
scaled to use integer math directly in cases where the
range of the variable is known.
For example, in the following two pieces of code, the
range of the variable is known to be two digits after the
decimal. Thus, if you multiply all of the floating-point
numbers by 100, you can use integer math instead of
floating-point math. In the example, the integer-math
method in Code 7 uses 761 bytes less than the floating-
point equivalent in Code 6, as shown in Figure 23 and
Figure 24.
Code 6 Use a Lookup Table Instead of Calculation
int iTest2, iTest3; Sometimes it may be more efficient to use a lookup table
float fTest1; (LUT) instead of doing calculations. There are multiple
void main(void) tradeoffs, such as speed, accuracy, and code space. The
{ choice is based on the type of application.
fTest1 = iTest2 * 2.42; For example, the project given in AN2017 – PSoC 1
if(fTest1 > 7.5) Temperature Measurement with Thermistor offers an
{ option for the floating-point and LUT method
iTest3 = 2; implementation. The use of a LUT in place of floating-point
} math in this project saves 4187 bytes of memory (3779
else bytes for the lookup table and 7966 bytes for the floating-
{ point equation), but accuracy is the tradeoff.
iTest3 = 1;
} Maintain Consistency in Data Type
} When choosing a data type for a variable, choose the
smallest data type required for the function. For example,
choose BYTE instead of int if the maximum value of the
Figure 23. ROM Usage for Code 6
variable is not greater than 256. Similarly, choose
unsigned variables instead of signed variables, as
applicable. For example, consider Code 4 if the variables
“iTest1” and “iTest2” do not exceed 255 in the program.
Then you can declare them as “unsigned char” instead of
“unsigned int,” as shown in Code 8. The ROM usage is
shown in Figure 25. Code 8 consumes 84 bytes less than
Code 4.
Code 8
unsigned char cTest1, cTest2;
void main(void)
Code 7 {
cTest1 = cTest2 *3;
int iTest1, iTest2, iTest3; }
void main(void)
{
iTest1 = iTest2 * 242;
if(iTest1 > 750)
{
iTest3 = 2;
}
else
{
iTest3 = 1;
}
}
Code 9
Figure 25. ROM Usage for Code 8
typedef struct
{
int iData;
BYTE bData;
}sData;
typedef struct
{
sData myArray[10];
}sArray;
sArray myTest;
sData* myPtr;
When you know the positive and negative range of a void main(void)
signed variable, you can offset the variable to bring it to {
positive values and thus use unsigned math functions. myPtr = myTest.myArray;
Similarly, if the variable is expected to have a value myPtr->iData = 100;
between –10 and +10, offset the variable by 10, so that }
the code 0 corresponds to –10, and 20 corresponds to
+10.
Figure 26. ROM Usage for Code 9
Maintain consistency in the data type used, because
typecasting is expensive in terms of code space. If you
absolutely need to use typecasting in the program,
typecast the variables to use the same math libraries to
save code space for the math libraries.
Code 12
Guideline 4: Using Switch Statement Versus BYTE bTest1, bTest2;
If-Else Statement void main(void)
{
For case decisions, you can use either a switch statement
if(bTest1 == 4)
or an if-else statement. The difference between the two is
{
that the switch statement always does a 16-bit bTest2=1;
comparison, whereas the if-else statement bases its }
comparison on the variable type. In the case of a single- else if(bTest1 == 3)
byte variable (BYTE), the ImageCraft compiler produces {
more efficient code using an if-else construct compared to bTest2 = 2;
a switch construct. This is because an 8-bit comparison }
needs less code space than a 16-bit comparison. else if(bTest1 ==2)
The switch statement uses 9 additional bytes, plus 5 bytes {
for each case. For example, a four-case switch statement bTest2 = 3;
with a default clause, as shown in Code 11, uses (9 + 4 × }
4) = 25 more bytes than the equivalent else
Code 12, as shown in Figure 28 and Figure 29. {
bTest2=4;
Code 11 }
}
BYTE bTest1, bTest2;
void main(void)
{ Figure 29. ROM Usage for Code 12
switch(bTest1)
{
case 4:
{
bTest2 = 1;
break;
}
case 3:
{
bTest2 = 2;
break;
}
case 2:
{
When the case decision is for a 2-byte variable (WORD),
bTest2 = 3;
the resulting code size is nearly identical for either
break;
implementation.
}
default:
{
bTest2 = 4;
}
}
}
Note The instruction MOV REG[0xD0],0x0 sets the Guideline 7: Calculating C Code Flash
RAM page number of the global variable Usage and Execution Time
“bTest1/bTest2/bTest3.”
When code memory usage and program execution time
If the size of a variable is a single bit or if all the bits are a concern, knowing the flash usage of a function or a
defined in the variable are being assigned/manipulated piece of code and its execution time can be useful in
simultaneously, then use direct assignment to manipulate manually optimizing the code.
them, as shown in Code 15. This uses the MOV
instruction, which is one cycle faster than the XOR, AND, To find out the code size of a function, refer to the
and OR instructions. <projectname>.mp file in Workspace > Output Files. The
.mp file provides details on code memory usage by code
Note To find out how many cycles an instruction takes to areas and the functions/constants defined in the areas. It
execute, refer to the Assembly Language User Guide, also provides details on RAM usage by RAM areas and
Appendix A5, “Instruction Set Summary,” in PSoC the address of global variables defined in those areas, as
Designer at Help > Documentation > Compiler and shown in Figure 31.
Programming Documents. Figure 31. Address and Memory Details in .mp File
Code 15
Code 16
while (1)
int bTest; {
void main(void) }
{ address: 8X XX JMP address
bTest = ++bTest;
} The JMP instruction takes five CPU cycles for execution. If
the CPU clock is 24 MHz, then the execution of the JMP
void function1(int a) instruction takes:
{ a++;
1
return; 5 × 24 µ𝑠 = 0.208 µ𝑠
}
At this rate, the CPU executes approximately one (JMP)
void function2(int b) instruction per 0.208 µS = (1/0.208) = 4.8 million
{ b--; instructions per second.
return;
} Example 2:
Consider an example for simple addition as follows.
Figure 32. Flash Calculation Using .mp File
void main(void)
{
BYTE bTest1, bTest2;
while(1)
{
bTest1 = bTest1 + bTest2;
}
}
Document History
Document Title: PSoC® 1 M8C ImageCraft C Code Optimization – AN60486
Document Number: 001-60486
PSoC is a registered trademark of Cypress Semiconductor Corp. PSoC Creator and PSoC Designer are trademarks of Cypress Semiconductor Corp.
All other trademarks or registered trademarks referenced herein are the property of their respective owners.
© Cypress Semiconductor Corporation, 2010-2014. The information contained herein is subject to change without notice. Cypress Semiconductor
Corporation assumes no responsibility for the use of any circuitry other than circuitry embodied in a Cypress product. Nor does it convey or imply any
license under patent or other rights. Cypress products are not warranted nor intended to be used for medical, life support, life saving, critical control or
safety applications, unless pursuant to an express written agreement with Cypress. Furthermore, Cypress does not authorize its products for use as
critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The
inclusion of Cypress products in life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies
Cypress against all charges.
This Source Code (software and/or firmware) is owned by Cypress Semiconductor Corporation (Cypress) and is protected by and subject to worldwide
patent protection (United States and foreign), United States copyright laws and international treaty provisions. Cypress hereby grants to licensee a
personal, non-exclusive, non-transferable license to copy, use, modify, create derivative works of, and compile the Cypress Source Code and derivative
works for the sole purpose of creating custom software and or firmware in support of licensee product to be used only in conjunction with a Cypress
integrated circuit as specified in the applicable agreement. Any reproduction, modification, translation, compilation, or representation of this Source
Code except as specified above is prohibited without the express written permission of Cypress.
Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the
right to make changes without further notice to the materials described herein. Cypress does not assume any liability arising out of the application or
use of any product or circuit described herein. Cypress does not authorize its products for use as critical components in life-support systems where a
malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress’ product in a life-support systems
application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
Use may be limited by and subject to the applicable Cypress software license agreement.