O'Reilly logo

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Mastering Embedded Linux Programming

Book Description

Harness the power of Linux to create versatile and robust embedded solutions

About This Book

  • Create efficient and secure embedded devices using Linux
  • Minimize project costs by using open source tools and programs
  • Explore each component technology in depth, using sample implementations as a guide

Who This Book Is For

This book is ideal for Linux developers and system programmers who are already familiar with embedded systems and who want to know how to create best-in-class devices. A basic understanding of C programming and experience with systems programming is needed.

What You Will Learn

  • Understand the role of the Linux kernel and select an appropriate role for your application
  • Use Buildroot and Yocto to create embedded Linux systems quickly and efficiently
  • Create customized bootloaders using U-Boot
  • Employ perf and ftrace to identify performance bottlenecks
  • Understand device trees and make changes to accommodate new hardware on your device
  • Write applications that interact with Linux device drivers
  • Design and write multi-threaded applications using POSIX threads
  • Measure real-time latencies and tune the Linux kernel to minimize them

In Detail

Mastering Embedded Linux Programming takes you through the product cycle and gives you an in-depth description of the components and options that are available at each stage. You will begin by learning about toolchains, bootloaders, the Linux kernel, and how to configure a root filesystem to create a basic working device. You will then learn how to use the two most commonly used build systems, Buildroot and Yocto, to speed up and simplify the development process. Building on this solid base, the next section considers how to make best use of raw NAND/NOR flash memory and managed flash eMMC chips, including mechanisms for increasing the lifetime of the devices and to perform reliable in-field updates. Next, you need to consider what techniques are best suited to writing applications for your device. We will then see how functions are split between processes and the usage of POSIX threads, which have a big impact on the responsiveness and performance of the final device The closing sections look at the techniques available to developers for profiling and tracing applications and kernel code using perf and ftrace.

Style and approach

This book is an easy-to-follow and pragmatic guide consisting of an in-depth analysis of the implementation of embedded devices. Each topic has a logical approach to it; this coupled with hints and best practices helps you understand embedded Linux better.

Downloading the example code for this book. You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the code file.

