ICCAVR
ICCAVR
INTRODUCTION .............................................................................................5
Version, Trademarks, and Copyrights .................................................. 5
Software License Agreement................................................................ 6
IMPORTANT: Licensing the Software ................................................ 8
Transferring a License to Another Computer ....................................... 9
Using the Hardware Dongle ............................................................... 10
Annual Maintenance ........................................................................... 11
Support................................................................................................ 12
Product Updates .................................................................................. 14
File Types and File Extensions ........................................................... 15
ImageCraft C Compiler Extensions .................................................... 17
Converting from Other ANSI C Compilers ........................................ 19
Optimizations...................................................................................... 21
Acknowledgments .............................................................................. 24
GETTING STARTED .....................................................................................25
Quick Start Guide ............................................................................... 25
Example Projects ................................................................................ 27
EMBEDDED PROGRAMMING....................................................................29
Embedded Programming Basics ......................................................... 29
Some Pitfalls ....................................................................................... 30
Best Practices ...................................................................................... 32
Bit Twiddling ...................................................................................... 34
General Debugging Hints ................................................................... 36
Debugging and Flash Programming With AVR Studio ..................... 40
CODE::BLOCKS IDE .....................................................................................43
Code::Blocks IDE ............................................................................... 43
Useful General Settings for CodeBlocks IDE .................................... 45
ImageCraft Enhancements to CodeBlocks ......................................... 46
Migrating From Version 7 Projects .................................................... 47
IDE and the Compiler ......................................................................... 48
Project Management ........................................................................... 49
Editor .................................................................................................. 51
Handy CodeBlocks Editor Features.................................................... 52
Multi-Target Support and Build Properties ........................................ 53
C::B Supported Variables ................................................................... 60
Menu Reference: Build Options - Project........................................... 64
1
JumpStarter C for AVR – C Compiler for Atmel AVR
2
JumpStarter C for AVR – C Compiler for Atmel AVR
3
JumpStarter C for AVR – C Compiler for Atmel AVR
4
INTRODUCTION
LIMITED WARRANTY
LIMITED WARRANTY. ImageCraft warrants that the SOFTWARE will perform
substantially in accordance with the accompanying written materials and will be free
from defects in materials and workmanship under normal use and service for a period
of thirty (30) days from the date of receipt. Any implied warranties on the SOFTWARE
are limited to 30 days. Some states do not allow limitations on the duration of an
implied warranty, so the above limitations may not apply to you. This limited warranty
gives you specific legal rights. You may have others, which vary from state to state.
CUSTOMER REMEDIES. ImageCraft’s entire liability and your exclusive remedy shall
be, at ImageCraft’s option, (a) return of the price paid or (b) repair or replacement of
the SOFTWARE that does not meet ImageCraft’s Limited Warranty and that is
returned to ImageCraft. This Limited Warranty is void if failure of the SOFTWARE has
resulted from accident, abuse, or misapplication. Any replacement SOFTWARE will
be warranted for the remainder of the original warranty period or 30 days, whichever is
longer.
NO OTHER WARRANTIES. ImageCraft disclaims all other warranties, either express
or implied, including but not limited to implied warranties of merchantability and fitness
for a particular purpose, with respect to the SOFTWARE, the accompanying written
materials, and any accompanying hardware.
6
JumpStarter C for AVR – C Compiler for Atmel AVR
7
JumpStarter C for AVR – C Compiler for Atmel AVR
8
JumpStarter C for AVR – C Compiler for Atmel AVR
9
JumpStarter C for AVR – C Compiler for Atmel AVR
10
JumpStarter C for AVR – C Compiler for Atmel AVR
Annual Maintenance
Purchasing a license also provides a year of maintenance support. During the
maintenance period, you can upgrade to the latest version by installing the latest
demo from our website and contact us at [email protected] for support.
After one year, the compiler will emit an informational message in the IDE status
window informing you that your maintenance period has expired. This does not affect
the generated code. You may still download the latest demo, but we may request that
you have a current maintenance contract before providing support.
Maintenance is very inexpensively priced at $50 per 12 months. You may purchase it
on our website on the respective compiler tools page and by providing your serial
number in the customer notes. Once we process the order, we will email you a
maintenance code which you enter using the ICCV8AVR License Manager.
11
JumpStarter C for AVR – C Compiler for Atmel AVR
Support
Our experience since releasing our first compiler in 1994 is that most compiler “bug
reports” are in fact not defects with our compilers. If you are not experienced with
Standard C or embedded system programming, please refer to a good C tutorial book
or websites for help or try the C FAQ site http://c-faq.com/.
Email is the best method to contact us. We will usually get back to you within the same
day and sometimes even the same hour or minute. Some people assume that they
will only get help if they use threatening tones or are abusive. Please do not do this.
We will support you to the best of our ability. We build our reputation based on
excellent support.
Before contacting us, find out the version number of the software by selecting “About
JumpStarter C for AVR” in the Help menu.
E-mail support questions to [email protected]
Program updates are available free of charge for the first six months. Files are
available from our website: http://www.imagecraft.com
Sometimes we will request that you send us your project files so we may duplicate a
problem. If possible, please use a zip utility to include all your project files, including
your own header files, in a single email attachment. If you cannot send us the entire
project when requested, it is usually sufficient if you can construct a compilable
function and send that to us. Please do not send us any files unless requested.
We have a mailing list called icc-avr pertinent to our JumpStarter C for AVR product
users. To subscribe, send an email to [email protected].
You do not need a Yahoo ID to join. However, if you wish to use the Yahoogroups web
features (e.g., file area, checking the archive, etc.), then you must obtain a Yahoo ID.
The mailing list should not be used for general support questions. On the other hand,
our customers who are active on the mailing lists probably have more hardware-
specific knowledge than we do, as we are primarily a software company. We may
request that you send your questions there.
Our postal address and telephone numbers are
ImageCraft
2625 Middlefield Rd, #685
Palo Alto, CA 94306
U.S.A.
(650) 493-9326
(866) 889-4834 (FAX, toll free)
12
JumpStarter C for AVR – C Compiler for Atmel AVR
If you purchased the product from one of our international distributors, you may wish
to query them for support first.
13
JumpStarter C for AVR – C Compiler for Atmel AVR
Product Updates
The product version number consists of a major number and a minor number. For
example, V8.02 consists of the major number of 8 and the minor number of .02. Within
the initial six months of purchase, you may update to the latest minor version free of
charge. To receive updates afterward, you may purchase the low-cost annual
maintenance plan. Upgrades to a new major version usually require an additional
cost.
With the software protection scheme used in the product, you get the upgrades by
downloading the latest “demo” available on the website and installing it in the same
PC as your current installation. Your existing license will work on the newly installed
files. You may have multiple versions of the products on the same machine
concurrently. Do keep in mind that they share the same Windows Registry entries and
all other system-related information.
14
JumpStarter C for AVR – C Compiler for Atmel AVR
Input Files
.a - is a library file. The package comes with several libraries. libcavr.a is the
basic library containing the Standard C library and Atmel AVR-specific routines.
The linker links in modules (or files) from a library only if the module is referenced.
You may create or modify libraries as needed.
Our library format is in ASCII.
.c - is a C source file.
.h - is a header file.
.i - is a C preprocessed source file. This is removed after a successful compile.
.s - is an assembly source file or an output file from the compiler. If latter, it is
removed after a successful compile.
Output Files
.cof - a COFF format output file.
.dbg - ImageCraft internal debug command file.
.eep - an Intel HEX output file containing EEPROM initialization data.
.elf - a production ELF file. Useful for use with Atmle Studio 4 or Studio 6.
.hex - an Intel HEX output file.
15
JumpStarter C for AVR – C Compiler for Atmel AVR
.lst - an interspersed C and asm listing file. The object code and final addresses
for your program files are gathered into a single listing file.
.mp - a map file. It contains the symbol and size information of your program in a
concise form.
.o - an object file, produced by the assembler. An output executable file is the
result of linking multiple object files.
.s - for each C source file, an assembly output is generated by the compiler. This
is deleted after a successful compile.
.s19 - a Motorola Motorola/Freescale S19 Record executable file.
16
JumpStarter C for AVR – C Compiler for Atmel AVR
Extended Keywords
__flash refers to flash objects, e.g. “__flash unsigned int i = 0x55;”
__packed modifies a struct type so that no padding is inserted between elements
of the struct. __packed must appear before the struct keyword:
// correct
__packed struct ...
or
typedef __packed struct ...
// incorrect
struct __packed ...
Notes:
1. if placed after the struct keyword, then __packed is actually a struct tag
name, and not interpreted as a keyword, e.g. as in the last example above.
2. some CPU, for example, the ARM Cortex-M0, do not support non-aligned access
of 16 or 32 bit data. In that case, accesses to packed structure members may
cause the compiler or your program to fail.
#pragma
The supported #pragma are described in Pragmas.
Predefined Macros
The supported predefined macros are described in Predefined Macros.
C++ Comments
If you enable Compiler Extensions (Project->Options->Compiler), you may use
C++ style comments in your source code.
17
JumpStarter C for AVR – C Compiler for Atmel AVR
Binary Constants
If you enable Compiler Extensions (Project->Options->Compiler), you may use
0b<1|0>* to specify a binary constant. For example, 0b10101 is decimal 21.
Inline Assembly
You may use the pseudo function asm(“string”) to specify inline asm code.See
Inline Assembly.
18
JumpStarter C for AVR – C Compiler for Atmel AVR
#pragma abs_pragma:0x1000
char porta;
#pragma end_abs_pragma
Nevertheless, to fully support AVR’s Harvard Architecture, we added __flash
extended keyword to specify that location of the item is in the flash memory.
__flash may appear any places where const or volatile is valid.
Calling convention. The registers used to pass arguments to
functions are different between the compilers. This should
normally only affect hand-written assembly functions.
Some compilers do not support inline assembly and use
intrinsic functions and other extensions to achieve the same
goals.
19
JumpStarter C for AVR – C Compiler for Atmel AVR
20
JumpStarter C for AVR – C Compiler for Atmel AVR
Optimizations
ImageCraft compilers are derived from the LCC compiler (see Acknowledgments). As
such, the portable front end of the LCC compilers perform the following optimizations:
Algebraic Simplifications and Constant Folding.
The compiler may replace expensive algebraic expressions with simpler
expressions (e.g., adding by 0, dividing by 1, etc.). The compiler also evaluates
constant expressions and “folds” them (e.g., 1+1 becomes 2). The compiler also
performs these optimizations on floating-point constants and the results may be
slightly different if the floating-point constants are not “folded.” This is because the
precision and range of the floating-point operations of the host CPU (e.g., Intel
processors) differ from the target CPU. In most cases, any minor differences will
not be an issue.
Basic Block Common Subexpression Elimination.
Expressions that are reused within a basic block (i.e., a sequence of straight line
code without jumps) may be cached in a compiler-created temporary and not
recomputed.
Switch Optimizations.
The compiler analyzes the switch values and generates code using a combination
of binary searches and jump tables. The jump tables are effective for densely
packed switch values and the binary searches locate the right jump table quickly.
In the case where the values are widely spread or few in numbers, a simple if-
then-else search is performed.
The compiler code generator (the “backend”) uses a technique called bottom-up tree
rewriting with dynamic programming to generate assembly code, meaning that the
generated code is locally (i.e., per expression) optimal. In addition, the backend may
perform the following optimizations. Note that these are ImageCraft enhancements
and not part of the standard LCC distribution.
Peephole Optimizations.
While locally optimal, the generated code may still have redundant fragments
resulting from different C statements. Peephole optimizations eliminate some of
these redundancies.
Register Allocation.
For targets with multiple machine registers (e.g., AVR, MSP430, and ARM), for
each function, the compiler performs register allocation and tries to pack as many
local variables as possible into the machine registers and thereby increase
21
JumpStarter C for AVR – C Compiler for Atmel AVR
22
JumpStarter C for AVR – C Compiler for Atmel AVR
23
JumpStarter C for AVR – C Compiler for Atmel AVR
Acknowledgments
The front end of the compiler is derived from lcc: “lcc source code (C) 1995, by David
R. Hanson and AT&T. Reproduced by permission.”
The CodeBlocks IDE is an open-source cross-platform C/C++ IDE from http://
www.codeblocks.org.
The assembler/linker is a distant descendant of Alan Baldwin’s public-domain
assembler/linker package.
The Application Builder was originally written by Andy Clark.
Some of the 16-bit arithmetic multiply/divide/modulo routines were written by Atmel.
Other people have contributed to the floating-point and long arithmetic library routines,
for which we are eternally grateful to: Jack Tidwell, Johannes Assenbaum, and Everett
Greene.
Frans Kievith rewrote some of the library functions in assembly. David Raymond
contributed to smaller divide, mod, and multiply functions. The io????v.h header
files are written by Johannes Assenbaum.
The C preprocessor is licensed from Unicals http://www.unicals.com.
The installation uses the 7 Zip program 7za.exe for unpacking some of the files. A
copy of the program is installed under c:\iccv8avr\bin. 7 Zip uses the GNU LGPL
license and you may obtain your copy of the program from their site , http://
www.7-zip.org/.
The Atmel USB drivers and installer and the AVR XML device description files are
distributed with permission from Atmel Corporation.
All code used with permission. Please report all bugs to us directly.
24
GETTING STARTED
Creating a Project
1. Start the Code::Blocks IDE.
2. Click on File->New->Project...
3. Click on ImageCraft AVR Project.
4. Click on Go.
5. Enter the name of your project in the Project Title text box. The other empty
or <invalid> text boxes will be filled in automatically for you as you enter the
project title.
6. Click on Next when you are satisfied with the project name and paths.
7. Click Finish and you will have a project framework set up for you with the
main.c already created.
NOTE: We recommend that you enter #include <iccioavr.h> in each
source file that contains code that references the target Atmel part. This allows for
changing the target in the IDE without requiring an edit of each file that accesses
the target processor. Ultimately this makes the source more portable from project
to project.
8. Click on Ok.
9. At this point you are ready to begin writing code for your project.
10. Repeat items 1 - 8 for as many projects that you want in the current workspace.
Compiling/Building a Project
1. If your workspace only contains one project, go to item #2. Otherwise, if your
JumpStarter C for AVR – C Compiler for Atmel AVR
26
JumpStarter C for AVR – C Compiler for Atmel AVR
Example Projects
Our compiler product is designed with the philosophy of powerful professional
features that are easy to use. The compilers are command-line programs with lots of
command-line switches to customize their operations, but the user interface is
primarily through a GUI IDE (Integrated Development Environment).
The best way to get familiarized with our tools is by working with the provided example
programs. Once installed, invoke the “JumpStarter C for AVR CodeBlocks IDE” from
the Start menu ImageCraft Development Tools, then File->Open, making
sure that the file type is set to either “All Files” or “CB Workspace Files” and browse to
c:\iccv8avr\examples.avr\ and select examples.workspace.
The C::B IDE organizes your work files into projects and workspace. Think of a project
as a set of files that produce one executable, and a workspace consists of one or
more possibly related projects. For example, you may want to organize all projects for
a particular vendor under a single workspace, or you may simply work at the project
level and eschew workspace altogether.
The examples.workspace comprises over a few projects. Invoking Build-
>Rebuild Workspace will rebuild all the projects. They are a collection of projects
from various and sundry sources that are intended to give you some insight into using
our development tool set and the new C::B IDE.
You will also note that some projects have warnings related to the target part being
replaced by a newer part. Those projects will be updated to the newer target part in
the near future.
At any given time, one of the projects is the active project, indicating by the project
name being in bold in the workspace list. When you do Build->Build or Build-
>Rebuild, the active project will be built.
Source files are C or assembly files that are needed for the project. They have .c and
.s extensions respectively. C::B display them under the “project” folder icon under
each project name. Double-click on a file to open the file in the editor.
After you have become accustomed to working with the examples, take a look at the
"Properties..." of some of the projects. It won't be apparent immediately, but this entire
workspace was created in such a way that it is portable. By placing the workspace
file, examples.workspace, and the CBprojects directory inside the
examples.avr directory and setting the IDE to use "relative paths," the entire project
is portable. You can move examples.avr directory to another disk drive, to another
computer, or just another layer up or down in its current path and it will remain usable
without modification of file paths in the projects.
27
JumpStarter C for AVR – C Compiler for Atmel AVR
If you browse through the examples.avr directory, you will notice that two proejcts
are not in the examples.workspace: “AVR Butterfly” and “RTEEPROM.” This is
because “AVR Butterfly” requires Code Compression to build, which is only available
under the ADV or PRO license, and RTEEPROM builds a library .a file, which is again,
only available under the ADV or PRO license. Of course, you may incorporate the
rteeprom.c source file in your own project without building a library archive file.
28
EMBEDDED PROGRAMMING
Some Pitfalls
If you only have experience in writing C/C++/Java/etc. for PC, Mac, or other host
platforms, there are some learning curves in writing efficient embedded programs. For
example:
Our compilers are C compilers and not C++ compilers. Besides the obvious
difference that C does not support classes, templates, etc., declarations are
allowed only after a beginning { and the compiler does not perform much of the
cross-module checking. For example, if you define a global variable to have type
A, but then declare it in another module that it has type B, unless the compiler
sees the conflicting types in the same translation unit, then it will not complain,
unless you have the PRO edition and enable Cross Module Type Checking.
See Build Options - Compiler.
Typically a “Hello World” program will not compile as is, because printf and
other stdio functions require a low-level function (putchar) to write to the output
device. This is highly device- and board-specific. For example, some devices may
not support any UART port at all, or sometimes you want the output to be
displayed on a LCD.
Therefore, to use printf and other output functions, you must supply your own
putchar routines. We do provide some examples under the
c:\iccv8avr\examples.avr\ directory.
Embedded devices typically have small memory footprints. A full implementation
of printf with %f floating-point support typically uses over 10K bytes of program
memory, which is sometimes bigger than the total memory available in some of
these devices.
For this reason, we provide 3 versions of the printf functions, with different
features and different memory requirements. You can select the different versions
under Project->Build Options->Target.
Even then, sometimes you just cannot use printf and must use a lower-level
function instead.
Writing code for a microcontroller (MCU) typically requires initializing the MCU
peripheral devices by writing various values to their IO registers, and then read
and write to other IO registers to perform some functions, such as converting an
analog signal into digital value using the ADC converter.
C excels in allowing you to write such code without resorting to writing assembly
code, as the IO registers usually are mapped in such a way that you can refer to
them by name, e.g.
30
JumpStarter C for AVR – C Compiler for Atmel AVR
31
JumpStarter C for AVR – C Compiler for Atmel AVR
Best Practices
The best way to debug your programs is not to have bugs in the first place. The
following rules may help eliminate some of the problem areas.
Enable MISRA Checks and Cross Module Type Checking. See Build Options -
Compiler.
Heed the warnings from the compiler. For example, when our compiler says,
“calling a function without prototype may cause a runtime error...,” we mean it. If
your function returns a long and you do not declare the prototype, for example,
your program may fail.
Declare handlers for all interrupts, even if you don’t expect the interrupt to trigger.
Have the fail-safe handler do something that informs you that, indeed, something
unexpected has happened.
Accessing a non-8-bit variable is often non-atomic on 8-bit architectures. For
example,
extern unsigned counter;
...
while (counter != SOME_NUMBER)
...
Accessing counter may require multiple instructions, which can get interrupted.
If counter is modified inside an interrupt handler, then the value accessed in the
loop may be inconsistent.
Setting a bit in an 8-bit variable is also often non-atomic. When in doubt, check the
.lst listing file.
Pointers and arrays are not the same. Arrays have storage space associated with
them. A pointer is meant to contain address of another storage space.
Access pointers and arrays with care. If a pointer does not contain a valid
address, reading it will return garbage and writing to it could cause your program
to crash. Do not make any assumption about variable layout in SRAM or on the
stack.
C does not do array bound checking so it is possible for you to accidentally
access off the array boundary. Remember that array index starts at 0 and thus the
last element is one less than the size you declare.
Use typecast only when absolutely necessary.
32
JumpStarter C for AVR – C Compiler for Atmel AVR
Declare any variables that may change by an interrupt handler with the
volatile qualifier.
Some CPUs have an alignments requirement. For example, reading a byte
stream and then trying to access a 16-bit or 32-bit item in an arbitrary position of
the stream may cause the CPU to fault due to the item address not being aligned.
33
JumpStarter C for AVR – C Compiler for Atmel AVR
Bit Twiddling
A common task in programming the microcontroller is to turn on or off some bits in the
IO registers. Fortunately, Standard C is well suited to bit twiddling without resorting to
assembly instructions or other non-standard C constructs. C defines some bitwise
operators that are particularly useful.
Note that while our compilers generate optimal instructions for bit operations, they
may be non-atomic even on 8-bit variables. Use them with care if the variable are
accessed in both the main application and inside an interrupt handler.
a | b - bitwise or. The expression denoted by a is bitwise or’ed with the
expression denoted by b. This is used to turn on certain bits, especially when
used in the assignment form |=. For example:
PORTA |= 0x80; // turn on bit 7 (msb)
a & b - bitwise and. This operator is useful for checking if certain bits are set. For
example:
if ((PINA & 0x81) == 0) // check bit 7 and bit 0
Note that the parentheses are needed around the expressions of an & operator,
since it has lower precedence than the == operator. This is a source of many
programming bugs in C programs. Note the use of PINA vs. PORTA to read a port.
a ^ b - bitwise exclusive or. This operator is useful for complementing a bit. For
example, in the following case, bit 7 is flipped:
PORTA ^= 0x80; // flip bit 7
~a - bitwise complement. This operator performs a ones-complement on the
expression. This is especially useful when combined with the bitwise and operator
to turn off certain bits:
PORTA &= ~0x80; // turn off bit 7
The compiler generates optimal machine instructions for these operations. For
example, the sbic instruction might be used for a bitwise and operator for
conditional branching based on bit status.
Bit Macros
Some examples of macros that can be useful in handling bit manipulations are:
#define SetBit(x,y) (x|=(1<<y))
#define ClrBit(x,y) (x&=~(1<<y))
#define ToggleBit(x,y) (x^=(1<<y))
34
JumpStarter C for AVR – C Compiler for Atmel AVR
35
JumpStarter C for AVR – C Compiler for Atmel AVR
36
JumpStarter C for AVR – C Compiler for Atmel AVR
If you access a global variable inside an interrupt handler, be sure that any
modifications of the global variable in the main application cannot be interrupted.
Non-atomic access (i.e., access that may require multiple machine instructions)
includes access to 16- or 32-bit variables, bit operations and non-basic C types
(i.e., array).
Spurious or unexpected interrupt behaviors can crash your program:
You should always set up a handler for “unused” interrupts. An unexpected
interrupt can cause problems.
Beware that accesses to variables larger than the natural data size of the
CPU require multiple accesses. For example, writing a 16-bit value on an 8-bit
CPU probably requires at least two instructions. Therefore, accessing the
variable in both the main application and interrupt handlers must be done with
care. For example, the main program writing to the 16-bit variable may get
interrupted in the middle of the 2-instruction sequence. If the interrupt handler
examines the variable value, it would be in an inconsistent state.
Most CPU architectures do not allow nested interrupts by default. If you
bypass the CPU mechanism and do use nested interrupts, be careful not to
have unbound nested interrupts.
On most systems, it is best to set your interrupt handlers to execute as fast as
possible and to use as few resources as possible. You should be careful
about calling functions (your own or a library) inside an interrupt handler. For
example, it is almost never a good idea to call such a heavy-duty library func-
tion as printf inside an interrupt handler.
With few exceptions, our compilers generate reentrant code. That is, your
function may be interrupted and called again as long as you are careful with
how you use global variables. Most library functions are also reentrant, with
printf and related functions being the main exceptions.
Test your external memory interface carefully. For example, do not just walk the
entire external RAM range and verify write a few patterns in a single loop, as it
might not detect the case where the high address bits are not working correctly.
The compiler may be doing something unexpected, even though it is correct. For
example, for RISC-like targets such as the Atmel AVR, TI MSP430 and the ARM
CPU, the compilers may put multiple local variables in the same machine register
as long as the usage of the local variables does not overlap. This greatly improves
the generated code, even though it may be surprising when debugging. For
example, if you put a watch window on two variables that happen to be allocated
to the same register by the compiler, both variables would appear to be changing,
even though your program is modifying only one of them.
37
JumpStarter C for AVR – C Compiler for Atmel AVR
38
JumpStarter C for AVR – C Compiler for Atmel AVR
Listing File
One of the output files produced by the compiler is a listing file of the name
<file>.lst. The listing file contains your program's assembly code as generated by
the compiler, interspersed with the C source code and the machine code and program
locations. Data values are not included, and library code is shown only in the
registered version.
Filenames with .lis extensions are assembler output listing files and do not contain
full information and should generally not be used.
39
JumpStarter C for AVR – C Compiler for Atmel AVR
General Comments
For using with our compiler, you do not use AS6 to build your project or to edit your
code. You continue to use our CodeBlocks IDE to maintain your project. When you
build a project using our compiler, the following output files are produced, all with the
project name as the filename but with different extensions:
.COF - COFF file output, suitable for source debugging.
.ELF - ELF file output, suitable for device programming. Note that some other
compilers emit ELF file for debugging and AS6 supports ELF for debugging.
However, the ELF file produced by ICC does not contain debug symbols and
cannot be used for debugging.
This is the recommended file for device programming as it can contain settings for
the fuse, lockbits, etc., as well as content for both flash and EEPROM.
.HEX - Intel HEX file output, suitable for flash programming. The .elf file should be
used in most cases.
.EEP - Intel HEX file output containing the EEPROM content.
With AS6, you may connect to a real AVR device through one of the supported
interfaces such as JTAGICE3, or use the built-in software simulator.
40
JumpStarter C for AVR – C Compiler for Atmel AVR
1. Select the Tool (the interface) and target Device and click Apply.
2. Select Production file on the left pane.
3. Browse and select the .elf file, select any optional checkboxes and click on
Program to program the device.
Instead of using the .elf file, you can also select Memories on the left pane and
choose to program a MCU part independently of the other parts. In this case, you will
browse and select Intel HEX files.
41
JumpStarter C for AVR – C Compiler for Atmel AVR
42
CODE::BLOCKS IDE
Code::Blocks IDE
Introduced in V8 of our product line, Code::Blocks IDE (C::B) is an open-source cross-
platform C/C++ IDE based on the concept of functional extensions using plugins. This
allows developers to provide plugins that enhance the IDE without hard-coding these
enhancements into the core IDE code.
C::B has workspace and project support and symbol browsing (e.g., jumping to a
function declaration or implementation), and the editor supports all modern features
such as syntax highlighting and code folding.
The base C::B is very flexible and can support a variety of host and cross compilers.
Our goal in porting C::B is to make it integral to the specific product that we support.
For example, you may invoke Project->Build Options and select the target
device list by name, and the appropriate memory addresses will automatically be used
when you build the projects.
For users of our previous generation of IDE, this is the type of features that makes our
IDE very easy to use. We expended a lot of effort to bring ease-of-use features to
C::B.
The C::B project has extensive documentation on the IDE at http://
www.codeblocks.org/, as such we will not describe C::B in details. This chapter
highlights the modifications ImageCraft made to C::B to better support our users, plus
the main C::B features that are most useful to our users.
Basic Workflow
The basic workflow is to organize all files that are used to produce a single executable
output into a project. The most important files are the source files (.c extension for a
C source file and .s for assembly source file), but notes and include files can be
added to the project. Multiple related projects (e.g., an application project and the
bootloader project) can optionally be organized in a workspace.
For each project, you specify the compiler options using Project->Build
Options and invoke Project->Build (or click on the Build icon on the toolbar) to
build your project whenever you modify the source files. On some products, we
include extras such as the Application Builder for generating peripheral initialization
code via a GUI interface and direct device programming support of the target devices.
JumpStarter C for AVR – C Compiler for Atmel AVR
44
JumpStarter C for AVR – C Compiler for Atmel AVR
45
JumpStarter C for AVR – C Compiler for Atmel AVR
46
JumpStarter C for AVR – C Compiler for Atmel AVR
47
JumpStarter C for AVR – C Compiler for Atmel AVR
48
JumpStarter C for AVR – C Compiler for Atmel AVR
Project Management
The IDE’s Project Manager allows you to group a list of files into a project. This allows
you to break down your program into small modules. When you perform a project
Build function, only source files that have been changed are recompiled. Header file
dependencies are automatically generated. That is, if a source file includes a header
file, then the source file will be automatically recompiled if the header file changes.
Unlike the IDE in the previous versions of our products, C::B does not use the
standard makefile but instead uses an internal XML-based schema. Since a number
of our users like the option of using a standard makefile (perhaps in their batch build
and test process), C::B can generate a makefile if requested.
49
JumpStarter C for AVR – C Compiler for Atmel AVR
Building a Project
You can build a project by invoking Build->Build (Ctrl+F9)or by clicking on the
Build icon. The project manager recompiles only the files that are changed. This can
save a significant amount of time when your project gets larger. In some rare cases, if
somehow the project manager does not rebuild a source when it should, you can
perform a Build->Rebuild (Ctrl+F11) to rebuild all source files.
The various “Run” commands (e.g., Build->Build and Run) do not work for the
embedded products.
50
JumpStarter C for AVR – C Compiler for Atmel AVR
Editor
The C::B editor has most of the features you expect from a modern editor:
language-sensitive syntax highlighting
line number display
bookmarks
code folding: i.e., collapse a block of code
automatic brace matching
block indent and outdent
integrated code browing: the editor parses the C source files and allow you to
jump to function definition by selecting the function name on the drop-down list,
and other features
plus many other features. Since it uses a plugin architecture, you may even download
plugins that extend the functionality of the IDE and the editor. For example, Plugins-
>AStyle does automatic source-code formatting. To select a different formatting
style, use Settings->Editor->Source Formatter.
51
JumpStarter C for AVR – C Compiler for Atmel AVR
52
JumpStarter C for AVR – C Compiler for Atmel AVR
Output Directories
The default output directory for the primary target is .\(project directory), and
.\<target name> for non-default targets.
It is possible for multiple targets to share the same output directory (e.g.: the project
directory), but it is recommended to use different directories for cleaner housekeeping.
The Output Directory of a target can be changed by invoking Project->Build
Options, followed by switching to the Paths tab to enter the change in the Output
Directory box.
53
JumpStarter C for AVR – C Compiler for Atmel AVR
The active target for a project is indicated by the drop down box in the compiler
toolbar. You may select the active target using the drop down box, or by the menu
checkmark at Build->Select target.
54
JumpStarter C for AVR – C Compiler for Atmel AVR
Note that the Debug/Download option only displays the active target option. This may
change in a later release.
55
JumpStarter C for AVR – C Compiler for Atmel AVR
To find out which target(s) a file belongs to, right clicking on a file name in the Project
file list and bring up Properties, then switch to the Build tab:
56
JumpStarter C for AVR – C Compiler for Atmel AVR
At any time, you may invoke Project->Properties, and then switch to the Build
targets tab to examine or modify the files that belong to a target.
57
JumpStarter C for AVR – C Compiler for Atmel AVR
Add target adds a new target. You have to manually enter all its properties (compiler
and device properties, source file references etc.). The output directory default to
.\<target name>\, and the output name defaults to <target name>. These can
be changed in Build Options.
Rename a target changes the name of the selected target. It does not change the
output filename, or the output directory. You must change those manually if you so
desire.
Duplicate a target is similar to New target, except that it also copies the selected
target along with all its properties (compiler and device properties, source file
references etc.) to another newly named target.
Delete a target removes the selected target from the project. No files are removed,
however; you must remove those manually.
Virtual targets provide the ability to group multiple build targets under a "container
name". Then, you may select the virtual target as the active build target, and build all
the member build targets as a group. For example, you may create an “All” virtual
target which includes all the targets in the group.
Dependencies allows you to specify external files on which a relink occurs.
Re-order allows you to specify the build sequence.
Build options invokes the Project Options dialog for the selected target.
Create project from target exports the selected target as a new project. The new
project name will be the same as the original target name and it will have a single
target also with the same name. All options including the output directory and output
file names and source file references are retained.
If you move this newly exported project to a different folder, its relative file references
will become invalid. You may have to remove/re-add the file references and edit the
project options paths.
Building a Project
When you build a project, only the active target is built. As mentioned above, you can
create a virtual target so that multiple targets can be built at once, if desired.
58
JumpStarter C for AVR – C Compiler for Atmel AVR
Building a Workspace
A Workspace is made up of multiple projects. Within a workspace, each project may
have a different active target than the other projects in the same workspace. However,
when you perform a Build->Build Workspace or Build->Rebuild
Workspace, then the current active target is used for ALL projects, regardless of each
project’s own active target setting. If a project does not have a target by that name, it
will not be built.
59
JumpStarter C for AVR – C Compiler for Atmel AVR
60
JumpStarter C for AVR – C Compiler for Atmel AVR
$(ACTIVE_EDITOR_EXT)
The extension of the currently active file.
$(ALL_PROJECT_FILES)
A string containing the names of all files in the current project.
$(MAKEFILE)
The filename of the makefile.
$(CODEBLOCKS), $(APP_PATH), $(APPPATH), $(APP-PATH)
The path to the currently running instance of CodeBlocks.
$(DATAPATH), $(DATA_PATH), $(DATA-PATH)
The “shared” directory of the currently running instance of CodeBlocks.
$(PLUGINS)
The plugins directory of the currently running instance of CodeBlocks.
Build targets
$(FOOBAR_OUTPUT_FILE)
The output file of a specific target.
$(FOOBAR_OUTPUT_DIR)
The output directory of a specific target.
$(FOOBAR_OUTPUT_BASENAME)
The output file’s base name (no path, no extension) of a specific target.
$(TARGET_OUTPUT_DIR)
The output directory of the current target.
$(TARGET_OBJECT_DIR)
The object directory of the current target.
$(TARGET_NAME)
The name of the current target.
$(TARGET_OUTPUT_FILE)
The output file of the current target.
$(TARGET_OUTPUT_BASENAME)
61
JumpStarter C for AVR – C Compiler for Atmel AVR
The output file’s base name (no path, no extension) of the current target.
$(TARGET_CC), $(TARGET_CPP), $(TARGET_LD), $(TARGET_LIB)
The build tool executable (compiler, linker, etc.) of the current target.
$(TARGET_COMPILER_DIR)
The build tool executable root directory, typically c:\iccv8avr.
Language and encoding
$(LANGUAGE)
The system language in plain language.
$(ENCODING)
The character encoding in plain language.
Time and date
$(TDAY)
Current date in the form YYYYMMDD (for example, 20051228).
$(TODAY)
Current date in the form YYYY-MM-DD (for example 2005-12-28).
$(NOW)
Timestamp in the form YYYY-MM-DD-hh.mm (for example 2005-12-28-07.15).
$(NOW_L)
Timestamp in the form YYYY-MM-DD-hh.mm.ss (for example 2005-12-28-07.15.45).
$(WEEKDAY)
Plain-language day of the week (for example, “Wednesday”).
$(TDAY_UTC), $(TODAY_UTC), $(NOW_UTC), $(NOW_L_UTC),
$(WEEKDAY_UTC)
These are identical to the preceding types, but are expressed relative to UTC.
$(DAYCOUNT)
The number of the days passed since an arbitrarily chosen day zero (January 1,
2009). Useful as last component of a version/build number.
Random values
$(COIN)
62
JumpStarter C for AVR – C Compiler for Atmel AVR
This variable tosses a virtual coin (once per invocation) and returns 0 or 1.
$(RANDOM)
A 16-bit positive random number (0-65535).
Operating System Commands
The variable are substituted through the command of the operating system.
$(CMD_CP)
Copy command for files.
$(CMD_RM)
Remove command for files.
$(CMD_MV)
Move command for files.
$(CMD_MKDIR)
Make directory command.
$(CMD_RMDIR)
Remove directory command.
63
JumpStarter C for AVR – C Compiler for Atmel AVR
64
JumpStarter C for AVR – C Compiler for Atmel AVR
65
JumpStarter C for AVR – C Compiler for Atmel AVR
66
JumpStarter C for AVR – C Compiler for Atmel AVR
Macro Define(s) - When you define macros, separate them by semicolons. Each
macro definition is in the form
name[:value] or name[=value]
For example:
DEBUG=1;PRINT=printf
defines two macros, DEBUG and PRINT. DEBUG has the value 1 by default and
PRINT is defined as printf. This is equivalent to writing
#define DEBUG 1
#define PRINT printf
in the source code. A common usage is to use conditional preprocessor directives
to include or exclude certain code fragments.
The C Preprocessor predefines a number of macros. See Predefined Macros.
Macro Undefine(s) - same syntax as Macro Define(s) but with the opposite
meaning. It is acceptable to undefine a macro that has no definition.
Enable MISRA / Lint Checks - See MISRA / Lint Code Checking for
explanations of MISRA checks. Available in the PRO edition.
Enable Cross Module Type Checking - detect inconsistence in the
definitions and declarations of global functions and data
variables. Available in the PRO edition.
Since the compiler encourages the use of function prototyping, this check is most
useful for detecting accidental misdeclarations of global variables, which can
cause your program to fail.
Output File Format - select the choice of the output format. Usually a device
programmer requires simple Intel HEX or Motorola S19 format files. If you want
symbolic debugging, select one of the choices that include the debugging output.
For example, the AVR Studio understands COFF output format
Enable 64-bit “double” - enabled for the PROFESSIONAL
version. Specify the size of the double data type as 64 bits.
See Data Type Sizes. Note that this is significantly slower
and requires larger code space than 32-bit float.
Optimizations - control the levels and types of
optimizations. Currently, the choices are
Enable Code Compression - enabled for the ADVANCED and
PROFESSIONAL version. This invokes the Code Compressor
67
JumpStarter C for AVR – C Compiler for Atmel AVR
68
JumpStarter C for AVR – C Compiler for Atmel AVR
69
JumpStarter C for AVR – C Compiler for Atmel AVR
70
JumpStarter C for AVR – C Compiler for Atmel AVR
Return Stack Size - the compiler uses two stacks, one for the return addresses
for the function calls and interrupt handler (known as the hardware stack), and
one for parameter passing and local storage (known as the software stack). This
option allows you to control the size of the return stack. The size of the software
stack does not need to be specified. See Program Data and Constant Memory.
Each function call or interrupt handler uses two bytes of the return stack and 3
bytes if the CPU is a M256x. Therefore, you need to estimate the deepest level of
your call trees (i.e., the maximum number of nested routines your program may
call, possibly any interrupts), and enter the appropriate size here. Programs
using floating points or longs should specify a hardware stack size of at
least 30 bytes. However, in most cases, a hardware stack size of maximum 50
bytes should be sufficient. Since the hardware stack uses SRAM, if you specify a
stack that is too large, the stack may overflow into the global variables or the
software stack and Bad Things Can Happen.
Do Not Use R20..R23 - do not use R20 to R23 for code generation. See Global
Registers.
Instruction Set - Select instruction set supported by the device: Classic,
Enhanced, Enhanced (no MUL), or XMega. Only changeable if the device is set to
Custom.
Bootloader Options - Enabled only for devices that support boot loaders such as
the newer ATMega devices. You can specify whether the project is for building
Application Code or Bootloader code, and how large the boot size is. See
Bootloader Application.
Internal vs. External SRAM - Specify the type of data SRAM on your target
system. If you select external SRAM, the correct MCUCR bits will be set.
Non Default Startup - a startup file is always linked with your program (see
Startup File). In some cases, you may have different startup files based on the
project. This option allows you to specify the name of the startup file. If the
filename is not an absolute pathname, then the startup file must be in one of the
library directories.
Other Options - this allows you to enter any linker command-line arguments. See
Linker Arguments.
For example, in your source file:
#pragma text:bootloader
void boot() ... // function definition
#pragma text:text // reset
71
JumpStarter C for AVR – C Compiler for Atmel AVR
72
JumpStarter C for AVR – C Compiler for Atmel AVR
Pod Selection
You may select one of the following debug / programming pods:
AVR Dragon
JTAGICE MkII
JTAGICE3
Atmel-ICE
EEPROM Handling
You may select one of the following:
Program EEPROM with “#pragma eeprom” content. See Accessing EEPROM.
Preserve existing EEPROM content.
Erase EEPROM.
73
JumpStarter C for AVR – C Compiler for Atmel AVR
74
JUMPSTART DEBUGGER
If you are using the AVR Dragon or the JTAGMkII, then you must also install the filter
driver. You do not need the filter driver if you are using JTAGICE3 or Atmel-ICE:
5. Install the Windows libusb-win32 filter driver using the “filter wizard”:
Run c:\iccv8avr\libusb-Win32\bin\inf-wizard.exe and click “Next”.
Select the pod from the list of devices. If the pod does not show up, then the USB
drivers have not been installed. Restart the process if necessary.
Click “Next” until the wizard asks you for a location to put the generated .inf file.
This can be anywhere on your computer. Click “Save.”
Click on the “Install now” button to install the driver. Click “OK” if Windows warns
that the driver is unsigned.
Once the driver is installed, exit the wizard.
Depending on the Windows version, you may need to redo the filter driver installation
(but not the Atmel USB drivers) if you plug the hardware pod into a different USB port.
The debugger will warn you if it cannot detect the pod so that you may remedy the
situation.
You can now use JDB to debug your program. You will need to select the correct
options for your projects in Project - Debug/Download Interface. Once the options are
set, you can begin debugging by invoking “Debug->Start/Continue” or by clicking the
“run” icon in the toolbar.
76
JumpStarter C for AVR – C Compiler for Atmel AVR
77
JumpStarter C for AVR – C Compiler for Atmel AVR
Windows 10 Issues
We have had reports of an issue with the debugger sometimes fails to start under
Windows 10.
While we do not understand the mechanism creating this problem we have found the
following to be a solution:
78
JumpStarter C for AVR – C Compiler for Atmel AVR
79
JumpStarter C for AVR – C Compiler for Atmel AVR
Debugger Operations
JumpStart Debugger (JDB) is a state-of-the art debugger which is fully integrated with
the JumpStart C’s IDE; the IDE’s editor window can be used to set breakpoints, or
mouse over to peek at a variable’s value etc. To provide additional debugging features
without cluttering the CodeBlock User Interface (UI), JumpStart Debugger also
includes the Advanced Debug Toolbar (ADT), a separate UI that provides advanced
features.
CodeBlocks IDE debug commands are available under the Debug menu, or via right
click popup menus. Some of the more often invoked commands are also available as
toolbar icons. ADT has its own set of UI controls.
Basic Concepts
Program errors come in many forms; most often because the CPU runs the code that
we actually write, instead of the code that we meant to write (“do what I meant, not
what I wrote”). An MCU environment provides additional challenges ranging from
interrupts occurring to memory limitations. A debugger allows you to pause a program
and examine the program’s internal states. This provides insight as to what the
program is doing, and sometimes even why it is executing at that location in the first
place.
To debug, you typically set breakpoints in the program code prior to running the
program under the debugger control. When the program execution hits a breakpoint,
the CPU pauses execution, and you may then use debugger commands to examine
the program states and memory contents. There are many ways to use a debugger,
and users develop their own strategies of the most optimal methods for their own use.
JumpStart Debugger is a source-level debugger. Source-level means that you
breakpoints are set on C source lines, and the debugger is aware of the data types of
the variables. For example, if you examine the content of a struct variable, the
debugger shows the member field names and their content. The debugger maintains
internal structures mapping user program source information to the PC location and
memory addresses. These information is generated by the compiler tools during the
program build process.
A breakpoint stops at the “execution point” associated with a source line. Note that
some C source statements may contain multiple execution points, e.g. a for statement
for (int i = 0; i < 10; i++)contains 3 execution points, one for each part of
the for loop. Setting a breakpoint at a source line with multiple execution points would
pause at all execution points of that statement.
80
JumpStarter C for AVR – C Compiler for Atmel AVR
JumpStart Debugger requires a hardware debug pod to provide the low-level access
to the target device.
Debug functions can be loosely divided into these groups:
Breakpoints and source line stepping
Program state viewing
Data viewing
Sometimes your program may not behave as expected and not hit the breakpoints
you have set. In that case, "Debug->Break debugger" attempts to pause the CPU. As
the CPU may pause at a location that does not have C source level information (e.g.
81
JumpStarter C for AVR – C Compiler for Atmel AVR
within a library function provided by ImageCraft or some third party vendor), some of
the debug instructions may not be available, and you may have to use the ADT to
debug in assembler mode (see below).
Reset Target
This restarts the target device to allow you to restart debugging.
82
JumpStarter C for AVR – C Compiler for Atmel AVR
Breakpoints
Breakpoints are set in the normal editor window by clicking on the “gutter” on the left
hand side of the source file:
The red circle indicates that a breakpoint has been set at that source line. You can set
breakpoints in C source files at function names and at any source lines with C
executable statements.
The yellow triangle indicates the location of the currently paused program counter.
The following breakpoint commands are available under the Debug menu:
Debug->Toggle Breakpoint: set or clear a breakpoint at the cursor
Debug->Remove all breakpoints: remove all breakpoints from the project
Debug->Debugging windows->breakpoints: shows the breakpoint window. The
breakpoint window contains all the breakpoints in the project and shows whether
they are currently enabled or disabled.
A disabled breakpoint is useful to temporarily ignore a breakpoint during a debug
session without removing it.
Right-clicking at an entry in the breakpoint window brings up a context-menu with
further operations you can perform on the breakpoints:
83
JumpStarter C for AVR – C Compiler for Atmel AVR
Call Stack
Debug->Debugging windows->Call stack displays the call stack, which is the trace of
the function calls that leads to the current breakpoint locations. Usually the top of the
call chain is the main function, unless the program is paused at an interrupt handler or
unknown PC location with no source line information.
Variable Watching
The watch window displays the content of the variables you “add” to the watch
window. To show or hide the watch window, use Debug->Debugging windows-
>Watch. The values of the variables are updated automatically whenever the program
is paused. To add a variable to the watch window, right-click on the variable name,
84
JumpStarter C for AVR – C Compiler for Atmel AVR
then select Watch ‘<variable name>’ at the popup menu. You can remove a variable
from the watch window by right-clicking on the entry in the watch window and
selecting the action from the popup menu.
Note that values for variables that are not in-scope (e.g. a static variable defined in
another file or another function, or a local variable that is not used at that program
location) cannot be displayed correctly. This can be particularly jarring for local
variables: due to compiler optimizations, the value of a local variable is only valid
between its first use and last use. So, if the program is paused at a C line that is after
the last use of that variable, the value may not be displayed correctly. Another gotcha!
Is that if you assign a value to a variable but never use that variable with that assigned
value, then the compiler may never assign the value to the variable at all, and thus
you would not see it in the debugger either.
Debug/Download Options
This dialog box has two tabs: "Cortex or AVR Debug/Download Interface", and
"Debugger Behaviors". The “Debug/Download interface” tab controls the hardware
debug pod setup. Select the pod and options suitable for your hardware.
The Debugger Behaviors tab contains:
Do not flash MCU: If your program has not changed, this saves a small amount of
time since the debugger knows that it does not have to check the flash content
and re-program it if necessary.
Keep timers running in stop mode: Some MCUs allow the timers to run even while
the CPU core is paused by the debugger.
Run to main: the program pauses at the start of your main() function.
Do not run: the program stops at the reset vector.
Run: runs the program without pausing.
85
JumpStarter C for AVR – C Compiler for Atmel AVR
The top row of icons control program execution, mirroring the toolbar icons on the
CodeBlocks IDE. ADT also uses the same keyboard shortcut as the CodeBlock IDE’s
control.
There are five “views” in ADT. The second row of icons is used to select the display,
from left to right:
5. Core (CPU) Register View
6. Code View
7. Peripheral (I/O Register) View
8. Memory View
9. Simple Trace View
Each view is displayed as a tabbed window under the ADT control bar by default, or
each can be “torn off” to be its own floating window.
86
JumpStarter C for AVR – C Compiler for Atmel AVR
Code View
This displays the assembler code of the current program location, interspersed with C
source code if available. You can use the ADT toolbar icon to step (over) to the next
assembler or C instruction, or step into a function call.
87
JumpStarter C for AVR – C Compiler for Atmel AVR
Memory View
This displays the content of data (SRAM) memory in a variety of formats.
88
C PREPROCESSOR
C Preprocessor Dialects
The C preprocessor is a standard C99 preprocessor.
Extensions
#pragma and _Pragma() are described in Pragmas.
#region / #endregion are ignored by the preprocessor but are used by the
CodeBlocks IDE to allow manual code folding. These directives cannot improperly
overlay other control directives such as #if / #else / #endif. The same effect
can be achieved by using the pair
//{
//}
#warning is supported in addition to #error.
JumpStarter C for AVR – C Compiler for Atmel AVR
Predefined Macros
The product includes support for the following Standard C predefined macros.
“Current” refers to at the time of compilation:
__DATE__ expands to a string literal of the current date.
__FILE__ expands to a string literal of the current filename without the path
prefix.
__LINE__ expands to an integer of the current line number (line numbers start
with 1)
__STDC__ expands to the constant 1.
__TIME__ expand to a string literal of the current time in the form “hh:mm:ss”.
Table 1:
90
JumpStarter C for AVR – C Compiler for Atmel AVR
Table 1:
ICC08 _HC08
ICC11 _HC11
ICCM8C _M8C
91
JumpStarter C for AVR – C Compiler for Atmel AVR
Pragmas
The C Preprocessor accepts compiler-specific extensions using the #pragma control
and the equivalent C99 _Pragma() keyword; e.g., the following are equivalent:
#pragma abs_address:0x1000
_Pragma(“abs_address:0x1000”)
This allows you to write a macro definition that expands to a pragma control line:
#define EMOSFN(ty, f, param) PRAGMA(ctask eMOS__##f)
#define PRAGMA(x) _Pragma(#x)
...
expands to
#pragma
The compiler accepts the following pragmas:
#pragma warn message
Emits a warning message similar to the C preprocessor directive #warning.
#pragma ignore_unused_var name1 name2 ...
This must appear inside a function and specifies that the named arguments are
intentionally unused so no warning message should be generated for them.
#pragma interrupt_handler <func1>:<vector> <func2>:<vector>...
This declares functions as interrupt handlers so that the compiler generates the
interrupt handler return instruction instead of the normal function return, and
saves and restores all the registers that the functions use. It also generates the
interrupt vectors based on the vector numbers. See Interrupt Handling. This
pragma must precede the function definitions.
92
JumpStarter C for AVR – C Compiler for Atmel AVR
If vector number is -1, then no vector table entry is generated. One possible use is
for taking immediate action upon interrupt in an assembly routine with the vector
table setup done by hand, and then jumping to a C handler for normal processing.
#pragma ctask <func1> <func2>...
Specifies that these functions should not generate volatile register save and
restore code. See Assembly Interface and Calling Conventions regarding register
usage. This is typically used in a RTOS system where the RTOS kernel manages
the registers directly. See C Tasks.
#pragma data:<data name>
#pragma data:noinit
#pragma data:eeprom
#pragma data:user_signatures
#pragma data:data // to reset
Any global or file static variable definition appearing after this pragma is allocated
in the <data name> area instead of the normal data area. You must use
#pragma data:data to reset.
Use #pragma data:noinit if you don’t want the declared global variables to
be initialized.
Use #pragma data:eeprom to initialize the EEPROM content. See
Initializing EEPROM. The IDE generates -beeprom:<start>.<end> with
<start> being either 1 (for older AVR with potentially problem with EEPROM
location 0) or 0 (for all newer AVR). You may override the address range by
specifying a different -beeprom:<start>.<end> flag in the Project->Build
Options->Target->Advanced edit box.
Use #pragma data:user_signatures to initialize XMEGA special user
signatures flash page. See Generating Production ELF File.
Except for noinit eeprom and user_signatures, you must also declare
the base address of the area in the Build Options - Target “Other Options” edit box
in the form of -b<data name>:<start address>.<end address>. You
must also ensure that the address you specify for data name does not overlap
the memory used by the compiler for the default areas. See Linker Operations.
#pragma lit:<lit area>
93
JumpStarter C for AVR – C Compiler for Atmel AVR
Any const object definition appearing after this pragma is allocated in the <lit
area> area instead of the normal lit area. Use #pragma lit: lit to reset.
Note that if you use this pragma, you must manually ensure that the address you
specify for lit area does not overlap the memory used by the compiler for the
default areas. See Linker Operations.
#pragma ram_abs_address:<address>
#prgama lit_abs_address:<address>
#pragma code_abs_address:<address>
Does not use relocatable areas for the functions and global data, but instead
allocates them from the absolute address starting at <address>.
ram_abs_address is used for data definition, lit_abs_address is used for
tables and literals and code_abs_address is for defining functions.
<address> is either an integer constant or a compile time constant expression.
For example:
#define BASE 0x1000
#pragma ram_abs_address: (BASE + 0x10)
...
These pragmas are useful for accessing interrupt vectors and other hard-wired
items. See Program Areas. The address is a byte address and currently it is
limited to 64K bytes.
#pragma end_abs_address
Uses the normal relocatable areas for objects.
#pragma text:<text name>
#pragma text:text // to reset
Any function definition appearing after this pragma is allocated in the <text
name> area instead of the normal text area. Use #pragma text:text to reset
to the default allocation. For example:
#pragma text:mytext
void boot() ... // function definition
#pragma text:text // reset
In Build Options - Target, under “Other Options,” add
-bmytext:0x????
94
JumpStarter C for AVR – C Compiler for Atmel AVR
where 0x???? is the starting address of the area “bootloader.” Note that if you
use this pragma, you must manually ensure that the address you specify for text
name does not overlap the memory used by the compiler for the default areas.
See Linker Operations.
#pragma once
specifies that this file should be processed only once by the C preprocessor, even
if it is #include multiple times.
#pragma device_specific_function <func1> <func2> ...
This pragma is used for declaring functions that use device-specific IO registers
and therefore must be compiled using the device-specific header file and IO
register names. It tells the compiler to decorate the function names with the
$device_specific$ suffix in the output code. For example, upon seeing
#pragma device_specific_function putchar
the compiler generates _putchar$device_specific$ whenever it sees the
external identifier putchar. Upon seeing an undefined symbol with this suffix, the
linker emits a suitable error message.
95
JumpStarter C for AVR – C Compiler for Atmel AVR
Supported Directives
Long definitions can be broken into separate lines by using the line-continuation
character backslash at the end of the unfinished line.
Macro Definition
#define macname definition
A simple macro definition. All references to macname will be replaced by its
definition.
#define macname(arg [,args]) definition
A function-like macro, allowing arguments to be passed to the macro definition.
#undef macname
Undefine macname as a macro. Useful for later on redefining macname to another
definition.
C99 allows variable arguments in a function-like macro definition.
Conditional Processing
In conditional processing directives (#if/#ifdef/#elif/#else/#endif), a line
group refers to the lines between the directive and the next conditional processing
directive. Conditional directives must be well formed. For example, #else, if it exists,
must be the last directive of the chain before the #endif. A sequence of conditional
directives form a group, and groups of conditional directives can be nested.
defined(name)
Can only be used within the #if expression. Evaluate to 1 if name is a macro
name and 0 otherwise.
#if <expr>
Conditionally process the line group if <expr> evaluates to non-zero. <expr>
may contain arithmetic/logical operators and defined(name). However, since
the C preprocessor is separate from the C compiler proper, it cannot contain the
sizeof or typecast operators.
#ifdef name / #ifndef name
A shorthand for #if defined(name) and #if !defined(name),
respectively.
#elif <expr>
96
JumpStarter C for AVR – C Compiler for Atmel AVR
Others
#include <file> or #include “file”
Process the content of the file.
#line <line> [<“file”>]
Set the source line number and optionally the source file name.
#error “message”
Emit message as an error message.
#warning “message”
Emit message as a warning message. An ImageCraft extension.
97
JumpStarter C for AVR – C Compiler for Atmel AVR
98
C IN 16 PAGES
Preamble
There are many good C tutorial books and websites. Google is your friend. In
particular, check out the “C FAQ” website.
This section gives a very brief introduction to C using our compiler tools. Some are
“good practices” that may help you to be more productive. This chapter contains our
opinions; obviously there are many other good ideas and good practices out there.
More importantly, this does not replace a good C tutorial or reference book.
C Standards
C “escaped” Bell Laboratories in the late 1970s into the commercial world. By the
early 1980s, there were many C compilers for mainframe, PC, and even embedded
processors (the more things change, the more they stay the same...). The original C
standard committee had the foresight to have as one of its overriding goals to “codify
existing practices as much as possible.” Consequently, the first C standard (C86)
works in basically the same ways as people were used to, with just a few more
keywords (const and volatile) thrown in. C’s relative simplicity helps here -- even
if you hit some sort of compatibility bugs, it is often a minor exercise to tweak the
programs to conform to new standards.
When ISO picked up the task of standardizing C for the international community, C86
by and large was accepted with some minor changes and became known as C89.
These are the base dialects that the ImageCraft compilers more or less conform to.
“More or less” because there are some small differences (i.e., we only support 64-bit
double on select targets, and 32-bit floating-point for other targets, and thus are non-
conforming). However, 99+% of the time, if it is in the C86/C89 language standard, it is
supported by our compilers.
C99 is the latest C standard. While some people pushed for making the new C a
proper subset of C++, sanity prevailed and C99 looks remarkably like C89, with the
addition of a few new keywords and data types (e.g., _bool, complex, long long,
long double, etc.). We may support C99 at a future date.
There are two observations about this process. First, the C preprocessor is separate
from the compiler proper and does textual processing only. There are caveats about
#define macros that arise from this. For example, in the macro definition, it is
advisable that you put parentheses around the macro arguments to prevent
unintended results:
#define mul1(a, b) a * b // bad practice
#define mul2(a, b) ((a) * (b)) // good practice
mul1(i + j, k);
mul2(i + j, k);
mul1 produces an unexpected result for the arguments, whereas mul2 produces the
correct result (of course, it is not a good idea to #define simple operations such as
single multiplication, but that is another subject). Second, C files are translated into
assembler files and are then processed by the assembler. In fact, C is sometimes
called a high-level assembler, since the amount of translation between C and
assembly is relatively small, compared to the more complex languages such as C++,
Java, FORTRAN, etc.
100
JumpStarter C for AVR – C Compiler for Atmel AVR
#endif
101
JumpStarter C for AVR – C Compiler for Atmel AVR
Declaration
Everything in a C source file must be either a declaration or a statement. All variables
and type names must be declared before they can be referenced. Simple data
declarations are quite easy to read and to write:
[<storage class>] typename name;
Storage class is optional. It can be either auto, extern, or register. Not all
storage class names can appear in all declarations. The type name is sometimes a
simple type:
int, unsigned int, unsigned, signed int
short, unsigned short, signed short
char, unsigned char, signed char
float, double, and C99 added long double
a typedef’ed name
struct <tag> or union <tag>
What gets tricky is that there are three additional type modifiers: an array of ([]), a
function returning (()), and a pointer to (*), and combining them can make
declarations hard to write (and hard to read).
Reading a Declaration
You use the right-left rule, sort of like peeling an onion: you start with the name, and
read to the right until you can’t, then you move left until you can’t, and then move right
again. Nothing like a perverse example to demonstrate the point:
const int *(*f[5])(int *, char []);
Using the right-left rule, you get:
locate f, then move right, so f is an array of 5...
moving left, f is an array of 5 pointers...
moving right, f is an array of 5 pointers to a function...
continue to move right, f is an array of 5 pointers to a function with two arguments
(we can skip ahead and read the function prototype later)...
moving left, f is an array of 5 pointers to function with two arguments that returns
a pointer to...
102
JumpStarter C for AVR – C Compiler for Atmel AVR
moving left, f is an array of 5 pointers to function with two arguments that returns
a pointer to int...
moving left for the last time, f is an array of 5 pointers to function with two
arguments that returns a pointer to const int.
You can of course also use the right-left rule to write declarations. In the example, the
type qualifier const is also used. There are two type qualifiers: const (object is read
only) or volatile (object may change in unexpected ways).
volatile is for decorating an object that may be changed by an asynchronous
process -- e.g., a global variable that is updated by an interrupt handler. Marking such
variables as volatile tells the compilers not to cache the accessed values.
103
JumpStarter C for AVR – C Compiler for Atmel AVR
they are not the same thing. For example, an array has storage space associated with
it, whereas you must initialize a pointer to point to some valid space before accessing
it.
3) struct tag2;
struct tag2 { int junk; };
struct tag2 var3;
The tag is optional and is useful if you want to refer to the same struct type again
(for example, you can use struct tag1 to declare more variables of that type). In C,
within the same file, even if you have two identical-looking struct declarations, they
are different struct types. In the examples above, all of the structs have different
types, even though their struct types look identical.
However, in the case of separate files, this rule is relaxed: if two structs have the
same declaration, then they are equivalent. This makes sense, since in C, it is
impossible to have a single declaration to appear in more than one file. Declaring the
struct in a header file still means that a separate (but identical-looking) declaration
appears in each file that #include the header file.
Function Prototype
In the old days of C, it was sometimes acceptable to call a function without declaring it
first -- everything would work correctly anyway. However, with the ImageCraft
compilers, it is important to declare a function before referencing it, including the types
of the function arguments. Otherwise, it is possible that the compiler will not generate
the correct code. When you declare a function with a complete argument and return
type information, it’s called the function prototype of the function.
104
JumpStarter C for AVR – C Compiler for Atmel AVR
Semicolon Termination
The expression statement is one of the few statements in C that requires a
semicolon termination. The others are break, continue, return, goto, and do
statements. Sometimes you see things like:
#define foo blah blah;
...
void bar() { ... };
Those semicolons at the end are most likely extraneous and can possibly even cause
your program to fail subtly (to compile or to execute).
Integer Constants
Integer constants are either decimal (default), octal (starting with 0), or hexadecimal
(0x or 0X). Our compilers support the extension of using 0b as a prefix for binary
constants. You can explicitly change the type of an integer constant by adding U/u, L/
l, or combinations of them. The type of an integer is the first type of each list in the
following table that can hold the value of the constant:
105
JumpStarter C for AVR – C Compiler for Atmel AVR
Table 1:
both u/U and l/L unsigned long int unsigned long int
Expressions
Expression statements are where things happen. Every expression produces a value
and may contain side effects. In standard C, you can mix and match expressions of
different data types and, within certain rules, the compiler will convert the expressions
to the right type for you. Integer and floating-point expressions can be used together
and, in most cases, the expected things happen. A case where the unexpected may
happen is where the type of an expression solely depends on the types of its
operands and not how on they will be used. For example:
long_var = int_var1 * int_var2; // int multiply
long_var = (long)int_var1 * int_var2; // long multiply
The first multiplication is done as an integer multiply and not as a long multiply. If you
want long multiply, at least one of the operands must have the type long, as seen in
the second example. This also applies to assigning to floating-point variables, etc. as
well.
Another point of note is that the C standard says that operands are promoted to
equivalent types before the operation is done. In particular, an integer expression
must be promoted to at least int type if its type is smaller than an int type. However,
the “as-if” rule says that the promotion does not need to physically occur if the result is
the same. Our compilers will try to optimize the byte-sized operations whenever
possible. Some expressions are more difficult to optimize, especially if they produce
an intermediate value. For example,
106
JumpStarter C for AVR – C Compiler for Atmel AVR
char *p;
...
... *p++...
The compiler may not be as optimal, since *p is a temporary value that needs to be
preserved.
Operators
C has a rich set of operators, including bitwise operators that make handling IO
registers easy. There is no “logical” or “boolean” type per se, so any non-zero value is
taken as “true.” You may intermix any operators, including logical, bit-wise, etc., in an
expression. The following lists the operators from high to lower precedence. Within
each row, the operators have the same precedence.
Operators Associativity
107
JumpStarter C for AVR – C Compiler for Atmel AVR
Operators Associativity
a.) Standard C does not define whether a right shift is arithmetic or logical. All
ImageCraft compilers use arithmetic right shift for signed operands and logical
right shift for unsigned operands.
Macro Abuse
Some people use #define to define “better names” for some of the operators -- for
example, EQ instead of ==, BITAND instead of &, etc. This practice is generally not a
good idea, since it only serves to create a single-person dialect of the language,
making the program more difficult to maintain and be read by other people.
Operator Gotchas
108
JumpStarter C for AVR – C Compiler for Atmel AVR
Incorrectly using = instead of ==. Rather than donning the sin of “macro abuse,”
write carefully or use a tool such as lint or splint to catch errors like this.
Bitwise operators have higher precedence than logical operators. To many
programmers, C has the ideal mix of high-level constructs with low-level
accessibility. However, this is one case where even the inventors of C admit that
this is a misfeature. It means that you have to write:
if ((flags & bit1) != 0 && ...
with an “extra” set of parentheses to get the semantics correct. Unfortunately, the
power of backward compatibility is such that even C++ has to preserve this
mistake.
109
JumpStarter C for AVR – C Compiler for Atmel AVR
Statements
In the following, if-body, while-body, ...etc. are synonymous to C statements.
Expression Statement
[ label: ] [expression];
See Expressions and Type Promotions for discussion on expressions. An empty
semicolon by itself is a null expression statement.
Compound Statement
{ [statement ]* }
A compound statement is a sequence of zero or more statements enclosed in a set of
{}. Notably, local declarations are only valid immediately after a { and before any
executable statement, so sometimes a {} is introduced just for that purpose.
If Statement
if (<expr>) if-body [ else else-body ]
If <expr> evaluates to non-zero, then it executes the if-body. Otherwise, it
executes the else-body if it exists. There is no “dangling-else” problem, as an else
keyword is always associated with the nearest preceding if keyword.
While Statement
while (<expr>) while-body
Executes the while-body as long as the <expr> evaluates to non-zero. Note that
our compilers compile this to something similar to
goto bottom
loop_top: <while-body>
bottom: if <expr> goto loop_top
While not as straightforward as the obvious test-at-the-top translation, this sequence
executes n+2 branches for a loop that executes n times, vs. 2n+1 branches for the
obvious translation.
For Statement
for ( [<expr1>] ; <expr>; <expr2> ) for-body
110
JumpStarter C for AVR – C Compiler for Atmel AVR
Do Statement
do do-body while (<expr>);
Executes do-body at least once and, if <exp> evaluates to non-zero, repeat the
process.
Break Statement
break;
Valid only inside a loop body or inside a switch statement. It causes control to fall
outside of the loop or the switch. Inside a switch, execution falls through to the next
case, unless it is terminated by a break statement.
Continue Statement
continue;
Valid only inside a loop body. It causes control to go to the loop test. Inside a for
statement, it will skip the third expression normally executed.
Goto Statement
goto label;
Transfer control flow to label. There is no restriction on where label is located as
long as it is a valid label inside the same function. In other words, while usually not a
good idea, it is acceptable to jump into the middle of a loop or other “bad” places.
Return Statement
return [<expr>];
Transfer control flow back to the calling function and optionally return the value of the
specified expression.
Switch Statement
switch (<int expr>) switch-body
111
JumpStarter C for AVR – C Compiler for Atmel AVR
Evaluates the integer expression and transfers control to the case label inside the
switch-body having the same value as the expression. If there is no match and there
is a default label, then control is transferred to the default case. Note that the switch-
body is commonly written as
{ case <int>: [expression ;] * ... default: [expression;]* }
but this format is not required by the C language. A case label and a default label can
only appear inside a switch body. Another major gotcha is that execution falls through
to the next case, unless it is terminated by a break statement.
112
C LIBRARY AND STARTUP FILE
114
JumpStarter C for AVR – C Compiler for Atmel AVR
Startup File
crtavrram.o Normal startup file that also initializes the external SRAM.
crtmegaram.o ATmega startup file that also initializes the external SRAM.
115
JumpStarter C for AVR – C Compiler for Atmel AVR
116
JumpStarter C for AVR – C Compiler for Atmel AVR
You can use a different name for your custom startup file by specifying the name of
the startup file to use in Build Options - Target. Note that you must either specify the
startup with an absolute pathname or it must be located in the directory specified by
the Project Options Library path.
The rest of the interrupt vectors are described in Interrupt and Reset Handling.
117
JumpStarter C for AVR – C Compiler for Atmel AVR
Header Files
The following standard C header files are supported. Per C rules, you will only get a
warning from the compiler if you use a library function but do not #include the header
file (which contains the function prototype). However, your program may fail at runtime
since the compiler must know about the function prototype in order to generate correct
code in all cases.
assert.h - assert(), the assertion macros.
ctype.h - character type functions.
float.h - floating-point characteristics.
limits.h - data type sizes and ranges.
math.h - floating-point math functions.
stdarg.h - support for variable argument functions.
stddef.h - standard defines.
stdio.h - standard IO (input/output) functions.
stdlib.h - standard library including memory allocation functions.
string.h - string manipulation functions.
118
JumpStarter C for AVR – C Compiler for Atmel AVR
119
JumpStarter C for AVR – C Compiler for Atmel AVR
int toupper(int c)
returns the upper-case version of c if c is a lower-case character. Otherwise it
returns c.
120
JumpStarter C for AVR – C Compiler for Atmel AVR
121
JumpStarter C for AVR – C Compiler for Atmel AVR
returns a fraction f and stores a base-2 integer into *pexp that represents the value
of the input x. The return value is in the interval of [1/2, 1) and x equals f *
2**(*pexp).
float froundf(float x)
rounds x to the nearest integer.
float ldexpf(float x, int exp)
returns x * 2**exp.
float logf(float x)
returns the natural logarithm of x.
float log10f(float x)
returns the base-10 logarithm of x.
float modff(float x, float *pint)
returns a fraction f and stores an integer into *pint that represents x. f + (*pint)
equal x. abs(f) is in the interval [0, 1) and both f and *pint have the same sign
as x.
float powf(float x, float y) )
returns x raised to the power y.
float sqrtf(float x) )
returns the square root of x.
float sinf(float x)
returns the sine of x for x in radians.
float sinhf(float x)
returns the hyperbolic sine of x for x in radians.
float tanf(float x) )
returns the tangent of x for x in radians.
float tanhf(float x)
returns the hyperbolic tangent of x for x in radians.
Since, by default, float and double have the same size (32 bits), math.h also
contains a set of macros that map the function names to be without the f suffix form.
For example, pow is the same as powf, sin is the same as sinf, etc.
122
JumpStarter C for AVR – C Compiler for Atmel AVR
Standard IO Functions
Since standard file IO is not meaningful for an embedded microcontroller, much of the
standard stdio.h content is not applicable. Nevertheless, some IO functions are
supported.
Use #include <stdio.h> before using these functions. You will need to initialize
the output port. The lowest level of IO routines consists of the single-character input
(getchar) and output (putchar) routines. You will need to implement these routines
since they are specific to the target device. We provide example implementations and
for most cases, you just need to copy the correct example file to your project. See the
function descriptions below.
Once you implement the low level functions, you do not need to make modifications to
the high-level standard IO functions such as printf, sprintf, scanf, etc.
123
JumpStarter C for AVR – C Compiler for Atmel AVR
124
JumpStarter C for AVR – C Compiler for Atmel AVR
125
JumpStarter C for AVR – C Compiler for Atmel AVR
Non-white white-space characters in the format string must match exactly with the
input and white-space characters are matched with the longest sequence
(including null size) of white-space characters in the input. % introduces a format
specifier:
[l] long modifier. This optional modifier specifies that the matching argu-
ment is of the type pointer to long.
d the input is a decimal number. The argument must be a pointer to a
(long) int.
x/X the input is a hexadecimal number, possibly beginning with 0x or 0X.
The argument must be a pointer to an unsigned (long) int.
p the input is a hexadecimal number, possibly beginning
with 0x or 0X. The argument must be cast to a pointer to a
“void pointer,” e.g., void **.
u the input is a decimal number. The argument must be a pointer to an
unsigned (long) int.
o the input is a decimal number. The argument must be a pointer to an
unsigned (long) int.
c the input is a character. The argument must be a pointer to a character.
int sscanf(char *buf char *fmt, ...)
same as scanf except that the input is taken from the buffer buf.
int vprintf(char *fmt, va_list va); ) - same as printf except that
the arguments after the format string are specified using the stdarg mechanism.
If you enable the “Strings in FLASH” option, the literal format strings for printf/
scanf/etc. are now in flash. The following functions are provided:
cprintf, csprintf, cscanf, and csscanf. They behave in the same way as the
counterparts without the c prefix, except that the format string is in flash.
126
JumpStarter C for AVR – C Compiler for Atmel AVR
127
JumpStarter C for AVR – C Compiler for Atmel AVR
void exit(status)
terminates the program. Under an embedded environment, typically it simply
loops forever and its main use is to act as the return point for the user main
function.
void free(void *ptr)
frees a previously allocated heap memory.
char *ftoa(float f, int *status)
see dtoa above.
void itoa(char *buf, int value, int base)
converts a signed integer value to an ASCII string, using base as the radix. base
can be an integer from 2 to 36.
long labs(long i)
returns the absolute value of i.
void ltoa(char *buf, long value, int base)
converts a long value to an ASCII string, using base as the radix.
void utoa(char *buf, unsigned value, int base)
same as itoa except that the argument is taken as unsigned int.
void ultoa(char *buf, unsigned long value, int base)
same as ltoa except that the argument is taken as unsigned long.
void *malloc(size_t size)
allocates a memory chunk of size size from the heap. It returns 0 if it cannot
honor the request.
void _NewHeap(void *start, void *end)
initializes the heap for memory allocation routines. malloc
and related routines manage memory in the heap region. See
Program Areas for information on memory layout. A typical
call uses the address of the symbol _bss_end+1 as the “start”
value. The symbol _bss_end defines the end of the data memory
used by the compiler for global variables and strings.
128
JumpStarter C for AVR – C Compiler for Atmel AVR
129
JumpStarter C for AVR – C Compiler for Atmel AVR
String Functions
The following string functions and macros are declared in string.h:
Macros and Types
NULL is the null pointer, defined as value 0.
size_t is the unsigned type that can hold the result of a
sizeof operator.
Functions
void *memchr(void *s, int c, size_t n)
searches for the first occurrence of c in the array s of size n. It returns the address
of the matching element or the null pointer if no match is found.
int memcmp(void *s1, void *s2, size_t n)
compares two arrays, each of size n. It returns 0 if the arrays are equal and
greater than 0 if the first different element in s1 is greater than the corresponding
element in s2. Otherwise, it returns a number less than 0.
void *memcpy(void *s1, const void *s2, size_t n)
copies n bytes starting from s2 into s1.
void *memmove(void *s1, const void *s2, size_t n)
copies s2 into s1, each of size n. The routine works correctly even if the inputs
overlap. It returns s1.
void *memset(void *s, int c, size_t n)
stores c in all elements of the array s of size n. It returns s.
char *strcat(char *s1, const char *s2)
concatenates s2 onto s1 . It returns s1.
char *strchr(const char *s, int c)
searches for the first occurrence of c in s, including its terminating null character.
It returns the address of the matching element or the null pointer if no match is
found.
int strcmp(const char *s1, const char *s2)
compares two strings. It returns 0 if the strings are equal, and greater than 0 if the
first different element in s1 is greater than the corresponding element in s2.
Otherwise, it returns a number less than 0.
130
JumpStarter C for AVR – C Compiler for Atmel AVR
131
JumpStarter C for AVR – C Compiler for Atmel AVR
finds the substring of s1 that matches s2. It returns the address of the substring in
s1 if found and a null pointer otherwise.
char *strtok(char *s1, const char *delim)
splits s1 into tokens. Each token is separated by any of the characters in delim.
You specify the source string s1 in the first call to strtok. Subsequent calls to
strtok with s1 set to NULL will return the next token until no more token is
found, and strtok returns NULL.
strtok modifies the content of s1 and pointers into s1 are returned as return
values.
132
JumpStarter C for AVR – C Compiler for Atmel AVR
133
JumpStarter C for AVR – C Compiler for Atmel AVR
va_start(ap, fmt);
vfprintf(fmt, ap);
va_end(ap);
}
134
JumpStarter C for AVR – C Compiler for Atmel AVR
high address
HW Stack
sentinel
SW Stack
sentinel
Data Areas
low address
Summary
To use the stack checking functions:
1. #include <AVRdef.h>
135
JumpStarter C for AVR – C Compiler for Atmel AVR
2. Insert _StackCheck(); in your code where you want to check the stacks for
overflow. This may be anywhere in your code, e.g. inside your Watchdog Timer
function.
3. When _StackCheck() detects a stack overflow, it calls the function
_StackOverflowed() with an integer argument with a value of 1 to indicate
that the hardware stack has overflowed, and a value of 0 to indicate that the
software stack has overflowed.
4. The default _StackOverflowed() library function jumps to location 0 and
resets the program. To change this default behavior, write your own
_StackOverflowed function in your source code. This will override the default
one. For program debugging, your _StackOverflowed function should do
something to indicate a catastrophic condition, perhaps by blinking a LED. If you
are using a debugger, you can set a breakpoint at the _StackOverflowed
function to see if it gets called.
The prototypes for these two functions are listed in the header file
AVRdef.h.
Sentinels
The startup code writes a sentinel byte at the address just above the data area and a
similar byte at the address just above the software stack. If the sentinel bytes get
changed, then a stack overflow has occurred.
Note that if you are using dynamic memory allocation, you must skip the sentinel byte
at _bss_end for your heap allocation. See Standard Library And Memory Allocation
Functions.
136
JumpStarter C for AVR – C Compiler for Atmel AVR
137
JumpStarter C for AVR – C Compiler for Atmel AVR
138
PROGRAMMING THE AVR
140
JumpStarter C for AVR – C Compiler for Atmel AVR
(*) NOTES
If the target has USART rather than UART, vector number names are spelled
iv_USART_ rather than iv_UART_ (e.g., iv_USART_RXC).
If target has more than 1 U(S)ARTs, vector number names include the U(S)ART
number (e.g., iv_UART0_RXC).
141
JumpStarter C for AVR – C Compiler for Atmel AVR
142
JumpStarter C for AVR – C Compiler for Atmel AVR
143
JumpStarter C for AVR – C Compiler for Atmel AVR
For XMEGA, fuses3 byte is not used (yet) and must be set to 0xFF.
#pragma avr_lockbits (lockbits)
Currently, all AVR devices have just one byte for lock bits and the value 0xFC
disallows reading out the memories and changing the fuses by a hardware
programmer.
#pragma data:user_signatures
example:
#pragma data:user_signatures
unsigned char a[] = {“Copyright (C) 2013 ImageCraft” };
#pragma data:data
XMEGA only: “user signatures” is an extra page of flash memory in the xmega
devices, fully accessable by software and not deleted by chip erase. Since you
can place a large amount of data, it uses the same syntax as the #pragma
data:eeprom for initialized EEPROM data. Therefore, you must also end the
definition with #pragma data:data.
144
JumpStarter C for AVR – C Compiler for Atmel AVR
CRC Generation
You can have JumpStarter C for AVR compute the CRC of your flash image and then
programmatically verify it in your program. JumpStarter C for AVR calculates a 16-bit
CRC using a common algorithm (as a reference, please check the Wikipedia entry for
“CRC16”). The AVR routine uses a table of 512 bytes and takes about 80 bytes of
code. You may possibly reduce the total memory consumption by replacing the code
that does not use a table, but this will result in a slower running time.
To use, specify <address>in the Build Options - Target CRC edit box. The linker
stores the 4-byte CRC structure in <address>:
unsigned address;
unsigned crc16;
<address> must not be used for other purpose. Typically you would specify the
address 4 bytes before the end of the flash memory.
CRC is computed from location 0 to <address>.
In your code, write
#include <crc.h>
...
__flash unsigned char *p = (__flash unsigned char *)0x????;
unsigned int crc16;
...
crc16 = calc_crc16((__flash unsigned char *)0, p[0]);
if (crc16 != p[1])
// CRC mismatched
0x???? is the same as <address> in the -crc switch. The header file crc.h
contains the declaration for the calc_crc16 routine. Thus p[0] contains the address
and p[1] contains the crc value calculated by the linker.
Obviously CRC is not foolproof since any flash memory corruption means that the
CRC checking code may not operate correctly. Nevertheless, CRC can be part of a
quality assurance workflow.
145
JumpStarter C for AVR – C Compiler for Atmel AVR
146
JumpStarter C for AVR – C Compiler for Atmel AVR
Strings
As explained in Program Data and Constant Memory, the separation of program and
data memory in the AVR’s Harvard architecture introduces some complexity. This
section explains this complexity as it relates to literal strings.
The compiler places switch tables and items declared as __flash into program
memory. The last thorny issue is the allocation of literal strings. The problem is that, in
C, strings are converted to char pointers. If strings are allocated in the program
memory, either all the string library functions must be duplicated to handle different
pointer flavors, or the strings must also be allocated in the data memory. The
ImageCraft compiler offers two options for dealing with this.
147
JumpStarter C for AVR – C Compiler for Atmel AVR
Stacks
The generated code uses two stacks: a hardware stack that is used by the subroutine
calls and interrupt handlers, and a software stack for allocating stack frames for
parameters, temporaries and local variables. Although it may seem cumbersome,
using two stacks instead of one allows the most transparent and code efficient use of
the data RAM.
Since the hardware stack is used primarily to store function return addresses, it is
typically much smaller than the software stack. In general, if your program is not call-
intensive and if it does not use call-intensive library functions such as printf with %f
format, then the default of 16 bytes should work well. In most cases, a maximum value
of 40 bytes for the hardware stack is sufficient unless your program has deeply
recursive routines.
The hardware stack is allocated at the top of the data memory, and the software stack
is allocated a number of bytes below that. The size of the hardware stack and the size
of the data memory are controlled by settings in the target tab of Build Options -
Target. The data area is allocated starting at 0x60, 0x100 or 0x200, depending
on the device, after the IO space. This allows the data area and the software stack to
grow toward each other.
If you select a device target with 32K or 64K of external SRAM, then the stacks are
placed at the top of the internal SRAM and grow downward toward the low memory
addresses. See Program and Data Memory Usage.
Stack Checking
A common source of random program failure is stack overflowing other data memory
regions. Either of the two stacks can overflow, and Bad Things Can Happen (tm) when
a stack overflows. You can use the Stack Checking Functions to detect overflow
situations.
148
JumpStarter C for AVR – C Compiler for Atmel AVR
Inline Assembly
Besides writing assembly functions in assembly files, inline assembly allows you to
write assembly code within your C file. You may of course use assembly source files
as part of your project as well. The syntax for inline assembly is:
asm(“<string>”);
Multiple assembly statements can be separated by the newline character \n. String
concatenations can be used to specify multiple statements without using additional
asm keywords. To access a C variable inside an assembly statement, use the
%<name> format:
register unsigned char uc;
asm(“mov %uc,R0\n”
“sleep\n”);
Any C variable can be referenced this way, except for C goto labels. In general, using
inline assembly to reference local registers is limited in power: it is possible that no
CPU registers are available if you have declared too many register variables in that
function. In such a scenario, you would get an error from the assembler. There is also
no way to control allocation of register variables, so your inline instruction may fail. For
example, using the ldi instruction requires the register to be one of the 16 upper
registers, but there is no way to request that using inline assembly. There is also no
way to reference the upper half of an integer register.
Inline assembly may be used inside or outside of a C function. The compiler indents
each line of the inline assembly for readability. Unlike the AVR assembler, the
ImageCraft assembler allows labels to be placed anywhere (not just at the first
character of the lines in your file) so that you may create assembly labels in your inline
assembly code. You may get a warning on asm statements that are outside of a
function. You may ignore these warnings.
149
JumpStarter C for AVR – C Compiler for Atmel AVR
IO Registers
IO registers, including the Status Register SREG, can be accessed in two ways. The
IO addresses between 0x00 to 0x3F can be used with the IN and OUT instructions to
read and write the IO registers, or the data memory addresses between 0x20 to 0x5F
can be used with the normal data accessing instructions and addressing modes. Both
methods are available in C:
Data memory addresses. A direct address can be used directly through pointer
indirection and type casting. For example, SREG is at data memory address
0x5F:
unsigned char c = *(volatile unsigned char *)0x5F;
// read SREG
*(volatile unsigned char *)0x5F |= 0x80;
// turn on the Global Interrupt bit
Note that for non-XMega devices, data memory 0 to 31 refer to the CPU registers!
Care must be taken not to change the CPU registers inadvertently.
This is the preferred method, since the compiler automatically generates the low-
level instructions such as in, out, sbrs, and sbrc when accessing data memory in
the IO register region.
IO addresses. You may use inline assembly and preprocessor macros to access
IO addresses:
register unsigned char uc;
asm(“in %uc,$3F”); // read SREG
asm(“out $3F,%uc”); // turn on the Global Interrupt bit
This is not recommended, as inline assembly may prevent the compiler from
performing certain optimizations.
Note: To read a general-purpose IO pin, you need to access PINx instead of PORTx,
for example, PINA instead of PORTA. Please refer to Atmel’s documentation for
details.
150
JumpStarter C for AVR – C Compiler for Atmel AVR
XMega IO Registers
With XMega, Atmel introduces new syntax to access the io registers, using structs and
unions. They are different from the older AVR and it is imperative to read Atmel’s
AppNote AVR1000 “Getting Started with Writing C-Code for the XMEGA” for details.
This is the current link http://www.atmel.com/Images/doc8075.pdf. In case Atmel
moves the URL, use a search engine to locate the proper URL.
ImageCraft IO header files support the new syntax fully. In version 8.02 and above,
the compiler accepts C++ style anonymous union and struct and thus become fully
compatible with the Atmel AppNote examples. The previous versions of the compiler
do not support C++ anonymous union and use standard C syntax to access multi-byte
struct members:
Remember, 8.02 and above use the left column syntax, just like the Atmel examples.
151
JumpStarter C for AVR – C Compiler for Atmel AVR
Global Registers
Sometimes it is more efficient if your program has access to global registers. For
example, in your interrupt handlers, you may want to increment a global variable that
another part of the program may need to access. Using regular C global variables in
this manner may require more overhead than you want in interrupt handlers due to the
overhead of saving and restoring registers and the overhead of accessing memory
where the global variables reside.
You can ask the compiler not to use the registers R20, R21, R22, and R23 by
checking the Compiler->Options->Target->”Do Not Use R20..R23” option. You should
not check this option in general since the compiler may generate larger program
because it has less registers to use. You cannot reserve other registers besides this
set. This setting affects all the files in the project.
In rare cases when your program contains complex statements using long and
floating-point expressions, the compiler may complain that it cannot compile such
expressions with this option selected. When that happens, you will need to simplify
those expressions.
You can access these registers in your C program by using the pragma:
#pragma global_register <name>:<reg#> <name>:<reg#>...
for example:
#pragma global_register timer_16:20 timer_8:22 timer2_8:23
extern unsigned int timer_16;
char timer_8, timer2_8;
..
#pragma interrupt_handler timer0:8 timer1:7
void timer0()
{
timer_8++;
}
Note that you must still declare the data types of the global register variables. They
must be of char, short, or int types, and you are responsible to ensure that the
register numbering is correct. A 2-byte global register will use the register number you
specified and the next register number to hold its content. For example, timer_16
above is an unsigned int, and it will occupy register R20 and R21.
Since these registers are in the upper 16 set of the AVR registers, very efficient code
will be generated for them when assigning constants, etc.
152
JumpStarter C for AVR – C Compiler for Atmel AVR
The libraries are provided in versions that are compiled with and without this option
set and the IDE automatically selects the correct library version based on the project
option.
153
JumpStarter C for AVR – C Compiler for Atmel AVR
Using C
#pragma abs_address
In a C file, put the following:
#pragma abs_address:0x1000
unsigned LCD_control_register;
#pragma end_abs_address
#pragma abs_address:0x2000
unsigned char dual_port_SRAM[100];
#pragma end_abs_address
These variables may be declared as extern per the usual C rules in other files. Note
that you cannot initialize them in the declarations.
154
JumpStarter C for AVR – C Compiler for Atmel AVR
Note the interface convention of prefixing an external variable names with an '_' in the
assembler file and the use of two colons to define them as global variables.
155
JumpStarter C for AVR – C Compiler for Atmel AVR
156
JumpStarter C for AVR – C Compiler for Atmel AVR
Since changing RAMPZ affects data SRAM access via the Z pointer registers, if you
need to modify RAMPZ, then you should save the previous value and restore it when
you are done. We provide a set of library functions for accessing extended flash
locations that preserves the value of RAMPZ; see Greater Than 64K Access
Functions for details.
With the other RAMP registers, you can just safely use a register and set it to zero
afterward. This ensures that RAMP registers have the default values except in the
cases where you need to modify them.
157
JumpStarter C for AVR – C Compiler for Atmel AVR
where 0x????? is an address beyond the text area. You can check the map file for
the ending address of the text area and set the upper64K_lit starting address
beyond that.
Then in your code, whenever you access atable, you can use:
Pre-XMega:
...
RAMPZ = 1; // atable’s page
... = atable[..]; // read
XMega:
...
... = FlashReadWord(atable_page, &atable[...]);
...
FlashReadWord and related routines read from the flash and preserve the value of
RAMPZ.
char lo_buffer[1024*4];
158
JumpStarter C for AVR – C Compiler for Atmel AVR
...
... = EDataReadBytes(page_no, &hi_buffer[0], &lo_buf-
fer[0], sizeof (lo_buffer));
...
159
JumpStarter C for AVR – C Compiler for Atmel AVR
C Tasks
As described in the Assembly Interface and Calling Conventions page, the compiler
normally generates code to save and restore the preserved registers. Under some
circumstances, this behavior may not be desirable. For example, if you are using a
RTOS (Real Time Operating System), the RTOS manages the saving and restoring of
the registers as part of the task switching process and the code inserted by the
compiler becomes redundant.
To disable this behavior, use the command #pragma ctask. For example,
#pragma ctask drive_motor emit_siren
....
void drive_motor() { ... }
void emit_siren() {...}
The pragma must appear before the definitions of the functions. Note that by default,
the routine main has this attribute set, since main should never return and it is
unnecessary to save and restore any register for it.
160
JumpStarter C for AVR – C Compiler for Atmel AVR
Bootloader Applications
Some of the newer megadevices support bootloader applications. You can either build
a bootloader as a standalone application or have a single application that contains
both the main code and the bootloader code.
161
JumpStarter C for AVR – C Compiler for Atmel AVR
Interrupt Handling
C Interrupt Handlers
Interrupt handlers can be written in C. In the file where you define the function, before
the function definition you must inform the compiler that the function is an interrupt
handler by using a pragma:
#pragma interrupt_handler <func name>:<vector number>
Here, vector number is the interrupt's vector number. Note that the vector number
starts with one, which is the reset vector. This pragma has two effects:
For an interrupt function, the compiler generates the reti instruction instead of
the ret instruction, and saves and restores all registers used in the function.
The compiler generates the interrupt vector based on the vector number and the
target device.
For example:
#pragma interrupt_handler timer_handler:4
...
void timer_handler()
{
...
}
The compiler generates the instruction
rjmp _timer_handler ; for classic devices, or
jmp _timer_handler ; for Mega devices
at location 0x06 (byte address) for the classic devices and 0xC (byte address) for the
Mega devices (Mega devices use 2-word interrupt vector entries vs. 1 word for the
classic non-Mega devices).
You may place multiple names in a single interrupt_handler pragma, separated
by spaces. If you wish to use one interrupt handler for multiple interrupt entries, just
declare it multiple times with different vector numbers. For example:
#pragma interrupt_handler timer_ovf:7 timer_ovf:8
The C header files ioXXXXv.h define consistent global names for interrupt vector
numbers, enabling fully symbolic interrupt_handler pragma and easy target
swapping. Global interrupt vector numbers are named iv_<vector_name> with
<vector_name> as in AVR data sheets. For example:
162
JumpStarter C for AVR – C Compiler for Atmel AVR
163
JumpStarter C for AVR – C Compiler for Atmel AVR
Depending on target macro expansion may result in different code. For names
supported by distinct headers, see the avr_asm_lst and mega_asm_lst files in the
ICCAVR include directory.
164
JumpStarter C for AVR – C Compiler for Atmel AVR
Accessing EEPROM
The EEPROM can be accessed at runtime using library functions. Use #include
<eeprom.h> before calling these functions.
IMPORTANT: These functions do not work for the XMega. XMega support will be
provided in a later release.
EEPROM_READ(int location, object)
This macro calls the EEPROMReadBytes function (see below) to read in the data
object from the EEPROM location(s). The int “object” can be any program variable,
including structures and arrays. For example,
int i;
EEPROM_READ(0x1, i); // read 2 bytes into i
EEPROM_WRITE(int location, object)
This macro calls the EEPROMWriteBytes function (see the next section) to write
the data object to the EEPROM location(s). The int “object” can be any program
variable, including structures and arrays. For example,
int i;
EEPROM_WRITE(0x1, i); // write 2 bytes to 0x1
There are actually 3 sets of macros and functions:
Most classic and mega AVRs
AVRs with 256 bytes of EEPROM
MegaAVRs with extended IO
The IDE predefines certain macros (e.g., ATMega168), so that the right macros and
functions are used when you #include the eeprom.h header file. Thus, you may
use the names given here for these macros and functions.
Initializing EEPROM
EEPROM can be initialized in your program source file by allocation of a global
variable to a special area called eeprom. In C source, this can be done using
pragmas. See Program Areas for a discussion of the different program areas. The
resulting file is <output file>.eep. For example,
#pragma data:eeprom
int foo = 0x1234;
char table[] = { 0, 1, 2, 3, 4, 5 };
165
JumpStarter C for AVR – C Compiler for Atmel AVR
#pragma data:data
...
int i;
EEPROM_READ((int)&foo, i); // i now has 0x1234
The second pragma is necessary to reset the data area name back to the default
data.
Note that to work around the hardware bug in the older AVRs, location 0 is not used
for the initialized EEPROM data for some of these older devices (mostly the pre-Mega
AT90S series).
Note that when using this in an external declaration (e.g. accessing foo in another
file), you do not use the pragma. For example, in another file:
extern int foo;
int i;
EEPROM_READ((int)&foo, i);
Internal Functions
The following functions can be used directly if needed, but the macros described
above should suffice for most if not all situations.
unsigned char EEPROMread(int location)
Reads a byte from the specified EEPROM location.
int EEPROMwrite(int location, unsigned char byte)
Writes byte to the specified EEPROM location. Returns 0 if successful.
void EEPROMReadBytes(int location, void *ptr, int size)
Reads size bytes starting from the EEPROM location into a buffer pointed to
by ptr.
void EEPROMWriteBytes(int location, void *ptr, int size)
Writes size bytes to EEPROM starting with location with content from a buffer
pointed to by ptr.
166
JumpStarter C for AVR – C Compiler for Atmel AVR
multitasking environment. A ready function is provided for you to ensure that the
operation is completed. This is particularly useful for the EEPROM write function,
since writing EEPROM may take a long time.
167
JumpStarter C for AVR – C Compiler for Atmel AVR
168
JumpStarter C for AVR – C Compiler for Atmel AVR
AVR Features
AVR uses the Harvard architecture and separate the program and data memory.
See Program Data and Constant Memory.
Program memory size is specified in bytes (e.g. M32 has 32K bytes of flash) but
each instruction is at least 2 bytes long. Therefore, program locations encoded in
the instructions are word addresses. When used as storage for literal tables etc.,
the program memory is byte addressable using the lpm/elpm family of
instructions.
JumpStarter C for AVR programs such as the compiler proper, the assembler and
linker use byte addresses in most usages and the tools do the appropriate word
address conversion as necessary.
The registers are not all general purpose. AVR instructions that use immediate
source operands (e.g. addi, ldi etc.) only operate on the upper 16 registers
R16 to R31. There are only 3 set of “pointer” registers: R26/R27 or X, R28/R29 or
Y, and R30/R31 or Z. Y and Z can use the displacement mode with an offset but X
cannot use such mode.
The generated code use two stacks (see Program Data and Constant Memory),
the native hardware stack for CALL return addresses and a software stack using
the Y pointer. While this makes it more challenging to ensure that both stacks
have sufficient space, the alternative of using a single stack generates
substantially more code.
Device-Specific Instructions
Devices with 8K or less bytes of program memory do not support the jmp and call
instructions, and only the rjmp and rcall relative instructions. The initial generation
of the AVR (sometimes known as “classic” AVRs) do not have the newer instructions
such as the multiply instructions and the extended lpm instructions.
169
JumpStarter C for AVR – C Compiler for Atmel AVR
M128x Considerations
The M128x AVRs have 128K bytes of flash. Indirect function calls use 16 bit word
pointers and can reach the entire address space (see Program Areas for description
of func_lit) and you do not need to do anything special when using function
pointers.
However, to access constant in the upper 64K bytes, you will need to modify the
RAMPZ IO register to point to the upper bank manually (and reset it when done). We
may add support for “far” pointers in the future so constant accesses will be
transparent, albeit at the cost of larger code size.
M256x Considerations
The M256x AVRs have 256K bytes of flash. A 16-bit word pointer is no longer
sufficient to hold the value of all possible function addresses. For each function
pointer, a 3-byte entry is made in the efunc_lit area (see Program Areas). The
efunc_lit must be located in the lower 64 bytes of the address space.
For constant data, the same issue as with M128x applies and you must set the
RAMPZ IO register explicitly.
XMega Considerations
The XMega is largely backward compatible with the ATMega devices. One notable
difference is that the CPU registers are no longer mapped onto data memory space
and the IO registers have the same IO memory addresses and data memory
addresses. In previous AVRs, the IO registers are offset by 32 bytes when referenced
in the data memory space. Also see Accessing Memory Outside of the 64K Range for
issues on accessing extended memory space using RAMPD, RAMPX, RAMPY and
RAMPZ registers.
170
C RUNTIME ARCHITECTURE
Table 1:
pointer 2 0..65535
float 4 +/-1.175e-38..3.40e+38
double 4 +/-1.175e-38..3.40e+38
8 (**) +/-2.225e-308..1.798e+308
172
JumpStarter C for AVR – C Compiler for Atmel AVR
External Names
External C names are prefixed with an underscore. For example, the function main is
_main if referenced in an assembly module. Names are significant to 32 characters.
To make an assembly object global, use two colons after the name. For example,
_foo::
.word 1
.blkw 1
(In the C file)
extern int foo;
173
JumpStarter C for AVR – C Compiler for Atmel AVR
Preserved Registers
An assembly function must save and restore the following registers. These registers
are called preserved registers, since their contents are unchanged by a function call.
Local variables are assigned to these registers by the compiler.
R28/R29 or Y (this is the frame pointer)
R10/R11/R12/R13/R14/R15/R20/R21/R22/R23
You can ask the compiler not to use the registers R20, R21, R22, and R23, ; then you
do not need to save and restore these four registers. See Global Registers
Volatile Registers
The other registers:
R0/R1/R2/R3/R4/R5/R6/R7/R8/R9/R24/R25/R26/R27/R30/R31
SREG
can be used in a function without being saved or restored. These registers are called
volatile registers, since their contents may be changed by a function call.
Interrupt Handlers
Since an interrupt handler operates asynchronously to the normal program operation,
the interrupt handler or the functions it calls must not modify any machine registers.
Therefore, an interrupt handler must save and restore all registers that it uses. This is
done automatically if you use the compiler capability to declare a C function as an
interrupt handler. If you write a handler in assembly and if it calls normal C functions,
then the assembly handler must save and restore the volatile registers, since normal
C functions do not preserve them.
The exception is when you ask the compiler not to use the registers R20, R21, R22,
and R23 ; then the interrupt handlers may use these four registers directly.
Structure
Passing by Value
If passed by value, a structure is always passed through the stack, and not in
registers. Passing a structure by reference (i.e., passing the address of a structure) is
the same as passing the address of any data item; that is, a pointer to the structure
(which is 2 bytes) is passed.
Returning a Structure by Value
174
JumpStarter C for AVR – C Compiler for Atmel AVR
175
JumpStarter C for AVR – C Compiler for Atmel AVR
Function Pointers
To be fully compatible with the Code Compressor (tm), all indirect function references
must be through an extra level of indirection. This is done automatically for you in C if
you invoke a function by using a function pointer. In other words, function pointers
behave as expected, with the exception of being slightly slower.
The following assembly language example illustrates this:
; assume _foo is the name of the function
.area func_lit
PL_foo:: .word _foo ; create a function table entry
.area text
ldi R30,<PL_foo
ldi R31,>PL_foo
rcall xicall
You may use the library function xicall to call the function indirectly after putting the
address of the function table entry into the R30/R31 pair. Function table entries are put
in a special area called func_lit. See Program Areas.
For the M256x targets, the function tables are located in the efunc_lit area and
each entry is 3 bytes long, to allow the function to be located anywhere in the 256K
bytes address space. The function exicall is used instead of xicall, since 3 bytes
are used.
176
JumpStarter C for AVR – C Compiler for Atmel AVR
C Machine Routines
Most C operations are translated into direct Atmel AVR instructions. However, there
are some operations that are translated into subroutine calls because they involve
many machine instructions and would cause too much code bloat if the translations
were done inline. These routines are written in assembly language and can be
distinguished by the fact that the routine names do not start with an underscore or
have a two-underscore prefix. These routines may or may not use the standard calling
convention and you should not use them directly, as we may change their names or
implementations depending on the compiler releases.
177
JumpStarter C for AVR – C Compiler for Atmel AVR
Program Memory
The program memory is used for storing your program code, constant tables, and
initial values for certain data such as strings and global variables. See Program Data
and Constant Memory. The compiler generates a memory image in the form of an
output file that can be used by a suitable program such as an ISP (In System
Programming) Programmer.
HW High Address
Stack
SW
Stack
Heap
Global Variables
and Strings
The bottom of the memory map is address 0. The first 96 (0x60) locations are CPU
and IO registers. The newer ATMega devices have even greater amount of IO
registers. The compiler places global variables and strings from after the IO registers.
178
JumpStarter C for AVR – C Compiler for Atmel AVR
On top of the variables is the area where you can allocate dynamic memory. See
Standard Library And Memory Allocation Functions. At the high address, the hardware
stack starts at the end of the SRAM. Below that is the software stack which grows
downward. It is up to you, the programmer, to ensure that the hardware stack does not
grow past the software stack, and the software stack does not grow into the heap.
Otherwise, unexpected behaviors will result (oops...). See Program Data and
Constant Memory.
179
JumpStarter C for AVR – C Compiler for Atmel AVR
Program Areas
The compiler generates code and data into different “areas.” See Assembler
Directives. The areas used by the compiler, ordered here by increasing memory
address, are:
Read-Only Memory
vectors - this area contains the interrupt vectors.
func_lit - function table area. Each word in this area contains the address of a
function entry or a label for the switch table. To be fully compatible with the Code
Compressor (tm), all indirect function references must be through an extra level of
indirection. This is done automatically for you in C if you invoke a function by
using a function pointer. In assembly, the following example illustrates:
; assume _foo is the name of the function
.area func_lit
PL_foo:: .word _foo; create a function table entry
.area text
call PL_foo
efunc_lit - extended function table area. This serves the same function as
func_lit except that each entry is a 3 byte function address. This is only needed for
the ATMega256x devices.
idata - the initial values for the global data and strings are stored in this area and
copied to the data area at startup time.
lit - this area contains integer and floating-point constants, etc.
text - this area contains program code.
Data Memory
data - this is the data area containing initialized global and static variables, and
strings. The initial values of the global variables and strings are stored in the
idata area and copied to the data area at startup time.
bss - this is the data area containing C global variables without explicit
initialization. Per ANSI C definition, these variables get initialized to zero at startup
time.
noinit - you use #pragma data:noinit to put global variables that you do
not want any initialization. For example:
#pragma data:noinit
180
JumpStarter C for AVR – C Compiler for Atmel AVR
int junk;
#pragma data:data
EEPROM Memory
eeprom - this area contains the EEPROM data. EEPROM data is written to
<output file>.eep as an Intel HEX file regardless of the output file format.
The job of the linker is to collect areas of the same types from all the input object files
and concatenate them together in the output file. See Linker Operations.
181
JumpStarter C for AVR – C Compiler for Atmel AVR
using the same example as before, you can write the following in an assembly file:
.area battery_sram(abs)
.org 0x4000
_var1:: .blkw 1 ; note _ in the front
_var2:: .blkb 1 ; and two colons
The (abs) attribute tells the assembler that the area does not need relocation
and it is valid to use the .org directive in the area. In this example, we use .org
to set the starting address. In C the declaration will be exactly the same as before.
If you have data that have initialized values, then you can also use the following
pragma in C to define them (note this only works with data that have initialized
values):
#pragma abs_address:0x4000
int var1 = 5;
char var2 = 0;
#pragma end_abs_address
182
JumpStarter C for AVR – C Compiler for Atmel AVR
183
JumpStarter C for AVR – C Compiler for Atmel AVR
184
COMMAND-LINE COMPILER
OVERVIEW
Compilation Process
[ Underneath the user-friendly IDE is a set of command-line compiler programs. While
you do not need to understand this chapter to use the compiler, this chapter is good
for those who want to find out “what's under the hood.” ]
Given a list of files in a project, the compiler's job is to translate the files into an
executable file in some output format. Normally, the compilation process is hidden
from you through the use of the IDE’s Project Manager. However, it can be important
to have an understanding of what happens “under the hood”:
1. icppw.exe, the C preprocessor, processes the # directives in a C source file.
2. iccomavr.exe, the compiler proper, translates the preprocessed source file to
an assembly file.
3. iasavr.exe, the assembler, translates each assembly file (either from the
compiler or assembly files that you have written) into a relocatable object file.
4. ilnkavr.exe is the linker. After all the files have been translated into object files,
the linker combines them together to form an executable file. In addition, a map
file, a listing file, and debug information files are also output.
5. Optionally, the linker performs the Code Compression optimization and generates
optimized output file.
6. ilstavr.exe, the listing file manager, generates the .lst intersperse C and
asm listing file.
7. icc2avr-elf.exe generates the ELF production file.
All these details are handled by the compiler driver. You give it a list of files and ask it
to compile them into an executable file (default) or to some intermediate stage (for
example, to the object files). The driver invokes the compiler, the assembler, and the
linker as needed.
The previous versions of our IDE generate a makefile and invoke the make program to
interpret the makefile, which causes the compiler driver to be invoked.
Version 8’s Code::Blocks IDE (C::B) does not use the make program and uses an
internal build system that calls the compiler driver directly.
JumpStarter C for AVR – C Compiler for Atmel AVR
Driver
The compiler driver examines each input file and acts on the file based on the file's
extension and the command-line arguments it has received. The .c files and .s files
are C source files and assembly source files, respectively. The design philosophy for
the IDE is to make it as easy to use as possible. The command-line compiler, though,
is extremely flexible. You can control its behavior by passing command-line arguments
to it. If you want to interface with the compiler with your own GUI (for example, the
Codewright or Multiedit editor), here are some of the things you need to know.
Error messages referring to the source files begin with !E file(line):...
Warning messages use the same format but use !W as the prefix instead of !E.
To bypass the command-line length limit on Windows 95/NT, you may put
command-line arguments in a file and pass it to the compiler as @file or @-
file. If you pass it as @-file, the compiler will delete file after it is run.
The next section, Compiler Arguments, elaborates further on the subject.
186
JumpStarter C for AVR – C Compiler for Atmel AVR
Compiler Arguments
The IDE controls the behaviors of the compiler by passing command-line arguments
to the compiler driver. Normally you do not need to know what these command-line
arguments do, but you can see them in the Status Window when you perform a build.
This section is useful if you are using command line scripts to call the compiler
directly.
The best method to find the correct compiler flags is to use the IDE and invoke
ImageCraft->Create Makefile and then either use the generated makefile as is
or extract the relevant compiler and linker flags within. Note that the CodeBlocks IDE
does not use a makefile and uses an internal build system instead.
You call the compiler driver with different arguments and the driver in turn invokes
different passes of the compiler tool chain with the appropriate arguments.
The general format of a command is as follows:
iccavr [ arguments ] <file1> <file2> ... [ <lib1> ... ]
where iccavr is the name of the compiler driver. As you can see,
you can invoke the driver with multiple files and the driver
will perform the operations on all of the files. By default, the
driver then links all the object files together to create the
output file.
The driver automatically adds -I<install root>\include to the C preprocessor
argument and -L<install root>\lib to the linker argument.
For most of the common options, the driver knows which arguments
are destined for which compiler passes. You can also specify
which pass an argument applies to by using a -W<c> prefix. For
example:
-Wp is the preprocessor. For example, -Wp-e
-Wf is the compiler proper. For example, -Wf-Matmega
-Wa is the assembler.
-Wl (letter el) is the linker.
Driver Arguments
-c
Compile the file to the object file level only (does not invoke the linker).
187
JumpStarter C for AVR – C Compiler for Atmel AVR
-o <name>
Name the output file. By default, the output file name is the same as the input file
name, or the same as the first input file if you supply a list of files.
-v
Verbose mode. Print out each compiler pass as it is being executed.
188
JumpStarter C for AVR – C Compiler for Atmel AVR
Preprocessor Arguments
-D<name>[=value]
Define a macro. See Build Options - Compiler. The driver and the IDE predefines
certain macros. See Predefined Macros.
-e
Accept C++ comments.
-I<dir>
(Capital letter i) Specify the location(s) to look for header files. Multiple -I flags
can be supplied. The directories are searched in order they are specified.
-U<name>
Undefine a macro. See Build Options - Compiler.
189
JumpStarter C for AVR – C Compiler for Atmel AVR
Compiler Arguments
-A -A
Turn on strict ANSI checking. Single -A turns on some ANSI checking.
-e
Accept extensions including 0b???? binary constants. See Pragmas.
-g
Generate debug information.
When using with the driver, the following options must be used with the -Wf- prefix,
such as -Wf-str_in_flash.
Processor (best to use “Instruction Set” section below)
-Mavr_enhanced
Generate enhanced core instructions and call and jmp.
-Mavr_extended
Same as -Mavr_enhanced, plus 3 byte extended call and jmp
addressing and extended function table in efunc_lit area.
-Mavr_enhanced_small
Generate enhanced core instructions but not call and jmp.
-Mavr_mega
Generate ATMega instructions such as call and jmp instead of rcall and
rjmp.
Instruction Set
-MEnhanced
Enhanced core instructions.
-MExtended
3 byte extended call and jmp addressing and extended function
table in efunc_lit area.
-MHasMul
Use the MUL and related instructions.
-MLongJump
190
JumpStarter C for AVR – C Compiler for Atmel AVR
191
JumpStarter C for AVR – C Compiler for Atmel AVR
Assembler Arguments
-m
Enable case insensitivity with macro name. The default is that macro names are
case sensitive.
-n
Use only for assembling a Startup File. Normally the assembler inserts an implicit
.area text at the beginning of a file it is processing. This allows the common
case of omitting an area directive in the beginning of a code module to be
assembled correctly. However, the startup file has special requirements that this
implicit insertion should not be done.
-W
Turn on relocation wrapping. See Device-Specific Instructions. When using the
driver, you must use -Wa-W.
192
JumpStarter C for AVR – C Compiler for Atmel AVR
Linker Arguments
Address ranges are in the form <start>.<end>[:<start>.<end>]*. For example:
0x0.0x10000 ; one range
0x0.0x10000:0x11000.0x20000 ; two ranges
The compiler uses up to but not including the “end” address for memory allocation.
Typically the address ranges are not checked for overlaps. It’s up to you to ensure that
address ranges in the same memory space from within the same program area or
from different areas do not overlap. This includes any absolute memory regions used
by your programs using the .org assembly directive or one of the abs_address C
#pragma.
Specifying Addresses
If you use #pragma text / data / lit / abs_address to assign your own
memory areas, you must manually ensure that their addresses do not overlap the
ones used by the linker. As an attempt to overlap allocation may or may not cause the
linker to generate an error, you should always check the .mp map file (use the IDE
menu selection View->Map File) for potential problems.
-b<area>:<address ranges>
Assign the address ranges for the area. You can use this to create your own areas
with its own address. See Program Areas. For example:
-bmyarea:0x1000.0x2000:0x3000.0x4000
specifies that myarea goes from locations 0x1000 to 0x2000
and then from 0x3000 to 0x4000.
-bdata:<address ranges>
Assign the address ranges for the area named data, which is used by your
program’s global variables. -beeprom:<address ranges>
Assign the address ranges for the EEPROM. EEPROM data is written to <output
file>.eep as an Intel HEX file regardless of the output file format.
-bfunc_lit:<address ranges>
Assign the address ranges for the area named func_lit. The format is <start
address>[.<end address>], where addresses are byte addresses. func_lit is
the first area for the AVR compiler and thus this effectively declares the entire
usable space in the flash. For example, some typical values are:
-bfunc_lit:0x60.0x10000 for ATMega
-bfunc_lit:0x1a.0x800 for 23xx
193
JumpStarter C for AVR – C Compiler for Atmel AVR
Others
-cross_module_type_checking
Enable Cross Module Type Checking. Available in the PRO edition only.
-d<name>:<#>
Define a link time constant. <name> should be a symbol used in an assembly
instruction and cannot be used in the assembly directive .if etc.
-dhwstk_size:<size>
Define the size of the hardware stack. The hardware is allocated at the top of
SRAM, and then the software stack follows it. See Program Data and Constant
Memory.
-dram_end:<address>
Define the end of the internal RAM area. This is used by the Startup File to
initialize the value of the hardware Stacks. For the classic non-Mega devices,
ram_end is the size of the SRAM plus 96 bytes of IO and CPU registers minus
one. For the Mega devices, it is the size of the SRAM minus one. External SRAM
does not affect this value, since the hardware stack is always allocated in the
internal RAM for faster execution speed.
-e:<size>
Specify the total flash size of the target device.
-elim[:<area>]
Enable the Unused Code Elimination optimization. PRO versions only.
-F<pat>
Fill unused ROM locations with pat. Pattern must be an integer. Use 0x prefix for
hexadecimal integer.
-fcoff
Output format is COFF. Note that if you have EEPROM data, it is always written
as Intel HEX format in the <output>.eep file.
-fihx_coff
194
JumpStarter C for AVR – C Compiler for Atmel AVR
195
JumpStarter C for AVR – C Compiler for Atmel AVR
196
TOOL REFERENCES
MISRA checking is available in the PRO edition of our tools, although there are a few
warnings that possibly reflect errors so they are enabled all the time. Under the
Code::Blocks IDE, invoke Project->Build Options->Compiler->Enable
MISRA Checks to enable this option. This corresponds to the -MISRA_CHECK
compiler flag.
198
JumpStarter C for AVR – C Compiler for Atmel AVR
unsigned f(int i)
{
unsigned u = i; // WARNING: potential loss of sign
return u;
}
Explicit cast can be used to suppress this kind of warnings:
unsigned g = (unsigned) -1; // OK
unsigned f(int i)
{
unsigned u = (unsigned) i; // OK
return u;
}
199
JumpStarter C for AVR – C Compiler for Atmel AVR
An implicit array-to-pointer decay in the left operand of the -> member access
operator is considered suspicious. For example:
struct S {
int i;
} a[5];
int f(void)
{
return a -> i; // WARNING: the index is not specified
}
The warning can be suppressed by specifying the index of the dereferencing array
element explicitly:
int f(void)
{
return a[0].i; // OK
}
200
JumpStarter C for AVR – C Compiler for Atmel AVR
MISRA prohibits any kind of pointer arithmetic. This includes adding an integer to a
pointer and subtraction of an integer or pointer from another pointer, e.g.:
int i;
int *bar(unsigned);
int *f(int *p, int *q); int *f(int *p, int *q)
{
if(i < 33) {
return 1 + p; // WARNING: pointer +
integer
} else {
if(i < 55) {
return p - 1; // WARNING: pointer
- integer
} else {
if(i < 77) {
return bar(p - q); // WARNING: pointer
- pointer
} else {
/* do nothing */
}
}
}
return &p[2]; // OK
}
Note that array subscription ([]) and dereferencing (*, . and ->) operators are
allowed, so it is usually possible to rewrite the code that uses pointer arithmetic so that
it modifies integer indices instead of changing the pointers themselves. For example,
the following function
int strlen(const char *s)
{
int n = 0;
while(*s != '\0') {
s++; // WARNING
}
return n;
}
can be rewritten as
201
JumpStarter C for AVR – C Compiler for Atmel AVR
202
JumpStarter C for AVR – C Compiler for Atmel AVR
MISRA requires numeric constants to have proper types. That means then no numeric
constant shall be a subject to a conversion that changes it type; instead, where
possible, the numeric constant shall be suffixed so it has the suitable type. For
example:
unsigned f(unsigned i)
{
return i + 1; // WARNING: the literal "1" has type "int"
whereas
// an integer of type "unsigned int" is expected
}
double g(void)
{
return 1.f; // WARNING: the literal "1.f" has type
"float",
// but a value of type "double" is expected
}
The following functions are examples of the proper use of the numeric suffixes:
unsigned f(unsigned i)
{
return i + 1u; // OK
}
double g(void)
{
return 1.; // OK
}
!W (13):[warning] [MISRA 2460]expression modifies `i' more than once without an
intervening sequence point
203
JumpStarter C for AVR – C Compiler for Atmel AVR
If an expression modifies a variable more than once and there is no sequence point
between these two modifications, then the result of evaluation of the expression is
unexpected by the definition of the C Standard and the very expression is prohibited
by MISRA.
A sequence point is a point in the execution sequence of a program for which the C
Standard requires that all current changes (including modifications of variables) made
during previous evaluations are complete.
The following list enumerates locations of the sequence points:
The call to a function, after the arguments have been evaluated.
The end of the first operand of the following operators: logical AND &&, logical OR
||, conditional operator ? and comma operator.
The end of a full declarator;
The end of a full expression: an initializer, the expression in an expressifon
statement, the controlling expression of a selection statement (if or switch), the
controlling expression of a while or do statement, each of the expressions of a
for statement, the expression in a return statement;
Immediately before a library function returns;
After the actions associated with each formatted input/output function conversion
specifier.
Immediately before and immediately after each call to a comparison function, and
also between any call to a comparison function and any movement of the objects
passed as arguments to that call.
The following function mentions some expressions that violate this MISRA rule as well
as some common expressions that do not. Please see the comments for
explanations.
int (*fp)(int, int), (*fp2)(int, int), (*fp3)(int, int), a,
b, c;
204
JumpStarter C for AVR – C Compiler for Atmel AVR
j = i++ + i++;
// WARNING: two modifications of "i" that are not
delimited
// by a sequence point
j = p++[ *p++ ];
// WARNING: modifications of "p" interfere
fp(i++, j++);
// OK: the arguments modify different variables
fp(j++, j++);
// WARNING: modifications of "j" interfere
205
JumpStarter C for AVR – C Compiler for Atmel AVR
k = (k == 0) ? i++ : j++;
// OK: this expression modifies different
variables
k = (k == 0) ? i++ : i++;
// OK: only one of the "i"s is to be evaluated
i = a + b++ + b++;
// WARNING: the modifications of "b" interfere
i = a + b++ + c + b++;
// WARNING: ditto
}
206
JumpStarter C for AVR – C Compiler for Atmel AVR
void g(void)
{
typedef int T(void); // OK: not a function declaration
207
JumpStarter C for AVR – C Compiler for Atmel AVR
Advantages
Code Compressor decreases your program size transparently. It does not
interfere with traditional optimizations and can decrease code size even when
aggressive traditional optimizations are done.
Code Compressor does not affect source-level debugging.
Disadvantage
There is a slight increase in execution time due to function call overhead.
Theory of Operation
The Code Compressor replaces duplicate code blocks with a call to a single instance
of the code. It also optimizes long calls or jumps to relative offset calls or jumps if the
target device supports such instructions. Code compression occurs (if enabled) after
linking the entire code image. The Code Compressor uses the binary image of the
program as its input for finding duplicate code blocks. Therefore, it works regardless
whether the source code is written in C or assembly.
The Code Compressor is part of the linker, and thus it has the full debug and map file
information, plus other linker internal data. These are important as the Code
Compressor must only compress code and not literal data, and must adjust program
counter references (e.g., branch offset, etc.).
Debugger data is also adjusted so there is no loss of debugging capabilities when the
Code Compressor is used.
208
JumpStarter C for AVR – C Compiler for Atmel AVR
Compatibility Requirements
To make your code fully compatible with the Code Compressor, note that indirect
function references must be done through a function label entry in the func_lit
output area. See Program Areas. This is done automatically if you are using C.
To simplify its operations, the Code Compressor only compresses code in the text
area. Since the Code Compressor operates post-linking, the text area then must be
the last (e.g., highest memory addresses) relocatable code area. Otherwise, the text
area may be shrunk, but then there would be a hole between the end of the text area
and the next code region.
If you are using C and the default areas, then this should not cause any issues.
However, if you create your own areas, then you must ensure that either it is located
before the text area or that it is located in an absolute location (e.g., a bootloader).
Not Allowed
Function A Function X
Calls
Function B Function Y
Allowed
"text" "non_text"
Area Area
The above diagram shows a scenario that is problematic. Code areas created with the
AREA directive, using a name other than text, are not compressed or fixed up
following compression. If Function Y calls Function B, there is the potential that the
location of Function B will be changed by the Code Compressor. The call or jump
generated in the code for Function Y will go to the wrong location.
It is allowable for Function A to call a function in a non_text Area. The location for
Function B can change because it is in the text Area. Calls and jumps are fixed up in
the text area only. Following code compression, the call location to Function B from
Function X in the non-text Area will not be compressed.
All normal user code that is to be compressed must be in the default text Area. If you
create code in other area (for example, in a bootloader), then it must not call any
functions in the text Area. However, it is acceptable for a function in the text Area
to call functions in other areas.
209
JumpStarter C for AVR – C Compiler for Atmel AVR
If you reference any text area function by address, then it must be done indirectly. Its
address must be put in a word in the area func_lit. At runtime, you must de-
reference the content of this word to get the correct address of the function. Note that
if you are using C to call a function indirectly, the compiler will take care of all these
details for you. The information is useful if you are writing assembly code.
210
JumpStarter C for AVR – C Compiler for Atmel AVR
Assembler Syntax
Names
All names in the assembler must conform to the following specification:
(‘_’ | [a-Z]) [ [a-Z] | [0-9] | ‘_’ ] *
That is, a name must start with either an underscore ( _) or an alphabetic character,
followed by a sequence of alphabetic characters, digits, or underscores. In this
document, names and symbols are synonyms for each other. A name is either the
name of a symbol, which is a constant value, or the name of a label, which is the value
of the Program Counter (PC) at that moment. A name can be up to 30 characters in
length. Names are case-sensitive except for instruction mnemonics and assembler
directives.
211
JumpStarter C for AVR – C Compiler for Atmel AVR
Name Visibility
A symbol may either be used only within a program module or it can be made visible
to other modules. In the former case, the symbol is said to be a local symbol, and in
the latter case, it is called a global symbol.
If a name is not defined within the file in which it is referenced, then it is assumed to be
defined in another module and its value will be resolved by the linker. The linker is
sometimes referred to as a relocatable linker precisely because one of its purposes is
to relocate the values of global symbols to their final addresses.
Numbers
If a number is prefixed with 0x or $, said number is taken to be a hexadecimal
number.
Examples:
10
0x10
$10
0xBAD
0xBEEF
0xC0DE
-20
Labels
A name followed by one or two colons denotes a label. The value of the label is the
value of the Program Counter (PC) at that point of the program. A label with two
colons is a global symbol; that is, it is visible to other modules.
212
JumpStarter C for AVR – C Compiler for Atmel AVR
Commands
A command can be an AVR instruction, an assembler directive or a macro invocation.
The operands field denotes the operands needed for the command. This page does
not describe the AVR instructions per se, since the assembler uses the standard
vendor-defined names; consult the vendor’s documentation for instruction
descriptions.
The exceptions are:
xcall Applicable to mega devices that support long call or jump instructions
only. This is translated to either to rcall or call, depending on the location of
the target label.
xjmp Applicable to mega devices that support long call or jump instructions
only. This is translated to either to rjmp or jmp, depending on the location of the
target label.
Expressions
An instruction operand may involve an expression. For example, the direct addressing
mode is simply an expression:
lds R10,asymbol
The expression asymbol is an example of the simplest expression, which is just a
symbol or label name. In general, an expression is described by:
expr: term | ( expr ) | unop expr | expr binop expr
term: . | name | #name
The dot (.) is the current program counter. Parentheses () provide grouping.
Operator precedence is given below. Expressions cannot be arbitrarily complex, due
to the limitations of relocation information communicated to the linker. The basic rule is
that for an expression, there can only be only one relocatable symbol. For example,
lds R10,foo+bar
is invalid if both foo and bar are external symbols.
Operators
The following is the list of the operators and their precedence. Operators with higher
precedence are applied first. Only the addition operator may apply to a relocatable
symbol (such as an external symbol). All other operators must be applied to constants
or symbols resolvable by the assembler (such as a symbol defined in the file).
213
JumpStarter C for AVR – C Compiler for Atmel AVR
Note that to get the high and low byte of an expression, you use the > and <
operators, and not the high() and low() operators in the Atmel assembler.
* multiply binary 10
/ divide binary 10
% modulo binary 10
| bitwise OR binary 4
- negate unary 11
214
JumpStarter C for AVR – C Compiler for Atmel AVR
Assembler Directives
Assembly directives are commands to the assembler. Directives are case-insensitive.
215
JumpStarter C for AVR – C Compiler for Atmel AVR
.area foo(rel,con)
.area foo(rel,ovr)
.ascii “strings”
.asciz “strings”
These directives are used to define strings, which must be enclosed in a delimiter pair.
The delimiter can be any character as long as the beginning delimiter matches the
closing delimiter. Within the delimiters, any printable ASCII characters are valid, plus
the following C-style escape characters, all of which start with a backslash (\):
\e escape
\b backspace
\f form feed
\n line feed
\r carriage return
\t tab
\<up to 3 octal digits> character with value equal to the
octal digits
.asciz adds a NUL character (\0) at the end. It is acceptable to embed \0 within the
string.
Examples: .asciz “Hello World\n”
.asciz “123\0456”
.blkb <value>
.blkw <value>
216
JumpStarter C for AVR – C Compiler for Atmel AVR
.blkl <value>
These directives reserve space without giving them values. The number of items
reserved is given by the operand.
.else
Forms a conditional clause together with a preceding .if and following .endif. If
the if clause conditional is true, then all the assembly statements from the .else to
the ending .endif (the else clause) are ignored. Otherwise, if the if clause
conditional is false, then the if clause is ignored and the else clause is processed
by the assembler. See .if.
.endif
Ends a conditional statement. See .if and .else.
.endmacro
Ends a macro statement. See .macro.
.eaddr
Use only for the M256x and the ‘ (back quote) operator. Generates the 3-byte code
address of the symbol. For example:
.eaddr ‘function_name
<symbol> = <value>
Defines a numeric constant value for a symbol.
Example: foo = 5
217
JumpStarter C for AVR – C Compiler for Atmel AVR
.include “<filename>”
Processes the contents in the file specified by filename. If the file does not exist,
then the assembler will try to open the filename created by concatenating the path
specified via the –I command-line switch with the specified filename.
Example: .include “registers.h”
.macro <macroname>
Defines a macro. The body of the macro consists of all the statements up to the
.endmacro statement. Any assembly statement is allowed in a macro body except
for another macro statement. Within a macro body, the expression @digit, where
digit is between 0 and 9, is replaced by the corresponding macro argument when
the macro is invoked. You cannot define a macro name that conflicts with an
instruction mnemonic or an assembly directive. See .endmacro and Macro
Invocation. For example, the following defines a macro named foo:
.macro foo
lds @0,a
mov @1,@0
.endmacro
Invoking foo with two arguments:
foo R10,R11
is equivalent to writing:
lds R10,a
mov R11,R10
218
JumpStarter C for AVR – C Compiler for Atmel AVR
.org <value>
Sets the Program Counter (PC) to value. This directive is only valid for areas with the
abs attribute. Note that value is a byte address.
Example: .area interrupt_vectors(abs)
.org 0xFFD0
.dc.w reset
219
JumpStarter C for AVR – C Compiler for Atmel AVR
Assembly Instructions
CALL and JMP, are only available for devices with larger than 8K bytes of code
memory. For the high and low byte operators, see Operators..
Table 1:
FMULSU Rd,Rr
[MegaAVR]
Branch Instructions
220
JumpStarter C for AVR – C Compiler for Atmel AVR
Table 1:
BRBS s,label BRBC s,label BRxx label c
EIJMP EICALL
[Enhanced MegaAVR] [Enhanced MegaAVR]
PUSH Rr POP Rd
BREAK
221
JumpStarter C for AVR – C Compiler for Atmel AVR
Table 1:
xch
222
JumpStarter C for AVR – C Compiler for Atmel AVR
Linker Operations
The main purpose of the linker is to combine multiple object files into an output file
suitable to be loaded by a device programmer or target simulator. The linker can also
take input from a “library,” which is basically a file containing multiple object files. In
producing the output file, the linker resolves any references between the input files. In
some detail, the linking steps involve:
1. Making the startup file be the first file to be linked. The startup file initializes the
execution environment for the C program to run.
2. Appending any libraries that you explicitly requested (or in most cases, as were
requested by the IDE) to the list of files to be linked. Library modules that are
directly or indirectly referenced will be linked in. All the user-specified object files
(for example, your program files) are linked.
3. Appending the standard C library libcavr.a to the end of the file list.
4. Scanning the object files to find unresolved references. The linker marks the
object file (possibly in the library) that satisfies the references and adds to its list of
unresolved references. It repeats the process until there are no outstanding
unresolved references.
5. Combining “areas” in all marked object files into an output file and generating map
and listing files as needed.
Lastly, if this is the PRO edition and if the Code Compressor (tm) optimization option is
on, then the Code Compressor is called.
Memory Allocation
As the linker combines areas from the input object files, it assigns memory addresses
to them based on the address ranges passed in from the command line (see Linker
Arguments). These arguments in turn are normally passed down from the IDE based
on the specified device. That is, in the normal case, you do not need to do anything
and the IDE/compiler will do the correct memory allocation for you.
If you use #pragma text / data / lit / abs_address to assign your own
memory areas, you must manually ensure that their addresses do not overlap the
ones used by the linker. As an attempt to overlap allocation may or may not cause the
linker to generate an error, you should always check the .mp map file (use the IDE
menu selection View->Map File) for potential problems.
223
JumpStarter C for AVR – C Compiler for Atmel AVR
Scope Rules
There are 3 scopes where items can be declared: FILE scope, FUNCTION scope,
and BLOCK scope. They correspond to the lexical scoping in C.
Convention
<addr> is an address and is always in hexadecimal. This can be either a code or data
address, depending on the context.
<line no> is a line number and is always in decimal.
<name> is a valid C or assembly name, or a file or directory name.
<type> is a data type specifier. See Type Specifier below.
<#> is a decimal number.
224
JumpStarter C for AVR – C Compiler for Atmel AVR
Top-Level Commands
IMAGECRAFT DEBUG FORMAT
Starting at V1.1, this is the first line of the debug file.
VERSION <#.#>
Specifies the version number of the debug format. The current version is 1.4.
CPU <name>
Specifies the target CPU. Valid choices are Cortex, HC11, HC12, HC16, AVR,
M8C, HC08, MSP430, or ARM.
DIR <name>
Specifies the directory path of all subsequent FILE commands. An ending slash
‘\’ is always present.
FILE <name>
Starts a file section. All the following debug commands apply to this file until the
end of file is reached or until the next FILE command is encountered. The full
path name is a concatenation of the last DIR command and the current FILE
command.
FUNC <name> <addr> <type>
Starts a C function section. All the following debug commands apply to this
function until the FUNCEND command is encountered. For assembler modules, no
FUNC command is needed. The <addr> is the starting address of the first
instruction of the function.
FUNCEND <addr>
225
JumpStarter C for AVR – C Compiler for Atmel AVR
Ends a function section. The <addr> is the address beyond the last instruction of
the function. To access the function return sequence, see BLOCKEND below.
DEFGLOBAL <name> <addr> <type>
Defines a file-scoped global symbol.
DEFSTATIC <name> <addr> <type>
Defines a file-scoped global symbol.
START <addr>
Specifies the address of the __start symbol, which is usually the starting
address of an ImageCraft generated program.
Function-Level Commands
BLOCK <line no> <addr>
Starts a block in which symbols may be defined. All DEFLOCAL and DEFREG
commands must come after a BLOCK command. In the current version, there is
only one group of BLOCK/BLOCKEND command per function and all local
variables are declared in this block, even if they are declared in an inner block in
the source code. (This will be remedied in a future version of the compiler and
debug format. See “Future Enhancements” below.)
The <line no> and <addr> are exactly the same as the ones specified in the
LINE command that follows it.
BLOCKEND <line no> <addr>
Ends a symbol-scoped block. The <line no> and <addr> are exactly the same
as the ones specified in the LINE command that follows it.
A special case is when <line no> is 0 (and this would be the last BLOCKEND in
the function). In this case, the function return sequence starts at this <addr> -
note that ImageCraft compiler generates only one return sequence per function.
LINE <line no> <addr>
Defines a line number and its code address.
DEFLOCAL <name> <offset> <type>
Defines a function-scoped symbol. <offset> is a decimal offset, usually from the
frame pointer.
DEFREG <name> <reg> <type>
226
JumpStarter C for AVR – C Compiler for Atmel AVR
Structure Declaration
STRUCT/UNION <size> <name>
Starts a structure or union declaration. <size> is the total size of the structure in
bytes. <name> is the structure tag name. If this structure has no tag in the source
file, a unique name of the form .<number> (dot followed by a number) will be
used. The .<number> is unique within a file scope as delimited by the FILE
command, and may be reused in other FILE units.
If the <size> is 0, this signifies a structure that is not defined in this FILE unit.
For example, the following C fragment:
struct bar { struct foo *p; struct bar *x; } bar;
outputs a STRUCT command with <size> equal to 0 for the structure tag foo if
the structure is not defined prior to the declaration. A STRUCTEND/UNIONEND
command must close off a STRUCT/UNION command. Nested declaration is not
used.
The STRUCT/UNION commands appear either at the file or function / block scope,
depending on the scope in the original C source. All data type references to
structures use the structure tag name <name>.
FIELD <offset> <name> <type>
227
JumpStarter C for AVR – C Compiler for Atmel AVR
Type Specifier
Base Type
Type specifier is read from left to right, and must end with one of the following base
types:
Size in
Base Type C Data Type
Bytes
C signed char 1
S short 2
I (letter i) int 2 or 4a
L long 4
X long long 8
D float / double b 4
Y double c 8
c unsigned char 1
s unsigned short 2
228
JumpStarter C for AVR – C Compiler for Atmel AVR
Size in
Base Type C Data Type
Bytes
i unsigned int 2 or 4
a.int and unsigned int are the only types whose sizes are dependent on the target CPU.
b.“double” is 32 bits except for certain compilers where you may enable “64-bit dou-
ble.” In which case, the data type character ‘Y’ is used.
c.64-bit double.
229
JumpStarter C for AVR – C Compiler for Atmel AVR
Future Enhancements
The following commands will be added to a later revision:
DEFTYPE, DEFCONST, both of which obey the scope rule.
Nested BLOCK/BLOCKEND commands and nested DEFLOCAL and DEFREG
commands.
This allows the inner scope local variables to be declared in the correct lexical
scope.
230
JumpStarter C for AVR – C Compiler for Atmel AVR
231
JumpStarter C for AVR – C Compiler for Atmel AVR
Librarian
A library is a collection of object files in a special form that the linker understands.
When a library's component object file is referenced by your program directly or
indirectly, the linker pulls out the library code and links it to your program. The
standard supplied library is libcavr.a, which contains the standard C and Atmel
AVR specific functions.
There are times where you need to modify or create libraries. A command-line tool
called ilibw.exe is provided for this purpose. You can also create a library project
using the IDE if you have the PRO edition of the compiler. See Menu Reference: Build
Options - Project.
Note that a library file must have the .a extension. See Linker Operations.
232
JumpStarter C for AVR – C Compiler for Atmel AVR
Deleting a Module
The command switch -d deletes a module from the library. For example, the following
deletes iochar.o from the libcavr.a library:
cd c:\iccv8avr\libsrc.avr
copy c:\iccv8avr\lib\libcavr.a ; copy library
ilibw.exe -d libcavr.a iochar.o ; delete
copy libcavr.a c:\iccv8avr\lib ; copy back
233
JumpStarter C for AVR – C Compiler for Atmel AVR
234
JumpStarter C for AVR – C Compiler for Atmel AVR
Symbols
.lis files ...................................................................................................................... 39
A
Accessing AVR features ......................................................................................... 139
Accessing EEPROM .............................................................................................. 165
Acknowledgments .................................................................................................... 24
Addressing Absolute Memory Locations ................................................................ 154
Assembler .............................................................................................................. 211
Assembler Directives .............................................................................................. 215
Assembler Operator Precedences ......................................................................... 214
Assembly Interface ................................................................................................. 173
B
Bit Twiddling ............................................................................................................. 34
C
C Library ................................................................................................................. 113
C Machine Routines ............................................................................................... 177
C Operator Precedences ........................................................................................ 107
Character Type Functions ...................................................................................... 119
Code Compressor .................................................................................................. 208
Compilation Process .............................................................................................. 185
Compiler Arguments ............................................................................................... 187
Compiler Options: Compiler ..................................................................................... 66
Compiler Options: Paths .......................................................................................... 65
Compiler Options: Target ......................................................................................... 69
Converting from Other Compilers ............................................................................. 19
Creating a New Project ............................................................................................ 49
D
Data Type Sizes ..................................................................................................... 171
Driver ...................................................................................................................... 186
E
Editor Windows ........................................................................................................ 51
F
File Types ................................................................................................................. 15
Floating Point Math Functions ................................................................................ 121
I
ImageCraft Debug Format ...................................................................................... 224
Inline Assembly ...................................................................................................... 149
235
JumpStarter C for AVR – C Compiler for Atmel AVR
236