Application Development for Embedded Systems

55
Application Development for Embedded Systems Andrea Marongiu, Carlo Caione { a.marongiu , carlo.caione }@ unibo.it

description

Application Development for Embedded Systems. Andrea Marongiu, Carlo Caione { a.marongiu , carlo.caione }@ unibo.it. Application Cross-Development. Cross development is the separation of the build environment from the target environment . - PowerPoint PPT Presentation

Transcript of Application Development for Embedded Systems

Page 1: Application Development for Embedded Systems

Application Development for Embedded Systems

Andrea Marongiu, Carlo Caione {a.marongiu, carlo.caione}@unibo.it

Page 2: Application Development for Embedded Systems

Application Cross-Development Cross development is the separation of the

build environment from the target environment.

Embedded computers where a device has extremely limited resources, are typically not powerful enough to run a compiler, a file system, or a development environment.

Since debugging and testing may also require more resources than are available on an embedded system, cross-compilation can be less involved and less prone to errors than native compilation.

Page 3: Application Development for Embedded Systems

Application Cross-Development

FavouriteEditor

.c

Tool Chain

.o

Targetarchitecture

Target HW Simulator

HW

DevelopmentBoard

Debugger

Page 4: Application Development for Embedded Systems

Toolchain The first and most essential product to

develop applications on any embedded device is a cross-toolchain

A set of tools running on a host machine, used to 1. Compile high-level source code into target object

code2. Link pre-existing collections of object files

(libraries)3. Assemble the whole thing into an executable

object by the target machine

Let us take a closer look..

Page 5: Application Development for Embedded Systems

GNU Toolchain A collection of programming tools produced by the

GNU Project. These tools form a toolchain (suite of tools used in a serial manner) used for developing applications and operating systems.

It plays a vital role in development of Linux kernel, and software for embedded systems.

Projects included in the GNU toolchain are: GNU Compiler Collection (GCC): Suite of compilers for several

programming languages; GNU Binutils: Suite of tools including linker, assembler and other

tools; GNU Debugger (GDB): Code debugging tool; GNU make: Automation tool for compilation and build; GNU build system (autotools):

Page 7: Application Development for Embedded Systems

Compiling code

#include <stdio.h>#define TRUE 1#define FALSE 0

main() { int i; i = 5 * 2; printf(“5 times 2 is %d.\n”, i); printf(“TRUE is %d.\n”, TRUE); printf(“FALSE is %d.\n”, FALSE);}

Handled by the pre-processor

Handled by the compiler

Implemented in C library

Page 8: Application Development for Embedded Systems

Compiling code The pre-processor handles

