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
Preface Although many good books cover Linux, none brings together so many dimensions of information and advice specifically targeted to the embedded Linux developer. Indeed, there are some very good books written about the Linux kernel, Linux system administration, and so on. You will find references right here in this book to many of the ones that I consider to be at the top of their categories.
Much of the material presented in this book is motivated by questions I've received over the years from development engineers, in my capacity as an embedded Linux consultant and my present role as a Field Application Engineer for Monta Vista Software, the leading vendor of embedded Linux distributions.
Embedded Linux presents the experienced software engineer with several unique challenges. First, those with many years of experience with legacy real-time operating systems (RTOSes) find it difficult to transition their thinking from those environments to Linux. Second, experienced application developers often have difficulty understanding the relative complexities of a cross-development environment.
Although this is a primer, intended for developers new to embedded Linux, I am confident that even developers who are experienced in embedded Linux will find some useful tips and techniques that I have learned over the years.