Table of Contents

  1. Mastering Embedded Linux Programming
    1. Table of Contents
    2. Mastering Embedded Linux Programming
    3. Credits
    4. Foreword
    5. About the Author
    6. About the Reviewers
    7. www.PacktPub.com
      1. Support files, eBooks, discount offers, and more
        1. Why subscribe?
        2. Free access for Packt account holders
    8. Preface
      1. What this book covers
      2. What you need for this book
      3. Who this book is for
      4. Conventions
      5. Reader feedback
      6. Customer support
        1. Downloading the example code
        2. Errata
        3. Piracy
        4. Questions
    9. 1. Starting Out
      1. Selecting the right operating system
      2. The players
      3. Project lifecycle
        1. The four elements of embedded Linux
      4. Open source
        1. Licenses
      5. Hardware for embedded Linux
      6. Hardware used in this book
        1. The BeagleBone Black
        2. QEMU
      7. Software used in this book
      8. Summary
    10. 2. Learning About Toolchains
      1. What is a toolchain?
      2. Types of toolchain - native versus cross toolchain
        1. CPU architectures
      3. Choosing the C library
      4. Finding a toolchain
        1. Building a toolchain using crosstool-NG
        2. Installing crosstool-NG
        3. Selecting the toolchain
      5. Anatomy of a toolchain
        1. Finding out about your cross compiler
        2. The sysroot, library, and header files
      6. Other tools in the toolchain
      7. Looking at the components of the C library
      8. Linking with libraries: static and dynamic linking
        1. Static libraries
        2. Shared libraries
          1. Understanding shared library version numbers
      9. The art of cross compiling
        1. Simple makefiles
        2. Autotools
          1. An example: SQLite
        3. Package configuration
      10. Problems with cross compiling
      11. Summary
    11. 3. All About Bootloaders
      1. What does a bootloader do?
      2. The boot sequence
        1. Phase 1: ROM code
        2. Phase 2: SPL
        3. Phase 3: TPL
      3. Booting with UEFI firmware
      4. Moving from bootloader to kernel
      5. Introducing device trees
        1. Device tree basics
        2. The reg property
        3. Phandles and interrupts
        4. Device tree include files
        5. Compiling a device tree
      6. Choosing a bootloader
      7. U-Boot
        1. Building U-Boot
        2. Installing U-Boot
        3. Using U-Boot
          1. Environment variables
          2. Boot image format
          3. Loading images
        4. Booting Linux
          1. Automating the boot with U-Boot scripts
        5. Porting U-Boot to a new board
        6. Kconfig and U-Boot
          1. Board-specific files
          2. Configuration header files
        7. Building and testing
        8. Falcon mode
      8. Barebox
        1. Getting Barebox
        2. Building Barebox
      9. Summary
    12. 4. Porting and Configuring the Kernel
      1. What does the kernel do?
      2. Choosing a kernel
        1. Kernel development cycle
        2. Stable and long term support releases
        3. Vendor support
        4. Licensing
      3. Building the kernel
        1. Getting the source
        2. Understanding kernel configuration
        3. Using LOCALVERSION to identify your kernel
        4. Kernel modules
      4. Compiling
        1. Compiling the kernel image
        2. Compiling device trees
        3. Compiling modules
      5. Cleaning kernel sources
      6. Booting your kernel
        1. BeagleBone Black
        2. QEMU
        3. Kernel panic
        4. Early user space
        5. Kernel messages
        6. Kernel command line
      7. Porting Linux to a new board
        1. With a device tree
        2. Without a device tree
      8. Additional reading
      9. Summary
    13. 5. Building a Root Filesystem
      1. What should be in the root filesystem?
        1. Directory layout
        2. Staging directory
          1. POSIX file access permissions
          2. File ownership permissions in the staging directory
      2. Programs for the root filesystem
        1. The init program
        2. Shell
        3. Utilities
        4. BusyBox to the rescue!
          1. Building BusyBox
        5. ToyBox – an alternative to BusyBox
      3. Libraries for the root filesystem
        1. Reducing size by stripping
      4. Device nodes
      5. The proc and sysfs filesystems
        1. Mounting filesystems
      6. Kernel modules
      7. Transfering the root filesystem to the target
      8. Creating a boot ramdisk
        1. Standalone ramdisk
        2. Booting the ramdisk
          1. Booting with QEMU
          2. Booting the BeagleBone Black
          3. Mounting proc
        3. Building a ramdisk cpio into the kernel image
          1. Another way to build a kernel with ramdisk
        4. The old initrd format
      9. The init program
      10. Configuring user accounts
        1. Adding user accounts to the root filesystem
      11. Starting a daemon process
      12. A better way of managing device nodes
        1. An example using devtmpfs
        2. An example using mdev
        3. Are static device nodes so bad after all?
      13. Configuring the network
        1. Network components for glibc
      14. Creating filesystem images with device tables
        1. Putting the root filesytem onto an SD card
      15. Mounting the root filesystem using NFS
        1. Testing with QEMU
        2. Testing with BeagleBone Black
        3. Problems with file permissions
      16. Using TFTP to load the kernel
      17. Additional reading
      18. Summary
    14. 6. Selecting a Build System
      1. No more rolling your own embedded Linux
      2. Build systems
      3. Package formats and package managers
      4. Buildroot
        1. Background
        2. Stable releases and support
        3. Installing
        4. Configuring
        5. Running
        6. Creating a custom BSP
          1. U-Boot
          2. Linux
          3. Build
        7. Adding your own code
          1. Overlay
          2. Adding a package
        8. License compliance
      5. The Yocto Project
        1. Background
        2. Stable releases and support
        3. Installing the Yocto Project
        4. Configuring
        5. Building
        6. Running
        7. Layers
          1. BitBake and recipes
        8. Customizing images via local.conf
        9. Writing an image recipe
        10. Creating an SDK
        11. License audit
      6. Further reading
      7. Summary
    15. 7. Creating a Storage Strategy
      1. Storage options
        1. NOR flash
        2. NAND flash
        3. Managed flash
          1. MultiMediaCard and secure digital cards
          2. eMMC
          3. Other types of managed flash
      2. Accessing flash memory from the bootloader
        1. U-Boot and NOR flash
        2. U-Boot and NAND flash
        3. U-Boot and MMC, SD and eMMC
      3. Accessing flash memory from Linux
        1. Memory technology devices
          1. MTD partitions
          2. MTD device drivers
          3. The MTD character device, mtd
          4. The MTD block device, mtdblock
          5. Logging kernel oops to MTD
          6. Simulating NAND memory
        2. The MMC block driver
      4. Filesystems for flash memory
        1. Flash translation layers
      5. Filesystems for NOR and NAND flash memory
        1. JFFS2
          1. Summary nodes
          2. Clean markers
          3. Creating a JFFS2 filesystem
        2. YAFFS2
          1. Creating a YAFFS2 filesystem
        3. UBI and UBIFS
          1. UBI
          2. UBIFS
      6. Filesystems for managed flash
        1. Flashbench
        2. Discard and TRIM
        3. Ext4
        4. F2FS
        5. FAT16/32
      7. Read-only compressed filesystems
        1. squashfs
      8. Temporary filesystems
      9. Making the root filesystem read-only
      10. Filesystem choices
      11. Updating in the field
        1. Granularity: file, package, or image?
        2. Atomic image update
      12. Further reading
      13. Summary
    16. 8. Introducing Device Drivers
      1. The role of device drivers
      2. Character devices
      3. Block devices
      4. Network devices
      5. Finding out about drivers at runtime
        1. Getting information from sysfs
        2. The devices: /sys/devices
        3. The drivers: /sys/class
        4. The block drivers: /sys/block
      6. Finding the right device driver
      7. Device drivers in user-space
        1. GPIO
          1. Handling interrupts from GPIO
        2. LEDs
        3. I2C
        4. SPI
      8. Writing a kernel device driver
        1. Designing a character device interface
        2. Anatomy of a device driver
          1. Compile and load
      9. Loading kernel modules
      10. Discovering hardware configuration
        1. Device trees
        2. Platform data
        3. Linking hardware with device drivers
      11. Additional reading
      12. Summary
    17. 9. Starting up - the init Program
      1. After the kernel has booted
      2. Introducing the init programs
      3. BusyBox init
        1. Buildroot init scripts
      4. System V init
        1. inittab
        2. The init.d scripts
        3. Adding a new daemon
        4. Starting and stopping services
      5. systemd
        1. Building systemd with the Yocto Project and Buildroot
          1. Introducing targets, services, and units
            1. Units
            2. Services
            3. Targets
        2. How systemd boots the system
        3. Adding your own service
        4. Adding a watchdog
        5. Implications for embedded Linux
      6. Further reading
      7. Summary
    18. 10. Learning About Processes and Threads
      1. Process or thread?
      2. Processes
        1. Creating a new process
        2. Terminating a process
        3. Running a different program
        4. Daemons
        5. Inter-process communication
          1. Message-based IPC
            1. Unix (or local) sockets
            2. FIFOs and named pipes
            3. POSIX message queues
          2. Summary of message-based IPC
          3. Shared memory-based IPC
            1. POSIX shared memory
      3. Threads
        1. Creating a new thread
        2. Terminating a thread
        3. Compiling a program with threads
        4. Inter-thread communication
        5. Mutual exclusion
        6. Changing conditions
        7. Partitioning the problem
      4. Scheduling
        1. Fairness versus determinism
        2. Timeshare policies
          1. Niceness
        3. Real-time policies
        4. Choosing a policy
        5. Choosing a real-time priority
      5. Further reading
      6. Summary
    19. 11. Managing Memory
      1. Virtual memory basics
      2. Kernel space memory layout
        1. How much memory does the kernel use?
      3. User space memory layout
      4. Process memory map
      5. Swap
        1. Swap to compressed memory (zram)
      6. Mapping memory with mmap
        1. Using mmap to allocate private memory
        2. Using mmap to share memory
        3. Using mmap to access device memory
      7. How much memory does my application use?
      8. Per-process memory usage
        1. Using top and ps
        2. Using smem
        3. Other tools to consider
      9. Identifying memory leaks
        1. mtrace
        2. Valgrind
      10. Running out of memory
      11. Further reading
      12. Summary
    20. 12. Debugging with GDB
      1. The GNU debugger
      2. Preparing to debug
      3. Debugging applications using GDB
      4. Remote debugging using gdbserver
        1. Setting up the Yocto Project
        2. Setting up Buildroot
      5. Starting to debug
        1. Connecting GDB and gdbserver
        2. Setting the sysroot
        3. GDB command files
        4. Overview of GDB commands
          1. Breakpoints
          2. Running and stepping
          3. Information commands
        5. Running to a breakpoint
      6. Debugging shared libraries
        1. The Yocto Project
        2. Buildroot
        3. Other libraries
      7. Just-in-time debugging
      8. Debugging forks and threads
      9. Core files
        1. Using GDB to look at core files
      10. GDB user interfaces
        1. Terminal user interface
        2. Data display debugger
        3. Eclipse
      11. Debugging kernel code
        1. Debugging kernel code with kgdb
        2. A sample debug session
        3. Debugging early code
        4. Debugging modules
        5. Debugging kernel code with kdb
        6. Looking at an oops
        7. Preserving the oops
      12. Additional reading
      13. Summary
    21. 13. Profiling and Tracing
      1. The observer effect
        1. Symbol tables and compile flags
      2. Beginning to profile
      3. Profiling with top
        1. Poor man's profiler
      4. Introducing perf
        1. Configuring the kernel for perf
        2. Building perf with the Yocto Project
        3. Building perf with Buildroot
        4. Profiling with perf
        5. Call graphs
        6. perf annotate
      5. Other profilers: OProfile and gprof
      6. Tracing events
      7. Introducing Ftrace
        1. Preparing to use Ftrace
        2. Dynamic Ftrace and trace filters
        3. Trace events
      8. Using LTTng
        1. LTTng and the Yocto Project
        2. LTTng and Buildroot
        3. Using LTTng for kernel tracing
      9. Using Valgrind for application profiling
      10. Callgrind
      11. Helgrind
      12. Using strace to show system calls
      13. Summary
    22. 14. Real-time Programming
      1. What is real-time?
      2. Identifying the sources of non-determinism
      3. Understanding scheduling latency
      4. Kernel preemption
      5. The real-time Linux kernel (PREEMPT_RT)
      6. Threaded interrupt handlers
      7. Preemptible kernel locks
      8. Getting the PREEMPT_RT patches
        1. The Yocto Project and PREEMPT_RT
      9. High resolution timers
      10. Avoiding page faults in a real-time application
      11. Interrupt shielding
      12. Measuring scheduling latencies
        1. cyclictest
        2. Using Ftrace
        3. Combining cyclictest and Ftrace
      13. Further reading
      14. Summary
    23. Index