Macros (#define) Inclusions (#include) Conditional code inclusion (#ifdef, #if) Language extensions (#pragma).

The compiler processes source code and turns it into assembler modules.

The assembler converts them to target binary code.

The linker takes the object files and searches library files to find the routines it calls. It calculates the address references and incorporates any symbolic information to create an executable file format.

Page 9: Application Development for Embedded Systems

GCC (GNU Compiler Collection) The GNU Compiler Collection (usually shortened to GCC)

is a set of compilers produced for various programming languages by the GNU Project.

It is a tool used by nearly every embedded engineer, even those who don’t target Linux

When starting an embedded project, the first tool needed is a cross-compiler, a compiler that generates code intended to work on a machine different from the one on which the code generation occurred.

When used in an embedded project, GCC capably does cross-compilation, without complaint

GCC is available for most embedded platforms, for example Symbian, Freescale Power Architecture-based chips, Playstation and Sega Dreamcast

Page 10: Application Development for Embedded Systems

GCC Architecture

Multiple front-endsCommon intermediate

representation

Retargetable!

Page 11: Application Development for Embedded Systems

GNU Binutils The GNU Binary Utilities, or binutils, is a collection of

programming tools for the manipulation of object code in various object file formats.

The most important tools are

as – Assembler: Transforms the assembly code produced by the compiler into a binary format executable by the target machine

ld – Linker: Takes as input several object files and generates a single executable, resolving interactions between symbols

ar – Archiver: Combines together (possibly) multiple object files into a library. This could be later linked to other applications either statically or dynamically

objdump – Dumper: It allows recreating an assembler file from an object file. It can also dump additional information about different segments of the output file format

Page 12: Application Development for Embedded Systems

Object Archives (Libraries)‣ In computer science, a library is a collection of

subroutines or classes used to develop software‣ Libraries contain code and data that provide

services to independent programs. This allows the sharing and changing of code and data in a modular fashion

‣ Executables and libraries make references known as links to each other through the process known as linking, which is typically done by a linker

‣ Two types of libraries:1. Static libraries2. Dynamic / shared libraries

Page 13: Application Development for Embedded Systems

Runtime Libraries Compilers only generate a small subset of high-level languages

facilities and commands from built-in routines.

It relies on libraries to provide the full range of functions that the language offers: Processor dependent: mathematical functions, string

manipulation and similar features that use the processor and don’t need to communicate with peripherals;

I/O dependent: defines the hardware that the software need to access. The library routine either drives directly the hardware or calls the operating system to perform its task;

System calls: typical routines are those which dinamically allocate memory, task control commands, use semaphores, etc;

Exit routines: used to terminate programs free up the memory used by the application.

Page 14: Application Development for Embedded Systems

Newlib Newlib is a C standard library implementation intended for

use on embedded systems.

It is a conglomeration of several library parts, all under free software licenses that make them easily usable on embedded products.

The section System Calls of the newlib documentation describes how it can be used with many operating systems.

Its primary use is on embedded systems that lack any kind of operating system; in that case it calls a "board support package" that can do things like write a byte of output on a serial port, or read a sector from a disk or other memory device.

As of 2007, devkitARM, a popular toolchain for programming homebrew software for Nintendo DS and Game Boy Advance systems, includes Newlib as its C library

Page 15: Application Development for Embedded Systems

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

C Code GCC

BSP / Kernel

Newlib

Hardware

atoi(), strtol(), bzero(), strcat(), ...

_exit(),close(),fork(),kill(),...

Newlib

Page 16: Application Development for Embedded Systems

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

BSP / Kernel

read()

BSP Kernel

UART_read()

read()

UART

read()

UART

Interrupt 0x80

kernel + BSP

Newlib

Page 17: Application Development for Embedded Systems

Building a ToolchainAn example: arm-elf-gcc We’ve introduced the three main software

blocks composing a toolchain Binutils – Target specific tools Gcc – Compiler for target machine C library – Target specific C library

We now describe the entire process of building a complete toolchain for a ARM7 processor

Page 18: Application Development for Embedded Systems

Building the toolchain for ARM The source code for binutils, gcc and

newlib can be downloaded at http://www.gnu.org/software/binutils/ http://gcc.gnu.org/mirrors.html ftp://sources.redhat.com/pub/newlib/index.html

The standard procedure to build and install each of the products consists of three steps Configuration Build Install

Page 19: Application Development for Embedded Systems

Building the toolchain for ARM For each of the product, create a separate

source and build directory$ROOT> mkdir binutils-src$ROOT> mkdir gcc-src$ROOT> mkdir newlib-src$ROOT> mkdir binutils-build$ROOT> mkdir gcc-build$ROOT> mkdir newlib-build

Then create an INSTALL folder for the entire toolchain

$ROOT> mkdir INSTALL

Page 20: Application Development for Embedded Systems

Building the toolchain for ARM Build and install the binutils specifying the

arm-elf target$ROOT> cd binutils-build$ROOT> ../binutils-src/configure --target=arm-elf \

--prefix=../INSTALL \--program-prefix=arm-elf-

$ROOT> make all install

At the end of the process, in the folder $ROOT/INSTALL/bin we’ll find the cross-tools

$ROOT> ll INSTALL/bin

Page 21: Application Development for Embedded Systems

Building the toolchain for ARM Add to your $PATH environment variable the path

to the binutils just installed, so that the compiler can use them to build the cross-compiler

$ROOT> export PATH=$ROOT/INSTALL/bin:$PATH

Build and install the cross-compiler specifying the arm-elf target and the location of the C library headers

$ROOT> cd gcc-build$ROOT> ../gcc-src/configure --target=arm-elf \

--prefix=../INSTALL \--program-prefix=arm-elf- \--enable-languages=c,c++ \--with-newlib \

--with-headers=../newlib-src/newlib/libc/include$ROOT> make all-gcc install-gcc

Page 22: Application Development for Embedded Systems

Building the toolchain for ARM Build and install the C library$ROOT> cd newlib-build$ROOT> ../newlib-src/configure --target=arm-elf \

--prefix=../INSTALL$ROOT> make all install

Finally, install the entire compiler$ROOT> cd gcc-build$ROOT> make all install

Page 23: Application Development for Embedded Systems

Building the toolchain for ARM

Take a look at the $ROOT/INSTALL/bin folder

Page 24: Application Development for Embedded Systems

Embedded Application Programming

Multimedia SoC

Microcontroller

SW & HW Low Complexity

• The application may use directly the HW• The programmer know the HW and read and write directly internal register

Complex HW

• Programmer needs abstraction layers.• Embedded O.S.• Application use HW facilities throught system call & driver

Custom middleware

• HW programmed by statically linking API•Standard / Custom API•Microkernel

Complexity

Page 25: Application Development for Embedded Systems

Embedded Application Programming

Multimedia SoC

Microcontroller

SW & HW Low Complexity

• The application may use directly the HW• The programmer know the HW and read and write directly internal register

Complex HW

• Programmer needs abstraction layers.• Embedded O.S.• Application use HW facilities throught system call & driver

Custom middleware

• HW programmed by statically linking API•Standard / Custom API•Microkernel

Complexity

Page 26: Application Development for Embedded Systems

Application Cross-Development

FavouriteEditor

Tool Chain

.o

Targetarchitecture

Target HW Simulator

HW

DevelopmentBoard

Debugger

.cApplication

0x0…0 App.

CPU

MEM

Page 27: Application Development for Embedded Systems

Embedded Application Programming

Multimedia SoC

Microcontroller

SW & HW Low Complexity

• The application may use directly the HW• The programmer know the HW and read and write directly internal register

Complex HW

• Programmer needs abstraction layers.• Embedded O.S.• Application use HW facilities throught system call & driver

Custom middleware

• HW programmed by statically linking API•Standard / Custom API•Microkernel

Complexity

Page 28: Application Development for Embedded Systems

O.S. Embedded Why we need an O.S. on embedded system:

Depends on complexity Hardware complexity, programmer needs abstraction layers Multi-process execution => scheduler Memory Managment Unit Store data => File system

Differents O.S.: Windows CE Linux embedded : based on general purpose linux +

BSP ucLinux : Lite version of Linux embedded (No MMU

support) RTems : (No File System, No MMU )

Page 29: Application Development for Embedded Systems

Application Cross-Development

Tool Chain

.o

Targetarchitecture

Target HW Simulator

HW

DevelopmentBoard

Debugger

FavouriteEditor

0x0…0

.c.c.cMicrokernel source code

App.

MEM

CPU

Page 30: Application Development for Embedded Systems

Embedded Application Programming

Multimedia SoC

Microcontroller

SW & HW Low Complexity

• The application may use directly the HW• The programmer know the HW and read and write directly internal register

Complex HW

• Programmer needs abstraction layers.• Embedded O.S.• Application use HW facilities throught system call & driver

Custom middleware

• HW programmed by statically linking API•Standard / Custom API•Microkernel

Complexity

Page 31: Application Development for Embedded Systems

Application Cross-Development

Tool Chain

.o

Targetarchitecture

Target HW Simulator

HW

DevelopmentBoard

Debugger

FavouriteEditor

0x0…0

.c.c.cO.S. kernel source code

O.S. kernel

MEM

CPU

Page 32: Application Development for Embedded Systems

Application Cross-Development

Tool Chain

.o

Targetarchitecture

Target HW Simulator

HW

DevelopmentBoard

Debugger

FavouriteEditor

0x0…0

.cApplication

App. CPU

MEM

O.S. kernel

Page 33: Application Development for Embedded Systems

Linux kernel patching

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

+kernel vanilla BSP patches

‣ Download the new kernel from www.kernel.org

‣ Kernel untar:$ tar -xvf <dir>/linux-2.6.33.tar.bz2

‣ Kernel patch:$ bunzip2 -c <BSP>/linux-2.6.33-BSP.patch.bz2 | patch -p1

[carlo@naomi linux-2.6.34-ARCH]$ ls -altotal 6614drwxr-xr-x 21 root root 624 Jul 6 15:01 .drwxr-xr-x 4 root root 120 Jul 6 15:01 ..drwxr-xr-x 4 root root 120 Jul 5 23:07 archdrwxr-xr-x 2 root root 104 Jul 5 23:07 block-rw-r--r-- 1 root root 111523 Jul 5 23:06 .configdrwxr-xr-x 3 root root 96 Jul 5 23:07 cryptodrwxr-xr-x 3 root root 72 Jul 5 23:06 Documentationdrwxr-xr-x 80 root root 2016 Jul 5 23:07 driversdrwxr-xr-x 62 root root 1560 Jul 5 23:06 fsdrwxr-xr-x 16 root root 400 Jul 5 23:06 includedrwxr-xr-x 2 root root 72 Jul 5 23:07 initdrwxr-xr-x 6 root root 296 Jul 5 23:06 kerneldrwxr-xr-x 2 root root 176 Jul 5 23:07 lib-rw-r--r-- 1 root root 53184 Jul 5 23:06 Makefiledrwxr-xr-x 2 root root 104 Jul 5 23:07 mm-rw-r--r-- 1 root root 646765 Jul 5 23:06 Module.symversdrwxr-xr-x 41 root root 1040 Jul 5 23:07 netdrwxr-xr-x 2 root root 72 Jul 5 23:06 samplesdrwxr-xr-x 12 root root 2544 Jul 5 22:51 scriptsdrwxr-xr-x 6 root root 176 Jul 5 23:07 securitydrwxr-xr-x 19 root root 480 Jul 5 23:06 sounddrwxr-xr-x 2 root root 48 Jul 5 23:06 .tmp_versionsdrwxr-xr-x 2 root root 72 Jul 5 23:07 usrdrwxr-xr-x 3 root root 72 Jul 5 23:07 virt-rw-r--r-- 1 root root 5941605 Jul 5 23:05 vmlinux[carlo@naomi linux-2.6.34-ARCH]$

Page 34: Application Development for Embedded Systems

Linux kernel configuration

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

Generic linux kernel Specific linux kernel (hw)configuration

‣ Kernel configuration:$ make ARCH=arm CROSS_COMPILE=${CROSS_COMPILER} target_defconfig$ make ARCH=arm CROSS_COMPILE=${CROSS_COMPILER} menuconfig

‣ Decide if module or not

Page 35: Application Development for Embedded Systems

Linux kernel cross-compiling

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

linux kernel cross-compilingmodules .ko

zImage

‣ Kernel compiling:$ make ARCH=arm CROSS_COMPILE=${CROSS_COMPILER}

‣ In computing, a loadable kernel module (or LKM) is an object file that contains code to extend the running kernel, or so-called base kernel, of an operating system

‣ Without loadable kernel modules, an operating system would have to have all possible anticipated functionality already compiled directly into the base kernel. Much of that functionality would reside in memory without being used, wasting memory, and would require that users rebuild and reboot the base kernel every time new functionality is desired

‣ Module loading $ insmod ${MODULE}.ko

‣Module unloading $ rmmod ${MODULE}.ko

./linux-2.6.x/driver/...

./linux-2.6.x/arch/boot/zImage

Page 36: Application Development for Embedded Systems

Host and Target

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

host target

‣ Cross-compiling the kernel

‣ Cross-compiling the root filesystem

‣ Executing

zImage + rootfs

JTAG

RS232

ETHERNET

MEMORYBOOTLOADER

Page 37: Application Development for Embedded Systems

Transfer zImage + rootfs to target

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ How to transfer zImage and rootfs into target?

• JTAG

• USB/UART/ETH... connection in bootloader mode

ELF/BIN/HEX JTAG Programmer Flash

ELF/BIN/HEX USB/UART/... Bootloader Flash

Page 38: Application Development for Embedded Systems

TFTP

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Trivial File Transfer Protocol (TFTP) is a file transfer protocol, with the functionality of a very basic form of File Transfer Protocol (FTP)

‣ Due to its simple design, TFTP could be implemented using a very small amount of memory

‣ TFTP is designed to be small and easy to implement, therefore, lacks most of the features of a regular FTP. TFTP only reads and writes files (or mail) from/to a remote server. It cannot list directories, and currently has no provisions for user authentication

‣ TFTP used the ethernet port

Page 39: Application Development for Embedded Systems

zModem

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Old communication protocol used in communication over serial connection

‣ Dramatically improved performance compared to older protocols, ZMODEM also offered restartable transfers, auto-start by the sender, an expanded 32-bit CRC, and control character quoting

Page 40: Application Development for Embedded Systems

Rootfs and wear leveling

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Wear leveling (also written wear levelling) is a technique for prolonging the service life of some kinds of erasable computer storage media, such as Flash memory used in solid-state drives and USB Flash drives

‣ Wear leveling attempts to work around limitations of these storage medias by arranging data so that erasures and re-writes are distributed evenly across the medium. In this way, no single erase block prematurely fails due to a high concentration of write cycles

• CRAMFS‣ The compressed ROM file system (or cramfs) is a free (GPL'ed) read-only Linux file system designed for simplicity and space-efficiency. It is mainly used in embedded systems and small-footprint systems

• JFFS‣ The Journalling Flash File System (or JFFS) is a log-structured file system for use on NOR flash memory devices on the Linux operating system

• JFFS2‣ Journalling Flash File System version 2 or JFFS2 is a log-structured file system for use in flash memory devices. It is the successor to JFFS. JFFS2 has been included in the Linux kernel since the 2.4.10 release. JFFS2 is also available for Open Firmware, the eCos RTOS and the RedBoot bootloader

Page 41: Application Development for Embedded Systems

NFS

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Flash the whole rootfs every time we change something is a waste of time

Network File System (NFS) is a network file system protocol originally developed by Sun Microsystems in 1984, allowing a user on a client computer to access files over a network in a manner similar to how local storage is accessed

Host TargetFlashrootfsrootfs

NFS + ETH

cross-tools

Page 42: Application Development for Embedded Systems

Loadable Kernel Modules

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ The Linux kernel is what's known as a monolithic kernel, which means that the majority of the operating system functionality is called the kernel and runs in a privileged mode. This differs from a micro-kernel, which runs only basic functionality as the kernel and pushes other functionality outside the privileged space.

‣ Linux can be dynamically altered at run time through the use of Linux kernel modules (LKMs)

‣ Dynamically alterable means that you can load new functionality into the kernel, unload functionality from the kernel, and even add new LKMs that use other LKMs. The advantage to LKMs is that you can minimize the memory footprint for a kernel, loading only those elements that are needed (which can be an important feature in embedded systems)

Applications

Kernel

CPU Memory Devices

syscalls

LKM

Page 43: Application Development for Embedded Systems

LKM

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h>

static int hello3_data __initdata = 3;

static int __init hello_3_init(void){ printk(KERN_ALERT "Hello, world %d\n", hello3_data); return 0;}

static void __exit hello_3_exit(void){ printk(KERN_ALERT "Goodbye, world 3\n");}

module_init(hello_3_init);module_exit(hello_3_exit);

MODULE_LICENSE("GPL");MODULE_AUTHOR(“Author”);

Module macros

Entry/exit macros

Module constructor /destructor

‣ The skeleton of a LKM:

Page 44: Application Development for Embedded Systems

LKM lifecycle

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

User

-Spa

ceKe

rnel

-Spa

ceinsmod rmmod

init_module delete_module

sys_init_module sys_delete_module

... ...

utilities

System Calls

Kernel Functions

Page 45: Application Development for Embedded Systems

user-space / kernel-space communication

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ How it it possible to transfer data between user-space and kernel-space?

• Procfs / Sysfs

• Character / block devices

• Socket

• Ioctl

• Syscalls

• Signals

• Mmap

Page 46: Application Development for Embedded Systems

Procfs

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

[carlo@naomi ~]$ cat /proc/version Linux version 2.6.34-ARCH (tobias@T-POWA-LX) (gcc version 4.5.0 20100610 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Jul 5 21:03:38 UTC 2010

#include <linux/fs.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/utsname.h>static int version_proc_show(struct seq_file *m, void *v){

seq_printf(m, linux_proc_banner,utsname()->sysname,utsname()->release,utsname()->version);return 0;

}static int version_proc_open(struct inode *inode, struct file *file){

return single_open(file, version_proc_show, NULL);

}

static const struct file_operations version_proc_fops = {.open = version_proc_open,.read = seq_read,.llseek = seq_lseek,.release = single_release,

};

static int __init proc_version_init(void){proc_create("version", 0, NULL, &version_proc_fops);return 0;

}

module_init(proc_version_init);

Page 47: Application Development for Embedded Systems

ioctl

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ In computing, ioctl, short for input/output control, is a system call for device-specific operations and other operations which cannot be expressed by regular system calls

‣ Uses:

• The most common use of ioctls is to control hardware devices

• One use of ioctls exposed to end-user applications is terminal I/O

• When applications need to extend the kernel, for instance to accelerate network processing, ioctl calls provide a convenient way to bridge userspace code to kernel extensions

‣ A Unix ioctl call takes as parameters:

• An open file descriptor

• A request code number

• Either an integer value, possibly unsigned (going to the driver) or a pointer to data (either going to the driver, coming back from the driver, or both).

Page 48: Application Development for Embedded Systems

ioctl in kernel-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <asm/uaccess.h>#include "chardev.h“

#define SUCCESS 0#define DEVICE_NAME "char_dev“#define BUF_LEN 80

...

struct file_operations Fops = {.read = device_read,.write = device_write,.ioctl = device_ioctl,.open = device_open,.release = device_release, /* a.k.a. close */

};

...

int init_module(){int ret_val;ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);if (ret_val < 0) {

printk(KERN_ALERT "%s failed with %d\n“,"Sorry, registering the character device ", ret_val); return ret_val;

}return 0;

}

Page 49: Application Development for Embedded Systems

ioctl in kernel-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

int device_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)

{int i;char *temp;char ch;

switch (ioctl_num) {

case IOCTL_SET_MSG:

temp = (char *)ioctl_param;

get_user(ch, temp);for (i = 0; ch && i < BUF_LEN; i++, temp++)

get_user(ch, temp);

device_write(file, (char *)ioctl_param, i, 0);break;

case IOCTL_GET_MSG:

i = device_read(file, (char *)ioctl_param, 99, 0);

put_user('\0', (char *)ioctl_param + i);break;

case IOCTL_GET_NTH_BYTE:

return Message[ioctl_param];break;

}

return SUCCESS;}

Page 50: Application Development for Embedded Systems

ioctl in user-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

#include "chardev.h“#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>...

ioctl_set_msg(int file_desc, char *message){

int ret_val;

ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

if (ret_val < 0) {printf("ioctl_set_msg failed:%d\n", ret_val);exit(-1);

}}

...

main(){int file_desc, ret_val;char *msg = "Message passed by ioctl\n";file_desc = open(DEVICE_FILE_NAME, 0);if (file_desc < 0) {

printf("Can't open device file: %s\n", DEVICE_FILE_NAME);exit(-1);

}ioctl_get_nth_byte(file_desc);ioctl_get_msg(file_desc);ioctl_set_msg(file_desc, msg);close(file_desc);

}

Page 51: Application Development for Embedded Systems

Synchronization in kernel-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ In kernel space:

- Different modules interact one each other

- HW Interrupts can preempt important kernel tasks

‣ Interrupt and timers:

- There are two sources of interrupts in Linux, synchronous and asynchronous- Synchronous interrupts, better known as exceptions, are generated by the CPU control unit

- They can be generated by software special functions (ex. Timers) (SW interrupts)- Asynchronous interrupts (known as interrupts) are generated by HW resources, such as serial module, or HW timers Interrupts

- The address of all the interrupt service routines depends on architecture

Page 52: Application Development for Embedded Systems

Synchronization in kernel-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Interrupt:

- The nature of an asynchronous interrupt is that it happens at any time

- If it happens during a time when the kernel is busy performing an important function, then the kernel must do the following:

• Switch over and execute as much of the interrupt service routine as necessary• Switch back and finish the remainder of the task it was performing before the interrupt occurred• Switch back yet again and finish the remainder of the interrupt service routine

The first half of the interrupt service routine is referred to as the top half, while the second half is referred to as the bottom half

Page 53: Application Development for Embedded Systems

Synchronization in kernel-space

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Timers:

• Easy for device-driver programmers to use• Used mainly for detecting device “lockups”• But could also be used for other purposes• The driver-writer merely needs to:

• define a “customized” timeout-function

• allocate and initialize a kernel-structure

• call standard routines for timer-control

Page 54: Application Development for Embedded Systems

Kernel preemption

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

‣ Kernel preemption is a method used in monolithic kernels, whereby the scheduler is permitted to forcibly perform a context switch on a driver or other part of the kernel during its execution, rather than co-operatively wait for the driver or kernel function to complete its execution and return control of the processor to the scheduler

‣ The main motivation for making a kernel preemptive is to reduce the dispatch latency of the user mode processes

• Delay between the time they become runnable and the time they actually begin running • A race condition can occur when the outcome of a computation depends on how two or more interleaved kernel control paths are nested

Page 55: Application Development for Embedded Systems

Synchronization primitives

Carlo Caione <[email protected]>MPHS - AA. 2010/2011

Technique Description Scope

Per-CPU variables Duplicate a data structure among CPUs All CPUs

Atomic operation Atomic read-modify-write instruction All

Memory barrier Avoid instruction re-ordering Local CPU

Spin lock Lock with busy wait All

Semaphore Lock with blocking wait (sleep) All

Seqlocks Lock based on access counter All

Local interrupt disabling

Forbid interrupt on a single CPU Local

Local softirq disabling Forbid deferrable function on a single CPU Local

Read-copy-update (RCU)

Lock-free access to shared data through pointers All