Prentice Hall Open Source Software Development Series Foreword Preface Practical Advice for the Practicing Embedded Developer Intended Audience What This Book Is Not Conventions Used Organization of the Book Follow Along GPL Copyright Notice Acknowledgments About the Author Chapter 1. Introduction 1.1. Why Linux? 1.2. Embedded Linux Today 1.3. Open Source and the GPL 1.3.1. Free Versus Freedom 1.4. Standards and Relevant Bodies 1.4.1. Linux Standard Base 1.4.2. Open Source Development Labs 1.4.2.1. OSDL: Carrier Grade Linux 1.4.2.2. OSDL: Mobile Linux Initiative 1.4.2.3. Service Availability Forum 1.5. Chapter Summary 1.5.1. Suggestions for Additional Reading Chapter 2. Your First Embedded Experience 2.1. Embedded or Not? 2.1.1. BIOS Versus Bootloader 2.2. Anatomy of an Embedded System 2.2.1. Typical Embedded Linux Setup 2.2.2. Starting the Target Board 2.3. Storage Considerations 2.3.1. Flash Memory 2.3.2. NAND Flash 2.3.3. Flash Usage 2.3.4. Flash File Systems 2.3.5. Memory Space 2.3.6. Execution Contexts 2.3.7. Process Virtual Memory 2.3.8. Cross-Development Environment 2.4. Embedded Linux Distributions 2.4.1. Commercial Linux Distributions 2.4.2. Do-It-Yourself Linux Distributions 2.5. Chapter Summary 2.5.1. Suggestions for Additional Reading Chapter 3. Processor Basics 3.1. Stand-alone Processors 3.1.1. IBM 970FX 3.1.2. Intel Pentium M 3.1.3. Freescale MPC7448 3.1.4. Companion Chipsets 3.2. Integrated Processors: Systems on Chip 3.2.1. PowerPC 3.2.2. AMCC PowerPC 3.2.3. Freescale PowerPC 3.2.4. MIPS 3.2.5. Broadcom MIPS 3.2.6. AMD MIPS 3.2.7. Other MIPS 3.2.8. ARM 3.2.9. TI ARM 3.2.10. Freescale ARM 3.2.11. Intel ARM XScale 3.2.12. Other ARM 3.2.13. Other Architectures 3.3. Hardware Platforms 3.3.1. CompactPCI 3.3.2. ATCA 3.4. Chapter Summary 3.4.1. Suggestions For Additional Reading Chapter 4. The Linux KernelA Different Perspective 4.1. Background 4.1.1. Kernel Versions 4.1.2. Kernel Source Repositories 4.2. Linux Kernel Construction 4.2.1. Top-Level Source Directory 4.2.2. Compiling the Kernel 4.2.3. The Kernel Proper: vmlinux 4.2.4. Kernel Image Components 4.2.5. Subdirectory Layout 4.3. Kernel Build System 4.3.1. The Dot-Config 4.3.2. Configuration Editor(s) 4.3.3. Makefile Targets 4.3.4. Kernel Configuration 4.3.5. Custom Configuration Options 4.3.6. Kernel Makefiles 4.3.7. Kernel Documentation 4.4. Obtaining a Linux Kernel 4.4.1. What Else Do I Need? 4.5. Chapter Summary 4.5.1. Suggestions for Additional Reading Chapter 5. Kernel Initialization 5.1. Composite Kernel Image: Piggy and Friends 5.1.1. The Image Object 5.1.2. Architecture Objects 5.1.3. Bootstrap Loader 5.1.4. Boot Messages 5.2. Initialization Flow of Control 5.2.1. Kernel Entry Point: head.o 5.2.2. Kernel Startup: main.c 5.2.3. Architecture Setup 5.3. Kernel Command Line Processing 5.3.1. The __setup Macro 5.4. Subsystem Initialization 5.4.1. The *__initcall Macros 5.5. The init Thread 5.5.1. Initialization via initcalls 5.5.2. Final Boot Steps 5.6. Chapter Summary 5.6.1. Suggestions for Additional Reading Chapter 6. System Initialization 6.1. Root File System 6.1.1. FHS: File System Hierarchy Standard 6.1.2. File System Layout 6.1.3. Minimal File System 6.1.4. The Root FS Challenge 6.1.5. Trial-and-Error Method 6.1.6. Automated File System Build Tools 6.2. Kernel's Last Boot Steps 6.2.1. First User Space Program 6.2.2. Resolving Dependencies 6.2.3. Customized Initial Process 6.3. The Init Process 6.3.1. inittab 6.3.2. Example Web Server Startup Script 6.4. Initial RAM Disk 6.4.1. Initial RAM Disk Purpose 6.4.2. Booting with initrd 6.4.3. Bootloader Support for initrd 6.4.4. initrd Magic: linuxrc 6.4.5. The initrd Plumbing 6.4.6. Building an initrd Image 6.5. Using initramfs 6.6. Shutdown 6.7. Chapter Summary 6.7.1. Suggestions for Additional Reading Chapter 7. Bootloaders 7.1. Role of a Bootloader 7.2. Bootloader Challenges 7.2.1. DRAM Controller 7.2.2. Flash Versus RAM 7.2.3. Image Complexity 7.2.4. Execution Context 7.3. A Universal Bootloader: Das U-Boot 7.3.1. System Configuration: U-Boot 7.3.2. U-Boot Command Sets 7.3.3. Network Operations 7.3.4. Storage Subsystems 7.3.5. Booting from Disk: U-Boot 7.4. Porting U-Boot 7.4.1. EP405 U-Boot Port 7.4.2. U-Boot Makefile Configuration Target 7.4.3. EP405 Processor Initialization 7.4.4. Board-Specific Initialization 7.4.5. Porting Summary 7.4.6. U-Boot Image Format 7.5. Other Bootloaders 7.5.1. Lilo 7.5.2. GRUB 7.5.3. Still More Bootloaders 7.6. Chapter Summary 7.6.1. Suggestions for Additional Reading Chapter 8. Device Driver Basics 8.1. Device Driver Concepts 8.1.1. Loadable Modules 8.1.2. Device Driver Architecture 8.1.3. Minimal Device Driver Example 8.1.4. Module Build Infrastructure 8.1.5. Installing Your Device Driver 8.1.6. Loading Your Module 8.2. Module Utilities 8.2.1. insmod 8.2.2. Module Parameters 8.2.3. lsmod 8.2.4. modprobe 8.2.5. depmod 8.2.6. rmmod 8.2.7. modinfo 8.3. Driver Methods 8.3.1. Driver File System Operations 8.3.2. Device Nodes and mknod 8.4. Bringing It All Together 8.5. Device Drivers and the GPL 8.6. Chapter Summary 8.6.1. Suggestions for Additional Reading Chapter 9. File Systems 9.1. Linux File System Concepts 9.1.1. Partitions 9.2. ext2 9.2.1. Mounting a File System 9.2.2. Checking File System Integrity 9.3. ext3 9.4. ReiserFS 9.5. JFFS2 9.6. cramfs 9.7. Network File System 9.7.1. Root File System on NFS 9.8. Pseudo File Systems 9.8.1. Proc File System 9.8.2. sysfs 9.9. Other File Systems 9.10. Building a Simple File System 9.11. Chapter Summary 9.11.1. Suggestions for Additional Reading Chapter 10. MTD Subsystem 10.1. Enabling MTD Services 10.1.1. Building MTD 10.2. MTD Basics 10.2.1. Configuring MTD 10.3. MTD Partitions 10.3.1. Redboot Partition Table Partitioning 10.3.2. Kernel Command Line Partitioning 10.3.3. Mapping Driver 10.3.4. Flash Chip Drivers 10.3.5. Board-Specific Initialization 10.4. MTD Utilities 10.4.1. JFFS2 Root File System 10.5. Chapter Summary 10.5.1. Suggestions for Additional Reading Chapter 11. BusyBox 11.1. Introduction to BusyBox 11.1.1. BusyBox is Easy 11.2. BusyBox Configuration 11.2.1. Cross-Compiling BusyBox 11.3. BusyBox Operation 11.3.1. BusyBox Init 11.3.2. Example rcS Initialization Script 11.3.3. BusyBox Target Installation 11.3.4. BusyBox Commands 11.4. Chapter Summary 11.4.1. Suggestions for Additional Reading Chapter 12. Embedded Development Environment 12.1. Cross-Development Environment 12.1.1. "Hello World"Embedded 12.2. Host System Requirements 12.2.1. Hardware Debug Probe 12.3. Hosting Target Boards 12.3.1. TFTP Server 12.3.2. BOOTP/DHCP Server 12.3.3. NFS Server 12.3.4. Target NFS Root Mount 12.3.5. U-Boot NFS Root Mount Example 12.4. Chapter Summary 12.4.1. Suggestions for Additional Reading Chapter 13. Development Tools 13.1. GNU Debugger (GDB) 13.1.1. Debugging a Core Dump 13.1.2. Invoking GDB 13.1.3. Debug Session in GDB 13.2. Data Display Debugger 13.3. cbrowser/cscope 13.4. Tracing and Profiling Tools 13.4.1. strace 13.4.2. strace Variations 13.4.3. ltrace 13.4.4. ps 13.4.5. top 13.4.6. mtrace 13.4.7. dmalloc 13.4.8. Kernel Oops 13.5. Binary Utilities 13.5.1. readelf 13.5.2. Examining Debug Info Using readelf 13.5.3. objdump 13.5.4. objcopy 13.6. Miscellaneous Binary Utilities 13.6.1. strip 13.6.2. addr2line 13.6.3. strings 13.6.4. ldd 13.6.5. nm 13.6.6. prelink 13.7. Chapter Summary 13.7.1. Suggestions for Additional Reading Chapter 14. Kernel Debugging Techniques 14.1. Challenges to Kernel Debugging 14.2. Using KGDB for Kernel Debugging 14.2.1. KGDB Kernel Configuration 14.2.2. Target Boot with KGDB Support 14.2.3. Useful Kernel Breakpoints 14.3. Debugging the Linux Kernel 14.3.1. gdb Remote Serial Protocol 14.3.2. Debugging Optimized Kernel Code 14.3.3. gdb User-Defined Commands 14.3.4. Useful Kernel gdb Macros 14.3.5. Debugging Loadable Modules 14.3.6. printk Debugging 14.3.7. Magic SysReq Key 14.4. Hardware-Assisted Debugging 14.4.1. Programming Flash Using a JTAG Probe 14.4.2. Debugging with a JTAG Probe 14.5. When It Doesn't Boot 14.5.1. Early Serial Debug Output 14.5.2. Dumping the printk Log Buffer 14.5.3. KGDB on Panic 14.6. Chapter Summary 14.6.1. Suggestions for Additional Reading Chapter 15. Debugging Embedded Linux Applications 15.1. Target Debugging 15.2. Remote (Cross) Debugging 15.2.1. gdbserver 15.3. Debugging with Shared Libraries 15.3.1. Shared Library Events in GDB 15.4. Debugging Multiple Tasks 15.4.1. Debugging Multiple Processes 15.4.2. Debugging Multithreaded Applications 15.4.3. Debugging Bootloader/Flash Code 15.5. Additional Remote Debug Options 15.5.1. Debugging via Serial Port 15.5.2. Attaching to a Running Process 15.6. Chapter Summary 15.6.1. Suggestions for Additional Reading Chapter 16. Porting Linux 16.1. Linux Source Organization 16.1.1. The Architecture Branch 16.2. Custom Linux for Your Board 16.2.1. Prerequisites and Assumptions 16.2.2. Customizing Kernel Initialization 16.2.3. Static Kernel Command Line 16.3. Platform Initialization 16.3.1. Early Variable Access 16.3.2. Board Information Structure 16.3.3. Machine-Dependent Calls 16.4. Putting It All Together 16.4.1. Other Architectures 16.5. Chapter Summary 16.5.1. Suggestions for Additional Reading Chapter 17. Linux and Real Time 17.1. What Is Real Time? 17.1.1. Soft Real Time 17.1.2. Hard Real Time 17.1.3. Linux Scheduling 17.1.4. Latency 17.2. Kernel Preemption 17.2.1. Impediments to Preemption 17.2.2. Preemption Models 17.2.3. SMP Kernel 17.2.4. Sources of Preemption Latency 17.3. Real-Time Kernel Patch 17.3.1. Real-Time Features 17.3.1.1. Spinlock Converted to Mutex 17.3.1.2. ISRs as Kernel Tasks 17.3.1.3. Preemptable Softirqs 17.3.1.4. Preempt RCU 17.3.2. O(1) Scheduler 17.3.3. Creating a Real-Time Process 17.3.4. Critical Section Management 17.4. Debugging the Real-Time Kernel 17.4.1. Soft Lockup Detection 17.4.2. Preemption Debugging 17.4.3. Debug Wakeup Timing 17.4.4. Wakeup Latency History 17.4.5. Interrupt Off Timing 17.4.6. Interrupt Off History 17.4.7. Latency Tracing 17.4.8. Debugging Deadlock Conditions 17.4.9. Runtime Control of Locking Mode 17.5. Chapter Summary 17.5.1. Suggestions for Additional Reading Appendix A. GNU Public License Preamble Terms and Conditions for Copying, Distribution and Modification No Warranty Appendix B. U-Boot Configurable Commands Appendix C. BusyBox Commands Appendix D. SDRAM Interface Considerations D.1. SDRAM Basics D.1.1. SDRAM Refresh D.2. Clocking D.3. SDRAM Setup D.4. Summary D.4.1. Suggestions for Additional Reading Appendix E. Open Source Resources Source Repositories and Developer Information Mailing Lists Linux News and Developments Open Source Insight and Discussion Appendix F. Sample BDI-2000 Configuration File
Foreword Computers are everywhere.
This fact, of course, is not a surprise to anyone who hasn't been living in a cave during the past 25 years or so. And you probably know that computers aren't just on our desktops, in our kitchens, and, increasingly, in our living rooms holding our music collections. They're also in our microwave ovens, our regular ovens, our cellphones, and our portable digital music players.
And if you're holding this book, you probably know a lot, or are interested in learning more about, these embedded computer systems.
Until not too long ago, embedded systems were not very powerful, and they ran special-purpose, proprietary operating systems that were very different from industry-standard ones. (Plus, they were much harder to develop for.) Today, embedded computers are as powerful as, if not more than, a modern home computer. (Consider the high-end gaming consoles, for example.)
Along with this power comes the capability to run a full-fledged operating system such as Linux. Using a system such as Linux for an embedded product makes a lot of sense. A large community of developers are making it possible. The development environment and the deployment environment can be surprisingly similar, which makes your life as a developer much easier. And you have both the security of a protected address space that a virtual memory-based system gives you, and the power and flexibility of a multiuser, multiprocess system. That's a good deal all around.
For this reason, companies all over the world are using Linux on many devices such as PDAs, home entertainment systems, and even, believe it or not, cellphones!
I'm excited about this book. It provides an excellent "guide up the learning curve" for the developer who wants to use Linux for his or her embedded system. It's clear, well-written, and well-organized; Chris's knowledge and understanding show through at every turn. It's not only informative and helpfulit's also enjoyable to read.
I hope you both learn something and have fun at the same time. I know I did.
Arnold Robbins
Series Editor