Skip to main content

IAR Embedded Workbench for RL78 5.20

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.

CPU features and constraints

The RL78 microcontroller is based on a 16-bit CISC Harvard architecture and has a full 16-bit data bus for RAM, CPU registers and peripheral units, and a 3-stage pipeline. It is designed for low-power applications and allows serial communication and ADC operation also in standby mode. Even though the RL78 microcontroller uses a CISC instruction set, the major part of the instructions are executed in 1–2 clock cycles.

The RL78 microcontroller has hardware facilities to assist with mathematics functions such as multiply, multiply/accumulate and divide. The multiply and MACC functions are executed in 1 and 2 clock cycles, respectively. The RL78 barrel shift function can execute a 16-bit SHIFT or ROTATE instruction in 1 clock cycle as well.

The compiler supports these hardware facilities by means of compiler options, extended keywords, pragma directives, etc.

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 microcontroller 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 Primitives for interrupts, concurrency, and OS-related programming.

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.

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

You can use object files generated from tools from other vendors, provided that they follow the RL78 ABI specification, that you use the V2 calling convention, and that you do not use C++. In addition, the following limitations are known for modules using the Renesas standard C library, created by the Renesas RL78 compiler:

  • Variadic functions like the printf/scanf family of standard C functions are not supported

  • strtok is not supported

  • You must use the Far code model and the Near data model in the IAR compiler.

The RL78 ABI specifies full compatibility for C object code, and for the C library.