Skip to main content

IAR Embedded Workbench for Arm 9.70.x

Developing embedded software using IAR build tools

In this section:

Typically, embedded software written for a dedicated microcontroller is designed as an endless loop waiting for some external events to happen. The software is located in ROM and executes on reset. You must consider several hardware and software factors when you write this kind of software. To assist you, compiler options, extended keywords, pragma directives, etc., are included.

Mapping of memory

Embedded systems typically contain various types of memory, such as on-chip RAM, external DRAM or SRAM, ROM, EEPROM, or flash memory.

As an embedded software developer, you must understand the features of the different types of memory. For example, on-chip RAM is often faster than other types of memories, and variables that are accessed often would in time-critical applications benefit from being placed here. Conversely, some configuration data might be seldom accessed but must maintain its value after power off, so it should be saved in EEPROM or flash memory.

For efficient memory usage, the compiler provides several mechanisms for controlling placement of functions and data objects in memory. For more information, see Controlling data and function placement in memory.

The linker places sections of code and data in memory according to the directives you specify in the linker configuration file, see Placing code and data—the linker configuration file.

Communication with peripheral units

If external devices are connected to the microcontroller, you might need to initialize and control the signaling interface, for example by using chip select pins, and detect and handle external interrupt signals. Typically, this must be initialized and controlled at runtime. The normal way to do this is to use special function registers (SFR). These are typically available at dedicated addresses, containing bits that control the chip configuration.

Standard peripheral units are defined in device-specific I/O header files with the filename extension h. See Device support. For an example, see Accessing special function registers.

Event handling

In embedded systems, using interrupts is a method for handling external events immediately, for example, detecting that a button was pressed. In general, when an interrupt occurs in the code, the core immediately stops executing the code it runs, and starts executing an interrupt routine instead.

The compiler provides various primitives for managing hardware and software interrupts, which means that you can write your interrupt routines in C, see Interrupt functions for Cortex-M devices and Interrupt functions for Arm7/9/11, Cortex-A, and Cortex-R devices. See also Exception functions for 64-bit mode.

System startup

In all embedded systems, system startup code is executed to initialize the system—both the hardware and the software system—before the main function of the application is called. The CPU imposes this by starting execution from a fixed memory address.

As an embedded software developer, you must ensure that the startup code is located at the dedicated memory addresses, or can be accessed using a pointer from the vector table. This means that startup code and the initial vector table must be placed in non-volatile memory, such as ROM, EPROM, or flash.

A C/C++ application further needs to initialize all global variables. This initialization is handled by the linker in conjunction with the system startup code. For more information, see Application execution—an overview.

Real-time operating systems

In many cases, the embedded application is the only software running in the system. However, using an RTOS has some advantages.

For example, the timing of high-priority tasks is not affected by other parts of the program which are executed in lower priority tasks. This typically makes a program more deterministic and can reduce power consumption by using the CPU efficiently and putting the CPU in a lower-power state when idle.

Using an RTOS can make your program easier to read and maintain, and in many cases smaller as well. Application code can be cleanly separated into tasks that are independent of each other. This makes teamwork easier, as the development work can be easily split into separate tasks which are handled by one developer or a group of developers.

Finally, using an RTOS reduces the hardware dependence and creates a clean interface to the application, making it easier to port the program to different target hardware.

See also Managing a multithreaded environment.

Interoperability with other build tools

The IAR compiler and linker provide support for AEABI, the Embedded Application Binary Interface for Arm. For more information about this interface specification, see the www.arm.com web site.

The advantage of this interface is the interoperability between vendors supporting it—an application can be built up of libraries of object files produced by different vendors and linked with a linker from any vendor, as long as they adhere to the AEABI standard.

AEABI specifies full compatibility for C and C++ object code, and for the C library. The AEABI does not include specifications for the C++ library.

For more information about the AEABI support in the IAR build tools, see AEABI compliance.

The IAR build tools for Arm with version numbers from 8.xx and up are not fully compatible with earlier versions of the product. For more information, see the IAR Embedded Workbench® Migration Guide for ARM.

For more information, see Linker optimizations.