1484201825 %7B44BAC1FF%7D Mastering The Raspberry Pi %5BGay 2014 08 18%5D {44BAC1FF} [Gay 18]
User Manual: 1484201825 %7B44BAC1FF%7D Mastering the Raspberry Pi %5BGay 2014-08-18%5D
Open the PDF directly: View PDF .
Page Count: 482
Download | |
Open PDF In Browser | View PDF |
Technology in Action™ Mastering the Raspberry Pi A complete reference guide and project idea generator for the Raspberry Pi Warren Gay For your convenience Apress has placed some of the front matter material after the index. Please use the Bookmarks and Contents at a Glance links to access them. Contents at a Glance About the Author������������������������������������������������������������������������������������������������������������ xxvii About the Technical Reviewer����������������������������������������������������������������������������������������� xxix Acknowledgments����������������������������������������������������������������������������������������������������������� xxxi ■■Chapter 1: Why This Book?������������������������������������������������������������������������������������������������1 ■■Chapter 2: The Raspberry Pi����������������������������������������������������������������������������������������������5 ■■Chapter 3: Preparation������������������������������������������������������������������������������������������������������9 ■■Chapter 4: Power�������������������������������������������������������������������������������������������������������������17 ■■Chapter 5: Header Strips, LEDs, and Reset����������������������������������������������������������������������29 ■■Chapter 6: SDRAM�����������������������������������������������������������������������������������������������������������37 ■■Chapter 7: CPU�����������������������������������������������������������������������������������������������������������������53 ■■Chapter 8: USB�����������������������������������������������������������������������������������������������������������������69 ■■Chapter 9: Ethernet���������������������������������������������������������������������������������������������������������75 ■■Chapter 10: SD Card Storage�������������������������������������������������������������������������������������������83 ■■Chapter 11: UART�������������������������������������������������������������������������������������������������������������91 ■■Chapter 12: GPIO�����������������������������������������������������������������������������������������������������������117 ■■Chapter 13: 1-Wire Driver����������������������������������������������������������������������������������������������157 ■■Chapter 14: I2C Bus�������������������������������������������������������������������������������������������������������167 ■■Chapter 15: SPI Bus�������������������������������������������������������������������������������������������������������177 ■■Chapter 16: Boot������������������������������������������������������������������������������������������������������������191 ■■Chapter 17: Initialization�����������������������������������������������������������������������������������������������221 v ■ Contents at a Glance ■■Chapter 18: vcgencmd��������������������������������������������������������������������������������������������������229 ■■Chapter 19: Linux Console���������������������������������������������������������������������������������������������235 ■■Chapter 20: Cross-Compiling�����������������������������������������������������������������������������������������237 ■■Chapter 21: Cross-Compiling the Kernel�����������������������������������������������������������������������253 ■■Chapter 22: DHT11 Sensor���������������������������������������������������������������������������������������������263 ■■Chapter 23: MCP23017 GPIO Extender��������������������������������������������������������������������������275 ■■Chapter 24: Nunchuk-Mouse�����������������������������������������������������������������������������������������303 ■■Chapter 25: Real-Time Clock�����������������������������������������������������������������������������������������329 ■■Chapter 26: VS1838B IR Receiver���������������������������������������������������������������������������������349 ■■Chapter 27: Stepper Motor��������������������������������������������������������������������������������������������365 ■■Chapter 28: The H-Bridge Driver�����������������������������������������������������������������������������������383 ■■Chapter 29: Remote-Control Panel��������������������������������������������������������������������������������401 ■■Chapter 30: Pulse-Width Modulation�����������������������������������������������������������������������������421 ■■Appendix A: Glossary����������������������������������������������������������������������������������������������������439 ■■Appendix B: Power Standards���������������������������������������������������������������������������������������445 ■■Appendix C: Electronics Reference��������������������������������������������������������������������������������447 ■■Appendix D: Raspbian apt Commands���������������������������������������������������������������������������449 ■■Appendix E: ARM Compile Options��������������������������������������������������������������������������������453 ■■Appendix F: Mac OS X Tips��������������������������������������������������������������������������������������������455 ■■Bibliography������������������������������������������������������������������������������������������������������������������457 Index���������������������������������������������������������������������������������������������������������������������������������463 vi Chapter 1 Why This Book? This book developed out of a need for an in-depth work about the Raspberry Pi that just didn’t seem to exist. If I had found one, I would have gladly purchased it. A quick survey revealed a large number of “how to get started” books. But I pined for something with the kind of meat that appeals to engineering types. Give me numbers, formulas, and design procedures. Almost all of that information is available out there on the Internet somewhere. But I discovered that some questions take considerable time to research. If you know exactly where to look, the answer is right there. But if you’re just starting out with the Raspberry Pi, you have several online Easter-egg hunts ahead of you. How much is your time worth? Here’s a short sample of some of the questions answered in this book: • How much current can a general purpose input/output (GPIO) port source or sink? • What is the resistance of the GPIO internal pull-up/pull-down resistor? • Which GPIO does the 1-Wire interface use? • What is the GPIO voltage range for a 0 bit or 1 bit? • How do you budget the GPIO power? Some of these questions have simple answers, while others require an “it depends” explanation. You might be wondering why you need to know the internal GPIO pull-up resistance. Chapter 27 discusses this in connection with motor driver interfaces and what happens at boot time. A number of questions arise when you start designing interfaces to the outside world. While you may not aspire to be an electronics engineer, it helps to think like one. Who Needs This Book? This is an important question and the answer, of course, depends on what you are looking for. So let’s cut to the chase. This book is • Not an easy “how to get started” book (These are plentiful.) • Not a book about Scratch, Python, or Ruby programming • Not a “download package X, configure it, and install it thusly” book • Not a media server or retro games console handbook • Not a book on how to use or administer Linux 1 Chapter 1 ■ Why This Book? This book is targeted to those who have the following: • A college/university level or hobbyist interest • Some exposure to Linux (Raspbian Linux) • Some exposure to the C programming language • Some exposure to digital electronics This Book Is Primarily About In very broad terms, this book can be described primarily as follows: • A Raspberry Pi hardware reference, with software exploration • An electronics interfacing projects book, exploring the hardware and software to drive it In a nutshell, it is a reference and projects book for the Raspberry Pi. The reference coverage is extensive compared to other offerings. A considerable section of the book is also dedicated to projects. I believe that this combination makes it one of the best choices for a book investment. An ever-increasing number of interface boards can be purchased for the Pi, and the choices increase with each passing month. However, this book takes a “bare metal” approach and does not use any additional extender/adapter board solutions. You can, of course, use them, but they are not required. This text also uses a “poor student” approach, using cheap solutions that can be purchased as Buy It Now sales on eBay. These then are directly interfaced to the GPIO pins, and I discuss the challenges and safety precautions as required. This approach should also meet the needs of the hobbyist on a limited budget. You should have a beginning understanding of the C programming language to get the most out of the software presented. Since the projects involve electronic interfacing, a beginning understanding of digital electronics is also assumed. The book isn’t designed to teach electronics, but some formulas and design procedures are presented. Even those with no interest in programming or electronics will find the wealth of reference material in this book worth owning. The back of the book contains a bibliography for those who want to research topics further. Learning Approach Many times a construction article in a magazine or a book will focus on providing the reader with a virtual kit. By this, I mean that every tool, nut and bolt, component, and raw material is laid out, which if properly assembled, will achieve the project’s end purpose. This is fine for those who have no subject area knowledge but want to achieve that end result. However, this book does not use that approach. The goal of this book is to help you learn how to design solutions for your Rasbperry Pi. You cannot learn design if you’re not allowed to think for yourself! For this reason, I encourage the substitution of parts and design changes. Considerable effort is expended in design procedure. This book avoids a “here is exactly how you do it” approach that many online projects use. I explain the challenges that must be reviewed, and how they are evaluated and overcome. One simple example is the 2N2222A transistor driver (see Chapter 12), where the design procedure is provided. If you choose to use a different junk box transistor, you can calculate the base resistor needed, knowing its HFE (or measured on a digital multimeter). I provide a recipe of sorts, but you are not required to use the exact same ingredients. In some cases, a project is presented using a purchased assembled PCB driver. One example (in Chapter 27) is the ULN2003A stepper motor driver PCB that can be purchased from eBay for less than $5 (free shipping). The use of the PCB is entirely optional, since this single-chip solution can be breadboarded. The PCB, however, offers a cheap, ready-made solution with LED indicators that can be helpful in developing the solution. In many cases, the assembled PCB can be purchased for about the same price as the components themselves. Yet these PCB solutions don’t rob you of the interface design challenge that remains. They simply save you time. 2 Chapter 1 ■ Why This Book? It is intended that you, the reader, not use the presented projects as exact recipes to be followed. Use them as guidelines. Explore them as presented first if you like, but do not be afraid to substitute or alter them in some way. By the time you read this book, some PCBs used here may no longer be available. Clever eBay searches for chip numbers may turn up other manufactured PCB solutions. The text identifies the kind of things to watch out for, like unwanted pull-up resistors and how to locate them. By all means, change the presented software! It costs nothing to customize software. Experiment with it. The programs are purposely provided in a “raw” form. They are not meant to be deployed as finished solutions. They are boiled down as much as possible to be easily read and understood. In some cases, error checking was removed to make the code more readable. All software provided in this book is placed in the public domain with no restrictions. Mold it to your needs. If you follow the projects presented—or better, try them all—you’ll be in a good position to develop new interface projects of your own design. You’ll know what questions to ask and how to research solutions. You’ll know how to interface 3-volt logic to 5-volt logic systems. You’ll know how to plan for the state of the GPIO outputs as the Raspberry Pi boots up, when driving external circuits. Experience is the best teacher. Organization of This Book This book is organized into four major parts. The first part is an introduction, which does not present “how to get started” material but does cover topics like static IP addressing, SSH, and VNC access. I’ll otherwise assume that you already have all the “getting started” material that you need. Part 2 is a large reference section dedicated to the Raspberry Pi hardware. It begins with power supply topics, header strips (GPIO pins), LEDs, and how to wire a reset button. Additional chapters cover SDRAM, CPU, USB, Ethernet (wired and wireless), SD cards, and UART (including RS-232 adapters). A large focus chapter on GPIO is presented. Additional chapters cover Linux driver access to 1-Wire devices, the I2C bus, and the SPI bus. Each chapter examines the hardware and then the software API for it. In Part 3, important software aspects of the Raspberry Pi are examined. This part starts with a full exploration of the boot process, initialization (from boot to command prompt), and vcgencmd and its options. The Linux console and the serial console are documented. Finally, software development chapters on cross- compiling the kernel are covered in detail. Part 4 is the fun part of the book, where you apply what you learned to various projects. All of the projects are inexpensive and easy to build. They include interfacing 1-Wire sensors, an I2C GPIO extender, a nunchuk as a mouse, an infrared reader, unipolar and bipolar stepper motor drivers, switch debouncing, PWM, and a remote sensor/console. There is also a real-time clock project for the Model A owner (which can be tried on the Model B). These cover the majority of the interfacing use cases that you will encounter. The meanings of acronyms used in this advanced level book will be taken for granted. As the reader, you are likely familiar with the terms used. If however, you find yourself in need of clarification, Appendix A contains an extensive glossary of terms. Software in This Book I generally dislike the “download this guy’s package X from here and install it thusly” approach. The problem is that the magic remains buried inside package X, which may not always deliver in the ways that you need. Unless you study their source code, you become what ham radio people call an appliance operator. You learn how to install and configure things but you don’t learn how they work. For this reason, a bare metal approach is used. The code presented is unobstructed by hidden software layers. It is also independent of the changes that might occur to magic package X over time. Consequently, it is hoped that the programs that compile today will continue to compile successfully in the years to come. Python programmers need not despair. Knowing how things are done at the bare metal level can help your understanding. Learning exactly what happens at the system level is an improvement over a vague idea of what a Python package is doing for you. Those who write packages for Python can be inspired by this book. 3 Chapter 1 ■ Why This Book? The software listings have been kept as short as possible. Books filled with pages of code listings tend to be “fluffy.” To keep the listing content reduced, the unusual technique of #include-ing shared code is often used. Normally, program units are compiled separately and linked together at the end. But that approach requires header files, which would just fill more pages with listings. The source code used in this book is available for download from this website: git://github.com/ve3wwg/raspberry_pi.git There you can also obtain the associated make files. The git clone command can be used on your Raspberry Pi as follows: $ git clone git://github.com/ve3wwg/raspberry_pi.git To build a given project, simply change to the project subdirectory and type the following: $ cd ./raspberry_pi $ make If you are making program changes and want to force a rebuild from scratch, simply use this: $ make clobber all Final Words If you are still reading, you are considering purchasing or have purchased this book. That makes me truly excited for you, because chapters of great Raspberry Pi fun are in your hands! Think of this book as a Raspberry Pi owners manual with fun reference projects included. Some may view it as a cookbook, containing basic idea recipes that can be tailored to personal needs. If you own a Raspberry Pi, you need this book! A lot of effort went into including photos, figures, and tables. These make the book instantly more useful as a reference and enjoyable to read. Additional effort went into making the cross-references to other areas of the book instantly available. Finally, this is the type of book that you can lie down on the couch with, read through once, while absorbing things along the way. Afterward, you can review the chapters and projects that interest you most. Hopefully, you will be inspired to try all of the projects presented! 4 Chapter 2 The Raspberry Pi Before considering the details about each resource within the Raspberry Pi, it is useful to take a high-level inventory. In this chapter, let’s just list what you get when you purchase a Pi. In later chapters, you’ll be looking at each resource from two perspectives: • The hardware itself—what it is and how it works • The driving software and API behind it In some cases, the hardware will have one or more kernel modules behind it, forming the device driver layer. They expose a software API that interfaces between the application and the hardware device. For example, applications communicate with the driver by using ioctl(2) calls, while the driver communicates with the I2C devices on the bus. The /sys/class file system is another way that device drivers expose themselves to applications. You’ll see this when you examine GPIO in Chapter 12. There are some cases where drivers don’t currently exist in Raspbian Linux. An example is the Pi’s PWM peripheral that you’ll look at in Chapter 30. Here we must map the device’s registers into the application memory space and drive the peripheral directly from the application. Both direct access and driver access have their advantages and disadvantages. So while our summary inventory here simply lists the hardware devices, you’ll be examining each from a hardware and software point of view in the chapters ahead. Models A hardware inventory is directly affected by the model of the unit being examined. The Raspberry Pi comes in two models: • Model A (introduced later as a hardware-reduced model) • Model B (introduced first and is the full hardware model) Figure 2-1 shows the Model B and its interfaces. Table 2-1 indicates the differences between the two models. 5 Chapter 2 ■ The Raspberry Pi Figure 2-1. Model B interfaces Table 2-1. Model Differences Resource Model A Model B RAM 256 MB 512 MB USB ports 1 2 Ethernet port None 10/100 Ethernet (RJ45) Power consumption10 300 mA (1.5 W) 700 mA (3.5 W) Target price9 $25.00 $35.00 As you can see, one of the first differences to note is the amount of RAM available. The revision 2.0 (Rev 2.0) Model B has 512 MB of RAM instead of 256 MB. The GPU also shares use of the RAM. So keep that in mind when budgeting RAM. In addition, the Model A does not include an Ethernet port but can support networking through a USB network adapter. Keep in mind that only one USB port exists on the Model A, requiring a hub if other USB devices are needed. Finally, the power consumption differs considerably between the two models. The Model A is listed as requiring 300 mA vs. 700 mA for the Model B. Both of these figures should be considered low because consumption rises considerably when the GPU is active (when using the desktop through the HDMI display port). The maximum current flow that is permitted through the 5 V micro-USB connection is about 1.1 A because of the fuse. However, when purchasing a power supply/adapter, it is recommended that you seek supplies that are rated higher than 1.2 A because they often don’t live up to their specifications. Chapter 4 provides more details about power supplies. 6 Chapter 2 ■ The Raspberry Pi Hardware in Common The two Raspberry Pi models share some common features, which are summarized in Table 2-2.9 The Hardware column lists the broad categories; the Features column provides additional specifics. Table 2-2. Common Hardware Features Hardware Features Comments System on a chip Broadcom BCM2835 CPU, GPU, DSP, SDRAM, and USB port CPU model Clock rate ARM1176JZF-S core With floating point 700 MHz Overclockable to 800 MHz GPU Broadcom VideoCore IV OpenGL ES 2.0 3D OpenVG 3D MPEG-2 Video output Audio output VC-1 Microsoft, licensed 1080p30 H.264 Blu-ray Disc capable, 40 Mbit/s MPEG-4 AVC high-profile decoder and encoder 1 Gpixel/s, 1.5 Gtexels/s 24 GFLOPS with DMA Composite RCA PAL and NTSC HDMI Rev 1.3 and 1.4 Raw LCD panels Via DSI 3.5 mm jack HDMI Storage SD/MMC/SDIO Peripherals 8 × GPIO Card slot UART Power source I2C bus 100 kHz SPI bus Two chip selects, +3.3 V, +5 V, ground 5 V via micro-USB Which Model? One of the questions that naturally follows a model feature comparison is why the Model A? Why wouldn’t everyone just buy Model B? Power consumption is one deciding factor. If your application is battery powered, perhaps a data-gathering node in a remote location, then power consumption becomes a critical factor. If the unit is supplemented by solar power, the Model A’s power requirements are more easily satisfied. Cost is another advantage. When an Arduino/AVR class of application is being considered, the added capability of the Pi running Linux, complete with a file system on SD, makes it irresistible. Especially at the model A price of $25. 7 Chapter 2 ■ The Raspberry Pi Unit cost may be critical to students in developing countries. Networking can be sacrificed, if it still permits the student to learn on the cheaper Model A. If network capability is needed later, even temporarily, a USB network adapter can be attached or borrowed. The main advantage of the Model B is its networking capability. Networking today is so often taken for granted. Yet it remains a powerful way to integrate a larger system of components. The project outlined in Chapter 29 demonstrates how powerful ØMQ (ZeroMQ) can be in bringing separate nodes together. 8 Chapter 3 Preparation While it is assumed that you’ve already started with the Raspberry Pi, there may be a few things that you want to do before working through the rest of this book. For example, if you normally use a laptop or desktop computer, you may prefer to access your Pi from there. Consequently, some of the preparation in this chapter pertains to network access. If you plan to do most or all of the projects in this book, I highly recommend using something like the Adafruit Pi Cobbler (covered later in this chapter). This hardware breaks out the GPIO lines in a way that you can access them on a breadboard. If you’re industrious, you could build a prototyping station out of a block of wood. I took this approach but would buy the Adafruit Pi Cobbler if I were to do it again (this was tedious work). Static IP Address The standard Raspbian SD card image provides a capable Linux system, which when plugged into a network, uses DHCP to automatically assign an IP address to it. If you’d like to connect to it remotely from a desktop or laptop, then the dynamic IP address that DHCP assigns is problematic. There are downloadable Windows programs for scanning the network. If you are using a Linux or Mac host, you can use Nmap to scan for it. The following is an example session from a MacBook Pro, using the MacPorts collection nmap command. Here a range of IP addresses are scanned from 1–254: $ sudo nmap −sP 192.168.0.1−254 Starting Nmap 6.25 (http://nmap.org) at 2013−04−14 19:12 EDT . . . Nmap scan report for mac (192.168.0.129) Host is up. Nmap scan report for rasp (192.168.0.132) Host is up (0.00071s latency). MAC Address : B8:27:EB:2B:69:E8 (Raspberry Pi Foundation) Nmap done : 254 IP addresses (6 hosts up) scanned in 6.01 seconds $ In this example, the Raspberry Pi is clearly identified on 192.168.0.132, complete with its MAC address. While this discovery approach works, it takes time and is inconvenient. If you’d prefer to change your Raspberry Pi to use a static IP address, see the “Wired Ethernet” section in Chapter 9 for instructions. 9 Chapter 3 ■ Preparation Using SSH If you know the IP address of your Raspberry Pi or have the name registered in your hosts file, you can log into it by using SSH. In this example, we log in as user pi on a host named rasp (in this example, from a Mac): $ ssh pi@rasp pi@rasp’s password: Linux raspberrypi 3.2.27+ #250 PREEMPT ... armv6l ... Last login : Fri Jan 18 22:19:50 2013 from 192.168.0.179 $ Files can also be copied to and from the Raspberry Pi, using the scp command. Do a man scp on the Raspberry Pi to find out more. It is possible to display X Window System (X-Window) graphics on your laptop/desktop, if there is an X-Window server running on it. (Windows users can use Cygwin for this, available from www.cygwin.com.) Using Apple's OS X as an example, first configure the security of your X-Window server to allow requests. Here I’ll take the lazy approach of allowing all hosts (performed on the Mac) by using the xhost command: $ xhost + access control disabled, clients can connect from any host $ From the Raspberry Pi, connected through the SSH session, we can launch Xpdf, so that it opens a window on the Mac: $ export DISPLAY=192.168.0.179:0 $ xpdf & Here, I’ve specified the Mac’s IP address (alternatively, an /etc/hosts name could be used) and pointed the Raspberry Pi to use the Mac’s display number :0. Then we run the xpdf command in the background, so that we can continue to issue commands in the current SSH session. In the meantime, the Xpdf window will open on the Mac, while the Xpdf program runs on the Raspberry Pi. This doesn’t give you graphical access to the Pi’s desktop, but for developers, SSH is often adequate. If you want remote graphical access to the Raspberry’s desktop, see the next section, where VNC is introduced. VNC If you’re already using a laptop or your favorite desktop computer, you can conveniently access your Raspberry Pi’s graphical desktop over the network. Once the Raspberry Pi’s VNC server is installed, all you need is a VNC client on your accessing computer. Once this is available, you no longer need a keyboard, mouse, or HDMI display device connected to the Raspberry Pi. Simply power up the Pi on your workbench, with a network cable plugged into it. You can easily install the VNC server software on the Pi at the cost of about 10.4 MB in the root file system. The command to initiate the download and installation is as follows: $ sudo apt–get install tightvncserver After the software is installed, the only remaining step is to configure your access to the desktop. The vncserver command starts up a server, after which you can connect remotely to it. 10 Chapter 3 ■ Preparation Using SSH to log in on the Raspberry Pi, type the following command: $ vncserver :1 –geometry 1024x740 –depth 16 –pixelformat rgb565 You will require a password to access your desktop. Password: Verify: Would you like to enter a view–only password (y/n ) ? n New 'X' desktop is rasp:1 Creating default startup script/home/pi/.vnc/xstartup Starting applications specified in/home/pi/.vnc/xstartup Log file is/home/pi/.vnc/rasp:1.log $ The password prompts are presented only the first time that you start the VNC server. Display Number In the vncserver command just shown, the first argument identifies the display number. Your normal Raspberry Pi X-Window desktop is on display :0. So when you start up a VNC server, choose a new unique display number like :1. It doesn’t have to be the number 1. To a limited degree, you can run multiple VNC servers if you find that useful. For example, you might choose to start another VNC server on :2 with a different display resolution. Geometry The -geometry 1024x740 argument configures the VNC server’s resolution in pixels. This example’s resolution is unusual in that normally 1024×768 would be used for a display resolution, a common geometry choice for monitors. But this need not be tied to a physical monitor resolution. I chose the unusual height of ×740 to prevent the VNC client program from using scrollbars (on a Mac). Some experimentation may be required to find the best geometry to use. Depth The -depth 16 argument is the pixel-depth specification. Higher depths are possible, but the resulting additional network trafficc might curb your enthusiasm. Pixel Format The last command-line argument given is -pixelformat rgb565. This particular example specifies that each pixel is 5 bits, 6 bits, 5 bits—for red, green and blue, respectively. Password Setup To keep unauthorized people from accessing your VNC server, a password is accepted from you when you start the server for the first time. The password chosen can be changed later with the vncpasswd command. 11 Chapter 3 ■ Preparation Server Startup If you often use VNC, you may want to define a personal script or alias to start it on demand. Alternatively, have it started automatically by the Raspberry Pi as part of the Linux initialization. See Chapter 17 for more information about initialization scripts. VNC Viewers To access your VNC server on the Raspberry Pi, you need a corresponding VNC viewer on the client side. On the Mac, you can use the MacPorts collection to install a viewer: $ sudo port install vnc Once the viewer is installed, you can access your VNC server on the Raspberry Pi at 192.168.0.170, display :1, with this: $ vncviewer 192.168.0.170:1 If you have your Raspberry Pi in the hosts file under rasp, you can use the name instead: $ vncviewer rasp:1 When the VNC viewer connects to the server, you will be prompted for a password. This obviously keeps others out of your VNC server. For Ubuntu Linux, you can install the xvnc4viewer package. For Windows, several choices are available, such as RealVNC and TightVNC. If you find that the screen resolution doesn’t work well with your client computer, experiment with different VNC server resolutions (-geometry). I prefer to use a resolution that doesn’t result in scrollbars in the viewer. Scrolling around your Raspberry Pi desktop is a nuisance. You can eliminate the need for scrolling by reducing the geometry dimensions. Stopping VNC Server Normally, you don’t need to stop the VNC server if you are just going to reboot or shut down your Raspberry Pi. But if you want to stop the VNC server without rebooting, this can be accomplished. Supply the display number that you used in the VNC server startup (:1 in this example) using the -kill option: $ vncserver –kill :1 This can be useful as a security measure, or to save CPU resources when the server isn’t being used. This can also be useful if you suspect a VNC software problem and need to restart it. Prototype Station The danger of working with the tiny Raspberry Pi’s PCB is that it moves all over the surface as wires tug at it. Given its low mass, it moves easily and can fall on the floor and short wires out in the process (especially around curious cats). 12 Chapter 3 ■ Preparation For this reason, I mounted my Raspberry Pi on a nice block of wood. A small plank can be purchased from the lumberyard for a modest amount. I chose to use teak since it looks nice and doesn’t crack or warp. Even if you choose to use something like the Adafruit Pi Cobbler, you may find it useful to anchor the Raspberry Pi PCB. Mount the PCB on the wood with spacers. Figure 3-1 shows my prototype station. Figure 3-1. A simple prototype station Retro Fahnestock clips were installed and carefully wired to a connector on header strip P1 (the wiring was the most labor-intensive part of this project). ■■Tip Fahnestock clips can be economically purchased at places like www.tubesandmore.com (part # S-H11-4043-6). A small PCB for the RS-232 interface was acquired from eBay ($2.32 total) and mounted at the end of the station. Wires from the RS-232 PCB were routed back to RX/TX and +3.3 V clips and simply clipped into place (this allows you to disconnect them, if you wish to use those GPIO pins for some other purpose). The RS-232 PCB is permanently grounded for convenience. The RS-232 PCB is necessary only for those who wish to use a serial console or to interface with some other serial device. The PCB acquired was advertised on eBay as “MAX232CSE Transfer Chip RS-232 To TTL Converter Module COM Serial Board.” The converter (based on the MAX232CSE chip) will work with TTL or 3.3 V interfaces. Connecting the RS-232 converter’s VCC connection to the Raspberry Pi +3.3 V supply makes it compatible with the Pi. ■■Caution Do not connect the RS-232 converter to +5 V, or you will damage the Pi. For additional information about this, see Chapter 11. In Figure 3-1 you can see a simple bracket holding a small push button (top right). This has been wired up to P6 for a reset button. This is not strictly required if your power supply is working correctly (power-on reset works rather well). Unlike an AVR setup, you are not likely to use reset very often. Chapter 5 has more details about this. 13 Chapter 3 ■ Preparation The LED was added to the station last. It was soldered to a pair of half-inch finishing nails, nailed into the wood. The LED’s cathode has a 220 W resister soldered in series with it to limit the current and wired to ground. The anode is connected to the Fahnestock clip labeled LED. The LED can be tested by connecting an alligator lead from the LED clip to the +3.3 V supply clip (this LED also tolerates +5 V). Be sure to choose a low- to medium-current LED that requires about 10 mA or less (16 mA is the maximum source current from a GPIO pin). To test your prototyping station, you may want to use the script listed in the “GPIO Tester” section in Chapter 12. That script can be used to blink a given GPIO pin on and off in 1-second intervals. Adafruit Pi Cobbler A much easier approach to prototype connections for GPIO is to simply purchase the Adafruit Pi Cobbler kit, which is available from the following site: learn.adafruit.com/adafruit-pi-cobbler-kit/overview This kit provides you with these features: • Header connector for the Pi’s P1 • Ribbon cable • Small breakout PCB • Breakout header pins After assembly, you plug the ribbon cable onto the header P1. At the other end of the ribbon cable is a small PCB that provides 26 pins that plug into your prototype breadboard. A small amount of assembly is required. Gertboard Students might consider using a Gertboard, which is available from this site: uk.farnell.com The main reason behind this recommendation is that the Raspberry Pi’s connections to the outside world are sensitive, 3.3 V, and vulnerable to static electricity. Students will want to connect all manner of buttons, switches, motors, and relays. Many of these interfaces require additional buffers and drivers, which is what the Gertboard is there for. In addition to providing the usual access to the Pi’s GPIO pins, the Gertboard also provides these features: • Twelve buffered I/O pins • Three push buttons • Six open collector drivers (up to 50 V, 500 mA) • A motor controller (18 V, 2 A) • A two-channel 8/10/12 bit digital-to-analog converter • A two-channel 10-bit analog-to-digital converter • A 28-pin DIP ATmega microcontroller This provides a ready-made learning environment for the student, who is anxious to wire up something and just “make it work.” Many of the 3-volt logic and buffering concerns are eliminated, allowing the student to focus on projects. 14 Chapter 3 ■ Preparation Bare Metal Despite the availability of nice adapters like the Gertboard, the focus of this text is on interfacing directly to the Pi’s 3 V GPIO pins. Here are some of the reasons: • No specific adapter has to be purchased for the projects in this book. • Any specified adapter can go out of production. • You’ll not likely use an expensive adapter on each deployed Pi. • Bare metal interfacing will exercise your design skills. If we were to do projects with only wiring involved, there wouldn’t be much learning involved. Facing the design issues that arise from working with weak 3 V GPIOs driving the outside world will be much more educational. The third bullet speaks to finished projects. If you’re building a robot, for example, you’re not going to buy Gertboards everywhere you need to control a motor or read sensor data. You’re going to want to economize and build that yourself. This book is designed to help you face those kinds of challenges. 15 Chapter 4 Power One of the most frequently neglected parts of a system tends to be the power supply—at least when everything is working. Only when things get weird does the power supply begin to get some scrutiny. The Raspberry Pi owner needs to give the power supply extra respect. Unlike many AVR class boards, where the raw input voltage is followed by an onboard 5 V regulator, the Pi expects its power to be regulated at the input. The Pi does include onboard regulators, but these regulate to lower voltages (3.3 V and lower). Figure 4-1 illustrates the rather fragile Micro-USB power input connector. There is a large round capacitor directly behind the connector that people often grab for leverage. It is a mistake to grab it, however, as many have reported “popping it off” by accident. Figure 4-1. Micro-USB power input 17 Chapter 4 ■ Power Calculating Power Sometimes power supplies are specified in terms of voltage, and power handling capability in watts. The Pi’s input voltage of 5 V must support a minimum of 700 mA (Model B). Let’s compute a power supply figure in watts (this does not include any added peripherals): P= V´I = 5 ´ 0.7 = 3.5 W The 3.5 W represents a minimum requirement, so we should overprovision this by an additional 50%: P = 3.5 ´ 1.50 = 5.25 W The additional 50% yields a power requirement of 5.25 W. ■■Tip Allow 50% extra capacity for your power supply. A power supply gone bad may cause damage or many other problems. One common power-related problem for the Pi is loss of data on the SD card. Current Requirement Since the power supply being sought produces one output voltage (5 V), you’ll likely see adapters with advertised current ratings instead of power. In this case, you can simply factor a 50% additional current instead: Isup ply = IPi ´ 1.50 = 0.700 ´ 1.50 = 1.05 A To double-check our work, let’s see whether this agrees with the power rating we computed earlier: P= V´I = 5 ´ 1.05 = 5.25 W The result does agree. You can conclude this section knowing that you minimally need a 5 V supply that produces one of the following: • 5.25 W or more • 1.05 A or more (ignoring peripherals) Supplies that can meet either requirement, should be sufficient. However, you should be aware that not all advertised ratings are what they seem. Cheap supplies often fail to meet their own claims, so an additional margin must always be factored in. 18 Chapter 4 ■ Power Peripheral Power Each additional circuit that draws power, especially USB peripherals, must be considered in a power budget. Depending on its type, a given USB peripheral plugged into a USB 2 port can expect up to 500 mA of current, assuming it can obtain it. (Pre Rev 2.0 USB ports were limited to 140 mA by polyfuses.) Wireless adapters are known to be power hungry. Don’t forget about the keyboard and mouse when used, since they also add to the power consumption. If you’ve attached an RS-232 level shifter circuit (perhaps using MAX232CPE), you should budget for that small amount also in the 3 V supply budget. This will indirectly add to your +5 V budget, since the 3 V regulator is powered from it. (The USB ports use the +5 V supply.) Anything that draws power from your Raspberry Pi should be tallied. Model B Input Power The Raspberry Pi’s input voltage is fixed at exactly 5 V (±0.25 V). Looking at the schematic in Figure 4-2, you can see how the power enters the micro-USB port on the pin marked VBUS. Notice that the power flows through fuse F3, which is rated at 6 V, 1.1 A. If after an accidental short, you find that you can’t get the unit to power up, check that fuse with an ohmmeter. Figure 4-2. Model B Rev 2.0 input power 19 Chapter 4 ■ Power If you bring the input +5 V power into the Pi through header P1, P5, or TP1, for example, you will lose the safety of the fuse F3. So if you bypass the micro-USB port to bring in power, you may want to include a safety fuse in the supplying circuit. Figure 4-3 shows the 3.3 V regulator for the Pi. Everything at the 3.3 V level is supplied by this regulator, and the current is limited by it. Figure 4-3. 3.3 V power Model A Input Power Like the Model B, the Model A receives its power from the micro-USB port. The Model A power requirement is 300 mA, which is easily supported by a powered USB hub or desktop USB 2 port. A USB 2 port is typically able to supply a maximum of 500 mA unless the power is divided among neighboring ports. You may find in practice, however, that not all USB ports will deliver 500 mA. As with the Model B, factor the power required by your USB peripherals. If your total nears or exceeds 500 mA, you may need to power your Model A from a separate power source. Don’t try to run a wireless USB adapter from the Model A’s USB port if the Pi is powered by a USB port itself. The total current needed by the Pi and wireless adapter will likely exceed 500 mA. Supply the wireless adapter power from a USB hub, or power the Pi from a 1.2 A or better power source. Also be aware that not all USB hubs function correctly under Linux, so check compatibility if you’re buying one for that purpose. 3.3 Volt Power Since the 3.3 V supply appears at P1-01, P1-17, and P5-02, it is useful to examine Figure 4-3 (shown previously) to note its source. This supply is indirectly derived from the input 5 V supply, passing through regulator RG2. The maximum excess current that can be drawn from it is 50 mA; the Raspberry Pi uses up the remaining capacity of this regulator. When planning a design, you need to budget this 3 V supply carefully. Each GPIO output pin draws from this power source an additional 3 to 16 mA, depending on how it is used. For more information about this, see Chapter 12. Powered USB Hubs If your power budget is stretched by USB peripherals, you may want to consider the use of a powered USB hub. In this way, the hub rather than your Raspberry Pi provides the necessary power to the downstream peripherals. The hub is especially attractive for the Model A because it provides additional ports. 20 Chapter 4 ■ Power Again, take into account that not all USB hubs work with (Raspbian) Linux. The kernel needs to cooperate with connected USB hubs, so software support is critical. The following web page lists known working USB hubs: http://elinux.org/RPi_Powered_USB_Hubs Power Adapters This section pertains mostly to the Model B because the Model A is easily supported by a USB 2 port. We’ll first look at an unsuitable source of power and consider the factors for finding suitable units. An Unsuitable Supply The example shown in Figure 4-4 was purchased on eBay for $1.18 with free shipping (see the upcoming warning about fakes). For this reason, it was tempting to use it. Figure 4-4. Model A1265 Apple adapter This is an adapter/charger with the following ratings: • Model: A1265 • Input: 100–240 VAC • Output: 5 V, 1 A When plugged in, the Raspberry Pi’s power LED immediately lights up, which is a good sign for an adapter (vs. a charger). A fast rise time on the power leads to successful power-on resets. When the voltage was measured, the reading was +4.88 V on the +5 V supply. While not ideal, it is within the range of acceptable voltages. (The voltage must be between 4.75 and 5.25 V.) The Apple unit seemed to work fairly well when HDMI graphics were not being utilized (using serial console, SSH, or VNC). However, I found that when HDMI was used and the GPU had work to do (move a window across the desktop, for example), the system would tend to seize up. This clearly indicates that the adapter does not fully deliver or regulate well enough. 21 Chapter 4 ■ Power ■■Caution Be very careful of counterfeit Apple chargers/adapters. The Raspberry Pi Foundation has seen returned units damaged by these. For a video and further information, see www.raspberrypi.org/archives/2151. E-book Adapters Some people have reported good success using e-book power adapters. I have also successfully used a 2 A Kobo charger. Best Power Source While it is possible to buy USB power adapters at low prices, it is wiser to spend more on a high-quality unit. It is not worth trashing your Raspberry Pi or experiencing random failures for the sake of saving a few dollars. If you lack an oscilloscope, you won’t be able to check how clean or dirty your supply current is. A better power adapter is cheaper than an oscilloscope. A shaky/noisy power supply can lead to all kinds of obscure and intermittent problems. A good place to start is to simply Google “recommended power supply Raspberry Pi.” Do your research and include your USB peripherals in the power budget. Remember that wireless USB adapters consume a lot of current—up to 500 mA. ■■Note A random Internet survey reveals a range of 330 mA to 480 mA for wireless USB adapter current consumption. Voltage Test If you have a DMM or other suitable voltmeter, it is worthwhile to perform a test after powering up the Pi. This is probably the very first thing you should do, if you are experiencing problems. Follow these steps to perform a voltage test: 1. Plug the Raspberry Pi’s micro-USB port into the power adapter’s USB port. 2. Plug in the power adapter. 3. Measure the voltage between P1-02 (+5 V) and P1-25 (Ground): expect +4.75 to +5.25 V. 4. Measure the voltage between P1-01 (+3.3 V) and P1-25 (Ground): expect +3.135 to +3.465 V. ■■Caution Be very careful with your multimeter probes around the pins of P1. Be especially careful not to short the +5 V to the +3.3 V pin, even for a fraction of a second. Doing so will zap your Pi! If you feel nervous or shaky about this, leave it alone. You may end up doing more harm than good. As a precaution, put a piece of wire insulation (or spaghetti) over the +3.3 V pin. The left side of Figure 4-5 shows the DMM probes testing for +5 V on header strip P1. Again, be very careful not to touch more than one pin at a time when performing these measurements. Be particularly careful not to short between 5 V and 3.3 V. To avoid a short-circuit, use a piece of wire insulation, heat shrink tubing, or even a spaghetti noodle over the other pin. 22 Chapter 4 ■ Power Figure 4-5. Measuring voltages The right side of Figure 4-5 shows the positive DMM probe moved to P1-01 to measure the +3.3 V pin. Appendix B lists the ATX power supply standard voltage levels, which include +5 ± 0.25 V and +3.3 ± 0.165 V. Battery Power Because of the small size of the Raspberry Pi, it may be desirable to run it from battery power. Doing so requires a regulator and some careful planning. To meet the Raspberry Pi requirements, you must form a power budget. Once you know your maximum current, you can flesh out the rest. The following example assumes that 1 A is required. Requirements For clarity, let’s list our battery power requirements: • Voltage 5 V, within ± 0.25 V • Current 1 A 23 Chapter 4 ■ Power Headroom The simplest approach is to use the linear LM7805 as the 5 V regulator. But there are some disadvantages: • There must be some headroom above the input voltage (about 2 V). • Allowing too much headroom increases the power dissipation in the regulator, resulting in wasted battery power. • A lower maximum output current can also result. Your batteries should provide a minimum input of 5+2 V (7 V). Any lower input voltage to the regulator will result in the regulator “dropping out” and dipping below 5 V. Clearly, a 6 V battery input will not do. LM7805 Regulation Figure 4-6 shows a very simple battery circuit using the LM7805 linear regulator. Resistor RL represents the load (the Raspberry Pi). Figure 4-6. Regulated battery supply The 8.4 V battery is formed from seven NiCad cells in series, each producing 1.2 V. The 8.4 V input allows the battery to drop to a low of 7 V before the minimum headroom of 2 V is violated. Depending on the exact 7805 regulator part chosen, a typical heat-sinked parameter set might be as follows: • Input voltage: 7–25 V • Output voltage: 1.5 A (heat-sinked) • Operating temperature: 125°C Be sure to use a heat sink on the regulator so that it can dissipate heat energy to the surrounding air. Without one, the regulator can enter a thermal shutdown state, reducing current flow to prevent its own destruction. When this happens, the output voltage will drop below +5 V. 24 Chapter 4 ■ Power Keep in mind that the amount of power dissipated by the battery is more than that received by the load. If we assume that the Raspberry Pi is consuming 700 mA, a minimum of 700 mA is also drawn from the battery through the regulator (and it could be slightly higher). Realize that the regulator is dissipating additional energy because of its higher input voltage. The total power dissipated by the regulator and the load is as follows: Pd = PL ´ PR = 5V ´ 0.7 A + (8.4 V - 5 V ) ´ 0.7 A = 3.5 W + 2.38 W = 5.88W The regulator must dissipate the difference between the input and the output voltages (2.38 W). This additional energy heats up the regulator with the energy being given away at the heat sink. Because of this, designers avoid using a high input voltage on linear regulator circuits. If the regulator is rated at a maximum of 1.5 A at 7 V (input), the power maximum for the regulator is about 10.5 W. If we apply an input voltage of 8.4 V instead of 7, we can derive what our 5 V maximum current will be: I max = Pmax Vin 10.5 W 8.4 V = 1.25 A = From this, we find that the 8.4 V battery regulator circuit can provide a maximum of 1.25 A at the output, without exceeding the regulator’s power rating. Multiply 8.4 V by 1.25 A to convince yourself that this equals 10.5 W. DC-DC Buck Converter If the application is designed for data acquisition, for example, it is desirable to have it run as long as possible on a given set of batteries or charge cycle. A switching regulator may be more suitable than the linear regulator. Figure 4-7 shows a very small PCB that is about 1.5 SD cards in length. This unit was purchased from eBay for $1.40, with free shipping. At these prices, why would you build one? Figure 4-7. DC-DC buck converter 25 Chapter 4 ■ Power They are also simple to use. You have + and – input connections and + and – output connections. Feed power in at one voltage and get power out at another voltage. This is so simple that you’ll forgive me if I omit the diagram for it. But don’t immediately wire it up to your Raspberry Pi, until you have calibrated the output voltage. While it might come precalibrated for 5 V, it is best not to count on it. If the unit produces a higher voltage, you might fry the Pi. The regulated output voltage is easily adjusted by a multiturn trim pot on the PCB. Adjust the pot while you read your DMM. The specifications for the unit I purchased are provided in Table 4-1 for your general amusement. Notice the wide range of input voltages and the fact that it operates at a temperature as low as –40ºC. The wide range of input voltages and current up to 3 A clearly makes this a great device to attach to solar panels that might vary widely in voltage. Table 4-1. DC-DC buck converter specifications Parameter Min Max Units Parameter Input voltage 4.00 35.0 Volts Output ripple 3.0 Amps Load regulation ±0.5 % 30.0 Volts Voltage regulation ±2.5 % Conversion efficiency 92 % Working temperature –40 +85 °C Switching frequency 150 kHz PCB size 45×20×12 mm Net weight 10 g Input current Output voltage 1.23 Min Max Units 30.9 mA The specification claims up to a 92% conversion efficiency. Using 15 V on the input, I performed my own little experiment with measurements. With the unit adjusted to produce 5.1 V at the output, the readings shown in Table 4-2 were taken. Table 4-2. Readings taken from experiment Parameter Input Output Units Voltage 15.13 5.10 Volts Current 0.190 0.410 Amps Power 2.87 2.09 Watts From the table we expected to see more power used on the input side (2.87 W). The power used on the output side was 2.09 W. The efficiency then becomes a matter of division: 2.09 = 0.728 2.87 From this we can conclude that the measured conversion efficiency was about 72.8%. How well could we have done if we used the LM7805 regulator? The following is a best case estimate, since I don’t have an actual current reading for that scenario. But we do know that at least as much current that flows out of the regulator must flow into it (likely more). So what is the absolute best that the LM7805 regulator could theoretically do? Let’s apply the same current draw of 410 mA for the Raspberry Pi at 5.10 V, as shown in Table 4-3. (This was operating without HDMI output in use.) 26 Chapter 4 ■ Power Table 4-3. Hypothetical LM7805 power use Parameter Input Output Units Voltage 7.1 5.10 Volts Current 0.410 0.410 Amps Power 2.91 2.09 Watts The power efficiency for this best case scenario amounts to this: 2.09 = 0.718 2.91 The absolute best case efficiency for the LM7805 regulator is 71.8%. But this is achieved at its optimal input voltage. Increasing the input voltage to 12 V causes the power dissipation to rise considerably, resulting in a 42.5% efficiency (this calculation is left to the reader as an exercise). Attempting to operate the LM7805 regulator at 15.13 V, as we did with the buck converter, would cause the efficiency to drop to less than 33.7%. Clearly, the buck converter is much more efficient at converting power from a higher voltage source. Signs of Insufficient Power In the forums, it has been reported that ping sometimes doesn’t work from the desktop (with HDMI), yet works OK in console mode.42 Additionally, I have seen that desktop windows can freeze if you move them (HDMI). As you start to move the terminal window, for example, the motion would freeze part way through, as if the mouse stopped working. These are signs of the Raspberry Pi being power starved. The GPU consumes more power when it is active, performing accelerated graphics. Either the desktop freezes (GPU starvation) or the network interface fails (ping). There may be other symptoms related to HDMI activity. Another problem that has been reported is resetting of the Raspberry Pi shortly after starting to boot. The board starts to consume more power as the kernel boots up, which can result in the Pi being starved.43 If you lose your Ethernet connection when you plug in a USB device, this too may be a sign of insufficient power.44 While it may seem that a 1 A power supply should be enough to supply a 700 mA Raspberry Pi, you will be better off using a 2 A supply instead. Many power supplies simply don’t deliver their full advertised ratings. The micro-USB cable is something else to suspect. Some are manufactured with thin conductors that can result in a significant voltage drop. Measuring the voltage as shown previously in the “Voltage Test” section may help diagnose that. Try a higher-quality cable to see whether there is an improvement. No Power If your Pi appears dead, even though power is present at the input, the input polyfuse could have blown. If this was a recent event, allow the unit to cool down. The polymer in the fuse recrystallizes, but this can take several hours. If you think the F3 poly fuse is permanently destroyed, see the Linux wiki page45 for how to test it. 27 Chapter 5 Header Strips, LEDs, and Reset In this chapter, an inventory of the Raspberry Pi header strips, LEDs, and reset button connections is covered. These are important interfaces from the Pi to the outside world. You may want to use a bookmark for Table 5-3, which outlines the general purpose input/output (GPIO) pins on header strip P1. Status LEDs The Model A Raspberry Pi has a subset of the Model B LED indicators because it lacks the Ethernet port. The Model B has three additional LEDs, each showing the network status. Table 5-1 provides a list of LED statuses. Table 5-1. Status LEDs LED Color Model A Model B Comment ACT Green OK ACT SD card access activity PWR Red Yes Yes Power supply FDX Green N/A Yes LAN: Full duplex LNK Green N/A Yes LAN: Link 100 Yellow N/A 100 Labeled incorrectly on Rev 1.0 as 10M: 10/100 Mbit link OK or ACT LED This green LED indicates SD card I/O activity. This active low LED is internally driven by the kernel on GPIO 16 (see the kernel source file bcm2708.c in arm/mach-bcm2708). PWR LED This red LED simply indicates that the Raspberry Pi has power. Figure 5-1 shows that the power LED is supplied from the 3.3 V regulator.14 Consequently, the LED indicates only that power is arriving through the 3.3 V regulator. 29 Chapter 5 ■ Header Strips, LEDs, and Reset Figure 5-1. Power LED The power LED indicator is not necessarily an indication that the power is good. It simply indicates that power is present. The LED can be lit and still not have sufficient voltage present for the CPU to operate correctly. If there is any doubt about how good the power supply is, refer to the “Voltage Test” section in Chapter 4, which has information about how to perform a voltage test. FDX LED This green LED indicates that the Ethernet port is operating in full-duplex mode. LNK LED This green LED indicates that the Ethernet port has an active link-level status. 10M or 10/100 LED Model B Rev 1.0 had this LED incorrectly labelled as 10M. The correct label is 100, which is found on Rev 2.0 boards. This yellow LED indicates that the 100 Mbit link is active (otherwise, it is a 10 Mbit link). 30 Chapter 5 ■ Header Strips, LEDs, and Reset Header P1 The Raspberry Pi includes a 13x2 pin strip identified as P1, which exposes GPIO pins. This includes the I2C, SPI, and UART peripherals as well as the +3.3 V, +5.0 V, and ground connections. Table 5-2 shows the pin assignments for the Model B, Rev 1.0 PCB. Table 5-2. Rev 1.0 GPIO Header Connector P1 (Top View) Lower Left Upper Left 3.3 V power P1-01 P1-02 5 V power GPIO 0 (I2C0_SDA)+R1=1.8k P1-03 P1-04 5 V power GPIO 1 (I2C0_SCL)+R2=1.8k P1-05 P1-06 Ground GPIO 4 (GPCLK 0/1-Wire) P1-07 P1-08 GPIO 14 (TXD) Ground P1-09 P1-10 GPIO 15 (RXD) GPIO 17 P1-11 P1-12 GPIO 18 (PCM_CLK) GPIO 21 (PCM_DOUT) P1-13 P1-14 Ground GPIO 22 P1-15 P1-16 GPIO 23 3.3 V power P1-17 P1-18 GPIO 24 GPIO 10 (MOSI) P1-19 P1-20 Ground GPIO 9 (MISO) P1-21 P1-22 GPIO 25 GPIO 11 (SCKL) P1-23 P1-24 GPIO 8 (CE0) Ground P1-25 P1-26 GPIO 7 (CE1) Lower Right Upper Right ■■Caution The Model A can supply a maximum of 500 mA from the +5 V pins of P1. The model B has a lower maximum limit of 300 mA. These limits are due to the fusible link F3 on the PCB (shown previously in Figure 4-2 in Chapter 4). Note also for both models, the +3.3 V pins of P1 and P5 are limited to a maximum of 50 mA. This is the remaining capacity of the onboard voltage regulator. GPIO currents also draw from this resource. (See Figure 4-3.) Table 5-3 shows the connections for the Model B revision 2.0. According to the Raspberry Pi website14, these pin assignments are not expected to change beyond Rev 2.0 in future revisions. The additional Rev 2.0 header P5 is shown in Table 5-4. 31 Chapter 5 ■ Header Strips, LEDs, and Reset Table 5-3. Rev 2.0 GPIO Header Connector P1 (Top View) Lower Left Upper Left 3.3 V power, 50 mA max P1-01 P1-02 5 V power GPIO 2 (I2C1_SDA1)+R1=1.8k P1-03 P1-04 5 V power GPIO 3 (I2C1_SCL1)+R2=1.8k P1-05 P1-06 Ground GPIO 4 (GPCLK 0/1-Wire) P1-07 P1-08 GPIO 14 (TXD0) Ground P1-09 P1-10 GPIO 15 (RXD0) GPIO 17 (GEN0) P1-11 P1-12 GPIO 18 (PCM_CLK/GEN1) GPIO 27 (GEN2) P1-13 P1-14 Ground GPIO 22 (GEN3) P1-15 P1-16 GPIO 23 (GEN4) 3.3 V power, 50 mA max P1-17 P1-18 GPIO 24 (GEN5) GPIO 10 (SPI_MOSI) P1-19 P1-20 Ground GPIO 9 (SPI_MISO) P1-21 P1-22 GPIO 25 (GEN6)) GPIO 11 (SPI_SCKL) P1-23 P1-24 GPIO 8 (CE0_N) Ground P1-25 P1-26 GPIO 7 (CE1_N) Lower Right Upper Right Table 5-4. Rev 2.0 P5 Header (Top View) Lower Left Lower Right Upper Left (Square) 5 V P5-01 P5-02 3.3 V, 50 mA GPIO 28 P5-03 P5-04 GPIO 29 GPIO 30 P5-05 P5-06 GPIO 31 Ground P5-07 P5-08 Ground Upper Right ■■Note Chapter 7 provides more information on identifying your Raspberry Pi. If you have an early pre Rev 2.0 board, be aware that the GPIO pins differ. Safe Mode If your Raspbian SD image supports it, a safe mode can be activated when needed. The New Out of Box Software (NOOBS) image still appears to support this feature. Pin P1-05, GPIO 3 is special to the boot sequence for Rev 2.0 models. (This is GPIO 1 on the pre Rev 2.0 Model B.) Grounding this pin or jumpering this to P1-06 (ground) causes the boot sequence to use a safe mode boot procedure. If the pin is used for some other purpose, you can prevent this with configuration parameter avoid_safe_mode=1. Be very careful that you don’t accidentally ground a power pin (like P1-01 or P1-02) when you do use it. 32 Chapter 5 ■ Header Strips, LEDs, and Reset If yours fails to respond to safe mode, it may be due to a manufacturing error. See this message: www.raspberrypi.org/phpBB3/viewtopic.php?f=29&t=12007 In that thread, it is suggested that you check the following: $ vcgencmd otp_dump | grep 30: 30:00000002 If you see the value 2, it means that the firmware thinks this is a Rev 1.0 board (even though it may be a Rev 2.0). When that applies, it will not support the safe mode sequence. Newer Rev 2.0 Pis do not have this issue. When safe mode is invoked by the jumper, the config.txt file is ignored except for the avoid_safe_mode parameter. Additionally, this mode overrides the kernel command line, and kernel_emergency.img is loaded. If this file is unavailable, kernel.img is used instead. The intent of this feature is to permit the user to overcome configuration problems without having to edit the SD card on another machine in order to make a correction. The booted emergency kernel is a BusyBox image with /boot mounted so that adjustments can be made. Additionally, the /dev/mmcblk0p2 root file system partition can be fixed up or mounted if necessary. Logic Levels The logic level used for GPIO pins is 3.3 V and is not tolerant of 5 V TTL logic. The Raspberry Pi PCB is designed to be plugged into PCB extension cards or otherwise carefully interfaced to 3 V logic. Input voltage parameters VIL and VIH are described in Chapter 12. This feature of the Pi makes it an interesting case study as we interface it to the outside world. GPIO Configuration at Reset The Raspberry Pi GPIO pins can be configured by software control to be input or output, to have pull-up or pull-down resistors, or to assume some specialized peripheral function. After reset, only GPIO 14 and 15 are assigned a special function (UART). After boot up, however, software can even reconfigure the UART pins as required. When a GPIO pin is configured for output, there is a limited amount of current that it can drive (source or sink). By default, each P1 GPIO is configured to use an 8 mA driver, when the pin is configured as an output. Chapter 12 has more information on the software control of this. ■■Note Raspbian 1-Wire bus is GPIO 4 (GPCLK0) Pin P1-07. 1-Wire Driver The default GPIO pin used for the 1-Wire driver is GPIO 4. This is hard-coded in the following kernel source file: arch/arm/mach–bcm2708/bcm2708.c If you need to change this default, alter the line in bcm2708.c that defines the macro W1_GPIO: #define W1_GPIO 4 Then rebuild your kernel. 33 Chapter 5 ■ Header Strips, LEDs, and Reset Header P5 Be careful with the orientation of this Model B Rev 2.0 header strip. See Figure 5-2: while looking down at P1, with its pin 1 at the lower left, the P5 strip has its pin 1 at the upper left (note the square pad on either side of the PCB). Figure 5-2. P5’s pin 1 location on the Rev 2.0 Model B As a practical matter, I found that the pins for P5 can be soldered into the PCB with some care (they are not included). However, the proximity of P5 to P1 makes it impossible to plug in a header connector to P1 and P5 at the same time. With the pins installed, it is possible to use individual wire plugs on the pins as needed. I ended up plugging in a dual-wire plug on P5-04 and P5-06, which is one row away from P1. These wires were then brought out to connectors on a wood strip for easier access. By default, GPIO pins 28 through 31 are configured for driving 16 mA. (Chapter 12 has more information about this.) Reset In the revision 2.0 Raspberry Pi, a reset circuit was implemented, as shown in Figure 5-4.11 To complete the reset circuit, attach a push button to pins 1 and 2 of P6, as shown in Figure 5-3.14 34 Chapter 5 ■ Header Strips, LEDs, and Reset Figure 5-3. Model B Rev 2.0 P6 Figure 5-4. Reset circuit To actuate the reset, P6 pin 1 is short-circuited to P6 pin 2. This resets the BCM2835 SoC chip. This is something you will want to avoid using while Raspbian Linux is up and running. Use reset as a last resort to avoid losing file content. 35 Chapter 6 SDRAM The Model B Rev 2.0 Raspberry Pi has 512 MB of SDRAM, while the older revisions and remaining models have 256 MB. Contrast this to the AVR class ATmega168p, which has 1 KB of static RAM. SDRAM is synchronous dynamic random access memory, which synchronizes with the system bus for improved performance. It uses a form of pipelining to gain this advantage. There isn’t much about the memory hardware that concerns the average Pi developer. However, in this chapter, you’ll examine some useful Raspbian Linux kernel interfaces that inform us how that memory is utilized. You’ll also examine how to access the memory-mapped ARM peripherals directly from your Linux application. /proc/meminfo The pseudo file /proc/meminfo provides us with information about memory utilization. This information varies somewhat by architecture and the compile options used for that kernel. Let’s study an example that is produced by Raspbian Linux, on the Raspberry Pi: $ cat /proc/meminfo MemTotal: 448996 MemFree: 340228 Buffers: 14408 Cached: 58532 SwapCached: 0 Active: 45948 Inactive: 51564 Active(anon): 24680 Inactive(anon): 820 Active(file): 21268 Inactive(file): 50744 Unevictable: 0 Mlocked: 0 SwapTotal: 102396 SwapFree: 102396 Dirty: 0 Writeback: 0 AnonPages: 24584 Mapped: 20056 Shmem: 932 Slab: 6088 SReclaimable: 2392 kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB 37 Chapter 6 ■ SDRAM SUnreclaim: KernelStack: PageTables: NFS_Unstable: Bounce: WritebackTmp: CommitLimit: Committed_AS: VmallocTotal: VmallocUsed: VmallocChunk: 3696 1216 1344 0 0 0 326892 215104 188416 744 186852 kB kB kB kB kB kB kB kB kB kB kB All of the memory values shown have the units KB to the right of them, indicating kilo (1,024) bytes. This next example was taken from a Model A Raspberry Pi, with 256 MB:63 $cat/proc/meminfo MemTotal: 190836 MemFree: 151352 Buffers: 7008 Cached: 20640 SwapCached: 0 Active: 14336 Inactive: 18648 Active(anon): 5468 Inactive(anon): 0 Active(file): 8868 Inactive(file): 18648 Unevictable: 0 Mlocked: 0 SwapTotal: 0 SwapFree: 0 Dirty: 0 Writeback: 0 AnonPages: 5348 Mapped: 6512 Shmem: 136 Slab: 3712 SReclaimable: 1584 SUnreclaim: 2128 KernelStack: 944 PageTables: 620 NFS_Unstable: 0 Bounce: 0 WritebackTmp: 0 CommitLimit: 95416 Committed_AS: 57876 VmallocTotal: 188416 VmallocUsed: 704 VmallocChunk: 186852 kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB kB Many of these values are noticeably smaller. 38 Chapter 6 ■ SDRAM In the sections that follow, a Model B to Model A comparison is provided. In some cases, the comparison isn’t meaningful because the values represent activity that has or has not occurred. For example, the value for AnonPages is going to depend on the mix of commands and applications that have run. But values from both models are provided for completeness. Other values such as MemTotal can be meaningfully compared, however. MemTotal The MemTotal line indicates the total amount of memory available, minus a few reserved binary regions. Note that memory allocated to the GPU is not factored into MemTotal. Some may choose to allocate the minimum of 16 MB to the GPU to make more memory available. MemTotal Model B Model A 448,996 KB 190,836 KB If we break this down a bit further, accounting for memory allocated to the GPU (see Chapter 16 for more details), we find that there is about 9.5 MB (1.9%) of memory that is unaccounted for, as shown in Table 6-1. Table 6-1. GPU and Main Memory Breakdown Memory Model B Comments MemTotal 448,996 KB /proc/meminfo gpu_mem 65,536 KB /boot/config.txt Total 514,532 KB 502.5 MB Unaccounted for 9,756 KB 9.5 MB MemFree MemFree normally represents the sum of LowFree + HighFree memory in kilobytes on the Intel x86 platform. For ARM, this simply represents the amount of memory available to user space programs. MemFree Model B Model A 340,228 KB 151,352 KB The Model B has 332.25 MB for application programs, which amounts to about 64.9% (Rev 2.0). The Model A values indicate about 57.7% of the memory is available. Buffers This value represents temporary buffers used within the kernel for raw disk blocks, and so forth. This value should not get much larger than about 20 MB or so.27 Buffers Model B Model A 14,408 KB 7,008 KB 39 Chapter 6 ■ SDRAM Cached This value represents the read file content that has been cached (page cache). This does not include the content reported for SwapCached. Cached Model B Model A 58,532 KB 20,640 KB SwapCached The value shown for SwapCached represents memory that was swapped out and is now swapped back in. For efficiency, these memory pages are still represented by swap disk space, should they be needed again. SwapCached Model B Model A 0 KB 0 KB The fact that the value is reported as zero is a happy sign that no swapping has occurred, or is no longer pertinent. Active The Active memory value represents recently used memory that is not reclaimed, unless absolutely necessary. Active Model B Model A 45,948 KB 14,336 KB Inactive This value represents memory that is not active and is likely to be reclaimed when memory is needed. Inactive Model B Model A 51,564 KB 18,648 KB Active(anon) This value represents memory that is not backed up by a file and is active. Active memory is not reclaimed unless absolutely necessary. Active(anon) 40 Model B Model A 24,680 KB 5,468 KB Chapter 6 ■ SDRAM Inactive(anon) This value represents memory that is not backed up by a file and is not active. Inactive memory is eligible to be reclaimed if memory is required. Inactive(anon) Model B Model A 820 KB 0 KB Active(file) This value represents file-backed memory, which is active. Active memory is reclaimed only if absolutely required. Active(file) Model B Model A 21,268 KB 8,868 KB Inactive(file) This value represents inactive memory that is backed by a file. Inactive memory is eligible for reclamation, when memory is required. Inactive(file) Model B Model A 50,744 KB 18,648 KB Unevictable This amount reflects the total amount of memory that cannot be reclaimed. Memory that is locked, for example, cannot be reclaimed. Unevictable Model B Model A 0 KB 0 KB Mlocked This value reports the amount of locked memory. Mlocked Model B Model A 0 KB 0 KB 41 Chapter 6 ■ SDRAM SwapTotal This value reports the total amount of swap space available in kilobytes. SwapTotal Model B Model A 102,396 KB 0 KB SwapFree This value reports the remaining amount of swap space available in kilobytes. SwapFree Model B Model A 102,396 KB 0 KB Dirty This value represents the kilobytes of memory that have been modified and are waiting to be written to disk. Dirty Model B Model A 0 KB 0 KB Writeback This value reports the amount of memory in kilobytes being written back to disk. Writeback Model B Model A 0 KB 0 KB AnonPages This represents the non-file-backed pages of memory mapped into user space. AnonPages Model B Model A 24,584 KB 5,348 KB Mapped This value reports the files that have been mapped into memory. This may include library code. Mapped 42 Model B Model A 20,056 KB 6,512 KB Chapter 6 ■ SDRAM Shmem This parameter does not appear to be documented well. However, it represents the amount of shared memory in kilobytes. Shmem Model B Model A 932 KB 136 KB Slab This parameter is described as “in-kernel data structures cache.”27 Slab Model B Model A 6,088 KB 3,712 KB SReclaimable This parameter is described as “Part of Slab that might be reclaimed, such as caches.”27 SReclaimable Model B Model A 2,392 KB 1,584 KB SUnreclaim This parameter is described as “Part of Slab that cannot be reclaimed [under] memory pressure.”27 SUnreclaim Model B Model A 3,696 KB 2,128 KB KernelStack This value reports the memory used by the kernel stack(s). KernelStack Model B Model A 1,216 KB 944 KB PageTables This value reports the amount of memory required by the page tables used in the kernel. Clearly, with more memory to manage, there is more memory dedicated to page tables. PageTables Model B Model A 1,344 KB 620 KB 43 Chapter 6 ■ SDRAM NFS_Unstable This value represents “NFS pages sent to the server, but not yet committed to stable storage.”27 This example data suggests that NFS is not being used. NFS_Unstable Model B Model A 0 KB 0 KB Bounce This reports the memory used for “block device bounce buffers.”27 Bounce Model B Model A 0 KB 0 KB WritebackTmp This parameter reports the memory used by FUSE for “temporary writeback buffers.”27 WritebackTmp Model B Model A 0 KB 0 KB CommitLimit The documentation states: Based on the overcommit ratio (vm.overcommit_ratio), this is the total amount of memory currently available to be allocated on the system. This limit is only adhered to if strict overcommit accounting is enabled (mode 2 in vm.overcommit_memory). The CommitLimit is calculated with the following formula:27 CommitLimit = ( vm.overcommit_ratio × Physical RAM) + Swap For example, a system with 1 GB of physical RAM and 7 GB of swap with a vm.overcommit_ratio of 30 would yield a CommitLimit of 7.3 GB. For more details, see the memory overcommit documentation in vm/overcommitaccounting. The formula can be written as follows: C = (R ´ r) + S The elements of this formula are described here: 44 • C is the overcommit limit. • R is the physical RAM available (MemTotal). • S is the swap space available (SwapTotal). • r is the overcommit ratio percent (expressed as a fraction). Chapter 6 ■ SDRAM The overcommit ratio, r, is not reported in the /proc/meminfo data. To obtain that ratio, we consult another pseudo file. This example was taken from a Rev 2.0 Model B, but it appears to be a value common to all Pis: $ cat /proc/sys/vm/overcommit_ratio 50 The value 50 is to be interpreted as r = 0.50 (50%). Using the overcommit formula, the value for S can be computed for the swap space available: S = C - (R ´ r) = 326892 - (448996 ´ 0.50) = 326892 - 262144 = 102394 KB This fits within 2 KB of the SwapTotal value of 102,396 KB reported by /proc/meminfo. The overcommit ratio is configurable by the user, by writing a value into the pseudo file. This example changes the ratio to 35%: $ sudo -i # echo 35 >/proc/sys/vm/overcommit_ratio # cat /proc/sys/vm/overcommit_ratio 35 The CommitLimit values reported by our example Raspberry Pi sessions are shown in Table 6-2 for comparison purposes. A Model B pre Rev 2.0 version is also included here for comparison. Table 6-2. Example Model B to Model A Memory Comparisons Model B Rev 2.0 Model B Pre 2.0 Model A CommitLimit 326,892 KB 127,868 KB 95,416 KB MemTotal 448,996 KB 124,672 KB 190,836 KB SwapTotal 102,396 KB 65,532 KB 0 KB Commit Ratio 50 50 50 With thanks to Dan Braun for providing the Model B Pre 2.0 data. The value of the Model A commit ratio was calculated here since it wasn’t available from the website. But if you calculate the swap space S for it, you arrive at the value of –2 KB, if you assume 50% for the commit ratio. This agrees with the 2 KB difference you saw earlier. 45 Chapter 6 ■ SDRAM Committed_AS This parameter is described as follows: The amount of memory presently allocated on the system. The committed memory is a sum of all of the memory which has been allocated by processes, even if it has not been “used” by them as of yet. A process which malloc()’s 1 GB of memory, but only touches 300 MB of it will only show up as using 300 MB of memory even if it has the address space allocated for the entire 1 GB. This 1 GB is memory which has been “committed” to by the VM and can be used at any time by the allocating application. With strict overcommit enabled on the system (mode 2 in vm.overcommit_memory), allocations which would exceed the CommitLimit(detailed above) will not be permitted. This is useful if one needs to guarantee that processes will not fail due to lack of memory once that memory has been successfully allocated.27 Committed_AS Model B Model A 215,104 KB 57,876 KB VmallocTotal This represents the total amount of allocated virtual memory address space. VmallocTotal Model B Model A 188,416 KB 188,416 KB VmallocUsed This is the amount of virtual memory that is in use, reported in kilobytes. VmallocUsed Model B Model A 744 KB 704 KB VmallocChunk This value reports the largest size of a vmalloc area, in kilobytes. VmallocChunk 46 Model B Model A 186,852 KB 186,852 KB Chapter 6 ■ SDRAM Physical Memory Let’s now turn our attention to the Raspberry Pi’s physical memory layout. Normally, physical memory isn’t a concern to application programmers, because the operating system and its drivers provide an abstract and often portable way to access them. However, when this support is absent, direct access to a peripheral like the PWM controller is necessary. Figure 6-1 illustrates the physical addressing used on the Raspberry Pi. The SDRAM starts at physical address zero and works up to the ARM/GPU split point (Chapter 16 defines the split point). The ARM peripherals are mapped to physical memory starting at the address of 0x20000000. This starting address is of keen interest to Pi programmers. Figure 6-1. Physical memory layout In the region labeled Peripherals, the offsets and addresses indicated in Table 6-3 are of interest to us. Table 6-3. Peripheral Offsets for the Raspberry Pi Peripheral Offset Address Description C Offset Macro Base 0x00000000 0x20000000 Starting address BCM2708_PERI_BASE PADS_GPIO 0x00100000 0x20100000 PADS base PADS_GPIO_BASE GPIO 00..27 0x0010002C 0x2010002C GPIO 00..27 pads PADS_GPIO_00_27 GPIO 28..45 0x00100030 0x20100030 GPIO 28..45 pads PADS_GPIO_28_45 GPIO 46..53 0x00100034 0x20100034 GPIO 46..53 pads PADS_GPIO_46_53 Clock 0x00101000 0x20101000 Clock registers CLK_BASE GPIO 0x00200000 0x20200000 GPIO registers GPIO_BASE GPPUD 0x00200025 0x20200025 Pull-up enable GPPUDCLK0 0x00200026 0x20200026 Pull-up clock 0 GPPUDCLK1 0x00200027 0x20200027 Pull-up clock 1 PWM 0x0020C000 0x2020C000 PWM registers PWM_BASE 47 Chapter 6 ■ SDRAM Throughout this book, you’ll see the macros BCM2708_PERI_BASE and GPIO_BASE, for example, used in programs that access the peripherals directly. Memory Mapping To gain access to physical memory under Linux, we make use of the /dev/mem character device and the mmap(2) system call. The /dev/mem node is shown here: $ ls −l /dev/mem crw−r−−−−T 1 root kmem 1, 1 Dec 31 1969 /dev/mem From the ownership information shown, it is immediately obvious that you’ll need root privileges to access it. This is sensible given that a process can cause havoc with direct access to the physical memory. Clearly, the Pi developer should exercise caution in what the applications do with it. The mmap(2) system call API is shown here: #includevoid ∗mmap( void size_t int int int off_t ) ; ∗addr, length, prot, flags, fd, offset /∗Address to use ∗/ /∗Number of bytes to access ∗/ /∗Memory protection ∗/ /∗Option flags ∗/ /∗Opened file descriptor ∗/ /∗Starting off set ∗/ Rather than look at all the options and flags available to this somewhat complicated system call, let’s look at the ones that we use in the following code: static char ∗map = 0; static void gpio_init() { int fd; char ∗map; fd = open("/dev/mem",O_RDWR|O_SYNC) ; if ( fd < 0 ) { perror("Opening /dev/mem") ; exit(1) ; } map = (char ∗) mmap( NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE ) ; 48 /∗Needs root access ∗/ /∗Any address ∗/ /∗ # of bytes ∗/ /∗Shared ∗/ /∗ /dev/mem ∗/ /∗Offset to GPIO ∗/ Chapter 6 ■ SDRAM if ( (long)map == −1L ) { perror("mmap(/dev/mem)"); exit(1) ; } } close(fd); ugpio = (volatile unsigned ∗)map; The first thing performed in this code is to open the device driver node /dev/mem. It is opened for reading and writing (O_RDWR), and the option flag O_SYNC requests that any write(2) call to this file descriptor result in blocking the execution of the caller until it has completed. Address Next, the mmap(2) call is invoked. The address argument is provided with NULL (zero) so that the kernel can choose where to map it into the caller’s address space. If the application were to specify a starting address to use and the kernel was not able use it, the system call would fail. The starting address is returned and assigned to the character pointer map in the preceding listing. Length Argument 2 is supplied with the macro BLOCK_SIZE in this example. This is the number of bytes you would like to map into your address space. This was defined earlier in the program as 4 KB: #define BLOCK_SIZE (4∗1024) While the application may not need the full 4 KB of physical memory mapped, mmap(2) may insist on using a multiple of the page size. This can be verified on the command line as follows: $ getconf PAGE_SIZE 4096 A program could determine this as well, by using the sysconf(2) system call: #include ... long sz = sysconf(_SC_PAGESIZE); Protection The third mmap(2) argument is supplied with the flags PROT_READ and PROT_WRITE. This indicates that the application wants both read and write access to the memory-mapped region. Flags The flags argument is supplied with the value MAP_SHARED. This permits nonexclusive access to the underlying mapping. 49 Chapter 6 ■ SDRAM File Descriptor This argument supplies the underlying opened file to be mapped into memory. In this case, we map a region of physical ARM memory into our application by using the opened device driver node /dev/mem. Offset This last argument specifies the location in physical memory where we want to start our access. For the GPIO registers, it is the address 0x20200000. Return Value The return value, when successful, will be an application address that points to the physical memory region we asked for. The application programmer need not be concerned with what this address is, except to save and use it for access. The return value is also used for indicating failure, so this should be checked and handled: if ( (long) map == –1L ) { perror("mmap(/dev/mem)"); exit(1); } The returned address (pointer) map is cast to a long integer and compared to -1L. This is the magic value that indicates that an error occurred. The error code is found in errno. Volatile The last section of this initialization code for GPIO assigns the address map to another variable, ugpio, as follows: ugpio = (volatile unsigned ∗)map; The value ugpio was defined earlier in the program: static volatile unsigned ∗ugpio = 0; There are two things noteworthy about this: • The data type is an unsigned int (32 bits on the Pi). • The pointed-to data is marked as volatile. Since the Pis registers are 32 bits in size, it is often more convenient to access them as 32-bit words. The unsigned data type is perfect for this. But be careful with offsets in conjunction with this pointer, since they will be word offsets rather than byte offsets. The volatile keyword tells the compiler not to optimize access to memory through the pointer variable. Imagine code that reads a peripheral register and reads the same register again later, to see whether an event has occurred. An optimizing compiler might say to itself, “I already have this value in CPU register R, so I’ll just use that since it is faster.” But the effect of this code is that it will never see a bit change in the peripheral’s register because that data was not fetched back into a CPU register. The volatile keyword forces the compiler to retrieve the value even though it would be faster to use the value still found in a register. 50 Chapter 6 ■ SDRAM Virtual Memory In the previous section, you looked at how to access physical memory in an application, provided that you had the rights to do so (root or setuid). The Broadcom Corporation PDF manual “BCM2835 ARM Peripherals,” page 5, also shows a virtual memory layout on the right. This should not be confused with the physical memory layout that you examined earlier. Virtual memory can be accessed through /dev/kmem driver node using mmap(2), but we won’t be needing that in this book. Final Thoughts on SDRAM Some parameters such as Buffers impact the performance of Raspbian Linux on the Pi. From our comparison, we saw that the Model A seems to use about half of the buffering available to the Model B Rev 2.0 Pi. This is reasonable when limited memory has to be divided between operating system and application use. Another performance area related to memory is how much SDRAM is dedicated to GPU use. This parameter is examined in Chapter 16. Probably the most important aspect of memory allocation is how much memory is available to the developer’s application programs. The value of MemFree is perhaps the most useful metric for this. When exceeding physical memory limits, the swapping parameters then become measurements of interest. Finally, we took a detailed look at how to access the Raspberry Pi peripherals directly using mmap(2). Until Raspbian Linux gains device drivers for peripherals such as PWM, the direct access technique will be necessary. Even with driver support, there are sometimes valid reasons to access the peripheral registers directly. 51 Chapter 7 CPU The Raspberry Pi includes an ARM 700 MHz CPU. In this chapter, you’ll first look at the versions of the Pi that have been released into the wild. Then after looking briefly at overclocking, you’ll examine how the CPU is exploited by the Linux application. Identification Several revisions of the Pi have been released and sold. Table 7-1 lists the known revisions and some of the changes related to them. Table 7-1. Board Identification40, 41 Code Model Rev. RAM P1-03 P1-05 P1-13 P5 Manuf. 0002 B 1.0 256 MB GPIO0 GPIO1 GPIO21 N Egoman? 0003 B 1.0+ 256 MB GPIO0 GPIO1 GPIO21 N Egoman? 0004 B 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Sony 0005 B 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Qisda 0006 B 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Egoman 0007 A 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Egoman 0008 A 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Sony 0009 A 2.0 256 MB GPIO1 GPIO2 GPIO27 Y Qisda 000d B 2.0 512 MB GPIO1 GPIO2 GPIO27 Y Egoman 000e B 2.0 512 MB GPIO1 GPIO2 GPIO27 Y Sony 000f B 2.0 512 MB GPIO1 GPIO2 GPIO27 Y Qisda Comments Fuse mod and D14 removed 53 Chapter 7 ■ CPU Once your Raspberry Pi has booted up in Raspbian Linux, you can check the board’s identification with the following command: $ cat /proc/cpuinfo Processor BogoMIPS Features CPU implementer CPU architecture CPU variant CPU part CPU revision Hardware Revision Serial : : : : : : : : : : : ARMv6–compatible processor rev 7 (v6l) 697.95 swp half thumb fastmult vfp edsp java tls 0x41 7 0x0 0xb76 7 BCM2708 000f 00000000f52b69d9 The preceding example reports a revision of 000f, which is a Rev 2.0 Pi. Overclocking Raspbian Linux for the Raspberry Pi is conservatively configured for reliability by default. Those with the need for speed can reconfigure it for increased performance but at the risk of less-reliable operation. Raspbian Linux 3.6.11 provides a raspi-config menu of five CPU profiles. The profile None is the default: Profile ARM CPU Core SDRAM Overvolt None 700 MHz 250 MHz 400 MHz 0 Modest 800 MHz 250 MHz 400 MHz 0 Medium 900 MHz 250 MHz 450 MHz 2 High 950 MHz 250 MHz 450 MHz 6 Turbo 1 GHz 500 MHz 600 MHz 6 The raspi-config requires root privileges and is started as follows: $ sudo raspi-config The initial menu screen provides an overclock selection with the description Configure overclocking. Choosing that menu item opens another menu, allowing you to choose a profile. Choosing a profile from this menu changes the following parameters in /boot/config.txt: Parameter None Modest Medium High Turbo arm_freq= 700 800 900 950 1000 core_freq= 250 250 250 250 500 sdram_freq= 400 400 450 450 600 over_voltage= 0 0 2 6 6 When trading reliability for performance, these factors should be considered as it relates to your application: 54 Chapter 7 ■ CPU • • How critical is the application for • Correctness/accuracy • Uptime How does increased performance relate to the results? • Improved accuracy (Fourier transforms, real-time processing) • Increased number of measurements/sampling points • What is the impact of failure? • Will the unit perform reliably in all required temperatures (in an enclosure, outdoors)? How do these performance profiles affect day-to-day performance? Developers are often concerned about compile times, so I did a simple compile-time test. The test procedure used is as follows: 1. With raspi-config, configure the desired overclocking profile. 2. Reboot. 3. Change to the book’s source code top-level directory. 4. Use the command make clobber. 5. Use the command time make. Table 7-2 summarizes the results in seconds for compiling all projects for this book, using the different overclocking profiles. The elapsed times did not always improve (Real), but they can vary widely because of how I/O to the SD card occurs. The CPU time otherwise improved, with one small exception between Medium and High “User” CPU time. Table 7-2. Profile Compile Tests Profile Real User System None 56.641 23.730 3.520 Modest 37.475 22.330 3.510 Medium 40.127 20.830 3.360 High 49.318 20.980 3.240 Turbo 32.756 15.380 2.650 Everyone has a different appetite for speed. I usually favor reliability over speed, since failure and intermittent problems can cause “wild goose chases” and otherwise waste valuable time. Yet in some situations performance can be important enough to accept the risks. An application performing real-time Fourier transforms on audio might justify Turbo mode, for example. 55 Chapter 7 ■ CPU Execution Connected with the idea of the CPU is program execution itself. Before you look at program execution, you need to take high-level view of the execution context. Figure 7-1 shows the operating environment that an executing program operates within. Figure 7-1. Program execution context At the lowest end of the address space is the “text” region containing the program code. This region of virtual memory is read-only, containing read-only program constants in addition to executable code. The next region (in increasing address) contains blocks of uninitialized arrays, buffers, static C variables, and extern storage. At the high end of memory are environment variables for the program, like PATH. You can easily check this yourself by using getenv("PATH") and printing the returned address for it. Its address will likely be the highest address in your Raspberry Pi application, except possibly for another environment variable. Below that, your main program’s stack begins and grows downward. Each function call causes a new stack frame to be created below the current one. If you now add a thread to the program, a new stack has to be allocated for it. Experiments on the Pi show that the first thread stack gets created approximately 123 MB below the main stack’s beginning. A second thread has its stack allocated about 8 MB below the first. Each new thread’s stack (by default) is allocated 8 MB of stack space. Dynamically allocated memory gets allocated from the heap, which sits between the static/extern region and the bottom end of the stack. 56 Chapter 7 ■ CPU Threads Before threads were perfected under Linux, many application developers tended to avoid them. Now, however, there is little reason to. Every attempt was made to keep the project programs in this book simple. This usually meant also avoiding threads. Yet, a few projects would have been more complicated without them. In the example using ØMQ, threads would have been present behind the scenes, even if we didn’t see them in our application code. With that introduction, let’s take a crash course on the pthread API as it applies to Raspbian Linux. pthread Headers All pthread functions require the following header file: #include When linking programs compiled to use pthreads, add the linker option: -lpthread: Link with the pthread library. pthread Error Handling The pthread routines return zero when they succeed and return an error code when they fail. The value errno is not used for these calls. The reason behind this is likely that it was thought that the traditional Unix errno approach would be phased out in the near future (at the time POSIX threads were being standardized). The original use of errno was as follows: extern int errno; However, this approach didn’t work for threaded programs. Imagine two threads concurrently opening files with open(2), which sets the errno value upon failure. Both threads cannot share the same int value for errno. Rather than change a vast body of code already using errno in this manner, other approaches were implemented to provide each thread with its own private copy of errno. This is one reason that programs today using errno must include the header file errno.h. The header file takes care of defining the thread specific reference to errno. Because the pthread standard was developing before the errno solution generally emerged, the pthread library returns the error code directly when there is an error and returns zero when the call is a success. If Unix were to be rewritten from scratch today, all system calls would probably work this way. pthread_create(3) The function pthread_create(3) is used to create a new thread of execution. The function call looks more daunting than it really is: int pthread_create( pthread_t ∗thread, const pthread_attr_t ∗attr, void ∗(∗start_routine)(void ∗), void ∗arg ); 57 Chapter 7 ■ CPU The call to pthread_create(3) creates a new stack, sets up registers, and performs other housekeeping. Let’s describe the arguments: thread: This first argument is simply a pointer to a pthread_t variable to receive the created thread’s ID value. The ID value allows you to query and control the created thread. If the call succeeds, the thread ID is returned to the calling program. attr: This is a pointer to a pthread_attr_t attribute object that supplies various options and parameters. If you can accept the defaults, simply supply zero or NULL. start_routine: As shown in the following code, this is simply the name of a start routine that accepts a void pointer and returns a void pointer. arg: This generic pointer is passed to start_routine. It may point to anything of interest to the thread function (start_routine). Often this is a structure containing values, or in a C++ program, it can be the pointer to an object. If you don’t need an argument value, supply zero (or NULL). returns: Zero is returned if the function is successful; otherwise, an error number is returned (not in errno). Error Description EAGAIN Insufficient resources to create another thread, or a system-imposed limit on the number of threads was encountered. EINVAL Invalid settings in attr. EPERM No permission to set the scheduling policy and parameters specified in attr. The C language syntax of argument 3 is a bit nasty for beginning C programmers. Let’s just show what the function for argument 3 looks like: void ∗ start_routine(void ∗arg) { ... return some_ptr; } The following is perhaps the simplest example of thread creation possible: static void ∗ my_thread(void ∗arg) { ... return 0; } int main(int argc, char ∗∗argv) { pthread_t tid; int rc; // thread execution // Thread rc = pthread_create(&tid,0,my_thread,0); assert(!rc); 58 ID Chapter 7 ■ CPU This example does not use thread attributes (argument 2 is zero). We also don’t care about the value passed into my_thread(), so argument 4 is provided a zero. Argument 3 simply needs to tell the system call what function to execute. The value of rc will be zero if the thread is successfully created (tested by the assert(3) macro). At this point, the main thread and the function my_thread() execute in parallel. Since there is only one CPU on the Raspberry Pi, only one executes at any instant of time. But they both execute concurrently, trading blocks of execution time in a preemptive manner. Each, of course, runs using its own stack. Thread my_thread() terminates gracefully, by returning. pthread_attr_t There are several thread attributes that can be fetched and set. You’ll look only at perhaps the most important attribute (stack size) to keep this crash course brief. For the full list of attributes and functions, you can view the man pages for it: $ man pthread_attr_init To initialize a new attribute, or to release a previously initialized pthread attribute, use this pair of routines: int pthread_attr_init(pthread_attr_t ∗attr); int pthread_attr_destroy(pthread_attr_t ∗attr); attr: Address of the pthread_attr_t variable to initialize/destroy returns: Zero upon success, or an error code when it fails (not in errno) Error Description ENOMEM Insufficient resources (memory) The Linux implementation of pthread_attr_init(3) may never return the ENOMEM error, but other Unix platforms might. The following is a simple example of creating and destroying an attribute object: pthread_attr_t attr; pthread_attr_init(&attr); // Initialize attr ... pthread_attr_destroy(&attr); // Destroy attr Perhaps one of the most important attributes of a thread is the stack size attribute: int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize); attr: The pointer to the attribute to fetch a value from, or to establish an attribute in. stacksize: This is a stack size value when setting the attribute, and a pointer to the receiving size_t variable when fetching the stack size. returns: Returns zero if the call is successful; otherwise, returns an error number (not in errno). 59 Chapter 7 ■ CPU The following error is possible for pthread_attr_setstacksize(3): Error Description EINVAL The stack size is less than PTHREAD_STACK_MIN (16,384) bytes. The Linux man page further states: On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stack size is not a multiple of the system page size. The following simple example obtains the system default stack size and increases it by 8 MB: pthread_attr_t attr; size_t stksiz; pthread_attr_init(&attr); pthread_attr_getstacksize (&attr,&stksiz); stksiz += 8 ∗ 1024 ∗ 1024; pthread_attr_setstacksize(&attr,stksiz); // // // // Initialize attr Get stack size Add 8 MB Set stack size The system default is provided by the initialization of attr. Then it is a matter of “getting” a value out of the attr object, and then putting in a new stack size in the call to pthread_attr_setstacksize(). Note that this set of operations has simply prepared the attributes object attr for use in a pthread_create() call. The attribute takes effect in the new thread, when the thread is actually created: pthread_attr_t attr; ... rc = pthread_create(&tid,&attr,my_thread,0); pthread_join(3) In the earlier pthread_create() example, the main program creates my_thread() and starts it executing. At some point, the main program is going to finish and want to exit (or return). If the main program exits before my_thread() completes, the entire process and the threads in it are destroyed, even if they have not completed. To cause the main program to wait until the thread completes, the function pthread_join(3) is used: int pthread_join(pthread_t thread, void **retval); thread: Thread ID of the thread to be joined with. retval: Pointer to the void * variable to receive the returned value. If you are uninterested in a return value, this argument can be supplied with zero (or NULL). returns: The function returns zero when successful; otherwise, an error number is returned (not in errno). 60 Chapter 7 ■ CPU The following example has added pthread_join(3), so that the main program does not exit until my_thread() exits. int main(int argc,char ∗∗argv) { pthread_t tid; void ∗retval = 0; int rc; rc = pthread_create(&tid,0,my_thread,0); assert(!rc); rc = pthread_join(tid,&retval); assert(!rc); return 0; // Thread ID // Returned value pointer // Wait for my_thread() } pthread_detach(3) The function pthread_join(3) causes the caller to wait until the indicated thread returns. Sometimes, however, a thread is created and never checked again. When that thread exits, some of its resources are retained to allow for a join operation on it. If there is never going to be a join, it is better for that thread to be forgotten when it exits and have its resources immediately released. The pthread_detach(3) function is used to indicate that no join will be performed on the named thread. This way, the named thread becomes configured to release itself automatically, when it exits. int pthread_detach(pthread_t thread); The argument and return values are as follows: thread: The thread ID of the thread to be altered, so that it will not wait for a join when it completes. Its resources will be immediately released upon the named thread’s termination. returns: Zero if the call was successful; otherwise, an error code is returned (not in errno). Error Description EINVAL Thread is not a joinable thread. ESRCH No thread with the ID thread could be found. The pthread_detach function simply requires the thread ID value as its argument: pthread_t tid; int rc; // Thread ID rc = pthread_create(&tid,0,my_thread,0); assert(!rc); pthread_detach(tid); // No joining with this thread 61 Chapter 7 ■ CPU pthread_self(3) Sometimes it is convenient in a piece of code to find out what the current thread ID is. The pthread_self(3) function is the right tool for the job: pthread_t pthread_self(void); An example of its use is shown here: pthread_t tid; tid = pthread_self(); pthread_kill(3) The pthread_kill(3) function allows the caller to send a signal to another thread. The handling of thread signals is beyond the scope of this text. But there is one very useful application of this function, which you’ll examine shortly: #include int pthread_kill(pthread_t thread, int sig); Notice that the header file for signal.h is needed for the function prototype and the signal definitions. thread: This is the thread ID that you want to signal (or test). sig: This is the signal that you wish to send. Alternatively, supply zero to test whether the thread exists. returns: Returns zero if the call is successful, or an error code (not in errno). Error Description EINVAL An invalid signal was specified. ESRCH No thread with the ID thread could be found. One useful application of the pthread_kill(3) function is to test whether another thread exists. If the sig argument is supplied with zero, no actual signal is delivered, but the error checking is still performed. If the function returns zero, you know that the thread still exists. But what does it mean when the thread exists? Does it mean that it is still executing? Or does it mean that it has not been reclaimed as part of a pthread_join(3), or as a consequence of pthread_detach(3) cleanup? It turns out that when the thread exists, it means that it is still executing. In other words, it has not returned from the thread function that was started. If the thread has returned, it is considered to be incapable of receiving a signal. Based on this, you know that you will get a zero returned when the thread is still executing. When error code ESRCH is returned instead, you know that the thread has completed. 62 Chapter 7 ■ CPU Mutexes While not strictly a CPU topic, mutexes cannot be separated from a discussion on threads. A mutex is a locking device that allows the software designer to stop one or more threads while another is working with a shared resource. In other words, one thread receives exclusive access. This is necessary to facilitate inter-thread communication. I’m simply going to describe the mutex API here, rather than the theory behind the application of mutexes. pthread_mutex_create(3) A mutex is initialized with the system call to pthread_mutex_init(3): int pthread_mutex_init( pthread_mutex_t ∗mutex, const pthread_mutexattr_t ∗attr ); mutex: A pointer to a pthread_mutex_t object, to be initialized. attr: A pointer to a pthread_mutexattr_t object, describing mutex options. Supply zero (or NULL), if you can accept the defaults. returns: Returns zero if the call is successful; otherwise, returns an error code (not in errno). Error Description EAGAIN The system lacks the necessary resources (other than memory) to initialize another mutex. ENOMEM Insufficient memory exists to initialize the mutex. EPERM The caller does not have the privilege to perform the operation. EBUSY The implementation has detected an attempt to reinitialize the object referenced by mutex, a previously initialized, but not yet destroyed, mutex. EINVAL The value specified by attr is invalid. An example of mutex initialization is provided here: pthread_mutex_t mutex; int rc; rc = pthread_mutex_init(&mutex,0); assert (!rc); 63 Chapter 7 ■ CPU pthread_mutex_destroy(3) When the application no longer needs a mutex, it should use pthread_mutex_destroy(3) to release its resources: pthread_mutex_t mutex ; int rc; ... rc = pthread_mutex_destroy(&mutex); assert(!rc); mutex: The address of the mutex to release resources for returns: Returns zero when successful, or an error code when it fails (not in errno) Error Description EBUSY Mutex is locked or in use in conjunction with a pthread_cond_wait(3) or pthread_cond_timedwait(3). EINVAL The value specified by mutex is invalid. pthread_mutex_lock(3) When a thread needs exclusive access to a resource, it must lock the resource’s mutex. As long as the cooperating threads follow the same procedure of locking first, they cannot both access the shared object at the same time. int pthread_mutex_lock(pthread_mutex_t ∗mutex); mutex: A pointer to the mutex to lock. returns: Returns zero if the mutex was successfully locked; otherwise, an error code is returned (not in errno). Error Description EINVAL The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT, and the calling thread’s priority is higher than the mutex’s current priority ceiling. Or the value specified by the mutex does not refer to an initialized mutex object. EAGAIN Maximum number of recursive locks for mutex has been exceeded. EDEADLK The current thread already owns the mutex. The following shows the function being called: pthread_mutex_t mutex; int rc; ... rc = pthread_mutex_lock(&mutex); 64 Chapter 7 ■ CPU pthread_mutex_unlock(3) When exclusive access to a resource is no longer required, the mutex is unlocked: int pthread_mutex_unlock(pthread_mutex_t ∗mutex); mutex: A pointer to the mutex to be unlocked. returns: Returns zero if the mutex was unlocked successfully; otherwise, an error code is returned (not in errno). Error Description EINVAL The value specified by mutex does not refer to an initialized mutex object. EPERM The current thread does not own the mutex. A simple example of unlocking a mutex is provided here: pthread_mutex_t mutex; int rc; ... rc = pthread_mutex_unlock(&mutex); Condition Variables Sometimes mutexes alone are not enough for efficient scheduling of CPU between different threads. Mutexes and condition variables are often used together to facilitate inter-thread communication. Some beginners might struggle with this concept, if they are seeing it for the first time. Why do we need condition variables when we have mutexes? Consider what is necessary in building a software queue that can hold a maximum of eight items. Before we can queue something, we need to first see if the queue is full. But we cannot test that until we have the queue locked—otherwise, another thread could be changing things under our own noses. So we lock the queue but find that it is full. What do we do now? Do we simply unlock and try again? This works but it wastes CPU resources. Wouldn’t it be better if we had some way of being alerted when the queue was no longer full? The condition variable works in concert with a mutex and a “signal” (of sorts). In pseudo code terms, a program trying to queue an item on a queue would perform the following steps: 1. Lock the mutex. We cannot examine anything in the queue until we lock it. 2. Check the queue’s capacity. Can we place a new item in it? If so: 3. a. Place the new item in the queue. b. Unlock and exit. If the queue is full, the following steps are performed: a. Using a condition variable, “wait” on it, with the associated mutex. b. When control returns from the wait, return to step 2. 65 Chapter 7 ■ CPU How does the condition variable help us? Consider the following steps: 1. The mutex is locked (1). 2. The wait is performed (3a). This causes the kernel to do the following: a. Put the calling thread to sleep (put on a wait queue) b. Unlock the mutex that was locked in step 1 Unlocking of the mutex in step 2b is necessary so that another thread can do something with the queue (hopefully, take an entry from the queue so that it is no longer full). If the mutex remained locked, no thread would be able to move. At some future point in time, another thread will do the following: 1. Lock the mutex 2. Find entries in the queue (it was currently full), and pull one item out of it 3. Unlock the mutex 4. Signal the condition variable that the “waiter” is using, so that it can wake up The waiting thread then awakens: 1. The kernel makes the “waiting” thread ready. 2. The mutex is successfully relocked. Once that thread awakens with the mutex locked, it can recheck the queue to see whether there is room to queue an item. Notice that the thread is awakened only when it has already reacquired the mutex lock. This is why condition variables are paired with a mutex in their use. pthread_cond_init(3) Like any other object, a condition variable needs to be initialized: int pthread_cond_init( pthread_cond_t const pthread_condattr_t ); ∗cond, ∗attr cond: A pointer to the pthread_cond_t structure to be initialized. attr: A pointer to a cond variable attribute if one is provided, or supply zero (or NULL). returns: Zero is returned if the call is successful; otherwise, an error code is returned (not in errno). Error Description EAGAIN The system lacked the necessary resources. ENOMEM Insufficient memory exists to initialize the condition variable. EBUSY The implementation has detected an attempt to reinitialize the object referenced by cond, a previously initialized, but not yet destroyed, condition variable. EINVAL The value specified by attr is invalid. 66 Chapter 7 ■ CPU pthread_cond_destroy(3) When a condition (cond) variable is no longer required, its resources should be released with the following call: int pthread_cond_destroy(pthread_cond_t ∗cond); cond: Condition variable to be released. returns: Zero if the call was successful; otherwise, returns an error code (not in errno). Error Description EBUSY Detected an attempt to destroy the object referenced by cond while it is referenced by pthread_cond_wait() or pthread_cond_timedwait() in another thread. EINVAL The value specified by cond is invalid. pthread_cond_wait(3) This function is one-half of the queue solution. The pthread_cond_wait(3) function is called with the mutex already locked. The kernel will then put the calling thread to sleep (on the wait queue) to release the CPU, while at the same time unlocking the mutex. The calling thread remains blocked until the condition variable cond is signaled in some way (more about that later). When the thread is awakened by the kernel, the system call returns with the mutex locked. At this point, the thread can check the application condition (like queue length) and then proceed if things are favorable, or call pthread_cond_wait(3) again to wait further. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); cond: Pointer to the condition variable to be used for the wake-up call. mutex: Pointer to the mutex to be associated with the condition variable. returns: Returns zero upon success; otherwise, an error code is returned (not in errno). Error Description EINVAL The value specified by cond, mutex is invalid. Or different mutexes were supplied for concurrent pthread_cond_timedwait() or pthread_cond_ wait() operations on the same condition variable. EPERM The mutex was not owned by the current thread at the time of the call. The following code snippet shows how a queuing function would use this. (Initialization of mutex and cond is assumed.) pthread_mutex_t mutex; pthread_cond_t cond; ... pthread_mutex_lock(&mutex); 67 Chapter 7 ■ CPU while ( queue.length >=max_length ) pthread_cond_wait(&cond,&mutex); // queue the item ... pthread_mutex_unlock(&mutex); The while loop retries the test to see whether the queue is “not full.” The while loop is necessary when multiple threads are inserting into the queue. Depending on timing, another thread could beat the current thread to queuing an item, making the queue full again. pthread_cond_signal(3) When an item is taken off the queue, a mechanism needs to wake up the thread attempting to put one entry into the full queue. One wake-up option is the pthread_cond_signal(3) system call: int pthread_cond_signal(pthread_cond_t ∗cond); cond: A pointer to the condition variable used to signal one thread. returns: Returns zero if the function call was successful; otherwise, an error number is returned (not in errno). Error Description EINVAL The value cond does not refer to an initialized condition variable. It is not an error if no other thread is waiting. This function does, however, wake up one waiting thread, if one or more are waiting on the specified condition variable. This call is preferred for performance reasons if signaling one thread will “work.” When there are special conditions whereby some threads may succeed and others would not, you need a broadcast call instead. When it can be used, waking one thread saves CPU cycles. pthread_cond_broadcast(3) This is the broadcast variant of pthread_cond_signal(3). If multiple waiters have different tests, a broadcast should be used to allow all waiters to wake up and consider the conditions found. int pthread_cond_broadcast(pthread_cond_t ∗cond); cond: A pointer to the condition variable to be signaled, waking all waiting threads. returns: Zero is returned when the call is successful; otherwise, an error number is returned (not in errno). Error Description EINVAL The value cond does not refer to an initialized condition variable. It is not an error to broadcast when there are no waiters. 68 Chapter 8 USB The USB port has become ubiquitous in the digital world, allowing the use of a large choice of peripherals. The Model B Raspberry Pi supports two USB 2 ports, and the Model A just one. This chapter briefly examines some power considerations associated with USB support and powered hubs. The remainder of this chapter examines the device driver interface available to the Raspbian Linux developer. Figure 8-1 serves as a chapter reference schematic of the Raspberry USB interface. Figure 8-1. USB interface 69 Chapter 8 ■ USB Power Early models of the Raspberry Pi limited each USB port to 100 mA because of the polyfuses included. Revision 2.0 models did away with these, leaving you with more options. Even with the polyfuses removed, the end user should remember that the USB ports are powered by the input to the Raspberry Pi PCB. This is supplied through fuse F3 (see Figure 4-3, shown previously in Chapter 4). This limits the maximum USB current to 500 mA for the Model A (which is the limit for one USB port anyway) and 300 mA for the Model B. Exceeding these limits could cause fuse F3 to blow. ■■Note Wireless USB adapters consume between 350 mA and 500 mA. Powered Hubs Whether you have a Model A or Model B Raspberry Pi, you’ll want to use a powered USB hub for high-current peripherals. This is particularly true for wireless network adapters, since they often require up to 500 mA. A USB hub requires coordination with the Linux kernel and thus requires Raspbian Linux driver support. A number of hubs have been reported not to work. The following web page is a good resource listing hubs that are known work with Raspbian Linux: http://elinux.org/RPi_Powered_USB_Hubs With the powered USB hub plugged in, you can list the USB devices that have registered with the kernel by using the lsusb command: # lsusb Bus 001 Bus 001 Bus 001 Bus 001 Device Device Device Device 001: 002: 003: 004: ID ID ID ID 1d6b:0002 0424:9512 0424:ec00 0451:2077 Linux Foundation 2.0 root hub Standard Microsystems Corp. Standard Microsystems Corp. Texas Instruments, Inc. TUSB2077 Hub The first three listed are the usual suspects from the Pi’s own hardware. The last line shows that a TUSB2077 Hub has been registered. Figure 8-2 shows my Belkin USB hub on a busy workbench. If your hub fails to appear in this report, it likely means that there is no driver support for it. 70 Chapter 8 ■ USB Figure 8-2. A powered USB hub USB API Support USB devices are normally supported by device drivers and appear as generic peripherals like keyboards, mice, or storage. The USB Boarduino is a little different, using the FTDI chipset, and supported by a driver. Once the Boarduino is plugged in, the lsusb command lists it, thanks to the FTDI chipset driver: $ lsusb ... Bus 001 Device 008: ID 0403:6001 Future Technology Devices \ International, Ltd FT232 USB–Serial (UART) IC The supporting driver makes the Boarduino available as a serial device: $ ls –l /dev/ttyUSB0 Crw–rw——T 1 root dialout 188, 0 Dec 31 1969 /dev/ttyUSB0 The serial device support allows the AVR device to be programmed by avrdude. A Raspberry Pi application can also communicate with the AVR device’s application. If you want to use network-like packets, the SLIP serial protocol, for example, can be used to communicate over that link. The “Serial API” section of Chapter 11 covers the Linux API for serial communications. libusb Although USB devices are supported by drivers and appear as generic devices, in some situations a user space program needs to communicate with specialized hardware. While Raspbian Linux has libusb installed, the developer will want to install the developer package for it: # apt–get install libusb–dev 71 Chapter 8 ■ USB The USB API is fairly large, complex and beyond the scope of this text. But the curious developer can read more about the libusb API at the website: http://libusb.sourceforge.net/doc/index.html In this chapter, you’ll examine just the beginnings of a libusb program, so that you can get a flavor of how the API works. Include Files The main include file for Raspbian libusb support is as follows: #include The next few pages show a simple USB program, which enumerates USB buses and devices. Once a device is located, an attempt is made to “claim” it and then release it (it will print CLAIMED if successful). However, when all of your USB devices are fully supported by drivers, none will be claimed. This list can be checked against the lsusb command output. The next example program was run on a Raspberry Pi with the following USB devices reported by lsusb: $ lsusb Bus 001 Bus 001 Bus 001 Bus 001 Bus 001 Bus 001 Bus 001 Device Device Device Device Device Device Device 002: 001: 003: 004: 005: 006: 007: ID ID ID ID ID ID ID 0424:9512 1d6b:0002 0424:ec00 05ac:1002 0451:2077 05ac:0204 045e:0040 Standard Microsystems Corp. Linux Foundation 2.0 root hub Standard Microsystems Corp. Apple, Inc. Extended Keyboard Hub [Mitsumi] Texas Instruments, Inc. TUSB2077 Hub Apple, Inc. Microsoft Corp. Wheel Mouse Optical The example program was compiled by the provided make file in the libusb subdirectory and invoked as follows: $ ./tusb Device: 007 045e:0040 0.0.0 class 3 Device: 006 05ac:0204 0.0.0 class 3 0.1.0 class 3 Device: 005 0451:2077 0.0.0 class 9 Device: 004 05ac:1002 0.0.0 class 9 Device: 003 0424:ec00 0.0.0 class 255 Device: 002 0424:9512 0.0.0 class 9 0.0.1 class 9 Device: 001 1d6b:0002 0.0.0 class 9 72 class 0.0 protocol 0 device 768, manuf 1, serial 0 class 0.0 protocol 0 device 290, manuf 1, serial 0 class 9.0 protocol 0 device 256, manuf 0, serial 0 class 9.0 protocol 0 device 290, manuf 1, serial 0 class 255.0 protocol 1 device 512, manuf 0, serial 0 class 9.0 protocol 2 device 512, manuf 0, serial 0 class 9.0 protocol 1 device 774, manuf 3, serial 1 Chapter 8 ■ USB These are easily compared by noting the device name, such as 007, which is reported by lsusb to be the Microsoft mouse. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ tusb.c – Scan list of USB devices and test claim/release. ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #include #include #include #include #include /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ See http://libusb.sourceforge.net/doc/index.html for API ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ int main(int argc, char ∗∗argv) { struct usb_bus ∗busses, ∗bus; struct usb_device ∗dev; struct usb_device_descriptor ∗desc; usb_dev_handle ∗hdev; int cx, ix, ax, rc; usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); for ( bus=busses; bus; bus = bus–>next ) { for ( dev=bus–>devices; dev; dev = dev–>next ) { desc = &dev–>descriptor; printf("Device: %s %04x:%04x ", dev–>filename, desc–>idVendor, desc–>idProduct); printf(" class %u.%d protocol %u", desc–>bDeviceClass, desc–>bDeviceSubClass, desc–>bDeviceProtocol); printf(" device %u, manuf %u, serial %u\n", desc–>bcdDevice, desc–>iManufacturer, desc–>iSerial Number); hdev = usb_open(dev); assert(hdev); 73 Chapter 8 ■ USB 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 74 rc = usb_claim_interface(hdev,0); if ( !rc ) { puts(" CLAIMED.."); rc = usb_release_interface(hdev, 0); puts(" RELEASED.."); assert(!rc); } usb_close(hdev); /∗Configurations ∗/ for ( cx=0; cx descriptor.bNumConfigurations; ++cx ) { /∗Interfaces ∗/ for ( ix=0; ix < dev–>config[cx].bNumInterfaces; ++ix ) { /∗Alternates ∗/ for ( ax=0; ax < dev–>config[cx].interface[ix].num_altsetting; ++ax ) { printf(" %d.%d.%d class %u\n", cx,ix,ax, dev–>config[cx].interface[ix].altsetting[ax].bInterfaceClass); } } } } } return 0; } /∗End tusb.c ∗/ Chapter 9 Ethernet Networking has become an important part of everyday life, whether wireless or by wire. Having a network adapter on your Raspberry Pi allows you to connect to it and do things on it from the comfort of your desktop or laptop computer. It also allows your application on the Pi to reach out to the outside world. Even when the Raspberry Pi is deployed as part of an embedded project, the network interface continues to be important. Remote logging and control are just two examples. Wired Ethernet The standard Raspbian SD card image provides a wired network connection, using DHCP to automatically assign an IP address to it. If you are using the HDMI output and keyboard devices to do work on the Pi, the dynamically assigned IP address is not a bother. But if you would like to eliminate the attached display and keyboard, connecting over the network is attractive. The only problem is the potentially changing IP address. (DHCP will not always use a different IP address, since the address is leased for a time.) It is difficult to contact your Raspberry Pi from a laptop until you know its IP address. As you saw in Chapter 3, you can use the nmap command to scan for it, but this is inconvenient: $ sudo nmap −sP 192.168.0.1−254 Starting Nmap 6.25 (http://nmap.org) at 2013−04−14 19:12 EDT . . . Nmap scan report for mac (192.168.0.129) Host is up. Nmap scan report for rasp (192.168.0.132) Host is up (0.00071s latency). MAC Address: B8:27:EB:2B:69:E8 ( Raspberry Pi Foundation ) Nmap done : 254 IP addresses (6 hosts up) scanned in 6.01 seconds $ If you use your Pi at school or away from your own premises, using DHCP may still be the best option for you. If you are plugging it into different networks as you travel, DHCP sets up your IP address properly and takes care of the name server configuration. However, if you are using your unit at home, or your school can assign you a valid IP address to use, a static IP address simplifies access. ■■Note Be sure to get approval and an IP address assigned to prevent network conflicts. 75 Chapter 9 ■ Ethernet /etc/network/interfaces As supplied by the standard Raspbian image, the /etc/network/interfaces file looks like this: $ cat /etc/network/interfaces auto lo iface lo inet loopback iface eth0 inet dhcp allow−hotplug wlan0 iface wlan0 inet manual wpa−roam/etc/wpa_supplicant/wpa_supplicant.conf iface default inet dhcp $ The wired Ethernet interface (Model B) is named eth0. The line starting with iface eth0 indicates that your network interface eth0 is using DHCP. If this is what you want, leave it as is. Changing to Static IP If you haven’t booted up your Raspberry Pi with the network cable plugged in, now is a good time to do that. This may save you time later, when we review the name server settings. Next, before you start changing it, save a backup of the /etc/network/interfaces file in case you want to change it back: $ sudo −i # cd /etc/network # cp interfaces interfaces.bak Next, edit the line in /etc/network/interfaces that begins with iface eth0 so that it reads like the following: iface eth0 inet static address 192.168.0.177 gateway 192.168.0.1 netmask 255.255.255.0 network 192.168.0.0 broadcast 192.168.0.255 In this example, we have established a fixed IP address of 192.168.0.177, along with the appropriate settings for gateway, netmask, network, and broadcast address. If the network is not your own, get a network administrator to help you with the correct values to use. There is one other file that needs to be checked and potentially edited: $ cat /etc/resolv.conf domain myfastisp.net search myfastisp.net nameserver 192.168.0.1 If you’ve booted up your Raspberry Pi previously while it was using DHCP (with network cable plugged in), these values may already be suitably configured. Otherwise, you’ll need to edit them to get the name service to work. In this example, the Internet Service Provider is myfastisp.net, and name service requests are forwarded through the firewall router at 192.168.0.1. 76 Chapter 9 ■ Ethernet Test Static IP Address Once you have configured things, the simplest thing to do is to reboot your Raspberry Pi to make the new settings take effect (use sudo /sbin/reboot or sudo /sbin/shutdown -r now). Once you’ve rebooted and logged in, check your IP address: $ ifconfig eth0 eth0 Link encap : Ethernet HWaddr b8:27:eb:2b:69:e9 inet addr:192.168.0.177 Bcast: 192.168.0.255 UP BROADCAST RUNNING MULTICAST MTU: 1500 Metric: RX packets: 1046 errors: 0 dropped : 3 overruns: TX packets: 757 errors: 0 dropped: 0 over runs : collisions:0 txqueuelen :1000 RX bytes: 74312 (72.5 KiB) TX bytes: 86127 (84.1 Mask: 255.255.255.0 1 0 frame: 0 0 carrier: 0 KiB) In the preceding example, the inet addr matches our configured static IP address. Let’s now check that the names are resolving. Normally, I would recommend nslookup or dig for this, but neither comes preinstalled on Raspbian. So let’s just use ping: $ ping −c1 google.com PING google.com (74.125.226.4) 56 (84) bytes of data. 64 bytes from yyz06s05−in−f4.1e100.net (74.125.226.4): . . . −−− google.com ping statistics −−− 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 11.933/11.933/11.933/0.000 ms $ In this example, we see that google.com was looked up and translated to the IP address 74.125.226.4. From this, we conclude that the name service is working. The -c1 option on the ping command line causes only one ping to be performed. Otherwise, ping will keep trying, and you may need to ^C to interrupt its execution. If the name google.com does not resolve, you’ll need to troubleshoot /etc/resolv.conf. As a last resort, you might switch back to using DHCP (interfaces.bak) and reboot. If the /etc/resolv.conf file is updated with new parameters, you might try again. USB Adapters If you have a USB Ethernet adapter (non-wireless), you can set up networking for that also. The following line added to /etc/network/interfaces will cause it to use DHCP: iface usb0 inet dhcp For a fixed usb0 IP address, configure as we did earlier (for eth0). For example: iface usb0 inet static address 192.168.0.178 gateway 192.168.0.1 netmask 255.255.255.0 network 192.168.0.0 broadcast 192.168.0.255 This provides interface usb0 with a fixed address of 192.168.0.178. 77 Chapter 9 ■ Ethernet /etc/hosts File If you have a static IP address for your Raspberry Pi, why not update your Linux, OS X, or Windows hosts file (typically, C:\Windows\system32\drivers\etc\hosts) with a hostname for it? For example, your hosts file could have the following line added: $ cat /etc/hosts . . . 192.168.0.177 rasp raspi rpi pi # My Raspberry Pi Now you can use a hostname of rasp, raspi, rpi, or pi to access your Raspberry Pi on the network. Wireless Ethernet If you haven’t already done so, review the “Powered USB Hubs” section of Chapter 8. Wi-Fi adapters can require 350 mA to 500 mA of current draw. The following web page lists good information about the various brands of Wi-Fi adapters available and their level of support: http://elinux.org/RPi_USB_Wi-Fi_Adapters I have a NetGear WN111(v2) RangeMax Next Wireless adapter available. Apparently, this adapter uses one of the following chips: • Atheros AR9170 • Atheros AR9101 Since the AR9170 shows up in the supported list for the D-Link DWA-160, there is a reasonable chance of driver support for it. After plugging it into the powered USB hub and rebooting, the console log shows that it is being “seen”: $ dmesg . . . [3.867883] [3.893138] [3.923115] [3.930064] [3.963095] [4.393875] [4.663403] [4.953470] [6.687035] [7.703098] usb 1_1.3.2: New USB device found, idVendor=0846, idProduct=9001 usb 1_1.3.2: New USB device strings: Mfr=16, Product=32, SerialNumber= usb 1_1.3.2: Product: USB2.0 WLAN usb 1_1.3.2: Manufacturer : ATHER usb 1_1.3.2: SerialNumber : 12345 cfg80211: Calling CRDA to update world regulatory domain usb 1_1.3.2: reset full_speed USB device number 5 using dwc_otg usbcore: registered new interface driver carl9170 usb 1_1.3.2: firmware not found. usb 1_1.3.2: kill pending tx urbs. But there is a troubling error message: “firmware not found.” Also visible in the log, we see that the driver is named carl9170. Further research reveals that it also requires a firmware file named carl9170-1.fw. While this file is available from other sources, the simplest way to install this file is to install it from Raspbian sources: $ sudo apt–get install firmware–linux 78 Chapter 9 ■ Ethernet The firmware file being sought and installed is as follows: $ ls –l /lib/firmware/carl9170−1.fw −rw−r−−r−−1 root root 13388 Jan 14 17:04 /lib/firmware/carl9170−1.fw Rebooting again, the missing firmware message is gone. The lsusb report also confirms the device is ready: # lsusb Bus 001 Bus 001 Bus 001 Bus 001 Bus 001 Device Device Device Device Device 001: ID 1d6b :0002 Linux Foundation 2.0 root hub 002: ID 0424:9512 Standard Microsystems Corp. 003: ID 0424: ec00 Standard Microsystems Corp. 004: ID 0451:2077 Texas Instruments, Inc. TUSB2077 Hub 005: ID 0846:9001 NetGear, Inc. WN111(v2) RangeMax Next Wireless \ [Atheros AR9170+AR9101] # The hardware driver support is now in place. The device now needs network configuration. Configuration You could edit the configuration files by hand if you knew all the possible keywords necessary for your particular wireless authentication protocol. The following Linux raspberrypi 3.2.27+ files are involved: Pathname Description /etc/network/interfaces Main configuration file for networks /etc/wpa_supplicant/wpa_supplicant.conf Authentication information You’ll find a variety of advice on how to configure these on the Internet. But the quickest path to success is to just use the wpa_gui dialog box from the Raspberry Pi desktop. Once you’ve done it this way, directly editing the configuration files can be performed later if you need to tweak it further. Figure 9-1 shows how to locate the wpa_gui dialog box from your Pi desktop. Once wpa_gui is started, click the Manage Networks tab, shown in Figure 9-2. If you’ve made prior attempts at configuring wlan0, delete them all from this menu. Then click the Scan button at the bottom right. 79 Chapter 9 ■ Ethernet Figure 9-1. wpa_gui dialog box Figure 9-2. The Manage Networks tab 80 Chapter 9 ■ Ethernet After clicking Scan, your wireless network should eventually appear in the scan list, as shown in Figure 9-3. Figure 9-3. Results of a wireless network scan Double-click the line representing your network. This brings up a new dialog box that allows you to fill in the remaining authentication parameters: Parameter Example Authentication WPA-Personal (PSK) Encryption CCMP PSK Pass phrase Enter settings that apply to your network. After completing the data input, click the Add button. As you exit the dialog box, be sure to select Save Configuration from the File menu. ■■Caution Don’t forget to pull down Save Configuration from the File menu before you exit the setup application. This is easily forgotten, and no reminder of unsaved changes is provided. 81 Chapter 9 ■ Ethernet After saving the new Wi-Fi configuration, reboot. After the Pi comes back up, log in and check the network interfaces. Look for interface wlan0: $ ifconfig . . . wlan0 Link encap: Ethernet HWaddr 00:22:3f:8d: 78: f9 inet addr:192.168.0.61 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU: 1500 Metric: 1 RX packets: 10514 errors: 0 dropped: 0 overruns: 0 frame : 0 TX packets: 121 errors: 0 dropped : 0 over runs: 0 carrier: 0 collisions:0 txqueuelen:1000 RX bytes: 767287 (749.3 KiB) TX bytes: 9188 (8.9 KiB) The preceding example shows that the wlan0 is available and has a DHCP-assigned IP address. You can now ping or ssh to this access point. 82 Chapter 10 SD Card Storage The file system is central to the Unix system design, from which Linux borrows. The necessary mass storage requirements have traditionally been fulfilled through hard disk subsystems. However, as Linux hosts become as small as cell phones, flash memory technology has replaced the bulky mechanical drive. SD Card Media The standard SD card is 32 mm long, 24 mm wide, and 2.1 mm thick. Figure 10-1 illustrates the connections available on the underside of the SD card. The schematic excerpt shown later will document how the connections are made to this media. Figure 10-1. SD card pinout SD Card Interface In the Raspberry Pi, the SD card is interfaced to the SoC through GPIO pins 46 through 53, seen in Figure 10-2. The SoC senses the insertion of an SD card through the closing of a socket switch (pins 10 and 11 of the socket). Thus GPIO 47 is brought to ground potential when the socket is occupied. Looking at the wiring in Figure 10-2, it might be assumed that all data transfers are 4 bits wide (GPIO 50 through GPIO 53). However, as the following sections will describe, this depends on the SD card media used. 83 Chapter 10 ■ SD Card Storage Figure 10-2. SD card circuit SD Card Basics The SD card includes an internal controller, also known as a Flash Storage Processor (FSP). In this configuration, the Linux host merely provides a command and waits for the response. The FSP takes care of all erase, programming, and read operations necessary to complete the command. In this way, Flash card designs are permitted to increase in complexity as new performance and storage densities are implemented. The SD card manages data with a sector size of 512 bytes. This was intentionally made the same as the IDE magnetic disk drive for compatibility with existing operating systems. Commands issued by the host include a sector address to allow read/writes of one or more sectors. ■■Note Operating systems may use a multiple of the 512-byte sector. Commands and data are protected by CRC codes in the FSP. The FSP also automatically performs a read after write to verify that the data is written correctly.21 If the data write is found defective, the FSP automatically corrects it, replacing the physical sector with another if necessary. The SD card soft error rate is much lower than a magnetic disk drive. In the rare case when errors are discovered, the last line of defense is a correcting ECC, which allows for data recovery. These errors are corrected in the media to prevent future unrecoverable errors. All of this activity is transparent to the host. 84 Chapter 10 ■ SD Card Storage Raspbian Block Size The block size used by the operating system may be a multiple of the media’s sector size. To determine the physical block size used under Raspbian, we first discover how the root file system is mounted (the following listing has been trimmed with ellipses): $ mount /dev/root on/type ext4 (rw, noatime, . . . ) . . . /dev/mmcblk0p1 on/boot type vfat (rw, relatime , . . . ) $ From this we deduce that the device used for the root file system is /dev/root. The pathname given is a symbolic link, so we need to determine the real device pathname: $ ls −dl /dev/root lrwxrwxrwx 1 root root 9 Jan 12 19:33/dev/root −> mmcblk0p2 $ From this, we deduce that the actual device pathname is /dev/mmcblk0p2. The naming convention used tells us the following: Component Name Number Prefix /dev/mmcblk Device number 0 0 Partition number p2 2 Type MMC block From the earlier mount command output, notice that the /boot file system was mounted on /dev/mmcblk0p1. (No symbolic link was used in this case.) From this we understand that the /boot file system is from partition 1 of the same SD card device. Using the root device information, we consult the /sys pseudo file system to find out the physical sector size. Here we supply mmcblk0 as the third-level pathname qualifier to query the device: $ cat /sys/block/mmcblk0/queue/physical_block_size 512 $ cat /sys/block/mmcblk0/queue/logical_block_size 512 $ The result shown informs us that the Raspbian Linux used in this example uses a block (sector) size of 512 bytes, both physically and logically. This precisely matches the SD card’s sector size. Since the /boot file system uses the same physical device as root, this also applies to that partition. Disk Cache While we’re examining mounted SD card file systems, let’s also check the type of device node used: $ ls −l /dev/mmcblk0p? brw−rw−−−T 1 root floppy 179, 1 Dec 31 1969 /dev/mmcblk0p1 brw−rw−−−T 1 root floppy 179, 2 Jan 12 19:33 /dev/mmcblk0p2 $ 85 Chapter 10 ■ SD Card Storage The example output shows a b at the beginning of the brw-rw—T field. This tells us that the disk device is a block device as opposed to a character device. (The associated character device would show a c instead.) Block devices are important for file systems because they provide a disk cache capability to vastly improve the file system performance. The output shows that both the root (partition 2) and the /boot (partition 1) file systems are mounted using block devices. Capacities and Performance SD cards allow a configurable data bus width within limits of the media. All SD cards start with one data bit line until the capabilities of the memory card are known: The SD bus allows dynamic configuration of the number of data lines. After power-up, by default, the SD card will use only DAT0 for data transfer. After initialization, the host can change the bus width (number of active data lines). This feature allows [an] easy trade-off between hardware cost and system performance.18 After the capabilities of the media are known, the data bus can be expanded under software control, as supported. Given that SD cards with memory capacities up to 2 GB operate with a 1-bit data bus, it is highly desirable to use a 4 GB or larger card on the Raspberry Pi, even if the extra storage is not required. More-advanced cards also offer greater transfer speeds by use of higher data clock rates. Table 10-1 summarizes SD card capabilities.19 Table 10-1. SD Card Capabilities Standard Description Greater Than Up To Data Bus SDSC Standard capacity 0 2 GB 1-bit SDHC High capacity 2 GB 32 GB 4-bit SDXC Extended capacity 32 GB 2 TB 4-bit Transfer Modes There are three basic data transfer modes used by SD cards:18 • SPI Bus mode • 1-bit SD mode • 4-bit SD mode SPI Bus Mode The SPI Bus mode is used mainly by consumer electronics using small microcontrollers supporting the SPI bus. Examining Table 10-2 reveals that data is transmitted 1 bit at a time in this mode (pin 2 or 7). 86 Chapter 10 ■ SD Card Storage Table 10-2. SPI Bus Mode Pin Name I/O Logic Description SPI 1 nCS I PP Card select (negative true) CS 2 DI I PP Data in MOSI 3 VSS S S Ground 4 VDD S S Power 5 CLK I PP Clock 6 VSS S S Ground 7 DO O PP Data out 8 NC MISO Memory cards nIRQ 9 SCLK O OD Interrupt on SDIO cards NC Not connected The various SD card connections are used in different ways, as documented by the Table 10-2 mnemonics in the columns I/O and Logic. Table 10-3 is a legend for these and also applies to later Tables 10-4 and 10-5. Table 10-3. Legend for I/O and Logic Notation Meaning I Input O Output I/O Input or output PP Push/pull logic OD Open drain S Power supply NC Not connected Notes Relative to card Or logic high 1-bit SD Mode Table 10-4 lists the pins and functions of the SD card when it is in 1-bit SD mode. The data traverses pin 7 (DAT0) while the clock is supplied on pin 5. Pin 2 is used to send commands and receive responses. This mode uses a proprietary transfer format. 87 Chapter 10 ■ SD Card Storage Table 10-4. 1-bit SD Mode Pin Name 1 NC 2 CMD I/O PP/OD Command/response 3 VSS S S Ground 4 VDD S S Power 5 CLK I PP Clock 6 VSS S S Ground 7 DAT0 I/O PP Data 0 8 NC NC nIRQ O 9 I/O Logic Description No connection Memory cards OD NC SDIO cards No connection 4-bit SD Mode This is the mode used when the data bus width is more than a single bit and supported by SDHC and SDXC cards. Higher data clock rates also improve transfer rates. Table 10-5 lists the pin assignments. Table 10-5. 4-bit SD Mode Pin Name I/O Logic Description 1 DAT3 I/O PP Data 3 2 CMD I/O PP/OD Command/response 3 VSS S S Ground 4 VDD S S Power 5 CLK I PP Clock 6 VSS S S Ground 7 DAT0 I/O PP Data 0 8 DAT1 I/O PP Data 1 nIRQ O OD SDIO cards share with interrupt DAT2 I/O PP Data 2 9 88 Chapter 10 ■ SD Card Storage Wear Leveling Unfortunately, Flash memory is subject to wear for each write operation performed (as each write requires erasing and programming a block of data). The design of Flash memory requires that a large block of memory be erased and rewritten, even if a single sector has changed value. For this reason, wear leveling is used as a technique to extend the life of the media. Wear leveling extends life by moving data to different physical blocks while retaining the same logical address. ■■Note ScanDisk calls the block of Flash memory being erased and rewritten a zone. Some cards use wear leveling.18 Indeed the SanDisk company indicates that their products do use wear leveling.20 However, the type of wear leveling supported by SanDisk is limited to zones within the media. Each SanDisk zone has 3% extra capacity, from which writes can be wear leveled within. If the zone size is 4 MB and is overprovisioned by 3%, this leaves about 245 spare sectors within each zone. Thus each 4 MB zone holds 8,192 active sectors at any given instant, rotated among 245 spares. ■■Note SanDisk indicates that the 4 MB zones may change with future memory capacities. Other manufacturers may not implement wear leveling at all or use a lower level of overprovisioning. Wear leveling is not specified in the SD card standard, so no manufacturer is compelled to follow SanDisk’s lead. Note that wear leveling applies to read/write file systems. If the file system is mounted read-only, no erase and program operations are occurring inside the card. So no “erase wear” is taking place. But do take into account all of the mounted partitions on the same media. If you are using your Raspberry Pi for educational purposes, you can probably ignore the issue. However, using known brands like SanDisk can provide you with additional quality assurance. Consider also the advantage of documented overprovisioning and wear leveling characteristics. ■■Caution Some brands of SD cards have been reported not to work with the Raspberry Pi, so the brand/product issue cannot be totally ignored. 89 Chapter 11 UART The Raspberry Pi has a UART interface to allow it to perform serial data communications. The data lines used are 3.3 V logic-level signals and should not be connected to TTL logic (+5 V) (they also are not RS-232 compatible). To communicate with equipment using RS-232, you will need a converter module. RS-232 Converter While an industrious person could build their own RS-232 converter, there is little need to do so when cheap converters are available. Figure 11-1 shows a MAX232CSE chip interface that I use. (This unit supports only the RX and TX lines.) When searching for a unit, be sure that you get one that works with 3 V logic levels. Some units work only with TTL (+5 V) logic, which would be harmful to the Pi. The MAX232CSE chip will support 3 V operation when its VCC supply pin is connected to +3 V. Figure 11-1. MAX232CSE interface 91 Chapter 11 ■ UART ■■Note Throughout this text, we’ll refer to 3 V, knowing that it is precisely 3.3 V. Figure 11-2 is a schematic excerpt of the UART section of the Raspberry Pi. The UART connections are shown as TXD0 and RXD0. Figure 11-2. UART interface Also when selecting a converter, consider whether you need only the data lines, or the data lines and the hardware flow control signals. Some units support only the RX and TX lines. For hardware flow control, you’ll also want the CTS and DTR signals. A full RS-232 converter would also include DTR, DSR, and CD signals. DTE or DCE When choosing your RS-232 converter, keep in mind that there are two types of serial connections: DCE: Data communications equipment (female connector) DTE: Data terminal equipment (male connector) 92 Chapter 11 ■ UART A normal USB serial adapter (for a laptop, for example) will present a DTE (male) connector. The wiring of this cable is such that it expects to plug into to a DCE (female) connection. When this holds true for your Raspberry Pi’s adapter, the laptop’s serial adapter can plug straight into the DCE (female) connector, eliminating the need for a crossover cable or null modem. Consequently, for your Pi, choose a RS-232 converter that provides a female (DCE) connector. Likewise, make sure that you acquire for the laptop/desktop a cable or USB device that presents a male (DTE) connection. Connecting DTE to DTE or DCE to DCE requires a crossover cable, and depending on the cable, a “gender mender” as well. It is best to get things “straight” right from the start. Assuming that you used a DCE converter for the Pi, connect the RS-232 converter’s 3 V logic TX to the Pi’s TXD0 and the RX to the Pi’s RXD0 data lines. All this business about DCE and DTR has always been rather confusing. If you also find this confusing, there is another practical way to look at it. Start with the connectors and the cable(s) that you plan to use. Make sure they mate at both ends and that the serial cable is known to be a straight cable (instead of a crossover). Once those physical problems are taken care of, you can get the wiring correct. Connect the TX to RX, and RX to TX. In other words, you wire the crossover in your own wiring between the RS-232 adapter and the Raspberry Pi. The important thing to remember is that somewhere the transmitting side needs to send a signal into the RX (receiving) side, in both directions. ■■Note A straight serial cable will connect pin 2 to pin 2, and pin 3 to pin 3 on a DB9 or DB25 cable. A crossover cable will cross these two, among other signal wire changes. RS-232 RS-232 is the traditional name for a series of standards related to serial communication. It was first introduced by the Radio Sector of the EIA in 1962.46 The first data terminals were teletypewriters (DTE) communicating with modems (DCE). Early serial communications were plagued by incompatibilities until later standards evolved. A serial link includes two data lines, with data being transmitted from a terminal and received by the same terminal. In addition to these data lines are several handshaking signals (such as RTS and CTS). By default, these are not provided for by the Raspberry Pi. Figure 11-3 shows a serial signal transmission, with time progressing from left to right. RS-232 equipment expects a signal that varies between –15 V and +15 V. Figure 11-3. Serial signal 93 Chapter 11 ■ UART The standard states that the signal is considered to be in a mark state, when the voltage is between –3 and –15 V. The signal is considered in a space state if the voltage is between +3 and +15 V. The RS-232 data line is in the mark state when the line is idle. Start Bit When an asynchronous character of data is to be sent, the line first shifts to a space level for the duration of 1 bit. This is known as the start bit (0). Data bits immediately follow. Asynchronous lines do not use a clock signal like synchronous links. The asynchronous receiver must have a clock matching the same baud rate as the transmitter. The receiver samples the line 16 times in the bit cell time to determine its value. Sampling helps to avoid a noise pulse from triggering a false data read. Data Bits Data bits immediately follow the start bit, least significant bit first. A space is a 0 data bit, while mark represents a 1 bit. Early teletype equipment used 5 data bits sending characters in the 5-bit Baudot code.47 For this reason, serial ports can be configured for 5, 6, 7, or 8 data bits. Before the ASCII character set was extended to 8 bits, it was common to use 7-bit serial data. Parity Bit An optional parity bit can be generated when transmitting or can be detected on the receiving side. The parity can be odd, even, or stick (mark or space). The most commonly used setting today is No Parity, which saves 1-bit time for faster communication. Older equipment often used parity to guard against errors from noisy serial lines. Odd parity is preferred over even because it forces at least one signal transition in the byte’s transmission. This helps with the data reliability. Mark or space parity is unusual and has limited usefulness. Mark parity could be used along with 2 stop bits to effectively provide 3 stop bits for very slow teletypewriter equipment. Mark or space parity reduces the effective throughput of data without providing any benefit, except possibly for diagnostic purposes. Table 11-1 summarizes the various parity configurations. Table 11-1. RS-232 Parity Settings Parity X Notes None N No parity bit Even E 1 if even number of data 1-bits Odd O 1 if odd number of data 1-bits Mark M Always at mark level (1) Space S Always at space level (0) Stop Bit(s) Asynchronous communication requires synchronizing the receiver with the transmitter. For this reason, 1 or more stop bits exist so that the receiver can synchronize with the leading edge of the next start bit. In effect, each stop bit followed by a start bit provides built-in synchronization. 94 Chapter 11 ■ UART Many UARTs support 1, 1.5, or 2 stop bits. The Broadcom SoC supports 1 or 2 stop bits only. The use of 2 stop bits was common for teletypewriter equipment and probably rarely used today. Using 1 stop bit increases the overall data throughput. Table 11-2 summarizes the stop-bit configurations. Table 11-2. Stop-Bit Configuration Stop Bits Description 1 1 stop bit 1.5 1.5 stop bits (†) 2 2 stop bits †Unsupported by the Raspberry Pi Baud Rate The baud rate is calculated from bits per second, which includes the start, data, parity, and stop bits. A link using 115200 baud, with no parity and 1 stop bit, provides the following data byte rate: B s+d +p+S 115200 = 1+ 8 + 0 +1 = 11, 520 bytes/s ec Drate = where B is the baud rate. s is the start bit (always 1). d is the number of data bits (5, 6, 7, or 8). p is the parity bit (0 or 1). S is the stop bit (1, 1.5, or 2). The 115200 baud link allows 11,250 bytes per second. If a parity bit is added, the throughput is reduced: 115200 1+ 8 +1+1 = 10 , 472.7 bytes/sec Drate = The addition of a parity bit reduces the transmission rate to 10,472.7 bytes per second. Table 11-3 lists the standard baud rates that a serial link can be configured for on the Raspberry Pi. 95 Chapter 11 ■ UART Table 11-3. Standard Baud Rates Rate Notes 75 Teletypewriters 110 Teletypewriters 300 Low-speed (acoustic) modem 1200 2400 4800 9600 19200 38400 57600 115200 Raspberry Pi console Break With asynchronous communication, it is also possible to send and receive a break signal. This is done by stretching the start bit beyond the data bits and the stop bit(s), and eventually returning the line to the mark state. When the receiver sees a space instead of a mark for the stop bit, it sees a framing error. Some UARTs distinguish between a framing error and a break by noting how long the line remains in the space state. A simple framing error can happen as part of noisy serial line communications (particularly when modems were used) and normally attributed to a received character error. Without break detection, it is possible to assume that a break has been received when several framing errors occur in a sequence. Short sequences of framing errors, however, can also just indicate a mismatch in baud rates between the two end points. Flow Control Any link that transmits from one side to a receiver on the other side has the problem of flow control. Imagine a factory assembly line where parts to be assembled arrive at the worker’s station faster than he can assemble them. At some point, the conveyor belt must be temporarily stopped, or some parts will not get assembled. Alternatively, if the conveyor belt is reduced in speed, the assembly worker will always be able to keep up, but perhaps at a slower than optimal pace. Unless the serial link receiver can process every character of data as fast as it arrives, it will need flow control. The simplest approach is to simply reduce the baud rate, so that the receiver can always keep up. But this isn’t always satisfactory and leads to a reduced overall throughput. A logging application might be able to write the information quickly, except when writes occur to an SD card, for example. A better approach is to signal to the transmitter to stop sending when the receiver is bogged down. Once the receiver catches up, it can then tell the transmitter to resume transmission. Note that this problem exists for both sides of a serial link: 96 • Data transmitted to the terminal (DTE) • Data transmitted to the data communications equipment (DCE) Chapter 11 ■ UART Two forms of flow control are used: • Hardware flow control • Software flow control Hardware Flow Control Hardware flow control uses additional signal lines to regulate the flow of data. The RS-232 standards have quite an elaborate set of signals defined, but the main signals needed for flow control are shown in Table 11-4. Unlike the data line, these signals are inactive in the space state and active in the mark state. Table 11-4. Hardware Flow Controls DTE Direction DCE Description Active RTS → RTS Request to send(†) Low CTS ← CTS Clear to send(†) DSR ← DSR Data set ready DTR → DTR Data terminal ready Low † Primary flow control signals The most important signals are the ones marked with a dagger in Table 11-4. When CTS is active (mark), for example, the DCE (Pi) is indicating that it is OK to send data. If the DCE gets overwhelmed by the volume of data, the CTS signal will change to the inactive (space) state. Upon seeing this, the DTE (laptop) is required to stop sending data. (Otherwise, loss of data may occur.) Similarly, the laptop operating as the DTE is receiving data from the DCE (Pi). If the laptop gets overwhelmed with the volume of incoming data, the RTS signal is changed to the inactive state (space). The remote end (DCE) is then expected to cease transmitting. When the laptop has caught up, it will reassert RTS, giving the DCE permission to resume. The DTR and DSR signals are intended to convey the readiness of the equipment at each end. If the terminal was deemed not ready (DTR), DSR is not made active by the DCE. Similarly, the terminal will not assert DTR unless it is ready. In modern serial links, DTR and DSR are often assumed to be true, leaving only CTS and RTS to handle flow control. Where flow control is required, hardware flow control is considered more reliable than software flow control. Software Flow Control To simplify the cabling and the supporting hardware for serial communications, the hardware flow controls can be omitted/ignored. In its place, a data protocol is used instead. Initially, each end of the link assumes readiness for reception of data. Data is sent until an XOFF character is received, indicating that transmission should stop. The receiver sends the XON character when it is ready to resume reception again. These software flow control characters are shown in Table 11-5. Table 11-5. Software Flow Control Characters Code Meaning ASCII Hex Keyboard XOFF Pause transmission DC3 13 Control-S XON Resume transmission DC1 11 Control-Q 97 Chapter 11 ■ UART In a terminal session, the keyboard commands can be used to control the serial connection. For example, if information is displaying too fast, the user can type Ctrl-S to cause the transmission to stop. Pressing Ctrl-Q allows it to resume. The disadvantages of software flow control include the following: 1. Line noise can prevent the receiver from seeing the XOFF character and can lead to loss of data (causing data overrun). 2. Line noise can prevent the remote end from seeing the XON character and can fail to resume transmission (causing a link “lockup”). 3. Line noise can cause a false XON/XOFF character to be received (data loss or link lockup). 4. The delay in the remote end seeing a transmitted XOFF character can cause loss of data if the receiving buffer is full. 5. The XON and XOFF characters cannot be used for data in the transmission. Problems 1 to 3 can cause link lockups or data loss to occur. Problem 4 is avoidable if the buffer notifies the other end early enough to prevent a buffer overflow. Problem 5 is an issue for binary data transmission. Raspberry Pi UARTs The Raspberry Pi supports two UARTs: UART Driver Node GPIO ALT UART0 drivers/tty/serial/amba- pl011.c /dev/ttyAMA0 14 & 15 0 UART1 The mini has no driver. 14 & 15 5 Some websites have incorrectly stated that the mini UART is the one being used. But this does not jibe with the Broadcom documentation, nor the Raspbian Linux device driver. The Broadcom BCM2835 ARM Peripherals manual states that the mini UART is UART1. UART1 is available only as alternate function 5 for GPIO 14 and 15. Raspbian Linux boots up using alternate function 0 for GPIO 14 and 15, providing the UART0 peripheral instead. Finally, the source code for the device driver references PL011 in the naming throughout. ARM PL011 UART By default, UART0 is provided after reset and boot-up, on GPIO 14 (TX) and 15 (RX), configured as alternate function 0 (Table 11-6). UART0 is the full UART, referred to as the ARM PL011 UART. Broadcom refers the interested reader to the ARM PrimeCell UART (PL011) Revision r1p5 Technical Reference Manual for more information. Table 11-6. UART0 Pins Function GPIO P1/P5 ALT Direction Description TXD 14 P1-08 0 Out DTE transmitted data RXD 15 P1-10 0 In DTE received data RTS 17 P1-11 3 Out Request to send CTS 30 P5-05 3 In Clear to send 98 Chapter 11 ■ UART RTS/CTS Access Hardware flow controls CTS and RTS are available on GPIO 30 and 17, respectively, when configured. By default these are GPIO inputs, but this can be changed. To gain access to the UART’s CTS and RTS signals, configure GPIO 30 and 17 to alternate function 3. Table 11-6 summarizes the connections that are used by the UART. The following short C program shows how to gain access to these signals. The listing for the included source file gpio_io.c is given in the “Direct Register Access” section of Chapter 12. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /********************************************************************* * rtscts.c Configure GPIO 17 & 30 for RTS & CTS *********************************************************************/ #include #include #include #include #include #include #include #include ; eol2 =#include "gpio_io.c" /*GPIO routines */ static inline void gpio_setalt(intgpio, unsigned alt) { INP_GPIO(gpio); SET_GPIO_ALT(gpio, alt); } int main(int argc, char **argv) { gpio_init(); gpio_setalt(17, 3); gpio_setalt(30, 3); return 0; /*Initialize GPIO access */ /*GPIO 17 ALT = 3 */ /*GPIO 3 0 ALT = 3 */ } /*End rtscts.c */ PL011 UART Features The Broadcom BCM2835 ARM Peripherals manual states that the following features are unsupported: • No Infrared Data Association (IrDA) support • No Serial InfraRed (SIR) protocol encoder/decoder (endec) • No direct memory access (DMA) • No support for signals DCD, DSR, DTR, and RI 99 Chapter 11 ■ UART The following features are supported, however: • Separate 16×8 transmit and 16×12 receive FIFO buffers • Programmable baud rate generator • False start-bit detection • Line-break generation and detection • Support of control functions CTS and RTS • Programmable hardware flow control • Fully programmable serial interface characteristics: • Data can be 5, 6, 7, or 8 bits. • Even, odd, mark, space, or no-parity bit generation and detection. • 1 or 2 stop-bit generation. • Baud rate generation, DC up to UARTCLK/16. Broadcom also states that there are some differences between its implementation of the UART and the 16C650 UART. But these are mostly device driver details: • Receive FIFO trigger levels are 1/8, 1/4, 1/2, 3/4, and 7/8. • Transmit FIFO trigger levels are 1/8, 1/4, 1/2, 3/4, and 7/8. • The internal register map address space and the bit function of each register differ. • 1.5 stop bits is not supported. • No independent receive clock. The only real concern to the application developer is that the 1.5 stop-bits configuration option is not available, which is rarely used these days anyway. If you need the RS-232 DCD, DSR, DTR, and RI signals, these can be implemented using GPIO input and output pins (along with the appropriate RS-232 line-level shifters). These are relatively slow-changing signals, which can easily be handled in user space. The one limitation of this approach, however, is that the hang-up TTY controls provided by the device driver will be absent. To change that, the device driver source code could be modified to support these signals using GPIO. The Raspbian Linux module of interest for this is as follows: drivers/tty/serial/amba-pl011.c Exclusive Serial Line Use As outlined in Chapter 19’s “Available Consoles” section, the serial device /dev/ttyAMA0 is easily applied as a serial console device. However, some Raspberry Pi application developers will want to use that serial interface for application purposes, instead of a console. Without taking measures for exclusive access, the console will write to your serial peripheral and respond to its input as well (as root console commands). Even if you turned off the console, there can still be unwanted interaction from a login prompt. 100 Chapter 11 ■ UART Procedure Use the following steps to configure exclusive serial port access: 1. Eliminate console references to console=ttyAMA0,... in the files: a. /boot/cmline.txt b. /boot/config.txt (check option cmdline="...") 2. Eliminate the kernel debugging option kgdboc=ttyAMA0,... as outlined for the console in step 1. 3. Eliminate the login prompt caused by the /etc/inittab entry. Look for ttyAMA0 and comment the line out. The line will look something like T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100. With these steps accomplished, reboot. The device /dev/ttyAMA0 should be available exclusively for your application to use. Verification To check that /etc/inittab has not launched a getty process, use the following after rebooting: $ ps aux | grep ttyAMA0 No entries should appear. To check that you have eliminated all kernel console references to the device, you can use the following: $ grep ttyAMA0 /proc/cmdline Serial API The Linux operating system provides access to serial port functions through a family of system and library calls. Most of these require that you have an open file descriptor for the serial device driver being used. For the Raspberry Pi, this will usually be the device /dev/ttyAMA0. Full information can be had from these man pages: • tcgetattr(3) • tty_ioctl(4)–ioctl(2) equivalents to tcgetattr(3) The bulk of the developer work for serial ports is configuration of the serial driver: • Physical characteristics: baud rate, data bits, parity, and stop bits • Driver processing characteristics: raw or cooked mode, for example Once the driver is configured, the software developer is able to use the usual read(2)/readv(2), write(2)/ writev(2), select(2), or poll(2) system calls. For an example program using some of this API, see the “Software” section of Chapter 27. 101 Chapter 11 ■ UART Header Files Programs involved in altering TTY settings will want to include the following include files: #include #include open(2) Most of the serial operations in this section require an open file descriptor to the TTY device being used. For the Raspberry Pi UART, you’ll want to specify /dev/ttyAMA0. int fd; fd = open("/dev/ttyAMA0",O_RDWR); /* Open for reading and writing */ if ( fd < 0 ) { perror("Opening/dev/ttyAMA0"); You may need to take special measures to gain access to the device, since by default it will be protected. Note the permissions and user/group ownership: $ ls –l /dev/ttyAMA0 crw–rw---1 root tty 204, 64 Feb 9 13:12 /dev/ttyAMA0 struct termios Many of the serial port configuration options require the use of the structure termios: struct termios { tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; cc_t c_line; cc_t c_cc[NCCS]; speed_t c_ispeed; speed_t c_ospeed; }; /* /* /* /* /* /* /* /* input mode flags */ output mode flags */ control mode flags */ local mode flags */ line discipline */ control characters */ input speed */ output speed */ The tables in the following sections describe the C language macros used for the members of the termios structure: 102 • Table 11-7 lists the macros for member c_iflag. • Table 11-8 lists the macros for member c_oflag. • Table 11-9 lists the macros for member c_cflag. • Table 11-10 lists the macros for member c_lflag. • Table 11-11 lists the macros for member c_cc. Chapter 11 ■ UART Table 11-7. Input (c_iflag) Flags Flag Set Description Flag Description BRKINT T Break causes SIGINT else 0x00 ISTRIP Strip off eighth bit F Break reads as 0x00 INLCR Translate NL to CR IXANY Any character will resume IUTF8 Input is UTF8 charset IXOFF Enable input XON/XOFF ICRNL Translate CR to NL IXON Enable output XON/XOFF IGNBRK Ignore break IGNPAR Ignore framing and parity errors IGNCR Ignore CR IUCLC Translate uppercase to lowercase INPCK Enable parity checking PARMRK T Prefix framing/parity error with \377 F Don’t prefix with \377 (byte reads 0) Table 11-8. Output (c_oflag) Flags Flag Description Flag Description CR0 CR delay mask 0 OFDEL Fill character is DEL else NUL CR1 CR delay mask 1 OFILL Use fill characters instead of timed delay CR2 CR delay mask 2 OLCUC Translate lowercase to uppercase CR3 CR delay mask 3 ONLCR Translate NL to CR-NL CRDLY CR delay: apply CR0-CR3 ONLRET Don’t output CR FF0 FF delay mask 0 ONOCR Don’t output CR at column 0 FF1 FF delay mask 1 OPOST Enable output processing FFDLY FF delay: apply FF0-FF1 TAB0 Tab delay mask 0 NL0 NL delay mask 0 TAB1 Tab delay mask 1 NL1 NL delay mask 1 TAB2 Tab delay mask 1 NLDLY NL delay: apply NL0-NL1 TAB3 Tab delay mask 2 OCRNL Translate CR to NL TABDLY Tab delay: apply TAB0-TAB3 103 Chapter 11 ■ UART Table 11-9. Control (c_cflag) Flags Flag Baud Flag Baud Flag Description B0 Hang-up B115200 115,200 CLOCAL Ignore modem controls B50 50 B230400 230,400 CMSPAR Stick parity B75 75 B460800 460,800 CREAD Enable receiver B110 110 B500000 500,000 CRTSCTS Enable RTS/CTS flow B134 134 B576000 576,000 CS5 5 data bits B150 150 B921600 921,600 CS6 6 data bits B200 200 B1000000 1,000,000 CS7 7 data bits B300 300 B1152000 1,152,000 CS8 8 data bits B600 600 B1500000 1,500,000 CSIZE Data bits mask B1200 1,200 B2000000 2,000,000 CSTOPB 2 stop bits (else 1) B1800 1,800 B2500000 2,500,000 HUPCL Modem control hang-up B2400 2,400 B3000000 3,000,000 PARENB Enable parity B4800 4,800 B3500000 3,500,000 PARODD Odd or stick = 1 parity B9600 9,600 B4000000 4,000,000 CBAUD Rate mask B19200 19,200 CBAUDEX Extended mask B38400 38,400 CIBAUD Input rate mask B57600 57,600 EXTA External A EXTB External B Table 11-10. Local (c_lflag) Flags Flag Description Flag Description ECHOCTL Echo controls as ^X ECHO Echo input IEXTEN Enable input processing ECHOE Erase previous char PENDIN Reprint upon reading ECHOK Erase line on kill ECHOKE Erase each char on kill ISIG Generate signals ECHONL Echo NL even if !ECHO NOFLSH No flush on signal ECHOPRT Print chars during erase TOSTOP Send SIGTTOU ICANON Enable canonical mode XCASE Terminal is uppercase 104 Chapter 11 ■ UART Table 11-11. Special (c_cc) Characters Macro Description Macro Description VEOF End-file (^D) VQUIT Quit (^\) VEOL End line (NUL) VREPRINT Reprint (^R) VEOL2 End line 2 VSTART XON (^Q) VERASE Erase (^H) VSTOP XOFF (^S) VINTR Interrupt (^C) VSUSP Suspend (^Z) VKILL Kill (^U) VTIME Time-out decsecs VLNEXT Literal next (^V) VWERASE Word erase (^W) VMIN Min chars to read tcgetattr(3) Before you make changes to the serial port settings, you will want to retrieve the current settings in case you later need to restore them. This also greatly simplifies configuration, allowing you to change only the settings that need changing. Use the tcgetattr(3) function to fetch the current serial device settings: int tcgetattr(int fd, struct termios *termios_p); where fd is the open TTY file descriptor. termios_p is the struct to be filled with current setting information. struct termios term; int rc; rc = tcgetattr(fd,&term); if ( rc < 0 ) { perror("tcgetattr(3)"); tcsetattr(3) When the termios structure has been defined with the serial parameters you wish to use, the tcsetattr(3) call is used to set them in the device driver: int tcsetattr( int fd, int optional_actions, const struct termios *termios_p ); where fd is the open TTY file descriptor to change. optional_actions is one of three actions (listed in the following table). termios_p is a pointer to the new settings to be applied. 105 Chapter 11 ■ UART The three choices for optional_actions are as follows: optional_actions Meaning TCSANOW The change occurs immediately. TCSADRAIN Change occurs after all output has been sent. TCSAFLUSH As TCSADRAIN, but pending input is discarded. The following shows an example of use: struct termios term; int rc; ... rc = tcsetattr(fd,TCSADRAIN,&term); if ( rc < 0 ) { perror("tcsetattr(3)"); tcsendbreak(3) A break signal can be transmitted to the remote end by calling the tcsendbreak(3) function: int tcsendbreak(int fd, int duration); where fd is the open TTY file descriptor. duration is the amount of time to use to represent a break. When the argument duration is zero, it sends a break signal lasting between 0.25 and 0.5 seconds. When the argument is nonzero, the man page states that some implementation-defined amount of time is used instead. int rc; rc = tcsendbreak(fd,0); if ( rc < 0 ) { perror("tcsendbreak(3)"); tcdrain(3) The function tcdrain(3) can be used to block the execution of the calling program until all of the output characters have been transmitted out of the UART: int tcdrain(int fd); where fd is the open TTY file descriptor. An example follows: int rc; rc = tcdrain(fd); if ( rc < 0 ) { perror("tcdrain(3)"); 106 Chapter 11 ■ UART tcflush(3) The tcflush(3) call can be used to flush pending input or output data from the serial port buffers. int tcflush(int fd, int queue_selector); where fd is the open TTY file descriptor. queue_selector determines which queue(s) are to be flushed. The following values are used for the queue_selector argument: queue_selector Description TCIFLUSH Flushes unread incoming data TCOFLUSH Flushes untransmitted output data TCIOFLUSH Flushes both unread and untransmitted data The following example flushes pending input data: int rc; rc = tcflush(fd,TCIFLUSH); tcflow(3) Various flow control operations can be performed by calling the tcflow(3) function: int tcflow(int fd, int action); where fd is the open TTY file descriptor. action is the flow control action required (as shown in the following table). The valid choices for action are as follows: action Description TCOOFF Suspends output (transmission stops) TCOON Resumes output TCIOFF Immediately sends a STOP character to stop the remote device TCION Transmits a START character to resume the remote device The following example shows the program immediately suspending output: int rc; rc = tcflow(fd,TCOOFF); if ( rc < 0 ) { perror("tcflow (3)"); 107 Chapter 11 ■ UART cfmakeraw(3) The cfmakeraw(3) function is a convenience routine to establish raw mode, where no special data conversions or mappings occur. The caller should first call upon tcgetattr(3) to define the initial termios structure settings. Then cfmakeraw(3) can be used to adjust those settings for raw mode: void cfmakeraw(struct termios *termios_p); where termios_p is a pointer to a struct populated with the serial device’s current settings, to be altered. Note that no file descriptor is provided since this function doesn’t actually change anything beyond the data structure that was passed to it. After calling cfmakeraw(3), the user will need to use cfsetattr(3) to inform the driver of the changes. struct termios term; int rc; rc = cfgetattr(fd,&term); /*Get settings */ cfmakeraw(&term); /* Alter settings for raw mode */ rc = tcsetattr(fd,TCSADRAIN,&term); /* Apply the settings */ Calling cfmakeraw(3) is equivalent to manually applying the following changes: struct termios term; ... term.c_iflag &= ~(IGNBRK | INLCR term.c_oflag &= ~OPOST; term.c_lflag &= ~(ECHO term.c_cflag &= ~(CSIZE term.c_cflag |=CS8; | BRKINT | PARMRK | ISTRIP | IGNCR | ICRNL | IXON); | ECHONL | ICANON | ISIG | IEXTEN); | PARENB); This is a good place to pause and discuss what raw mode is. There are two forms of serial I/O supported by Linux (and Unix generally): Cooked mode: The input, output, and echoing functions are modified/performed by the kernel. Raw mode: The input/output data is sent to/from the application unchanged by the kernel. The serial port developer, wishing to communicate with a serial device or AVR class microcontroller, will be very interested in raw mode. Using raw mode, the data you transmit is sent unmodified to its destination. Likewise, the data received is received as it was originally transmitted. Cooked mode, which is the norm, is a very different beast. The original purpose of serial lines for Unix was the handling of user interaction using terminal I/O (this is still true for the serial port console). Many terminal processing functions were considered common enough among applications to centralize them in the kernel. This saved the application from having to deal with these physical aspects and lead to consistency in their handling. This terminal handling is affectionately known as cooked mode. The main areas of cooked mode processing are as follows: Input processing: The type of kernel processing performed on serial input data (like backspace processing) Output processing: The type of kernel processing performed on serial output data (like converting a sent line feed into a carriage return and line-feed pair) Local processing: Involving input and output, processing features such as echo Control processing: Other serial controls 108 Chapter 11 ■ UART We can get a sense of how raw mode differs from cooked mode by looking at what cfmakeraw(3) changes. Looking at term.c_iflag &= ~ (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); we see that the following input processing features are disabled: Flag Description Setting IGNBRK Ignore break Disabled BRKINT Break reads as 0x00 Disabled PARMRK Don’t prefix with \377 (byte reads 0) Disabled ISTRIP Strip off eighth bit Disabled INLCR Translate NL to CR Disabled IGNCR Ignore CR Disabled ICRNL Translate CR to NL Disabled IXON Enable output XON/XOFF Disabled Disabling ISTRIP prevents the kernel from stripping the high-order bit in the byte. Disabling INLCR, ICRNL prevents the substitution of NL or CR characters (for input). Disabling IGNCR prevents the kernel from deleting the CR character from the input stream. Disabling IXON disables software flow control so that the characters XON and XOFF can be read by the application program. Looking at the output processing changes, term.c_oflag &= ~OPOST; we see that the following change applies: Flag Description Setting OPOST Enable output processing Disabled This disables all output processing features with one flag. Local processing includes both input and output. The following local processing flags are changed: term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG| IEXTEN); From this, we see that these local processing features are disabled: Flag Description Setting ECHO Echo input Disabled ECHONL Echo NL even if !ECHO Disabled ICANON Enable canonical mode Disabled ISIG Generate signals Disabled IEXTEN Enable input processing Disabled 109 Chapter 11 ■ UART Disabling ICANON means that all special nonsignal characters defined in c_cc are disregarded (like VERASE). Disabling ISIG means that there will be no signals sent to your application for characters like VINTR. Disabling IEXTEN disables other c_cc character processing like VEOL2, VLNEXT, VREPRINT, VWERASE, and the IUCLC flag. Disabling ECHO and ECHONL disables two aspects of character echoing. Finally, the following control aspects are changed: term.c_cflag &= ~ (CSIZE | PARENB); term.c_cflag |= CS8; meaning that: Flag Description Setting CSIZE Data bits mask Masked-out data bits PARENB Generate/detect parity Disabled CS8 8 data bits Set to 8-bit data The CSIZE masking is used to reset the data bits field to zeros. This allows the CS8 bit pattern to be or-ed in later, setting the data bits value to 8 bits. Disabling the PARENB flag causes parity generation on output to be disabled, and disables parity checking on input. If your raw link requires parity generation and checking, you’ll need to undo this particular change in your own code. You can see from this list that a plethora of special processing is altered to go from cooked mode to raw mode. It is no wonder that this support routine was made available. cfgetispeed(3) The current input baud rate for the line can be queried by the cfgetispeed(3) function: speed_t cfgetispeed(const struct termios *termios_p); where termios_p is the pointer to the structure containing the terminal configuration. Because the termios structure has been extended and modified over the years, this function provides a more portable way to extract the input baud rate, including the more recently added higher baud rates. struct termios term; speed_t baud_rate; baud_rate = cfgetispeed(&term); cfgetospeed(3) The current output baud rate can be extracted from the termios structure with speed_t cfgetospeed(const struct termios *termios_p); where termios_p is the pointer to the structure containing the terminal configuration. Because the termios structure has been extended and modified over the years, this function provides a portable way to extract the output baud rate, including the more recently added higher baud rates. 110 Chapter 11 ■ UART cfsetispeed(3) The cfsetispeed(3) function permits a portable way to establish an input baud rate in the termios structure: int cfsetispeed(struct termios *termios_p, speed_t speed); where termios_p is the pointer to the TTY configuration structure to be modified. speed is the input baud rate to apply. Note that this function only updates the termios data structure and has no direct effect on the device being used. struct termios term; int rc; rc = cfsetispeed(&term,115200); if ( rc < 0 ) { perror("cfsetispeed(3)"); cfsetospeed(3) The cfsetospeed(3) function sets the output baud rate in the termios structure: int cfsetospeed(struct termios *termios_p, speed_t speed); where termios_p is the pointer to the TTY configuration structure being modified. speed is the output baud rate to apply. Note that this function only updates the termios data structure with no direct effect on the device being used. struct termios term; int rc; rc = cfsetospeed(&term,9600); if ( rc < 0 ) { perror(“cfsetospeed(3)"); cfsetspeed(3) Most serial communication uses a common baud rate for transmitting and receiving. For this reason, this is the preferred function to invoke for establishing both the input and output baud rates: int cfsetspeed(struct termios *termios_p, speed_t speed); where termios_p is the pointer to the TTY configuration structure to be modified. speed is the input and output baud rate to apply. Note that this function only updates the termios data structure with no direct effect on the device being used. 111 Chapter 11 ■ UART struct termios term; int rc; rc = cfsetspeed(&term,9600); if ( rc < 0 ) { perror("cfsetsspeed(3)"); read(2) The read(2) system call can be used for reading from the serial port, in addition to normal Linux files and other devices: #include ssize_t read(int fd, void *buf, size_t count); where fd is the open file descriptor to read from. buf is the buffer to read the data into. count is the maximum number of bytes to read. returns an int, where -1 indicates an error, with the error code found in errno. 0 indicates that the serial port has been closed with the end-of-file character. >0 indicates the number of bytes read. The errors that pertain to blocking calls on a serial port include the following: Error Description EBADF fd is not a valid file descriptor. EFAULT buf is outside your accessible address space. EINTR The call was interrupted by a signal before any data was read. More will be said about EINTR near the end of this chapter. The following example reads up to 256 bytes into the array buf, from the serial port open on the file unit fd: int fd; char buf[256]; int rc; /*Opened serial port */ rc = read(fd,buf,sizeof buf); if ( rc < 0 ) { fprintf(stderr,"%s: reading serial port.\n",strerror(errno)); ... } else if ( !rc ) { /*End file */ } else { /*Process rc bytes in buf[] */ } 112 Chapter 11 ■ UART write(2) To transmit data on a serial link, you can use the write(2) system call: #include ssize_t write(int fd, const void *buf, size_t count); where fd is the file unit of the opened serial port. buf is the buffer containing the bytes to be transmitted. count is the number of bytes to transmit. returns an int, where -1 indicates that an error has occurred, with the error found in errno. 0 indicates no bytes were transmitted (end-of-file, port was closed). >0 indicates the number of bytes transmitted. The possible errors related to blocking calls for serial port writes include the following: Error Description EBADF fd is not a valid file descriptor or is not open for writing. EFAULT buf is outside your accessible address space. EINTR The call was interrupted by a signal before any data was written. Normally, only an error (-1) or a value of count is returned. If the serial port was opened for nonblocking I/O, the returned count can be less than the requested count (this mode of operation is not discussed here). In blocking mode (which we are assuming here), the call will return only when the full count requested has been written. Any failure would otherwise result in an error being returned instead. The following is an example of its use, as it pertains to a serial port: int fd; char buf[256]; int rc, n; strcpy(buf,"Hello World!\n"); n = strlen(buf); rc = write(fd,buf,n); if ( rc < 0 ) { fprintf(stderr,"%s: writing serial link.\n",strerror(errno)); ... } assert(rc == n); readv(2) and writev(2) An often neglected option for reading and writing are the readv(2) and writev(2) system calls. These tend to be more useful for programs that work with packets than for interactive terminal sessions. These are presented because the serial port application developer may want to use a protocol that has more than one buffer containing 113 Chapter 11 ■ UART headers, data, and trailer. Using the scatter-gather routines can enhance your code communicating with an AVR class microcontroller. The use of an I/O vector here is similar in concept to the I/O vectors used by I2C I/O operations in the ioctl(2,I2C_RDWR) system call (see Chapter 14). #include ssize_t readv(int fd, const struct iovec *iov, int iovcnt); ssize_t writev(int fd, const struct iovec *iov, int iovcnt); where fd is the open serial port file descriptor for reading/writing. iov is the I/O vector directing the reading/writing. iovcnt is the I/O vector count. returns an int, where -1 indicates an error, leaving the error code in errno, see read(2) or write(2). 0 indicates that an end-of-file condition occurred. >n indicates the actual number of bytes read/written. The I/O vector is shown here: struct iovec { void *iov _base; size_t iov_len; }; /*Starting address */ /*Number of bytes to transfer */ In the following example, a simple terminal writev(2) system call is used to piece together three pieces of information, to be transmitted to the terminal: • The text Hello • The person’s name provided in the argument name • The text !\n\r at the end One of the advantages of the writev(2) call is its ability to take separate buffers of data and transmit them as a whole in one I/O operation: void fun(int serport, const char *name) { struct iovec iov[3]; int rc; iov[0].iov_base = "Hello"; iov[0].iov_len = 6; iov[1].iov_base = (void *)name; iov[1].iov_len = strlen(name); iov[2].iov_base = "!\n\r"; iov[2].iov_len = 3; rc = writev(serport,iov,3); if ( rc < 0 ) { fprintf(stderr,"%s: writev(2)\n",strerror(errno)); abort(); } } 114 Chapter 11 ■ UART Each segment to be transmitted is described by one iov[x] member, each consisting of a buffer pointer and the number of bytes. The writev(2) system call is told how many iov[] entries to use in its third calling argument. Error EINTR One error code that afflicts many device I/O system calls is the EINTR error, “Interrupted system call.” This error code applies to read(2), readv(2), write(2), and writev(2) on devices that may “block” execution until the required data has been fully read/written. (This also applies to ioctl(2) when I2C I/O is performed.) The EINTR error is not returned for I/O to disk because these I/O calls don’t block for a long time (the I/O is to/from a file system disk memory buffer). The application developer should otherwise plan on handling this error. The EINTR error is the Unix way of working with signals. Consider what happens when your application is waiting for a single keystroke from the user at a terminal (or reading a packet from an AVR class device): rc = read(fd,buf,n); /*Block until n bytes read */ Until that read is satisfied (or the file descriptor is closed), execution will stop there. In the meantime, another process or thread may signal your application to do something, perhaps to shut down and exit. A signal handler like the following is invoked when the signal is handled: static void sigint_handler(int signo) { is_signaled = 1; /*Please exit this program */ } At this point, your application is in the middle of a system call, waiting to read from the serial port. The system call’s registers are saved on the stack frame, and your application has entered into the kernel. The handling of the signal means that the kernel calls your signal handler, placing another stack frame on your current stack. Because a signal can arrive at any time, there are many things you can’t do from within a signal handler. For example, you must not invoke malloc(3) or other non-reentrant functions. Otherwise, you risk doing another malloc(3) inside an interrupted malloc(3), which leads to disaster. The important point here is that a very limited number of safe things can be performed from inside a signal handler. One thing that is safe to do in a signal handler is to set a global variable of some kind, like the is_signaled variable in the example. One problem remains: how does the code blocked in the read(2) call respond to this notification? When the signal handler returns, the application will continue to block trying to read from the serial port. The Unix solution to this problem is to have the kernel return an error code EINTR after a signal handler receives a signal. In this manner, the read(2) call returns an error, allowing the application program to test whether it received a signal. The following code shows how the simple read(2) call is replaced with a loop that checks whether the signal handler was called: do { rc = read(fd, buf, n); /*Block until n bytes read */ if ( is_signaled ) longjmp(shutdown,1); /*Shutdown this server */ } while ( rc == –1 && errno == EINTR ); if ( rc == –1 ) { /*Check for non EINTR errors */ fprintf(stderr,"%s: read(2)\n",strerror(errno)); abort(); } 115 Chapter 11 ■ UART In this code snippet, we see that the read(2) call is performed as part of a loop. As long as an error is returned and the errno value is EINTR, we check for any interesting events (like is_signaled) and repeat the call. If any other type of error occurs or we succeed, we drop out of the loop. This is the basic template that should be used for any call that might receive EINTR, even if you don’t plan to handle signals in your application. Otherwise, you may find that your Pi application may run for weeks and then one day when you least expect it, fail because of a received EINTR error. 116 Chapter 12 GPIO General-purpose I/O is a topic near to the hearts of Raspberry Pi owners, because this is the interface to the outside world. The BCM2835 is flexibly designed to allow I/O pins to be reconfigured under software control. GPIO 14 can be an input, an output, or operate as a serial port TX data line, for example. This makes the Raspberry Pi very adaptable. One of the challenges related to the Pi’s GPIO interface is that it uses a weak CMOS 3 V interface. The GPIO pins are susceptible to static electricity damage, and the I/O pins are weak drivers (2 to 16 mA). Additionally, GPIO power must be budgeted from the total spare current capacity of 50 mA. Using adapter boards overcomes these problems but adds considerably to the cost. This then provides a fertile area for coming up with cheap and effective roll-your-own solutions. Pins and Designations Figures 12-1 and 12-2 show the schematic GPIO connections for the Raspberry Pi. You will notice that the GPIO pins are also designated with the GENx designation. (Gen 7 to 10 was not available prior to version 2.) This may have been an early attempt to follow the Arduino lead of naming their pins digital0 or analog4, for example, in a generic way. It appears, however, that this naming convention has not really caught on among Pi users. Despite this, these names are cross-referenced in Table 12-1. These are probably the preferred first choices when shopping for GPIO pins to use, since they are less likely to be required for special (alternate) functions like UART or SPI. 117 Chapter 12 ■ GPIO Figure 12-1. GPIO P1 header Table 12-1. Rev 2.0 GEN and GPIO Designations GENx GPIOy Header GEN0 GPIO 17 P1-11 GEN1 GPIO 18 P1-12 GEN2 GPIO 27 P1-13 GEN3 GPIO 22 P1-15 GEN4 GPIO 23 P1-16 GEN5 GPIO 24 P1-18 GEN6 GPIO 25 P1-22 GEN7 GPIO 28 P5-03 GEN8 GPIO 29 P5-04 GEN9 GPIO 30 P5-05 GEN10 GPIO 31 P5-06 118 Chapter 12 ■ GPIO A couple of GPIO pins have pull-up resistors. Figure 12-1 shows that GPIO pins 2 (SDA1) on P1-03, and GPIO 3 (SCL1) on P1-05, have an 1.8 kΩ pull-up resistor. This should be taken into account if you use these for something other than I2C. The layouts of headers P1 and P5, where the GPIO pins are made accessible, are documented in Chapter 5. ■■Note P5 was not present prior to version 2, but both Models A and B now include it (without header pins). Configuration After Reset Upon reset, most GPIO pins are configured as general-purpose inputs with the exceptions noted in Table 12-2. (Figure 12-2 applies to version 2, Models A and B.) The Pull-up column indicates how the internal pull-up resistor is initially configured. The pull-up resistors apply when the GPIO is configured as an input pin. Table 12-2. Rev 2.0 Configuration After Reset GPIO Pull-up Config ALT 0 High Input 1 High Input 2 High SDA1 0 3 High SCL1 0 4 High Input 5 High GPCLK1 6 High Output 7 High Input 8 High Input 9 Low Input 10 Low Input 11 Low Input 14 Low TXD0 0 15 Low RXD0 0 16 Low Output 17 Low Input 18 Low Input 21 Low Input 22 Low Input 23 Low Input 24 Low Input 0 (continued) 119 Chapter 12 ■ GPIO Table 12-2. (continued) GPIO Pull-up Config ALT 25 Low Input 27 Low Output 28 - Input 29 - Input 30 Low Input 31 Low Input 40 Low PWM0 0 45 - PWM1 0 Figure 12-2. GPIO P5 header Pull-up Resistors As noted earlier, GPIO pins 2 and 3 have an external resistor tied to the +3.3 V rail. The remaining GPIO pins are pulled high or low by an internal 50 kΩ resistor in the SoC.56, 48 The internal pull-up resistor is rather weak, and effective at only giving an unconnected GPIO input a defined state. A CMOS input should not be allowed to float midway between its logic, high or low. When pull-up resistance is needed for an external circuit, it is probably best to provide an external pull-up resistor, rather than rely on the weak internal one. Configuring Pull-up Resistors The pull-up configuration of a GPIO pin can be configured using the SoC registers GPPUP and GPPUDCLK0/1. (The “Physical Memory” section of Chapter 6 has the physical addresses for these registers.) 120 Chapter 12 ■ GPIO The GPPUP register is laid out as follows: Bits Field 31-2 - 1-0 PUD GPPUP Register Description Type Reset Unused GPIO pin pull-up/down R 0 00 01 10 11 R/W 0 Off—disable pull-up/down Pull-down enable Pull-up enable Reserved The GPPUDCLK0 register is laid out as follows: Bits Field GPPUDCLK0 Register Description 31-0 PUDCLKn n = 0..31 Type Reset R/W 0 0 No effect 1 Assert clock Finally, the GPPUDCLK1 register is formatted this way: Bits Field GPPUDCLK1 Register Description 31-22 - Reserved R 0 21-0 PUDCLKn n = 32..53 R/W 0 Type Reset 0 No effect 1 Assert clock According to the Broadcom documentation, the general procedure for programming the pull-up resistor is this: 1. Write the pull-up configuration desired in the rightmost 2 bits of the 32-bit GPPUP register. The configuration choices are as follows: 00: Disable pull-up control. 01: Enable pull-down control. 10: Enable pull-up control. 2. Wait 150 cycles to allow the preceding write to be registered. 3. Write a 1-bit to every GPIO position, in the group of 32 GPIO pins being configured. GPIOs 0–31 are configured by register GPPUDCLK0. 4. Wait another 150 cycles to allow step 3 to register. 5. Write 00 to GPPUP to remove the control signal. 121 Chapter 12 ■ GPIO 6. Wait another 150 cycles to allow step 5 to register. 7. Finally, write to GPPUDCLK0/1 to remove the clock. The Broadcom procedure may seem confusing because of the word clock. Writing to GPPUP and GPPUDCLK0/1 registers by using the preceding procedure is designed to provide a pulse to the internal pull-up resistor flip-flops (their data clock input). First a state is established in step 1, and then the configured 1 bits are clocked high in step 3 (for selected GPIO pins). Step 5 establishes a zero state, which is then sent to the flip-flop clock inputs in step 7. The documentation also states that the current settings for the pull-up drivers cannot be read. This makes sense when you consider that the state is held by these internal flip-flops that were changed by the procedure. (There is no register access available to read these flip-flops.) Fortunately, when configuring the state of a particular GPIO pin, you change only the pins you select by the GPPUDCLK0/1 register. The others remain unchanged. The program pullup.c, shown next, provides a simple utility to change the pull-up resistor settings. The program listing for gpio_io.c is provided in the “Direct Register Access” section of Chapter 12. The source for timed_wait.c is found in the “Source Code” section of Chapter 25. After compiling, the following example changes the GPIO 7 pull-up to high and GPIO 8 to low: $ ./pullup 7=low 8=high 1 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2 ∗ pullup.c : Change the pull−up resistor setting for GPIO pin 3 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ 4 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 #include "gpio_io.c" /∗GPIO routines ∗/ 15 #include "timed_wait.c" /∗Delay ∗/ 16 17 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 18 ∗ 0x7E200094 GPPUD GPIO Pin Pull−up/down Enable 19 ∗ 0x7E200098 GPPUDCLK0 GPIO Pin Pull−up/down Enable Clock 0 20 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ 21 22 #define GPIO_GPPUD ∗(ugpio+37) 23 #define GPIO_GPPUDCLK0 ∗(ugpio+38) 24 25 static inline void 26 gpio_setpullup(int gpio, int pull) { 27 unsigned mask = 1 << gpio; /∗GPIOs 0 to 31 only ∗/ 28 unsigned pmask = pull >=0 ? ( 1 << !! pull) : 0; 29 30 GPIO_GPPUD = pmask ; /∗Select pull−up setting ∗/ 31 timed_wait (0, 500, 0) ; 32 GPIO_GPPUDCLK0 = mask ; /∗Set the GPIO of interest ∗/ 33 timed_wait (0, 500, 0) ; 34 GPIO_GPPUD = 0 ; /∗Reset pmask ∗/ 122 Chapter 12 ■ GPIO 35 timed_wait (0, 500, 0); 36 GPIO_GPPUDCLK0 = 0 ; /∗Set the GPIO of interest ∗/ 37 timed_wait (0, 500, 0); 38 } 39 40 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 41 ∗ Command line arguments are of the form ={low , high or none }, 42 ∗ for example : ./pull−up 7=high 8=low 43 ∗ 44 ∗ Only the first character of the argument after '=' is checked. 45 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ 46 int 47 main(int argc, char ∗∗argv) { 48 int x, gpio, p; 49 char arg [64]; 50 51 gpio_init(); 52 53 for ( x=1; x 31 ) { 62 fprintf (stderr,"%s : GPIO must be <= 31\n", 63 argv[x]) ; 64 return 1; 65 } 66 gpio_setpullup(gpio, p); 67 } 68 return 0; 69 70 errxit : fprintf (stderr,"Argument '%s ' must be in the form\n" 71 " = where arg is h, l or n.\ n", 72 argv [ x ] ) ; 73 return 1; 74 } 75 76 /∗End pullup.c ∗/ The default drive strengths after booting are listed next, along with the GPIO addresses for the corresponding GPIO pads: Address GPIO Pads Reset Drive Strength 0x2010002C GPIO 0 to 27 8 mA 0x20100030 GPIO 28 to 45 16 mA 0x20100034 GPIO 46 to 53 8 mA 123 Chapter 12 ■ GPIO Table 12-3 summarizes the GPIO Pads Control register. Note that to be successful setting values in this register, the field labeled PASSWRD must receive the value 0x5A. This is a simple measure to avoid having the values trashed by an accidental write to this location. Table 12-3. GPIO Pads Control Bits Field Description 31:24 PASSWRD 0x5A 23:05 Reserved 0x00 04:04 SLEW Slew rate 03:03 HYST 02:00 DRIVE I/O Reset Must be 0x5A when writing W 0x00 Write as zero, read as don’t care R/W 0 Slew rate limited R/W 1 1 Slew rate not limited R/W 1 R/W 3 Enable input hysterisis 0 Disabled 1 Enabled Drive strength 0 2 mA 1 4 mA 2 6 mA 3 8 mA (default except 28 to 45) 4 10 mA 5 12 mA 6 14 mA 7 16 mA (GPIO 28 to 45) Testing Pull-up State If you want to test the state of the pull-up resistors, the following procedure can be used: 1. Make sure no connection is attached so that the input can float. 2. Configure the GPIO pin as an input. 3. Configure the GPIO as active high (that is, not active low). 4. Read the input value. a. A reading of 1 means that the input was pulled high. b. A reading of 0 means that the input was pulled low. Note that GPIO pins 2 and 3 are pulled up by external resistors, while others may be connected to other circuits (GPIO 6). This will affect your readings for those pins. Note also that pins configured for alternate functions may be outputs and will be driven. 124 Chapter 12 ■ GPIO When the input GPIO is configured with no pull-up, you might see random values, but this is unreliable. An input voltage can float above or below a threshold and remain there for a time. The script presented in the “GPIO Input Test” section of Chapter 12 can be used to test a GPIO input (^C to exit the script). Logic Levels GPIO pins use 3 V logic levels. The precise BCM2835 SoC logic-level specifications are as follows: Parameter Volts Description VIL £ 0.8 Voltage, input low VIH ³ 1.3 Voltage, input high As we work through several projects in this book, we’ll be making frequent references to these parameters. You might want to commit these voltage levels to memory or mark the page with a tab. The voltage levels between VIL and VIH are considered to be ambiguous or undefined, and must be avoided. Drive Strength How much drive can a GPIO pin provide in terms of current drive? The design of the SoC is such that each GPIO pin can safely sink or source up to 16 mA without causing it harm.28 The drive strength is also software configurable from 2 mA up to 16 mA.29 The boot-up default is to use the drive strength of 8 mA.28 However, as our test program pads.c will show, the GPIO outputs 28 to 45 were found configured for 16 mA (GPIO 28 to 31 are available on header P5). Table 12-3 shows the SoC registers for reading and configuring the drive strength of the GPIO pins. There are three registers, affecting GPIO pins in three groups of 28 (two groups affect user-accessible GPIOs). The slew rate, hysteresis, and drive strength settings all apply at the group level. The drive strength is configured through a 3-bit value from 2 mA to 16 mA, in increments of 2 mA. When writing to these registers, the field PASSWRD must contain the hexadecimal value 0x5A, as a guard against accidental changes. To visualize how the Raspberry Pi controls drive strength, examine Figure 12-3. The control lines Drive0 through Drive2 are enabled by bits in the DRIVE register. With these three control lines disabled (zero), only the bottom 2 mA amplifier is active (this amplifier is always enabled for outputs). This represents the weakest drive-strength setting. 125 Chapter 12 ■ GPIO Figure 12-3. Drive-strength control With Drive0 set to a 1, the top amplifier is enabled, adding another 2 mA of drive, for a total of 4 mA. Enabling Drive1 adds a further 4 mA of drive, totaling 8 mA. Enabling Drive2 brings the total drive capability to 16 mA. It should be mentioned that these drive capabilities are not current limiters in any way. What they do is apply more amplifier drive in order to meet the logic-level requirements (next section). If the GPIO output is wired up to a light load like a CMOS chip or MOSFET transistor where little current is drawn, then the minimum drive of 2 mA suffices. The single GPIO 2 mA buffer can effortlessly establish a logic high in its proper voltage range as well as bring the voltage to a logic low when required. When the GPIO output is loaded with a higher current load, the single 2 mA buffer may not be enough to keep the logic level within spec. By applying more amplifier drive, the output voltage levels are coerced into the correct operating range. Input Pins A GPIO input pin should experience voltages only between 0 and the 3.3 V maximum. Always exercise caution when interfacing to other circuits that use higher voltages like TTL logic, where 5 V is used. The SoC is not tolerant of overvoltages and can be damaged. While there exist protection diodes for protecting against negative input swings, these are weak and intended only to bleed away negative static charges. Be sure to design your input circuits so that the GPIO input never sees a negative input potential. 126 Chapter 12 ■ GPIO Output Pins As an output GPIO pin, the user bears full responsibility for current limiting. There is no current limiting provided. When the output pin is in the high state, as a voltage source, it tries to supply 3.3 V (within the limits of the transistor). If this output is shorted to ground (worst case), then as much current as can be supplied will flow. This will lead to permanent damage. The outputs also work to the specifications listed earlier, but the attached load can skew the operating voltage range. An output pin can source or sink current. The amount of current required and the amount of output drive configured alters the operating voltage profile. As long as you keep within the current limits for the configured drive capability, the voltage specifications should be met. Figure 12-4 illustrates how a GPIO port sources current into its load (Rload). Current flows from the +3.3 V supply, through transistor M1, out the GPIO pin, and into Rload to ground. Because of this, it takes a high (logic 1) to send current into the load. This makes the circuit an “active high” configuration. Figure 12-4. GPIO output high Figure 12-5 shows how the GPIO output sinks current instead. Because Rload is connected to the +3.3 V supply, current flows through Rload, into the GPIO output pin, and through the bottom transistor M2 to ground. To send current through the load, a low (logic 0) is written to the output port. This is the active low configuration. 127 Chapter 12 ■ GPIO Figure 12-5. GPIO output low Figure 12-6 shows the active high configuration’s Rload circuit element substituted with an LED and limiting resistor R. Since there is no current limiting provided by the GPIO port, resistor R must be provided to do this. Figure 12-6. GPIO driving an LED 128 Chapter 12 ■ GPIO Driving LEDs When an LED is hooked up to the GPIO output port, Rload becomes the LED and the limiting resistor (in series). The math is complicated slightly by the fact that the LED is a diode. As a diode, it has a voltage drop, which should be subtracted from the supply voltage. For red LEDs, the voltage drop is usually between 1.63 and 2.03 V.30 Knowing the current draw you want for the LED, the resistor R can be calculated from the following: R= VCC – VLED I LED where VCC is the supply voltage (+3.3 V). VLED is the voltage drop for the LED. ILED is the required current draw for the LED. For VLED it is best to assume the worst case and assume the lower voltage drop of 1.63 V. Assuming we need 8 mA to get reasonable brightness from the LED, we can calculate the resistance of the limiting resistor: 3.3 - 1.63 0.008 = 208.75W R= Since resistors come in standard values, we round up to a standard 10% component of 220 Ω. ■■Note Rounding resistance down would lead to higher current. It is better to err on the side of less current. The LED and the 220 Ω limiting resistor can be wired according to Figure 12-4 (and shown in Figure 12-6). When wired this way, a high is written to the GPIO output port to make current flow through the LED. The sense of the GPIO port can be altered by the sysfs file active_low (see Table 12-5 later in this chapter). Putting the GPIO pin 7 into active low mode reverses the logic sense, as follows: # echo 1 >/sys/class/gpio/gpio7/active_low With this mode in effect, writing a 1 to GPIO pin 7 causes the pin to go “low” on the output and causes the LED to go off: # echo 1 >/sys/class/gpio/gpio7/value If the LED was wired according to Figure 12-5, it would turn on instead. Driving Logic Interfaces For LEDs, the requirements of the interface are rather simple. The interface is a success if the LED is lit when the output port is in one state, and the LED is dark in the other. The precise voltage appearing at the GPIO output pin in these two states is of little concern, as long as the maximum current limits are respected. When interfacing to logic, the output voltage is critical. For the receiving logic, the output level must be at least VIH to reliably register a 1 bit (for the BCM2835, this is 1.3 V). Likewise, the output should present less than VIL to reliably register a 0 in the receiver (for the BCM2835, this is 0.8V). Any voltage level between these limits is ambiguous and can cause the receiver to randomly see a 0 or a 1. 129 Chapter 12 ■ GPIO There are a fairly large number of approaches to interfacing between different logic families. A good source of information is provided by the document “Microchip 3V Tips ’n Tricks.”31 Another document titled “Interfacing 3V and 5V Applications, AN240” describes the issues and challenges of interfacing between systems.32 It describes, for example, how a 5 V system can end up raising the 3 V supply voltage if precautions are not taken. Approaches to interfacing include direct connections (when safe), voltage-dividing resistors, diode resistor networks, and the more-complex op-amp comparators. When choosing an approach, remember to consider the necessary switching speed of the interface required. Driving Bi-color LEDs This is a good point to inject a note about driving bi-color LEDs. Some of these are configured so that one LED is forward biased while the other is reversed biased. This has the advantage of needing only the usual two LED leads. To change colors, you simply change the polarity of the power going into the pair. To drive these and choose a color, you need a way to reverse the current. This is normally done using the H-Bridge driver, which is explored in Chapter 28. There a bipolar stepper motor is driven by the H-Bridge driver. The LED, however, requires considerably less current, and so this is an easy assignment. If you choose a bi-color LED requiring 10 mA or less, you can drive it directly from a pair of GPIO outputs. Figure 12-7 illustrates the bi-color LED driving arrangement. Compare this configuration with the H-Bridge in Chapter 28’s Figure 28-1. Do you see the similarity? Figure 12-7. Driving a bi-colored LED The pair of GPIO outputs form an H-Bridge because each of the outputs themselves are a pair of CMOS driving transistors—an upper and lower half. It is this pairing that makes them capable of both sourcing and sinking a current. By using two GPIO outputs, you form an H-Bridge driver. To light the bi-color LED in one color, make one GPIO high (source), while the other is made low (sink). Then the current will flow through the LED from the first GPIO output into the second. To reverse the current and see the other color, make the first GPIO low and the other high. Now the current flows from the second GPIO output into the first. 130 Chapter 12 ■ GPIO Testing Drive Strength There’s nothing like finding out for yourself the configured parameters of your Raspberry Pi. The program pads.c (next) dumps out the GPIO Pads Control registers so that you can verify the actual parameters in effect. Each GPIO pin defaults to setting 3 (for 8 mA).28 Running the pads.c program on my Rev 2.0 Raspberry Pi showed that the GPIO group from 28 to 45 was configured for 16 mA. GPIO pins 28 to 31 are available on header P5. The following example session shows the output for my Raspberry Pi: $ sudo ./pads 07E1002C : 0000001B 07E10030 : 0000001F 07E10034 : 0000001B 1 1 1 1 1 1 3 7 3 The last four fields on each output line are as follows: 1. The word value in hexadecimal 2. The configured slew rate setting 3. The configured hysteresis setting 4. The drive-level code What this suggests is that GPIO 28 through 31 could be used, if you have higher current driving requirements. If you have a requirement to change these settings from within a C program, the program pads.c can be easily modified. Use the macro GETPAD32 (line 16) for inspiration. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ pads . c : Examine GPIO Pads Control ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #include #include #include #include #include #define #define #define #define #define BCM2708_PERI_BASE 0 x20000000 PADS_GPIO_BASE (BCM2708_PERI_BASE + 0 x100000 ) PADS_GPIO_00_27 0x002C PADS_GPIO_28_45 0x0030 PADS_GPIO_46_53 0x0034 #define GETPAD32(offset) #define BLOCK_SIZE ( ∗(unsigned ∗) ((char ∗) (pads)+offset)) (4∗1024) volatile unsigned ∗pads ; void initialize(void) { int mem_fd = open("/dev/mem",O_RDWR|O_SYNC); char ∗pads_map; 131 Chapter 12 ■ GPIO 27 if ( mem_fd <= 0 ) { 28 perror("Opening/dev/mem"); 29 exit(1); 30 } 31 32 pads_map = (char ∗)mmap( 33 NULL, /∗Any address ∗/ 34 BLOCK_SIZE, /∗Map length ∗/ 35 PROT_READ|PROT_WRITE, 36 MAP_SHARED, 37 mem_fd, /∗File to map ∗/ 38 PADS_GPIO_BASE /∗Offset to registers ∗/ 39 ); 40 41 if ( (long)pads_map == −1L ) { 42 perror("mmap failed."); 43 exit(1); 44 } 45 46 close(mem_fd); 47 pads = (volatile unsigned ∗)pads_map; 48 } 49 50 int 51 main(int argc,char ∗∗argv) { 52 int x; 53 union { 54 struct { 55 unsigned drive : 3; 56 unsigned hyst : 1; 57 unsigned slew : 1; 58 unsigned reserved : 13; 59 unsigned passwrd : 8; 60 } s; 61 unsigned w; 62 } word; 63 64 initialize(); 65 66 for ( x=PADS_GPIO_00_27; x<=PADS_GPIO_46_53; x += 4 ) { 67 word.w = GETPAD32(x) ; 68 printf("%08X : %08X %x %x %x\n" , 69 x+0x7E10000, word.w, 70 word.s.slew, word.s. hyst, word.s.drive) ; 71 } 72 73 return 0; 74 } 75 76 /∗End ∗/ 132 Chapter 12 ■ GPIO GPIO Current Budget Gert van Loo states that “the Raspberry-Pi 3V3 supply was designed with a maximum current of ~3 mA per GPIO pin.”29 He correctly concludes that if “you load each pin with 16 mA, the total current is 272 mA.” From this, we can calculate the designed current budget for GPIO pins: 1. 2. 272mA = 17 ) 16mA The Pi is designed for 17 × 3 mA = 51mA Gert is referring to 17 GPIO pins ( This is consistent with the 50 mA capacity figure we arrived at in Chapter 4. This is the remaining current capacity available from pins P1-01, P1-17, and P5-02. Consequently, when budgeting your 3.3 V supply current, factor in the following: GPIO: Current used for each GPIO output pin assigned (2 mA to 16 mA) +3.3 V: All current going to circuits powered from P1-01, P1-17, and P5-02. MAX232CSE: If you attached a RS-232 adapter, allow for about 15 mA. To save on your power budget, configure unused GPIO pins as inputs. Configuration Each GPIO pin is affected by several configuration choices: • General-purpose input, output, or alternate function • Input event detection method • Input pull-up/pull-down resistors • Output drive level Alternate Function Select When a GPIO pin is configured, you must choose whether it is an input, an output, or an alternate function (like the UART). The complete list of choices is shown in Table 12-4. The exact nature of what alternate function x means depends on the pin being configured. Table 12-4. Alternate Function Selection Code Function Selected ALT 000 GPIO pin is an input. 001 GPIO pin is an output. 100 GPIO pin is alternate function 0. 0 101 GPIO pin is alternate function 1. 1 110 GPIO pin is alternate function 2. 2 111 GPIO pin is alternate function 3. 3 011 GPIO pin is alternate function 4. 4 010 GPIO pin is alternate function 5. 5 133 Chapter 12 ■ GPIO The values shown in the table’s Code column are used in the configuration register itself. The alternate function numbers are listed in the ALT column. Keeping these two straight can be confusing when programming. Once the function has been selected, the configuration is then fine-tuned according to its peripheral type. Output Pins When a pin is configured for output, the remaining elements of configuration consist of the following: • Logic sense • Output state The output state of the GPIO pins can either be set by the kernel as a 32-bit word (affects 32 GPIOs at a time) or individually set or cleared. Having individual set/clear operations allows the host to change individual bits without disturbing the state of others (or having to know their state). Input Pins Input pins are more complex because of the additional hardware functionality offered. This requires that the input GPIO pin be configured for the following: • Detect rising input signals (synchronous/asynchronous) • Detect falling input signals (synchronous/asynchronous) • Detect high-level signals • Detect low-level signals • Logic sense • Interrupt handling (handled by driver) • Choose no pull-up; use a pull-up or pull-down resistor Once these choices have been made, it is possible to receive data related to input signal changes, or simply query the pin’s current state. Alternate Function When an alternate function such as the UART is chosen, many aspects of the pin’s configuration are predetermined. Despite this, each pin used by the peripheral should be preconfigured for input or output according to its function. These details are normally provided by the supporting driver. Sysfs GPIO Access In this section, we’re going to access the GPIO pins through the /sys pseudo file system. This is the GPIO driver interface. Because it provides file system objects, it is possible to control GPIO pins from the command line (or shell). The C/C++ programmer might be quick to dismiss this approach, because it might seem too slow. However, for input pins, the driver provides the advantage of providing a reasonable edge-level detection that is not possible when accessing the GPIO registers directly. The driver is able to receive interrupts when a GPIO state changes. This information can in turn be passed onto the application program using poll(2) or select(2). 134 Chapter 12 ■ GPIO Everything that you need for GPIO access is rooted in the top-level directory: /sys/class/gpio At this directory level, two main control pseudo files are maintained by the driver. These are write-only: export: Requests the kernel to export control of the requested GPIO pin by writing its number to the file unexport: Relinquishes control of the GPIO pin by writing its number to the file ■■Note Even root gets the permission denied if you try to read these files. Normally, the kernel manages the GPIO pins, especially if they are used for resources that need them (like the UART). In order for an application to manipulate a GPIO pin, it must first request that the kernel relinquish control of the requested pin. From a userspace perspective, the operation is like opening a file. The script or program should be prepared for failure in the event that a GPIO pin is busy. CORRECT USE OF SUDO It is tempting to perform some operations from a nonroot account, using sudo like this: $ sudo echo 17 >/sys/class/gpio/export -bash: /sys/class/gpio/export: Permission denied This does not work because the I/O redirection is performed by the shell before the sudo command begins. Change to interactive mode first and then the operation will succeed: $ sudo -i # echo 17 >/sys/class/gpio/export export The export pseudo file allows you to request a GPIO pin from the kernel. For example, if you want to manipulate GPIO pin 17, you request it from the kernel by writing its pin number to the pseudo file: $ # sudo –i echo 17 >/sys/class/gpio/export After a successful run, list the directory /sys/class/gpio: # ls export # gpio17 gpiochip0 unexport A new subdirectory (a symlink to a directory, actually) named gpio17 appears. This tells you that the kernel has given up control of GPIO 17 and has provided you this file system object to manipulate. At this point, you can consider the GPIO 17 as available. 135 Chapter 12 ■ GPIO unexport Some applications may require a GPIO pin for only a short time. When the application is finished with the pin, the application can release the pin back to the kernel. This is done by writing to the unexport pseudo file: $ # sudo echo -i 17 >/sys/class/gpio/unexport After this command completes, the pseudo object gpio17 disappears from the /sys/class/gpio directory. This confirms that the GPIO is now being managed by the driver and makes it impossible for userspace programs to mess with it (except for direct register access). gpioX Once you have a file system object like /sys/class/gpio/gpio17 to work with, you can configure it and perform I/O. The main objects that you’ll see are outlined in Table 12-5. The ones normally used by shell programs are simply as follows: direction: To set the I/O direction value: To read or write the I/O bit active_low: To alter the sense of logic Table 12-5. /sys/class/gpio/gpioX Objects Object Type R/W Values Description direction File R/W in Input pin out Output pin high Output & high low Output & low value File R/W 0 or 1 Read or write edge File R/W None No edge Rising Rising edge Falling Falling edge Both Rising or falling 0 Normal sense 1 Active low active_low File uevent File subsystem Symlink power Directory 136 R/W Symlink to self R Chapter 12 ■ GPIO The values used for direction are worth expanding on: Value Description in GPIO becomes an input port. out GPIO becomes an output port (with some prior state). high GPIO becomes output, but in a 1 state (high). low GPIO becomes output, but in a 0 state (low). The high and low options look like convenience frills, but they’re not. Consider configuring an output and setting it to 1: # echo out >/sys/class/gpio/gpio7/direction # echo 1 >/sys/class/gpio/gpio7/value Some time will pass before the execution of the second command takes place to establish the correct output level. If the GPIO output state was previously left in a zero state, the GPIO 7 pin will reflect a 0 (low) until the second command completes. For electronic devices operating in nanosecond time frames, this can be a problem. To provide glitch-free configuration, the following can be done instead: # echo high >/sys/class/gpio/gpio7/direction This way, the driver takes the necessary steps to establish the correct output level prior to making the pin an output. The settings of the file named edge affect how a C program (for example) would process poll(2) on the file named value (reading). A poll(2) system call could block the execution of the program until the required event occurred (like a rising edge). Active Low Sometimes it is desirable to have the logic inverted for the GPIO pin being used. For example, when driving an LED in the circuit configuration of Figure 12-5, a logic low is required to light the LED. Value Description 0 Noninverted logic 1 Inverted logic Inverting the logic allows you to light the LED with a logic 1: # echo 1 >/sys/class/gpio/gpio7/active_low # echo 1 >/sys/class/gpio/gpio7/value Conversely, if you don’t want inverted logic, you should be certain to establish that by writing a 0: # echo 0 >/sys/class/gpio/gpio7/active_low 137 Chapter 12 ■ GPIO Chip Level You will also notice the presence of a subdirectory named gpiochipN in /sys/class/gpio, where N is a numeric digit. The following main pseudo files exist within that directory: base: The value read should be the same value N, which is the first GPIO managed by this chip. label: The label (for example, bcm2708_gpio) of the chip, which is not necessarily unique. Used for diagnostic purposes. ngpio: The value read indicates how many GPIOs this chip manages, starting with the value read from base. GPIO Tester If you decided to build yourself a prototype board with the Raspberry Pi mounted on it, you may find this simple shell script useful for checking the wiring of the GPIO breakout clips. Or perhaps you just want to verify that the connection brought out to the breadboard is the correct one. Simply supply the GPIO pin number that you want to blink, on the command line: $ cat ./gp #!/bin/bash GPIO="$1" SYS=/sys/class/gpio DEV=/sys/class/gpio/gpio$GPIO if [ ! −d $DEV ] ; then # Make pin visible echo $GPIO >$SYS/export fi # Set pin to output echo out >$DEV/direction function put() { # Set value of pin (1 or 0) echo $1 >$DEV/value } while true ; do put 1 echo "GPIO $GPIO: on" sleep 1 put 0 echo "GPIO $GPIO: off $(date)" sleep 1 done # End 138 Chapter 12 ■ GPIO To exercise GPIO 25 (GEN6), use this command (project file scripts/gp): # ./gp 25 When testing with an LED and alligator clip lead, ground yourself to the ground pin first (or better still, a good ground like a water tap). Static electricity can be especially bad in the winter months. It not only can cause your Pi to reset but also can inflict internal damage. After discharging yourself to the ground pin, apply the lead and allow time enough for 1-second-on and 1-second-off events. ■■Note Cats are especially bad for static electricity. GPIO Input Test To test out the GPIO input capability, a simple script is presented next (and is available in the scripts subdirectory as a file named input). By default, it assumes 0 for the active low setting, meaning that normal logic applies to the input values. If, on the other hand, a 1 is used, inverted logic will be applied. Using the script named input, apply one of the following commands to start it (^C to end it): # ./input 0 . . . # ./input 1 # Normal "active high" logic # Use active low logic The script, of course, can be modified, but as listed, it reads an input on GPIO 25 (GEN6) and presents what it has read to GPIO 24 (GEN5). It additionally reports what has been read to standard output. If the output (GPIO 24) is wired to an LED, the input status will be visible in the LED (use Figure 12-6 as a guide for wiring). The script has its limitations, one of which is that the sleep(1) command is used. This causes it to have a somewhat sluggish response. If you don’t like that, you can comment out the else and sleep commands. As a consequence, it will hog the CPU, however, but be more responsive. #!/bin/bash ALO="${1:−0}" INP=25 OUT=24 # 1=active low, else 0 # Read from GPIO 25 (GEN6) # Write t o GPIO 24 (GEN5) set −eu trap "close_all" 0 function close_all() { close $INP close $OUT } function open() { # pin direction dev=$SYS/gpio$1 if [ ! −d $dev ] ; then echo $1 >$SYS/export fi 139 Chapter 12 ■ GPIO echo $2 >$dev/direction echo none >$dev/edge echo $ALO >$dev/active_low } function close() { # pin echo $1 >$SYS/unexport } function put() { # pin value echo $2 >$SYS/gpio$1/value } function get() { # pin read BIT <$SYS/gpio$1/value echo $BIT } count=0 SYS=/sys/class/gpio open $INP in open $OUT out put $OUT 1 LBIT=2 while true ; do RBIT=$(get $INP) if [ $RBIT −ne $LBIT ] ; then put $OUT $RBIT printf "%04d Status : %d\n" $count $RBIT LBIT=$RBIT let count=count+1 else sleep 1 fi done # End The following is an example session: # ./input 0000 Status 0001 Status 0002 Status 0003 Status ^C # : : : : 0 1 0 1 When GPIO 25 is grounded, 0 should be read, as reported in line 0000 of the example. If you then apply a high (for example, from the +3.3 V supply), a 1 should be reported. 140 Chapter 12 ■ GPIO Floating Potentials The beginning student may be puzzled about “glitches” seen by some GPIO inputs (28 or 29). When a GPIO input without a pull-up resistor is unattached, the line can “float,” or change over time, due to static electrical buildup. Unless a pull-up or pull-down resistor is attached (or configured), the pin can assume intermediate voltages. A voltage in the range of VIL = 0.8 V to VIH = 1.3 V is ambiguous to the Pi. Input voltages in this range may read randomly as 1s or 0s. ■■Caution If you are using a loose wire or alligator clip to apply high or low signals to an input GPIO pin, be very careful to avoid static electricity, which can cause damage. Use a ground strap or hold onto the Pi’s ground to bleed any static away, while changing connections. Static electricity may also cause your Raspberry Pi to reset. A real ground, like a water tap, is best for bleeding off static. When using a button or switch, for example, use a pull-up resistor to +3.3 V (or configure the SoC to use one). In this manner, high is immediately seen by the input when the switch or button is temporarily unconnected. ■■Note A switch is temporarily disconnected while changing its poles. Reading Events One of the shortcomings of the input script is that it must poll the input pin’s value continuously, to see if the value has changed. In a multiprocessing environment like Linux, it is rude to burn the CPU like this (hence the compromise with the sleep command). A better design would have the program wait for a change on the input pin, allowing other processes to use the CPU while it waits. The GPIO driver within the kernel is, in fact, able to do that, though not usable by shell commands. The C program evinput.c is an example program that takes advantage of this capability and is presented next. It uses the poll(2) system call to accomplish this. The basic procedure used is this: 1. The GPIO pin X is configured for input. 2. The value of /sys/class/gpio/gpioX/edge has been configured for the edge(s) to be reported (see Table 12-5). 3. When querying the input pin, the open file descriptor for /sys/class/gpio/gpioX/value is provided to the poll(2) call (line 111). 4. The time-out is specified as –1 in argument 3, so poll(2) will wait forever, if necessary. 5. When there is new data for the GPIO input, poll(2) returns and rc will be greater than zero, breaking out of the loop. 6. The program must rewind to the beginning of the pseudo file with lseek(2) (line 118). 7. Finally, the text is read from the value file in line 119. Step 6 can be omitted if you only need notification. However, to read the correct data, a rewind to the start of the pseudo file is required. The program shown also checks whether the signal handler was called. If it sees that variable is_signaled has been set, the routine gpio_poll() returns –1 to indicate to the caller that a program exit is needed (lines 112 to 113). 141 Chapter 12 ■ GPIO Test Run A test was performed using a GPIO output pin (27) wired to the input pin (17). In one session, GPIO output pin 27 was changed from 0 to 1 and back. The events were captured in the other session, running ./evinput. ■■Note If the reader compiles the programs using the included makefile for each program, the programs are automatically built to use setuid root. Doing this allows them to run with root privileges, without needing to use the sudo command. The following is a session output obtained from the ./evinput run. The output pauses after reporting the first line (line 4). Following that, new lines appear whenever the input pins change state. 1 2 3 4 5 6 7 8 9 $ ./evinput 17 Monitoring for GPIO input changes: GPIO GPIO GPIO GPIO ^C $ 17 17 17 17 changed: changed: changed: changed: 0 1 0 1 Input GPIO pin 17 was changed from this separate session, using output GPIO 27 (recall that it is wired to GPIO 17 for this test): 1 2 3 4 5 6 7 8 9 10 11 12 13 # cd /sys/class/gpio # echo 27 >export # ls export gpio27 gpiochip0 unexport # cd gpio27 # ls active_low direction edge power subsystem uevent value # echo out >direction # echo 0 >value # # s t a r t e d . / evinput 17 he r e . . . # echo 1 >value # echo 0 >value # echo 1 >value From the sessions shown, GPIO 17 was set low in the preceding line 9. After that, the ./evinput program was started and the first line is reported (line 4 in the evinput session). As the input pin changed state in lines 11+ (in the preceding code), the input events were being reported in lines 5+ (evinput session). 142 Chapter 12 ■ GPIO Checking the system with the top command, you’ll see that ./evinput does not consume CPU. Yet the program is indeed responsive to the input change events. This leaves the CPU for all of your other processes that you may need to run. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 / ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ evinput.c : Event driven GPIO input ∗ ∗ ./evinput gpio# ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #include #include #include #include #include #include #include #include #include static int gpio_inpin = –1; static int is_signaled = 0; typedef enum { gp_export=0, gp_unexport, gp_direction, gp_edge, gp_value } gpio_path_t; / ∗ GPIO input pin ∗/ / ∗ Exit program if signaled ∗/ / / / / / ∗ ∗ ∗ ∗ ∗ /sys/class/gpio/export ∗/ /sys/class/gpio/unexport ∗/ /sys/class/gpio%d/direction ∗/ /sys/class/gpio%d/edge ∗/ /sys/class/gpio%d/value ∗/ /∗ ∗ Internal : Create a pathname for type in buf. ∗ / static const char ∗ gpio_setpath(int pin, gpio_path_t type, char ∗ buf, unsigned bufsiz) { static const char ∗ paths[] = { "export", "unexport", "gpio%d/direction", "gpio%d/edge", "gpio%d/value"}; int slen; strncpy (buf, "/sys/class/gpio/", bufsiz); bufsiz –= (slen = strlen(buf)); snprintf(buf+slen, bufsiz, paths[type], pin); return buf; } /∗ ∗ Open /sys/class/gpio%d/value for edge detection : ∗/ static int 143 Chapter 12 ■ GPIO 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 144 gpio_open_edge(int pin, const char ∗ edge) char buf [128]; FILE ∗f; int fd; { /∗Export pin : /sys/class/gpio/export ∗/ gpio_setpath(pin, gp_export, buf, size of buf); f = fopen(buf, "w"); assert(f); fprintf(f,"%d\n", pin); fclose(f); /∗Direction : /sys/class/gpio%d/direction ∗/ gpio_setpath(pin, gp_direction, buf, size of buf); f = fopen(buf, "w"); assert(f); fprintf(f,"in\n"); fclose(f); /∗Edge : /sys/class/gpio%d/edge ∗/ gpio_setpath(pin, gp_edge, buf, size of buf); f = fopen (buf, "w"); assert(f); fprintf(f,"% s\n", edge); fclose(f); /∗Value : /sys/class/gpio%d/value ∗/ gpio_setpath(pin, gp_value, buf, size of buf); fd = open(buf,O_RDWR); return fd; } /∗ ∗ Close (unexport) GPIO pin : ∗ / static void gpio_close(int pin) { char buf[128]; FILE ∗f; / ∗ Unexport : /sys/class/gpio/unexport ∗/ gpio_setpath(pin, gp_unexport, buf, size of buf); f = fopen(buf, "w"); assert(f); fprintf(f,"%d\n", pin); fclose(f); } /∗ ∗ This routine will block until the open GPIO pin has changed ∗ value. This pin should be connected to the MCP23017 /INTA ∗ pin. Chapter 12 ■ GPIO 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 ∗/ static int gpio_poll(int fd) { struct pollfd polls; char buf [32]; int rc, n; /∗ /sys/class/gpio17/value ∗/ /∗Exceptions ∗ / polls.fd = fd; polls.events = POLLPRI; do } while { rc = poll(&polls, 1, –1); if ( is_signaled ) return –1; ( rc < 0 && errno == EINTR ); /∗Block ∗/ /∗Exit if ^C received ∗/ assert (rc > 0); lseek(fd, 0, SEEK_SET); n = read(fd, buf, size of buf) ; assert(n > 0); buf[n] = 0; rc = sscanf(buf,"% d",&n); assert(rc==1); return n; /∗Return value ∗/ } /∗ ∗ Signal handler to quit the program ∗ / static void sigint_handler(int signo) { is_signaled = 1; } /∗ ∗ Main program : ∗/ int main(int argc, char ∗∗ argv) int fd, v; usage: /∗Read value ∗/ : /∗Signal to exit program ∗/ { /∗ ∗ Get GPIO input pin to use : ∗/ if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } 145 Chapter 12 ■ GPIO 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 } 169 170 / ∗ if ( sscanf(argv[1], "%d",&gpio_inpin) != 1 ) goto usage; if ( gpio_inpin < 0 || gpio_inpin >=32 ) goto usage; signal (SIGINT, sigint_handler) ; fd = gpio_open_edge(gpio_inpin, "both"); /∗Trap on SIGINT ∗/ /∗GPIO input ∗/ puts("Monitoring for GPIO input changes: \n"); while ( (v = gpio_poll (fd)) >=0 ) { /∗Block until input changes ∗/ printf("GPIO %d changed: %d\n", gpio_inpin, v); } while ( !is_signaled ); /∗Quit if ^C' d ∗/ putchar('\n'); close(fd); gpio_close(gpio_inpin); return 0; /∗Close gpio%d/value ∗/ /∗Unexport gpio ∗ / End event.c ∗ / Direct Register Access It is possible to access the GPIO registers directly. The module gpio_io.c shows the code that can be used for this. It requires the program to invoke gpio_init() upon startup, which then makes the registers available. The code as presented is intended to be #included into the module using it. (Normally, it would be compiled as a separate module.) The API made available is outlined in the following subsections. These routines are used in several examples and projects within this book, including the following: pullup: Change the pull-up register setting. bipolar: Drive a bipolar stepper motor (Chapter 28). rtscts: Change the ALT function (Chapter 11). valt: View ALT function settings (subdir valt in source code). unipolar: Drive a unipolar stepper motor (Chapter 27). dht11: Humidity and temperature sensor (Chapter 22). pwm: Pulse width modulation (Chapter 30). gpio_init( ) This function call opens access to the GPIO registers. This will require root privileges, which is why many programs in this book were compiled with setuid root. The operation of this routine is to gain access to the physical memory space, so that the GPIO registers can be accessed. This procedure is covered in the “Memory Mapping” section of Chapter 6. void gpio_init(void); 146 Chapter 12 ■ GPIO gpio_config( ) This function call allows the caller to configure a pin as input or output: typedef enum { Input = 0, Output } direction_t; /∗GPIO is an Input ∗/ /∗GPIO is an Output ∗/ void gpio_config(int gpio,direction_t output); The arguments are as follows: gpio: The GPIO pin to be configured output: The value Input or Output gpio_write( ) This function permits the caller to set the output GPIO pin to a 1 or a 0. void gpio_write(int gpio,int bit); The arguments are as follows: gpio: The GPIO pin to write to bit: The value of the output bit (1 or 0) Only the least significant bit of argument bit is used. gpio_read( ) This function reads the requested GPIO pin and returns the bit (0 or 1). int gpio_read(int gpio); The single argument gpio is used to specify the GPIO pin to be read. gpio_io.c The following pages show the program listing for gpio_io.c: 1 2 3 4 5 6 7 8 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ gpio_io.c : GPIO Access Code ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #define BCM2708_PERI_BASE #define GPIO_BASE #define BLOCK_SIZE (4∗1024) 0x20000000 (BCM2708_PERI_BASE + 0x200000) 147 Chapter 12 ■ GPIO 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 148 /∗GPIO setup macros. Always use INP_GPIO (x) before using OUT_GPIO(x) or SET_GPIO_ALT(x, y ) ∗/ #define INP_GPIO (g) ∗(ugpio + ((g)/10)) &= ~(7 <<(((g) % 10)∗3)) #define OUT_GPIO(g) ∗(ugpio + ((g)/10)) |= (1 <<(((g) % 10)∗3)) #define SET_GPIO_ALT(g,a) \ ∗(ugpio + (((g)/10))) |= (((a) <=3?(a) + 4 : (a)==4?3:2)<<(((g)%10)∗3)) #define GPIO_SET ∗(ugpio+7) /∗ #define GPIO_CLR ∗(ugpio+10) /∗ #define GPIO_GET ∗(ugpio+13) /∗ typedef enum { Input = 0, Output } direction_t; sets bits ∗/ clears bits ∗/ gets all GPIO input levels ∗/ /∗GPIO is an Input∗/ /∗GPIO is an Output∗/ static volatile unsigned ∗ugpio; /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ Perform initialization to access GPIO registers: ∗ Sets up pointer ugpio. ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ static void gpio_init() { int fd; char ∗map; fd = open("/dev/mem",O_RDWR|O_SYNC); if ( fd < 0 ) { perror("Opening/dev/mem"); exit(1); } map = (char ∗ ) mmap( NULL, BLOCK_SIZE, PROT_READ| PROT_WRITE, MAP_SHARED, fd, GPIO_BASE ) ; /∗Any address ∗/ /∗ # of bytes ∗/ /∗Shared ∗/ /∗ /dev/mem ∗/ /∗Offset to GPIO ∗/ if ( (long)map == 1L ) { perror("mmap(/dev/mem)"); exit(1); } } /∗Needs root access ∗/ close(fd); ugpio = (volatile unsigned ∗)map; Chapter 12 ■ GPIO 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ Configure GPIO as Input or Output ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ static inline void gpio_config (int gpio, direction_t output) { INP_GPIO (gpio); if ( output ) { OUT_GPIO(gpio); } } /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ Write a bit to the GPIO pin ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ static inline void gpio_write(int gpio, int bit) { unsigned sel = 1 << gpio; if ( bit ) { GPIO_SET = sel; } else { GPIO_CLR = sel; } } /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ Read a bit from a GPIO pin ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ static inline int gpio_read(int gpio) { unsigned sel = 1 << gpio; return (GPIO_GET) & sel ? 1 : 0 ; } / ∗ End gpio_io.c ∗/ GPIO Transistor Driver The GPIO pins on the Pi are often going to be pressed into driving something in the outside world. GPIO pins 28 to 31 can drive up to 16 mA, maximum. The remaining GPIO pins are configured to drive up to 8 mA. These are fairly weak interfaces to the outside world. Sometimes all that is needed is a simple one-transistor buffer. The 2N2222A transistor is cheap and drives a fair amount of current. Figure 12-8 shows a simple driver circuit attached to a GPIO output pin. 149 Chapter 12 ■ GPIO Figure 12-8. 2N2222A driver The GPIO output driver sees only a diode-like path to ground through the base of transistor Q1. Resistor R1 is chosen to limit that current. The resistor shown as Rc in the figure represents the load, like a high-current LED in series with a current-limiting resistor. Alternatively, it may be a resistor chosen so that the Vout represents a stiffer output voltage. In the diagram, the resistor Rc is connected to the +5 V power supply. This is safe because current cannot flow from the collector into the base of Q1. This prevents 5 V from flowing into the GPIO pin (that junction is reversed biased). Thus Q1 allows you to convert the 3.3 V GPIO output into a 5 V TTL signal, for example. The 2N2222A transistor has an absolute maximum VCE of 30 V. This allows you to drive even higher voltage loads, provided that you stay within the transistor’s current and power ratings. Driver Design The transistor driver circuit is limited by the power-handling capability of Q1 and the maximum collector current. Looking at the datasheet, the maximum power listed for Q1 is 0.5 W at 25ºC. When the transistor is turned on (saturated), the voltage across Q1 (VCE) is between 0.3 V and 1 V (see VCE(sat) in the datasheet). The remainder of the voltage is developed across the load. If we assume the worst case of 1 V for VCE (leaving 4 V across the load), we can compute the maximum current for IC: IC = PQ1 VCE 1 0.3 = 3.3 A = Clearly, this calculated current exceeds the listed absolute maximum current IC of 600 mA. So we use the maximum current for IC = 600 mA instead. For safety, we use the minimum of these maximum ratings. While this transistor is clearly capable of driving up to 600 mA of current, let’s design our driver for a modest current flow of 100 mA. 150 Chapter 12 ■ GPIO The next thing to check is the HFE of the part. The parameter value required is the lowest HFE value for the amount of collector current flowing (HFE drops with increasing IC current). A STMicroelectronics datasheet shows its 2N2222A part as having an HFE = 40, IC = 500 mA, with VCE = 10 V . They also have a more favorable HFE value of 100, for 150 mA, but it is best to err on the side of safety. We can probably assume a safe compromise of HFE = 50. The HFE parameter is important because it affects how much current is required to drive Q1’s base. The input base current is calculated as follows: IC H FE 100mA = 50 = 2mA IB = This value tells us that the GPIO pin will need to supply up to 2 mA of drive into Q1’s base. With 2 mA of drive, Q1 will be able to conduct up to 100 mA in the collector circuit. A current of 2 mA is easily accommodated by any GPIO pin. Note that if you were to design closer to the design limits of this transistor (500 mA in this example), you should probably allow an additional 10% of base current “overdrive” to make certain that the transistor goes into saturation. Current flow into the base of Q1 creates a voltage drop of VBE = 0.7 V, from the input base lead to ground. So to calculate the resistor value R1 we take the VR1 divided by the current. The highest voltage coming from GPIO is going to be slightly less than the 3.3 V power supply rail. It is safe to assume that GPIOHIGH = 3 V. The voltage appearing across R1 is thus GPIOHIGH–VBE. GPIOHIGH - VBE IB 3 - 0.7 = 0.002 = 1,150W R1 = The nearest 10% standard resistor value is R1 = 1.2 kΩ. Using this resistor value as a check, let’s compute backward what our actual drive capability is from Q1. First we need to recompute IB now that we know R1 : GPIOHIGH - VBE R1 3 - 0.7 = 1200 = 1.9mA IB = This tells us that the GPIO output pin will not have to source more than 1.9 mA of current, using R1 = 1.2 kΩ. Now let’s calculate the maximum drive we can reliably expect in the collector circuit of Q1: I C = I B ´ H FE = 0.0019 ´ 50 = 95mA ■■Note This discussion glibly avoids the effects of components being within ±10% tolerance. This computes that the designed 2N2222A driver circuit is capable of driving up to 95 mA. 151 Chapter 12 ■ GPIO To obtain even more performance out of that driver (if you need it), you could choose a resistor closer to the actual value desired (1150 Ω). It turns out that a 1% resistor can be had at exactly 1.15 kΩ: I C = I B ´ H FE = 0.002 ´ 50 = 100mA Be careful that your design does not stress the transistor beyond its maximum ratings (power and current). You might be willing to risk the cheap transistor, but keep in mind that the poor little thing might be holding back a higher voltage (like a river dam). If the transistor is destroyed, the high voltage may come crashing into the base circuit and cause damage to the Pi’s GPIO pin. So be nice to Q1! Substitution You don’t have to use my choice of the 2N2222A transistor for driving a load. Substitute what you have or what you plan to order. Today’s DMMs can measure the transistor HFE, so that makes planning easier when using junk box parts. Another critical factor in selecting a part is the power capability of the transistor. You should probably know exactly what that limit is, unless you are driving an extremely light load. Finally, it is important to know what the maximum voltage ratings are for the selected transistor, if you plan to drive voltages higher than 3 V. You need to be able to count on it holding back those higher voltages in the collector circuit to prevent damage to the Pi. Inductive Loads Inductive loads like relays and motors present a special problem. They generate a high reverse voltage when current is switched off or interrupted. When the relay coil is turned off, the magnetic field collapses around the coil of wire. This induces a high voltage, which can damage the Pi (and can also provide a mild electric shock). Electric motors exhibit a similar problem. As the DC current sparks and stutters at the commutator inside the motor, high reverse voltage spikes are sent back into the driving circuit. This is due to the magnetic field collapsing around the motor windings. Consequently, inductive loads need a reverse-biased diode across the load to short out any induced currents. The diode conducts only when the back electromotive force (EMF) is generated by the inductive load. Figure 12-9 shows diode D1 reverse biased across the relay coil winding L1 (or motor). The diode bleeds away any reverse current that might be generated. Use a diode with sufficient current-carrying capability (matching at least the current in Q1). 152 Chapter 12 ■ GPIO Figure 12-9. Driver for inductive load Since there is no current-limiting resistor used in series with L1 , whether motor or relay, make sure that no more current than ICmax will flow. For relays, you need a coil resistance greater than or equal to 50 Ω, when driven from approximately 5 V. Otherwise, you risk burning out driver Q1 (assuming the 2N2222A with its power limit of 0.5 watts at 5 V). You can drive lower resistance coils, if you designed your driver to handle the additional current. For example, a 500 mA driver can handle coil resistances as low as 10 ohms (at 5 V). The 2N2222A transistor is probably suitable for only the smallest of electric motors. Depending on how it is used, a motor can stall and thus greatly increase its current demands. Motors also have high startup currents. If the motor is started and stopped frequently, the driving transistor may be overworked. Driver Summary This section on the transistor driver should not be thought of as your only choice in driver solutions. It was presented because it is simple and cheap and can fill the need for many small loads, like high-current LEDs or panel lightbulbs. Simple and cheap may be essential for robot building when many drivers are required. While students may use the Gertboard for labs, we still need to provide a substitute when the Raspberry Pi is integrated into something that was built (like a robot). It might be wise to stock up on a few good transistor types for this purpose. Utility gpio For this book, I have avoided using instances of “magic package X.” However, the wiringPi project is popular enough that no chapter on GPIO would be complete without mentioning it. The wiringPi project provides a handy utility for displaying and changing GPIO functionality. The package can be downloaded from here: https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install 153 Chapter 12 ■ GPIO This page lists instructions for obtaining, compiling, and installing the package. Once installed, the gpio command is available: $ gpio −h gpio : Usage : gpio −v gpio −h gpio [−g ] ... gpio [−p ] ... gpio readall gpio unexportall/exports ... gpio export/edge/unexport ... gpio drive gpio pwm−bal/pwm−ms gpio pwmr gpio pwmc gpio load spi / i2c gpio gbr gpio gbw There are many options and functions within this utility. I’ll just demonstrate some quick examples of the most useful ones. Once installed, the full details of the utility can be found by this command: $ man 1 gpio Displaying GPIO Settings The following command can be used to display your GPIO settings: $ gpio readall +----------+--------+---------+-------+-------+ | wiringPi | GPIO | Name | Mode | Value| +----------+--------+---------+-------+-------+ | 0 | 17 | GPIO 0 | IN | High | | 1 | 18 | GPIO 1 | IN | Low | | 2 | 27 | GPIO 2 | OUT | Low | | 3 | 22 | GPIO 3 | IN | Low | | 4 | 23 | GPIO 4 | IN | Low | | 5 | 24 | GPIO 5 | IN | Low | | 6 | 25 | GPIO 6 | IN | Low | | 7 | 4 | GPIO 7 | IN | Low | | 8 | 2 | SDA | ALT0 | High | | 9 | 3 | SCL | ALT0 | High | | 10 | 8 | CE0 | IN | Low | | 11 | 7 | CE1 | IN | Low | | 12 | 10 | MOSI | IN | Low | | 13 | 9 | MISO | IN | Low | | 14 | 11 | SCLK | IN | Low | | 15 | 14 | TxD | ALT0 | High | | 16 | 15 | RxD | ALT0 | High | 154 Chapter 12 ■ GPIO | 17 | 28 | GPIO8 | IN | Low | | 18 | 29 | GPIO9 | IN | Low | | 19 | 30 | GPIO10 | IN | Low | | 20 | 31 | GPIO11 | IN | Low | +----------+--------+---------+-------+-------+ Reading GPIO As a convenience, the gpio command allows you to read values from the command line: $ gpio export 27 in $ gpio −g read 27 0 $ gpio unexportall Use the -g option to specify that the pin number is a GPIO pin number. (I found the need for the -g option irksome.) Writing GPIO Like the read function, the gpio command can write values: $ $ $ 1 $ $ 0 $ gpio export 27 out gpio −g write 27 1 gpio −g read 27 gpio −g write 27 0 gpio −g read 27 gpio unexportall Use the -g option to specify GPIO pin numbers for the read/write commands. Modify Drive Levels The gpio command also enables you to alter the drive levels of the three available pads. The following changes pad 1 to drive level 6 (from 7): $ gpio drive 1 6 Use the pads program shown earlier in this chapter to verify the current settings: $ gpio drive 1 6 $ ./pads 07E1002C : 0000001B 1 1 3 07E10030 : 0000001E 1 1 6 07E10034 : 0000001B 1 1 3 This kind of change should not be made lightly. If you don’t have a sound reason to change these drive levels, it is recommended that you don’t. 155 Chapter 13 1-Wire Driver The 1-Wire protocol was developed by Dallas Semiconductor Corp. initially for the iButton.37 This communication protocol was attractive enough to be applied to other devices and soon adopted by other manufacturers. This chapter provides an overview of the 1-Wire protocol and how it is supported in the Raspberry Pi. 1-Wire Line and Power The 1-Wire protocol actually uses two wires: • Data: The single wire used for data communication • Ground: The ground or “return” wire The 1-Wire protocol was designed for communication with low–data content devices like temperature sensors. It provides for low-cost remote sensing by supplying power over the same wire used for data communications. Each sensor can accept power from the data line while the data line is in the high state (which is also the line’s idle state). The small amount of power that is siphoned off charges the chip’s internal capacitor (usually about 800 pF).37 When the data line is active (going low), the sensor chips continue to run off of their internal capacitors (in parasitic mode). Data communications cause the data line to fluctuate between low and high. So whenever the line level returns high again, even for an instant, the capacitor recharges. The device also provides an optional VDD pin, allowing power to be supplied to it directly. This is sometimes used when parasitic mode doesn’t work well enough. This, of course, requires an added wire, which adds to the cost of the circuit. We’ll be focusing on the parasitic mode in this chapter. In parasitic mode, VDD is connected to the ground. Line Driving The data line is driven by open collector transistors in the master and slave devices. The line is held high by a pull-up resistor when the driver transistors are all in the Off state. To initiate a signal, one transistor turns on and thus pulls the line down to ground potential. Figure 13-1 shows a simplified schematic of the master attached to the bus. Some voltage V (typically, +5 V) is applied to the 1-Wire bus through the pull-up resistor Rpullup. When the transistor M2 is in the Off state, the voltage on the bus remains high because of the pull-up resistor. However, when the master device activates transistor M2, current is caused to flow from the bus to the ground, acting like a signal short-circuit. Slave devices attached to the bus will see a voltage near zero. 157 Chapter 13 ■ 1-Wire Driver Figure 13-1. 1-Wire driver circuit ■■Note The Raspbian Linux 1-Wire bus uses GPIO 4 (GPCLK0) pin P1-07. Likewise, when a slave is signaled to respond, the master listens to the bus while the slave activates its driving transistor. Whenever all driving transistors are off, the bus returns to the high idle state. The master can request that all slave devices reset. After the master has made this request known, it relinquishes the bus and allows it to return to the high state. All slave devices that are connected to the bus respond by bringing the line low after a short pause. Multiple slaves will bring the line low at the same time, but this is permitted. This informs the master that at least one slave device is attached to the bus. Additionally, this procedure puts all slaves into a known reset state. Master and Slave The master device is always in control of the 1-Wire bus. Slaves speak only to the master, and only when requested. There is never slave-to-slave device communication. If the master finds that communication becomes difficult for some reason, it may force a bus reset. This corrects for an errant slave device that might be jabbering on the line. Protocol This section presents a simplistic introduction to the 1-Wire communication protocol. Knowing something about how the signaling works is not only interesting, but may be helpful for troubleshooting. More information is available on the Internet.38 Reset Figure 13-2 provides a simplified timing diagram of the reset procedure for the 1-Wire protocol. When the master driver begins, it must reset the 1-Wire bus to put all the slave devices into a known state. 158 Chapter 13 ■ 1-Wire Driver Figure 13-2. 1-Wire reset protocol For reset, the bus is brought low and held there for approximately 480 msec. Then the bus is released, and the pull-up resistor brings it high again. After a short time, slave devices connected to the bus start responding by bringing the line low and holding it for a time. Several slaves can participate in this at the same time. The master samples the bus at around 70 msec after it releases the bus. If it finds the line low, it knows that there is at least one slave connected and responding. Soon after the master sampling point, all slaves release the bus again and go into a listening state. They do not respond again until the master specifically addresses a slave device. For simplicity, we’ll omit the discovery protocol used. ■■Note Each slave has a guaranteed unique address. Data I/O The data protocol is shown in Figure 13-3. Whether writing a 0 or 1 bit, the sending device brings the bus line low. This announces the start of a data bit. Figure 13-3. 1-Wire read/write of 1 data bit 159 Chapter 13 ■ 1-Wire Driver When a 0 is being transmitted, the line is held low for approximately 60 msec. Then the bus is released and allowed to return high. When a 1 bit is being transmitted, the line is held low for only about 6 msec before releasing the bus. Another data bit is not begun until 70 msec after the start of the previous bit. This leaves a guard time of 10 msec between bits. The receiver then has ample time to process the bit and gains some signal noise immunity. The receiver notices a data bit is coming when the line drops low. It then starts a timer and samples the bus at approximately 15 msec. If the bus is still in the low state, a 0 data bit is registered. Otherwise, the data bit is interpreted as a 1. Having registered a data bit, the receiver then waits further until the line returns high (in the case of a 0 bit). The receiver remains idle until it notices the line going low again, announcing the start of the next bit. The sender can be either the master or the slave, but the master always has control. Slaves do not write data to the bus unless the master has specifically requested it. Slave Support Table 13-1 lists the slave devices that are supported by Raspbian Linux. The module names listed are found in the kernel source directory arch/arm/machbcm2708/slave. Table 13-1. 1-Wire Slave Driver Support Device Module Description DS18S20 w1_therm.c Precision digital thermometer DS18B20 Programmable resolution thermometer DS1822 Econo digital thermometer DS28EA00 9- to 12-bit digital thermometer with PIO bq27000 w1_bq27000.c Highly accurate battery monitor DS2408 w1_ds2408.c Eight-channel addressable switch DS2423 w1_ds2423.c 4 KB RAM with counter DS2431 w1_ds2431.c 1 KB EEPROM DS2433 w1_ds2433.c 4 KB EEPROM DS2760 w1_ds2760.c Precision Li+ battery monitor DS2780 w1_ds2780.c Stand-alone fuel gauge Reading Temperature The support for the usual temperature sensors is found in the kernel module w1_therm. When you first boot your Raspbian Linux, that module may not be loaded. You can check for it with the lsmod command: $ lsmod Module snd_bcm2835 snd_pcm snd_seq snd_timer snd_seq_device snd Size 12808 74834 52536 19698 6300 52489 snd_page_alloc 4951 160 Used by 1 1 snd_bcm2835 0 2 snd_seq, snd_pcm 1 snd_seq 7 snd_seq_device, snd_timer, snd_seq, snd_pcm, snd_bcm2835 1 snd_pcm Chapter 13 ■ 1-Wire Driver The module w1_therm is not loaded according to the example. This module also depends on the driver module wire. Another thing you can check is the pseudo file system: $ ls –l /sys/bus/w1 ls: cannot access /sys/bus/w1 : No such file or directory Having not found the pathname /sys/bus/w1, we have confirmation that the device driver is not loaded. Loading module w1_therm will bring in most of its module dependents: $ sudo modprobe w1_therm $ lsmod Module Size w1_therm 2705 wire 23530 cn 4649 snd_bcm2835 12808 snd_pcm 74834 ... Used by 0 1 w1_therm 1 wire 1 1 snd_bcm2835 After the wire module is loaded, you’ll see the /sys/bus/w1/devices directory. One more module is needed: $ sudo modprobe w1_gpio $ lsmod Module Size w1_gpio 1283 w1_therm 2705 wire 23530 cn 4649 snd_bcm2835 12808 ... $ cd /sys/bus/w1/devices $ ls w1_bus_master1 Used by 0 0 2 w1_therm,w1_gpio 1 wire 1 Once module w1_gpio is loaded, there is a bus master driver for GPIO pin 4 (the default GPIO for the 1-Wire bus) at the ready. The bus master makes its presence known by creating directory w1_bus_master1. Change to that directory and list it to see the associated pseudo files within it. Table 13-2 lists the initial set of pseudo files and symlinks found there. 161 Chapter 13 ■ 1-Wire Driver Table 13-2. w1_bus_masterX Files File Type Read Content driver Symlink power Directory subsystem Symlink uevent File DRIVER=w1_master_driver w1_master_add File Write device ID xx-xxxxxxxxxxxx to add slave w1_master_attempts File 88 w1_master_max_slave_count File 10 _master_name File w1_bus_master1 w1_master_pointer File 0xd7032148 w1_master_pullup File 1 w1_master_remove File Write device ID xx-xxxxxxxxxxxx to remove slave w1_master_search File –1 w1_master_slave_count File 0 w1_master_slaves File Not found w1_master_timeout File 10 Bus Master The bus master driver scans for new slave devices every 10 seconds (according to w1_master_timeout). File w1_master_attempts indicates how many scans have been performed to date. File w1_master_slave_count shows how many slaves have been detected out of a maximum of w1_master_max_slave_count. Reading w1_master_slaves provides a list of slaves found or not found. The following is an example output session produced while two DS18B20 temperature sensors were connected to the bus: $ cd /sys/bus/w1/devices/w1_bus_master1 $ cat w1_master_slaves 28−00000478d75e 28−0000047931b5 $ Slave Devices Figure 13-4 shows the pinout of the Dallas DS18B20 slave device. This temperature sensor is typical of many 1-wire slave devices. 162 Chapter 13 ■ 1-Wire Driver DALLAS DS1820 GND DQ VDD 1 2 3 BOTTOM VIEW 1 2 3 To-92 PIN DESCRIPTION GND - Ground DQ - Data In/Out VDD - Power Supply Voltage Figure 13-4. DS18B20 pin-out Slave devices are identified by a pair of digits representing the product family, followed by a hyphen and serial number in hexadecimal. The ID 28-00000478d75e is an example. You might also want to try different devices, like the similar DS18S20. Figure 13-5 illustrates the DS18B20 attached to the Raspberry Pi. Figure 13-5. 1-Wire with DS18B20 slave circuit 163 Chapter 13 ■ 1-Wire Driver When things are working correctly, the bus master detects slave devices automatically as part of its periodic scan. If the device you’ve attached is not showing up within 10 seconds or so, you may want to try forcing it. You can force adding a slave device entry as follows: # cd /sys/bus/w1/devices/w1_bus_master1 # echo 28−0000028f6667 >w1_master_add Upon doing this, subdirectory 28-0000028f6667 will appear, at least until the driver gives up trying to communicate with it (the following line with the ellipsis is abbreviated): # ls –ltr ./28–0000028f6667 total 0 –rw–r––r–– 1 root root 4096 lrwxrwxrwx 1 root root 0 –r––r––r–– 1 root root 4096 Drwxr–xr–x 2 root root 0 –r––r––r–– 1 root root 4096 –r––r––r–– 1 root root 4096 lrwxrwxrwx 1 root root 0 Jan Jan Jan Jan Jan Jan Jan 30 30 30 30 30 30 30 18:56 18:56 18:56 18:56 18:56 18:56 18:56 uevent subsystem –> ../../../bus/w1 w1_slave powerr name id driver –> .../w1_slave_driver If you want to remove a slave device, you can use the w1_master_remove file. The device will reappear in 10 seconds or so (due to a scanning period), if the device is still physically connected to the bus. # echo 28–0000028f6667 >w1_master_remove The following example shows how two DS18B20 temperature sensors show up on the 1-Wire bus: $ cd /sys/bus/w1/devices $ ls 28−00000478d75e 28−0000047931b5 w1_bus_master1 $ Reading the Temperature The slave device’s temperature can be read by reading its w1_slave pseudo file. In this example, we read two DS18B20 temperature sensors that are supposed to be accurate to ±0.5 ºC. Reading these two sensors together should show fairly good agreement (they were in close proximity of each other): $ cat 14 01 14 01 14 01 14 01 $ 28−00000478d75e/w1_slave 28−0000047931b5/w1_slave 4b 46 7f ff 0c 10 b4 : crc=b4 YES 4b 46 7f ff 0c 10 b4 t=17250 4b 46 7f ff 0c 10 b4 : crc=b4 YES 4b 46 7f ff 0c 10 b4 t=17250 Each sensor brings back two lines of data from the device driver. We see that both sensors agree exactly—that the temperature is 17.250ºC. This speaks well for their accuracy. The DS18B20 device also supports a wide temperature range (–55ºC to +125ºC), which make them good as outdoor sensors. If the read hangs at this point, it may be that the sensor hasn’t fully registered yet. This can happen if you forced adding it, but the driver was unable to communicate with it. 164 Chapter 13 ■ 1-Wire Driver 1-Wire GPIO Pin Raspbian Linux has its driver support for the 1-Wire bus on GPIO 4 (P1-07). This pin is hard-coded in the kernel driver. If you want to change this, look for the definition of W1_GPIO in the source file: arch/arm/mach-bcm2708/bcm2708.c Change the definition of W1_GPIO to the pin you require (found near line 73): // use GPIO 4 for the one–wire GPIO pin, if enabled #define W1_GPIO 4 Then, of course, you’ll need to rebuild and install the new kernel. 165 Chapter 14 I2C Bus The I2C bus, also known as the two-wire interface (TWI), was developed by Philips circa 1982 to allow communication with lower-speed peripherals.49 It was also economical because it required only two wires (excluding ground and power connections). Since then, other standards have been devised, building upon this framework, such as the SMBus. However, the original I2C bus remains popular as a simple, cost-effective way to connect peripherals. I2C Overview Figure 14-1 shows the I2C bus in the Raspberry Pi context. The Raspberry Pi provides the I2C bus using the BCM2835 as the bus master. Notice that the Pi also provides the external pull-up resistors R1 and R2, shown inside the dotted lines. Figure 14-1. The I2C bus 167 Chapter 14 ■ I2C Bus The two I2C bus lines are provided on the header strip P1: P1 Rev 1.0 Rev 2.0 + GPIO I2C Bus GPIO I2C Bus P1-03 0 SDA0 I2C-0 2 SDA1 I2C-1 P1-05 1 SCL0 3 SCL1 Note that the original Raspberry Pi provided I2C bus 0, but switched to using bus 1 with Rev 2.0 and later units. The design of the I2C bus is such that multiple peripherals are attached to the SDA and the SCL lines. Each slave (peripheral) has its own unique 7-bit address. For example, the MCP23017 GPIO extender peripheral might be configured with the address of 0x20. Each peripheral is called upon by the master by using this address. All nonaddressed peripherals are expected to remain quiet so that communication can proceed with the selected slave device. SDA and SCL The two bus lines used for I2C are as follows: Line P1 Idle Description SDA P1-03 High Serial data line SCL P1-05 High Serial clock line Both masters and slaves take turns at “grabbing the bus” at various times. Master and slave use open-drain transistors to drive the bus. It is because all participants are using open-drain drivers that pull-up resistors must be used (provided by the Pi). Otherwise, the data and clock lines would float between handoffs. The open-drain driver design allows all participants to drive the bus lines—just not at the same time. Slaves, for example, turn off their line drivers, allowing the master to drive the signal lines. The slaves just listen, until the master calls them by address. When the slave is required to answer, the slave will then assert its driver, thus grabbing the line. It is assumed by the slave that the master has already released the bus at this point. When the slave completes its own transmission, it releases the bus, allowing the master to resume. The idle state for both lines is high. The high state for the Raspberry Pi is +3.3 V. Other systems may use +5 V signaling. When shopping for I2C peripherals, you’ll want to choose ones that will operate at the 3 V level. Otherwise, 5 V peripherals can sometimes be used with careful planning or with use of signal adapters. The DS1307 Real-Time clock project is one such a case that is covered in Chapter 25. Multimaster and Arbitration The I2C protocol does support the idea of multiple masters. This complicates things, because two masters may grab the bus and transmit at the same time. When this happens, a process of arbitration is used to resolve the clash. Each transmitting master simultaneously monitors what it sees on the bus that it is driving. If a discrepancy is seen between what it is transmitting and what it is sensing on the bus line, it knows that it must release the bus and cease. The first node to notice conflict is required to release the bus. The other that has not noticed any discrepancy is free to continue its transmission, since its message has not been affected. If it too sees a problem, it will also cease and retry later. Not all devices support this arbitration. Ones that do are usually advertised as having multimaster support. Multimaster arbitration is not covered in this book, since this is an advanced I2C topic. 168 Chapter 14 ■ I2C Bus Bus Signaling The start and stop bits are special in the I2C protocol. The start bit is illustrated in Figure 14-2. Notice the SDA line transition from high to low, while the clock remains in the high (idle) state. The clock will follow by going low after 1/2 bit time following the SDA transition. This special signal combination informs all connected devices to “listen up,” since the next piece of information transmitted will be the device address. Figure 14-2. I2C start/stop signaling The stop bit is also special in that it allows slave devices to know whether more information is coming. When the SDA line transitions from low to high midway through a bit cell, it is interpreted as a stop bit. The stop bit signals the end of the message. There is also the concept of a repeated start, often labeled in diagrams as SR. This signal is electrically identical to the start bit, except that it occurs within a message in place of a stop bit. This signals to the peripheral that more data is being sent or required as part of another message. Data Bits Data bit timings are approximately as shown in Figure 14-3. The SDA line is expected to stabilize high or low according to the data bit being sent, prior to the SCL line going high. The receiver clocks in the data on the falling edge of SCL, and the process repeats for the next data bit. Note that most significant bits are transmitted first. Figure 14-3. I2C Data bit transmission 169 Chapter 14 ■ I2C Bus Message Formats Figure 14-4 displays two example I2C messages that can be used with the MCP23017 chip (Chapter 23). The simplest message is the write register request. Figure 14-4. Example I2C messages The diagram shows each message starting with the S (start) bit and ending with a P (stop) bit. After the start bit, each message begins with a byte containing the 7-bit peripheral address and a read/write bit. Every peripheral must read this byte in order to determine whether the message is addressed to it. The addressed peripheral is expected to return an ACK/NAK bit after the address is sent. If the peripheral fails to respond for any reason, the line will go high due to the pull-up resistor, indicating a NAK. The master, upon seeing a NAK, will send a stop bit and terminate the transmission. When the peripheral ACKs the address byte, the master then continues to write when the request is a write. The first example shows the MCP23017 8-bit register number being written next. This indicates which of the peripheral’s registers is to be written to. The peripheral will then ACK the register number, allowing the master to follow with the data byte to be written into the selected register. This too must be ACKed. If the master has no more data to send, the P (stop) bit is sent to end the transmission. Otherwise, more data bytes could follow with the sequence ending with the stop bit. The second example in Figure 14-4 shows how a message may be composed of both write and read messages. The initial sequence looks like the write, but this only writes a register number into the peripheral. Once the register number is ACKed, the master then sends an SR (start, repeated) bit. This tells the peripheral that no more write data is coming and to expect a peripheral address next. Since the address transmitted specifies the same peripheral, the same peripheral responds with an ACK. This request is a read, so the peripheral continues to respond with 8 bits of the requested read data, with the master ACKing the data received. The master terminates the message with a P (stop) to indicate that no more data is to be read. Many peripherals will support an auto-increment register mode. This is a feature of the peripheral, however, and not all devices support this. Once a peripheral’s register has been established by a write, successive reads or writes can occur in auto-increment mode, with the register being incremented with each byte transferred. This results in more-efficient transfers. 170 Chapter 14 ■ I2C Bus Which I2C Bus? Before we look at the I2C software API provided by Raspbian Linux, you should first determine which I2C bus you’ll be working with. Early Raspberry Pi revisions provided I2C bus 0 on header strip P1, while later units changed this to bus 1. This will matter to both commands and programs communicating with I2C peripherals. The “Identification” section of Chapter 7 discusses how to identify your Pi by displaying the firmware code from /proc/cpuinfo. What is displayed as a Revision is actually more of a firmware code. The following is a quick check example: $ grep Revision /proc/cpuinfo Revision : 000f From this information, use the firmware code (revision) number to determine which I2C bus to use: Revision I2C Bus 0002 0 0003 0 0004+ 1 SDA SCL P1-03 P1-05 GPIO-0 GPIO-1 GPIO-2 GPIO-3 I2C Bus Speed Unlike the SPI bus, the I2C bus operates at a fixed speed within Raspbian Linux. The SoC document claims I2C operation up to 400 kHz, but the reported clock rate during the Raspbian Linux boot is 100 kHz: $ dmesg | [1005.08] [1026.43] [1026.43] grep –i i2c i2c /dev entries driver bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at. . . (baudrate 100k) bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at . . .(baudrate 100k) Don’t be alarmed if the preceding grep command doesn’t provide any output. Later versions of Raspbian didn’t load bcm2708_i2c at boot time. You should see the same messages in the /var/log/syslog after you manually load the module as shown here: $ sudo $ tail . . . Mar 12 BSC0 Mar 12 BSC1 modprobe i2c_bcm2708 /var/log/syslog 20:16:55 raspberrypi kernel: [168.845802] bcm2708_i2c bcm2708_i2c.0: \ Controller at 0x20205000 (irq 79) (baudrate 100k) 20:16:55 raspberrypi kernel: [168.846423] bcm2708_i2c bcm2708_i2c.1: \ Controller at 0 x20804000 (irq 79) (baudrate 100k) 171 Chapter 14 ■ I2C Bus Tools Working with I2C peripherals is made easier with the use of utilities. These I2C utilities are easily installed using the following command: $ sudo apt−get install i2c−tools The i2c-tools package includes the following utilities: i2cdetect: Detects peripherals on the I2C line i2cdump: Dumps values from an I2C peripheral i2cset: Sets I2C registers and values i2cget: Gets I2C registers and values Each of these utilities has a man page available for additional information. We’ll be using some of these commands in this chapter and in later parts of this book. I2C API In this section, we’ll look at the bare-metal C language API for the I2C bus transactions. An application using this API is provided in Chapter 23’s “MCP23017 GPIO Extender” section. Kernel Module Support Access to the I2C bus is provided through the use of kernel modules. If lsmod indicates that the drivers are not loaded, you can load them at the command line: $ sudo modprobe i2c–dev $ sudo modprobe i2c–bcm2708 Once these modules are loaded, i2cdetect should be able to see bus-level support. On Revision 2.0 and later Raspberry Pis, the i2c-0 bus is for internal use. The user bus is shown as i2c-1. On early Pis this is reversed. $ i2cdetect –l i2c–0 unknown i2c–1 unknown bcm2708_i2c.0 bcm2708_i2c.1 N/A N/A After the driver support is available, the device nodes should appear under /dev: $ ls –l /dev/i2c* crw−rw−−−T 1 root root 89, 0 Feb 18 23:53 crw−rw−−−T 1 root root 89, 1 Feb 18 23:53 /dev/i2c−0 /dev/i2c−1 Header Files The following header files should be included in an I2C program: #include #include 172 Chapter 14 ■ I2C Bus open(2) Working with I2C devices is much like working with files. You’ll open a file descriptor, do some I/O operations with it, and then close it. The one difference is that you’ll want to use ioctl(2) calls instead of the usual read(2)/write(2) calls. #include #include #include int open(const char *pathname, int flags, mode_t mode); where pathname is the name of the file/directory/driver that you need to open/create. flags is the list of optional flags (use O_RDWR for reading and writing). mode is the permission bits to create a file (omit argument, or supply zero when not creating). returns -1 (error code in errno) or open file descriptor >=0 . Error Description EACCES Access to the file is not allowed. EFAULT The pathname points outside your accessible address space. EMFILE The process already has the maximum number of files open. ENFILE The system limit on the total number of open files has been reached. ENOMEM Insufficient kernel memory was available. To work with an I2C bus controller, your application must open the driver, made available at the device node: int fd; fd = open("/dev/i2c−1",O_RDWR); if ( fd < 0 ) { perror("Opening /dev/i2c−1"); Note that the device node (/dev/i2c-1) is owned by root, so you’ll need elevated privileges to open it or have your program use setuid(2). ioctl(2,I2C_FUNC) In I2C code, a check is normally performed to make sure that the driver has the right support. The I2C_FUNC ioctl(2) call allows the calling program to query the I2C capabilities. The capability flags returned are documented in Table 14-1. long funcs; int rc; rc = ioctl(fd,I2C_FUNCS,&funcs); if ( rc < 0 ) { perror("ioctl(2,I2C_FUNCS)"); abort(); } /* Check that we have plain I2C support */ assert(funcs & I2C_FUNC_I2C); 173 Chapter 14 ■ I2C Bus Table 14-1. I2C_FUNC bits Bit Mask Description I2C_FUNC_I2C Plain I2C is supported (non SMBus) I2C_FUNC_10BIT_ADDR Supports 10-bit addresses I2C_FUNC_PROTOCOL_MANGLING Supports: I2C_M_IGNORE_NAK I2C_M_REV_DIR_ADDR I2C_M_NOSTART I2C_M_NO_RD_ACK The assert() macro used here checks that at least plain I2C support exists. Otherwise, the program aborts. ioctl(2,I2C_RDWR) While it is possible to use ioctl(2,I2C_SLAVE) and then use read(2) and write(2) calls, this tends not to be practical. Consequently, the use of the ioctl(2,I2C_RDWR) system call will be promoted here instead. This system call allows considerable flexibility in carrying out complex I2C I/O transactions. The general API for any ioctl(2) call is as follows: #include int ioctl(int fd, int request, argp); where fd is the open file descriptor. request is the I/O command to perform. argp is an argument related to the command (type varies according to request). returns -1 (error code in errno), number of msgs completed (when request = I2C_RDWR). Error Description EBADF fd is not a valid descriptor. EFAULT argp references an inaccessible memory area. EINVAL request or argp is not valid. When the request argument is provided as I2C_RDWR, the argp argument is a pointer to struct i2c_rdwr_ioctl_data. This structure points to a list of messages and indicates how many of them are involved. struct i2c_rdwr_ioctl_data { struct i2c_msg *msgs; int nmsgs; }; 174 /* ptr to array of simple messages */ /* number of messages to exchange */ Chapter 14 ■ I2C Bus The individual I/O messages referenced by the preceding structure are described by struct i2c_msg: struct i2c_msg { __u16 __u16 __u16 __u8 }; addr; flags; len; *buf; /* /* /* /* 7/10 bit slave address */ Read/Write & options */ No. of bytes in buf */ Data buffer */ The members of this structure are as follows: addr: Normally this is the 7-bit slave address, unless flag I2C_M_TEN and function I2C_FUNC_10BIT_ADDR are used. Must be provided for each message. flags: Valid flags are listed in Table 14-2. Flag I2C_M_RD indicates the operation is a read. Otherwise, a write operation is assumed when this flag is absent. buf: The I/O buffer to use for reading/writing this message component. len: The number of bytes to read/write in this message component. Table 14-2. I2C Capability Flags Flag Description I2C_M_TEN 10-bit slave address used I2C_M_RD Read into buffer I2C_M_NOSTART Suppress (Re)Start bit I2C_M_REV_DIR_ADDR Invert R/W bit I2C_M_IGNORE_NAK Treat NAK as ACK I2C_M_NO_RD_ACK Read will not have ACK I2C_M_RECV_LEN Buffer can hold 32 additional bytes An actual ioctl(2,I2C_RDWR) call would be coded something like the following. In this example, a MCP23017 register address of 0x15 is being written out to peripheral address 0x20, followed by a read of 1 byte: int fd; struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[2]; static unsigned char reg_addr[] = {0x15}; unsigned char rbuf[1]; int rc; iomsgs[0].addr iomsgs[0].flags iomsgs[0].buf iomsgs[0].len = = = = 0x20; 0; reg_addr; 1; /* MCP23017−A */ /* Write operation. */ 175 Chapter 14 ■ I2C Bus iomsgs[1].addr iomsgs[1].flags iomsgs[1].buf iomsgs[1].len = = = = iomsgs[0].addr; I2C_M_RD; rbuf; 1; msgset.msgs msgset.nmsgs = iomsgs; = 2; /* Same MCP23017-A */ /* Read operation */ rc = ioctl(fd,I2C_RDWR,&msgset); if ( rc < 0 ) { perror("ioctl (2, I2C_RDWR)"); The example shown defines iomsgs[0] as a write of 1 byte, containing a register number. The entry iomsgs[1] describes a read of 1 byte from the peripheral. These two messages are performed in one ioctl(2) transaction. The flags member of iomsgs[x] determines whether the operation is a read (I2C_M_RD) or a write (0). ■■Note Don’t confuse the peripheral’s internal register with the peripheral’s I2C address. Each of the iomsgs[x].addr members must contain a valid I2C peripheral address. Each message can potentially address a different peripheral, though there are no examples of this in this book. The ioctl(2) will return an error with the first message failure. For this reason, you may not always want to combine multiple messages in one ioctl(2) call, especially when different devices are involved. The returned value, when successful, is the number of struct i2c_msg messages successfully performed. 176 Chapter 15 SPI Bus The Serial Peripheral Interface bus, known affectionately as spy, is a synchronous serial interface that was named by Motorola.39 The SPI protocol operates in full-duplex mode, allowing it to send and receive data simultaneously. Generally speaking, SPI has a speed advantage over the I2C protocol but requires more connections. SPI Basics Devices on the SPI bus communicate on a master/slave basis. Multiple slaves coexist on a given SPI bus, with each slave being selected for communication by a slave select signal (also known as chip select). Figure 15-1 shows the Raspberry Pi as the master communicating with a slave. Additional slaves would be connected as shown with the exception that a different slave select signal would be used. Figure 15-1. SPI interface Data is transmitted from the master to the slave by using the MOSI line (master out, slave in). As each bit is being sent out by the master, the slave sends data bits on the MISO line (master in, slave out). Bits are shifted out of the master and into the slave. Simultaneously, bits are shifted out of the slave and into the master. Both transfers occur to the beat of the system clock (CLK). Many SPI devices support only 8-bit transfers, while others are more flexible. The SPI bus is a de facto standard, meaning that there is no standard for data transfer width and SPI mode.39 The SPI controller can also be configured to transmit the most significant or the least significant bit first. All of this flexibility can result in confusion. 177 Chapter 15 ■ SPI Bus SPI Mode SPI operates in one of four possible clock signaling modes, based on two parameters: Parameter Description CPOL Clock polarity CPHA Clock phase Each parameter has two possibilities, resulting in four possible SPI modes of operation. Table 15-1 lists all four modes available. Note that a given mode is often referred to by using a pair of numbers like 1,0 or simply as mode 2 (for the same mode, as shown in the table). Both types of references are shown in the Mode column. Table 15-1. SPI Modes CPOL CPHA Mode Description 0 0 0,0 0 Noninverted clock, sampled on rising edge 0 1 0,1 1 Noninverted clock, sampled on falling edge 1 0 1,0 2 Inverted clock, sampled on rising edge 1 1 1,1 3 Inverted clock, sampled on falling edge Clock Sense Description Noninverted Signal is idle low, active high Inverted Signal is idle high, active low Peripheral manufacturers did not define a standard signaling convention in the beginning, so SPI controllers allow configuration to accommodate any of the four modes. However, once a mode has been chosen, all slaves on the same bus must agree. Signaling The clock polarity determines the idle clock level, while the phase determines whether the data line is sampled on the rising or falling clock signal. Figure 15-2 shows mode 0,0, which is perhaps the preferred form of SPI signaling. In Figure 15-2, the slave is selected first, by bringing the SS (slave select) active. Only one slave can be selected at a time, since there must be only one slave driving the MISO line. Shortly after the slave is selected, the master drives the MOSI line, and the slave simultaneously drives the MISO line with the first data bit. This can be the most or least significant bit, depending on how the controller is configured. The diagram shows the least significant bit first. 178 Chapter 15 ■ SPI Bus Figure 15-2. SPI signaling, modes 0 and 2 In mode 0,0 the first bit is clocked into the master and slave when the clock line falls from high to low. This clock transition is positioned midway in the data bit cell. The remaining bits are successively clocked into master and slave simultaneously as the clock transitions from high to low. The transmission ends when the master deactivates the slave select line. When the clock polarity is reversed (CPOL = 1, CPHA = 0), the clock signal shown in Figure 15-2 is simply inverted. The data is clocked at the same time in the data cell, but on the rising edge of the clock instead. Figure 15-3 shows the clock signals with the phase set to 1 (CPHA = 1). When the clock is noninverted (CPOL = 0), the data is clocked on the rising edge. Note that the clock must transition to its nonidle state one-half clock cycle earlier than when the phase is 0 (CPHA = 0). When the SPI mode is 1,1, the data is clocked in on the falling edge of the clock. Figure 15-3. SPI signaling modes 1 and 3 While the four different modes can be confusing, it is important to realize that the data is sampled at the same times within the data bit cells. The data bit is always sampled at the midpoint of the data cell. When the clock phase is 0 (CPHA = 0), the data is sampled on the trailing edge of the clock, whether falling or rising according to CPOL. When the clock phase is 1 (CPHA = 1), the data is sampled on the leading edge of the clock, whether rising or falling according to CPOL. 179 Chapter 15 ■ SPI Bus Slave Selection While some protocols address their slaves by using transmitted data, the SPI bus simply uses a dedicated line for each slave. The Raspberry Pi dedicates the GPIO pins listed in Table 15-2 as slave select lines (also known as chip enable lines). Table 15-2. Raspberry Pi Built-in Chip Enable Pins GPIO Chip Enable P1 8 CE0 P1-24 7 CE1 P1-26 The Raspbian Linux kernel driver supports the use of only these two chip enable lines. However, the driver is designed such that you don’t have to use them, or only these. It is possible, for example, to add a third GPIO pin as a slave select. The application simply takes responsibility for activating the slave select GPIO line prior to the data I/O and deactivates it after. When the driver is controlling the two slave selects, this is done automatically. Driver Support Raspbian Linux supports SPI through the spi_bcm2708 kernel module. As a loadable kernel module, it may not be loaded by default. Check for it by using the lsmod command: $ lsmod Module spidev spi_bcm2708 ... Size 5136 4401 Used by 0 0 If you would like the module loaded by default after a reboot, edit the /etc/modprobe.d file raspi-blacklist. conf. In the file, look for the line blacklist spi-bcm2708 and change that to a comment line, by putting a # character in front, as follows: # blacklist spi-bcm2708 With that module un-blacklisted, the module will automatically be loaded with each new reboot. The kernel module can be manually loaded by using modprobe command: $ sudo modprobe spi_bcm2708 This loads the module and its dependents. Once the kernel module support is present, the device driver nodes should appear: $ ls /dev/spi* /dev/spidev0.0 $ 180 /dev/spidev0.1 Chapter 15 ■ SPI Bus These two device nodes are named according to which slave select should be activated, as shown in Table 15-3. Table 15-3. SPI Device Nodes Pathname Bus Device GPIO SS /dev/spidev0.0 0 0 8 CE0 /dev/spidev0.1 0 1 7 CE1 If you open either of these device nodes by applying the option SPI_NO_CS, the node chosen makes no difference. Macro SPI_NO_CS indicates that slave select will be performed by the application instead of the driver, if any select is used at all. (When only one slave device is attached, the peripheral can be permanently selected.) SPI API The bare-metal API for SPI involves calls to ioctl(2) to configure the interface and further calls to ioctl(2) for simultaneous read and write. The usual read(2) and write(2) system calls can be used, when a one-sided transfer is being performed. Header Files The header files needed for SPI programming are as follows: #include #include #include #include #include #include The spidev.h include file defines several macros and the struct spi_ioc_transfer. Table 15-4 lists the main macros that are declared. The macros SPI_CPOL and SPI_CPHA are used in the definitions of the values SPI_MODE_x. If you prefer, it is possible to use SPI_CPOL and SPI_CPHA in place of the mode macros. 181 Chapter 15 ■ SPI Bus Table 15-4. SPI Macro Definitions Macro Supported Description SPI_CPOL Yes Clock polarity inverted (CPOL = 1) SPI_CPHA Yes Clock phase is 1 (CPHA = 1) SPI_MODE_0 Yes SPI Mode 0,0 (CPOL = 0, CPHA = 0) SPI_MODE_1 Yes SPI Mode 0,1 (CPOL = 0, CPHA = 1) SPI_MODE_2 Yes SPI Mode 1,0 (CPOL = 1, CPHA = 0) SPI_MODE_3 Yes SPI Mode 1,1 (CPOL = 1, CPHA = 1) SPI_CS_HIGH Yes Chip select is active high SPI_LSB_FIRST No LSB is transmitted first SPI_3WIRE No Use 3-Wire data I/O mode SPI_LOOP No Loop the MOSI/MISO data line SPI_NO_CS Yes Do not apply Chip Select SPI_READY No Enable extra Ready signal Communicating with an SPI device consists of the following system calls: open(2): Opens the SPI device driver node read(2): Reads with 0 bytes being transmitted write(2): Writes data while discarding received data ioctl(2): For configuration and bidirectional I/O close(2): Closes the SPI device driver node In SPI communication, the use of read(2) and write(2) is unusual. Normally, ioctl(2) is used to facilitate simultaneous read and write transfers. Open Device In order to perform SPI communication through the kernel driver, you need to open one of the device nodes by using open(2). The general format of the device pathname is /dev/spidev . as we saw earlier. The following is a code snippet opening bus 0, device 0. int fd; fd = open("/dev/spidev0.0",O_RDWR); if ( fd < 0 ) { perror("Unable to open SPI driver"); exit(1); } SPI communication involves both reading and writing, so the driver is opened for read and write (O_RDWR). 182 Chapter 15 ■ SPI Bus SPI Mode Macros Before SPI communications can be performed, the mode of communication needs to be configured. Table 15-5 lists the C language macros that can be used to configure the SPI mode to be used. Table 15-5. SPI Mode Macros Macro Effect Comments SPI_CPOL CPOL = 1 Or use SPI_MODE_x SPI_CPHA CPHA = 1 Or use SPI_MODE_x SPI_CS_HIGH SS is active high Unusual SPI_NO_CS Don’t assert select Not used/application controlled These bit values are simply or-ed together to specify the options that are required. The use of SPI_CPOL implies CPOL = 1. Its absence implies CPOL = 0. Similarly, the use of SPI_CPHA implies CPHA = 1 (otherwise, CPHA = 0). The options SPI_MODE_x use the SPI_CPOL and SPI_CPHA macros to define them. You don’t need to use them both in your code. The mode definitions are shown here: #define #define #define #define SPI_MODE_0 SPI_MODE_1 SPI_MODE_2 SPI_MODE_3 (0|0) (0|SPI_CPHA) (SPI_CPOL|0) (SPI_CPOL|SPI_CPHA) The unsupported options are not shown, though one or more of these could be supported in the future. ■■Note The mode values SPI_LOOP, SPI_LSB_FIRST, SPI_3WIRE, and SPI_READY are not currently supported in the wheezy release of Raspbian Linux. The following is an example that defines SPI_MODE_0: uint8_t mode = SPI_MODE_0; int rc; rc = ioctl(fd,SPI_IOC_WR_MODE,&mode); if ( rc < 0 ) { perror("Can't set SPI write mode."); If you’d like to find out how the SPI driver is currently configured, you can read the SPI mode with ioctl(2) as follows: uint8_t mode; int rc; rc = ioctl(fd,SPI_IOC_RD_MODE,&mode); if ( rc < 0 ) { perror("Can't get SPI read mode."); 183 Chapter 15 ■ SPI Bus Bits per Word The SPI driver also needs to know how many bits per I/O word are to be transmitted. While the driver will likely default to 8 bits, it is best not to depend on that. This can be configured with the following ioctl(2) call: uint8_t bits = 8; int rc; rc = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD,&bits); if ( rc < 0 ) { perror ("Can't set bits per SPI word."); ■■Note The SPI driver in the Raspbian wheezy release supports only 8-bit transfers. The currently configured value can be fetched with ioctl(2) as follows: uint8_t bits; int rc; rc = ioctl(fd,SPI_IOC_RD_BITS_PER_WORD,&bits); if ( rc == −1 ) { perror("Can't get bits per SPI word."); When the number of bits is not an even multiple of eight, the bits are assumed to be right-justified. For example, if the word length is set to 4 bits, the least significant 4 bits are transmitted. The higher-order bits are ignored. Likewise, when receiving data, the least significant bits contain the data. All of this is academic on the Pi, however, since the driver supports only byte-wide transfers. Clock Rate To configure the data transmission rate, you can set the clock rate with ioctl(2) as follows: uint32_t speed = 500000; /* Hz */ int rc; rc = ioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,&speed); if ( rc < 0 ) { perror("Can't configure SPI clock rate."); The current configured clock rate can be fetched by using the following ioctl(2) call: uint32_t speed; /* Hz */ int rc; rc = ioctl(fd,SPI_IOC_RD_MAX_SPEED_HZ,&speed); if ( rc < 0 ) { perror("Can't get SPI clock rate."); 184 Chapter 15 ■ SPI Bus Data I/O SPI communication involves transmitting data while simultaneously receiving data. For this reason, the read(2) and write(2) system calls are usually inappropriate. The ioctl(2) call can, however, perform a simultaneous read and write. The SPI_IOC_MESSAGE(n) form of the ioctl(2) call uses the following structure as its argument: struct spi_ioc_transfer { __u64 tx_buf; __u64 rx_buf; __u32 len; __u32 speed_hz; __u16 delay_usecs; __u8 bits_per_word; __u8 cs_change; __u32 pad; }; /* /* /* /* /* /* /* /* Ptr to tx buffer */ Ptr to rx buffer */ # of bytes */ Clock rate in Hz */ Delay in microseconds */ Bits per "word" */ Apply chip select */ Reserved */ The tx_buf and rx_buf structure members are defined as a 64-bit unsigned integers (__u64). For this reason, you must cast your buffer pointers when making assignments to them: uint8_t tx[32], rx[32]; struct spi_ioc_transfer tr; tr.tx_buf = (unsigned long) tx; tr.rx_buf = (unsigned long ) rx; On the Raspberry Pi, you will see example code that simply casts the pointers to unsigned long. The compiler automatically promotes these 32-bit values to a 64-bit value. This is safe on the Pi because the pointer value is a 32-bit value. If you do not wish to receive data (maybe because it is “don’t care” data), you can null out the receive buffer: uint8_t tx[32]; struct spi_ioc_transfer tr; tr.tx_buf = (unsigned long) tx; tr.rx_buf = 0; /* ignore received data */ Note that to receive data, the master must always transmit data to shift data out of the slave peripheral. If any byte transmitted will do, you can omit the transmit buffer. Zero bytes will then be automatically transmitted by the driver to shift the slave data out onto the MISO line. It is also permissible to transmit from the buffer you’re receiving into: uint8_t io[32]; struct spi_ioc_transfer tr; tr.tx_buf = (unsigned long) io; tr.rx_buf = (unsigned long) io; /* Transmit buffer */ /* is also recv buffer */ The len structure member indicates the number of bytes for the I/O transfer. Receive and transmit buffers (when both used) are expected to transfer the same number of bytes. 185 Chapter 15 ■ SPI Bus The member speed_hz defines the clock rate that you wish to use for this I/O, in Hz. This overrides any value configured in the mode setup, for the duration of the I/O. The value will be automatically rounded down to a supported clock rate when necessary. When the value speed_hz is 0, the previously configured clock rate is used (SPI_IOC_WR_MAX_SPEED_HZ). When the delay_usecs member is nonzero, it specifies the number of microseconds to delay between transfers. It is applied at the end of a transfer, rather than at the start. When there are multiple I/O transfers in a single ioctl(2) request, this allows time in between so that the peripheral can process the data. The bits_per_word member defines how many bits there are in a “word” unit. Often the unit is 1 byte (8 bits), but it need not be (but note that the Raspbian Linux driver supports only 8 bits). An application might use 9 bits to transmit the 8-bit byte and a parity bit, for example. The bits communicated on the SPI bus are taken from the least significant bits of the buffer bytes. This is true even when transmitting the most significant bit first. When the bits_per_word value is 0, the previously configured value from SPI_IOC_WR_BITS_PER_WORD is used. (See drivers/spi/spi-bcm2708.c in the function bcm2708_process_transfer()). ■■Note The Raspbian wheezy driver requires that bits_per_word is the value 8 or 0. The cs_change member is treated as a Boolean value. When 0, no chip select is performed by the driver. The application is expected to do what is necessary to notify the peripheral that it is selected (usually a GPIO pin is brought low). Once the I/O has completed, the application then must normally unselect the slave peripheral. When the cs_change member is true (non-zero), the slave selected will depend on the device pathname that was opened. The bus and the slave address are embedded in the device name: /dev/spidev . When cs_change is true, the driver asserts GPIO8 for spidev0.0 and asserts GPIO7 for spidev0.1 prior to I/O and then deactivates the same upon completion. Of course, using these two nodes requires two different open(2) calls. The SPI_IOC_MESSAGE(n) macro is used in the ioctl(2) call to perform one or more SPI I/O operations. The macro is unusual because it requires an argument n. (Perhaps someone will take it upon themselves someday to clean this interface up to work like I2C.) This specifies how many I/O transfers you would like to perform. An array of spi_ioc_transfer structures is declared and configured for each transfer required, as shown in the next example: struct spi_ioc_transfer io[3]; int rc; io[0].tx_buf = . . . ; ... io[2].bits_per_word = 8; /* Define 3 transfers */ /* Configure I/O */ rc = ioctl(fd,SPI_IOC_MESSAGE(3),& io[0]); The preceding example will perform three I/O transfers. Since the application never gets to perform any GPIO manipulation between these I/Os, this applies to communicating with one particular slave device. 186 Chapter 15 ■ SPI Bus The following example code brings all of the concepts together, to demonstrate one I/O. The spi_ioc_transfer structure is initialized so that 32 bytes are transmitted and simultaneously 32 are received. uint8_t tx[32], rx[32]; struct spi_ioc_transfer tr; int rc; tr.tx_buf tr.rx_buf tr.len tr.delay_usecs tr.speed_hz tr.bits_per_word = = = = = = (unsigned long) tx; (unsigned long) rx; 32; delay; speed; bits; rc = ioctl(fd,SPI_IOC_MESSAGE(1),&tr); if ( rc < 1 ) { perror("Can't send spi message"); Here a single I/O transmission occurs, with data being sent from array tx and received into array rx. The return value from the ioctl(2) call returns the number of bytes transferred (32 in the example). Otherwise, -1 is returned to indicate that an error has occurred. Close Like all Unix I/O operations, the device is closed when the open file descriptor is no longer required: close(fd); Write The write(2) system call can be used, if the received data is unimportant. Note, however, that no delay is applied with this call. Read The read(2) system call is actually inappropriate for SPI since the master must transmit data on MOSI in order for the slave to send bits back on the MISO line. However, when read(2) is used, the driver will automatically send out 0 bits as necessary to accomplish the read. (Be careful that your peripheral will accept 0 bytes without unintended consequences.) Like the write(2) call, no delay is provided. SPI Testing When developing your SPI communication software, you can perform a simple loopback test to test your framework. Once the framework checks out, you can then turn your attention to communicating with the actual device. While the Raspbian Linux driver does not support the SPI_LOOP mode bit (in the wheezy release), you can still physically loop your SPI bus by connecting a wire from the MOSI output back to the MISO input pin (connect GPIO 10 to GPIO 9). 187 Chapter 15 ■ SPI Bus A simple program, shown next, demonstrates this type of loopback test. It will write out 4 bytes (0x12, 0x23, 0x45, and 0x67) to the SPI driver. Because you have wired the MOSI pin to the MISO input, anything transmitted will also be received. When the program executes, it will report the number of bytes received and four hexadecimal values: $ sudo ./spiloop rc=4 12 23 45 67 $ If you remove the wire between MOSI and MISO, and connect the MISO to a high (+3.3 V), you should be able to read 0xFF for all of the received bytes. If you then connect MISO to ground, 0x00 will be received for each byte instead. (Be certain to apply to the correct pin, since applying high or low to an output can damage it, and do not apply +5 V.) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /******************************************** * spiloop.c − Example loop test * Connect MOSI (GPIO 10) to MISO (GPIO 9) ********************************************/ #include #include #include #include #include #include #include #include #include static int fd = −1; static void errxit(const char *msg) { perror(msg); exit(1); } int main(int argc, char ** argv) { static uint8_t tx[] = {0x12, 0x23, 0x45, 0x67}; static uint8_t rx[] = {0xFF, 0xFF, 0xFF, 0xFF}; struct spi_ioc_transfer ioc = { .tx_buf = (unsigned long) tx, .rx_buf = (unsigned long) rx, .len = 4, .speed_hz = 100000, .delay_usecs = 10, .bits_per_word = 8, .cs_change = 1 } ; uint8_t mode = SPI_MODE_0; int rc; 188 Chapter 15 ■ SPI Bus 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 } fd = open("/dev/spidev0.0",O_RDWR); if ( fd < 0 ) errxit("Opening SPI device."); rc = ioctl(fd,SPI_IOC_WR_MODE,&mode); if ( rc < 0 ) errxit("ioctl (2) setting SPI mode."); rc = ioctl(fd,SPI_IOC_WR_BITS_PER_WORD,&ioc.bits_per_word); if ( rc < 0 ) errxit("ioctl (2) setting SPI bits perword."); rc = ioctl(fd,SPI_IOC_MESSAGE(1),&ioc); if ( rc < 0 ) errxit("ioctl (2) for SPI I/O"); close(fd); printf("rc=%d %02X %02X %02X %02X\n", rc, rx[0], rx[1], rx[2], rx[3]); return 0; 189 Chapter 16 Boot When the power is first applied to the Raspberry Pi, or it has been reset (see the “Reset” section of Chapter 5), a boot sequence is initiated. As you will see in this chapter, it is the GPU that actually brings up the ARM CPU. The way that the Raspberry Pi is designed, it must be booted from firmware found on the SD card. It cannot boot from any other source. RISC code for the GPU is provided by the Raspberry Pi Foundation in the file bootcode.bin. After the second-stage boot loader has been executed, it is possible that other operating systems or ARM boot loaders such as U-Boot can be initiated. Booting ARM Linux Generally speaking, Linux under the ARM architecture needs a small amount of assistance to get started. The following are some of the minimal things that the boot loader needs to do:25 1. Initialize and configure memory (with MMU, cache, and DMA disabled) 2. Load the kernel image into memory 3. Optionally, load an initial RAM disk image 4. Initialize and provide boot parameters to the loaded kernel (ATAG list) 5. Obtain/determine the Linux machine type (MACH_TYPE) 6. Execute the kernel image with the correct starting register values (r1 = machine number, r2 points to the ATAG list) 7. Additionally, the boot loader is expected to perform some initialization of a serial and/or video console. In the Raspberry Pi, this boot-loading assistance comes from the embedded GPU in the SoC. The GPU supports a small RISC core that is able to run from initial code found in its ROM. From this small amount of code, the GPU is able to initialize itself and the SD card hardware. From the media on the SD card, it is able to bootstrap itself the rest of the way. For this reason, the Raspberry Pi must always bootstrap from an SD card. Boot Sequence This section looks at the startup sequence in greater detail. The participating hardware components, the files and data elements are considered. The boot procedure consists of the following sequence of events: 1. At power-up (or reset), the ARM CPU is offline.23 2. A small RISC core in the GPU begins to execute SoC ROM code (first-stage boot loader). 191 Chapter 16 ■ Boot 3. The GPU initializes the SD card hardware. 4. The GPU looks at the first FAT32 partition in the SD media. (There remains some question about specific limitations as Broadcom has documented this—for example, can it boot from a first FAT16 partition?) 5. The second-stage boot-loader firmware named bootcode.bin is loaded into the GPU. 6. The GPU control passes to the loaded bootcode.bin firmware (SDRAM is initially disabled). 7. The file start.elf is loaded by the GPU into RAM from the SD card. 8. An additional file, fixup.dat, is used to configure the SDRAM partition between GPU and ARM CPU. 9. The file config.txt is examined for configuration parameters that need to be processed. 10. Information found in cmdline.txt is presumably also passed to start.elf. 11. The GPU allows the ARM CPU to execute the program start.elf. 12. The module start.elf runs on the ARM CPU, with information about the kernel to be loaded. 13. The kernel is loaded, and execution control passes to it. Boot Files The FAT32 partition containing the boot files is normally mounted as /boot, after Raspbian Linux has come up. Table 16-1 lists the files that apply to the boot process. The text files can be edited to affect new configurations. The binary files can also be replaced by new revisions of the same. Table 16-1. /boot Files File Name Purpose Format bootcode.bin Second-stage boot loader Binary fixup.dat Configure split of GPU/CPU SDRAM Binary config.txt Configuration parameters Text cmdline.txt Command-line parameters for kernel Text start.elf ARM CPU code to be launched Binary kernel.img Kernel to be loaded Binary Name can be overridden with kernel= parameter in config.txt config.txt The config.txt file permits you to configure many aspects of the boot process. Some options affect physical devices, and others affect the kernel being loaded. 192 Chapter 16 ■ Boot Composite Video Settings The composite video output from the Raspberry Pi is primarily configured by three basic parameters: • sdtv_mode • sdtv_aspect • sdtv_disable_colourburst Standard Definition Video The parameter sdtv_mode determines the video mode (TV standard) of the composite video output jack. sdtv_mode Description 0 Normal NTSC (default) 1 Japanese NTSC (no pedestal) 2 Normal PAL 3 Brazilian PAL 525/60 Composite Aspect Ratio The sdtv_aspect parameter configures the composite video aspect ratio. sdtv_aspect Description 1 4:3 (default) 2 14:9 3 16:9 Color Burst By default, color burst is enabled. This permits the generation of color out of the composite video jack. Setting the video for monochrome may be desirable for a sharper display. sdtv_disable_colourburst Description 0 Color burst enabled (default) 1 Color burst disabled (monochrome) 193 Chapter 16 ■ Boot High-Definition Video This section covers config.txt settings that affect HDMI operation. HDMI Safe Mode The hdmi_safe parameter enables support of automatic HDMI configuration for optimal compatibility. hdmi_safe Description 0 Disabled (default) 1 Enabled When hdmi_safe=1 (enabled), the following settings are implied: • hdmi_force_hotplug=1 • config_hdmi_boost=4 • hdmi_group=1 • hdmi_mode=1 • disable_overscan=0 HDMI Force Hot-Plug This configuration setting allows you to force a hot-plug signal for the HDMI display, whether the display is connected or not. The NOOBS distribution enables this setting by default. hdmi_force_hotplug Description 0 Disabled (non-NOOBS default) 1 Use HDMI mode even when no HDMI monitor is detected (NOOBS default) HDMI Ignore Hot-Plug Enabling the hdmi_ignore_hotplug setting causes it to appear to the system that no HDMI display is attached, even if there is. This can help force composite video output, while the HDMI display is plugged in. hdmi_ignore_hotplug Description 0 Disabled (default) 1 Use composite video even if an HDMI display is detected 194 Chapter 16 ■ Boot HDMI Drive This mode allows you to choose between DVI (no sound) and HDMI mode (with sound, when supported). hdmi_drive Description 1 Normal DVI mode (no sound) 2 Normal HDMI mode (sound will be sent if supported and enabled) HDMI Ignore EDID Enabling this option causes the EDID information from the display to be ignored. Normally, this information is helpful and is used. hdmi_ignore_edid Description Unspecified Read EDID information 0xa5000080 Ignore EDID information HDMI EDID File When hdmi_edid_file is enabled, the EDID information is taken from the file named edid.txt. Otherwise, it is taken from the display, when available. hdmi_edid_file Description 0 Read EDID data from device (default) 1 Read EDID data from edid.txt file HDMI Force EDID Audio Enabling this option forces the support of all audio formats even if the display does not support them. This permits pass-through of DTS/AC3 when reported as unsupported. hdmi_force_edid_audio Description 0 Use EDID-provided values (default) 1 Pretend all audio formats are supported 195 Chapter 16 ■ Boot Avoid EDID Fuzzy Match Avoid fuzzy matching of modes described in the EDID. avoid_edid_fuzzy_match Description 0 Use fuzzy matching (default) 1 Avoid fuzzy matching HDMI Group The hdmi_group option defines the HDMI type. hdmi_group Description 0 Use the preferred group reported by the EDID (default) 1 CEA 2 DMT HDMI Mode This option defines the screen resolution to use in CEA or DMT format (see the parameter hdmi_group in the preceding subsection “HDMI Group”). In Table 16-2, the modifiers shown have the following meanings: H means 16:9 variant of a normally 4:3 mode. 2x means pixel doubled (higher clock rate). 4x means pixel quadrupled (higher clock rate). R means reduced blanking (fewer bytes are used for blanking within the data stream, resulting in lower clock rates). Table 16-2. HDMI Mode Settings Group CEA DMT Mode Resolution 1 VGA 2 480 p 60 Hz 3 480 p 60 Hz 4 720 p 5 6 Refresh Modifiers Resolution Refresh 640×350 85 Hz 640×400 85 Hz 720×400 85 Hz 60 Hz 640×480 60 Hz 1080 i 60 Hz 640×480 72 Hz 480 i 60 Hz 640×480 75 Hz H Notes (continued) 196 Chapter 16 ■ Boot Table 16-2. (continued) Group CEA DMT Mode Resolution Refresh Modifiers Resolution Refresh 7 480 i 60 Hz H 640×480 85 Hz 8 240 p 60 Hz 800×600 56 Hz 9 240 p 60 Hz H 800×600 60 Hz 10 480 i 60 Hz 4x 800×600 72 Hz 11 480 i 60 Hz 4x H 800×600 75 Hz 12 240 p 60 Hz 4x 800×600 85 Hz 13 240 p 60 Hz 4x H 800×600 120 Hz 14 480 p 60 Hz 2x 848×480 60 Hz 15 480 p 60 Hz 2x H 1024×768 43 Hz 16 1080 p 60 Hz 1024×768 60 Hz 17 576 p 50 Hz 1024×768 70 Hz 18 576 p 50 Hz 1024×768 75 Hz 19 720 p 50 Hz 1024×768 85 Hz 20 1080 i 50 Hz 1024×768 120 Hz 21 576 i 50 Hz 1152×864 75 Hz 22 576 i 50 Hz 23 288 p 50 Hz 24 288 p 50 Hz 25 576 i 26 H H 1280×768 Notes Don’t use R 1280×768 60 Hz H 1280×768 75 Hz 50 Hz 4x 1280×768 85 Hz 576 i 50 Hz 4x H 1280×768 120 Hz 27 288 p 50 Hz 4x 1280×800 28 288 p 50 Hz 4x H 1280×800 60 Hz 29 576 p 50 Hz 2x 1280×800 75 Hz 30 576 p 50 Hz 2x H 1280×800 85 Hz 31 1080 p 50 Hz 1280×800 120 Hz 32 1080 p 24 Hz 1280×960 60 Hz 33 1080 p 25 Hz 1280×960 85 Hz 34 1080 p 30 Hz 1280×960 120 Hz 35 480 p 60 Hz 4x 1280×1024 60 Hz 36 480 p 60 Hz 4x H 1280×1024 75 Hz 37 576 p 50 Hz 4x 1280×1024 85 Hz R R R R (continued) 197 Chapter 16 ■ Boot Table 16-2. (continued) Group CEA DMT Mode Resolution Refresh Modifiers Resolution Refresh Notes 38 576 p 50 Hz 4x H 1280×1024 120 Hz R 39 1080 i 50 Hz R 1360×768 60 Hz 40 1080 i 100 Hz 1360×768 120 Hz 41 720 p 100 Hz 1400×1050 42 576 p 100 Hz 1400×1050 60 Hz 43 576 p 100 Hz 1400×1050 75 Hz 44 576 i 100 Hz 1400×1050 85 Hz 45 576 i 100 Hz 1400×1050 120 Hz 46 1080 i 120 Hz 1440×900 47 720 p 120 Hz 1440×900 60 Hz 48 480 p 120 Hz 1440×900 75 Hz 49 480 p 120 Hz 1440×900 85 Hz 50 480 i 120 Hz 1440×900 120 Hz 51 480 i 120 Hz 1600×1200 60 Hz 52 576 p 200 Hz 1600×1200 65 Hz 53 576 p 200 Hz 1600×1200 70 Hz 54 576 i 200 Hz 1600×1200 75 Hz 55 576 i 200 Hz 1600×1200 85 Hz 56 480 p 240 Hz 1600×1200 120 Hz 57 480 p 240 Hz 58 480 i 240 Hz 59 480 i 240 Hz H H H H H H H R R R 1680×1050 R R R 1680×1050 60 Hz 1680×1050 75 Hz 60 1680×1050 85 Hz 61 1680×1050 120 Hz 62 1792×1344 60 Hz 63 1792×1344 75 Hz 64 1792×1344 120 Hz 65 1856×1392 60 Hz 66 1856×1392 75 Hz 67 1856×1392 120 Hz 68 1920×1200 H R R R R R (continued) 198 Chapter 16 ■ Boot Table 16-2. (continued) Group CEA DMT Mode Resolution Resolution Refresh 69 1920×1200 60 Hz 70 1920×1200 75 Hz 71 1920×1200 85 Hz 72 1920×1200 120 Hz 73 1920×1440 60 Hz 74 1920×1440 75 Hz 75 1920×1440 120 Hz 76 2560×1600 77 2560×1600 60 Hz 78 2560×1600 75 Hz 79 2560×1600 85 Hz 80 2560×1600 120 Hz 81 1366×768 60 Hz 82 1080 p Refresh Modifiers Notes R R R R 60 Hz 83 1600×900 R 84 2048×1152 R 1366×768 R 85 720 p 60 Hz 86 HDMI Boost The config_hdmi_boost parameter allows you to tweak the HDMI signal strength. config_hdmi_boost Description 0 Non-NOOBS default 1 2 3 4 Use if you have interference issues (NOOBS default setting) 5 6 7 Maximum strength 199 Chapter 16 ■ Boot HDMI Ignore CEC Init When this option is enabled, the CEC initialization is not sent to the device. This avoids bringing the TV out of standby and channel switch when rebooting. hdmi_ignore_cec_init Description 0 Normal (default) 1 Don’t send initial active source message HDMI Ignore CEC When this option is enabled, the assumption made is that CEC is not supported at all by the HDMI device, even if the device does have support. As a result, no CEC functions will be supported. hdmi_ignore_cec Description 0 Normal (default) 1 Disable CEC support Overscan Video A few options control the overscan support of the composite video output. When overscan is enabled, a certain number of pixels are skipped at the sides of the screen as configured. Disable Overscan The disable_overscan option can disable the overscan feature. It is enabled by default: disable_overscan Description 0 Overscan enabled (default) 1 Overscan disabled Overscan Left, Right, Top, and Bottom These parameters control the number of pixels to skip at the left, right, top, and bottom of the screen. Parameter Pixels to Skip overscan_left=0 At left overscan_right=0 At right overscan_top=0 At top overscan_bottom=0 At bottom 200 Chapter 16 ■ Boot Frame Buffer Settings The Linux frame buffer support is configured by a few configuration options described in this section. Frame Buffer Width The default is to define the width of the frame buffer as the display’s width minus the overscan pixels. framebuffer_width Description default Display width overscan framebuffer_width=n Set width to n pixels Frame Buffer Height The default is to define the height of the frame buffer as the display’s height minus the overscan pixels. framebuffer_height Description default Display height overscan framebuffer_height=n Set height to n pixels Frame Buffer Depth This parameter defines the number of bits per pixel. framebuffer_depth Description 8 Valid, but default RGB palette makes an unreadable screen 16 Default 24 Looks better but has corruption issues as of 6/15/2012 32 No corruption, but requires framebuffer_ignore_alpha=1, and shows wrong colors as of 6/15/2012 Frame Buffer Ignore Alpha The alpha channel can be disabled with this option. As of this writing, this option must be used when using a frame buffer depth of 32 bits. framebuffer_ignore_alpha Description 0 Alpha channel enabled (default) 1 Alpha channel disabled 201 Chapter 16 ■ Boot General Video Options The display can be flipped or rotated in different ways, according to the display_rotate option. You should be able to do both a flip and a rotate by adding the flip values to the rotate value. ■■Note I was unable to get the flip options to work on Linux Raspberry Pi 3.2.27+ #250. It is possible that a newer version of the boot-loader bootcode.bin may be needed. But as of 2014, this remains an issue. The 90º and 270º rotations require additional memory on the GPU, so these options won’t work with a 16 MB GPU split. display_rotate Description 0 0º (default) 1 90º 2 180º 3 270º 0x1000 Horizontal flip 0x2000 Vertical flip While the flip options are documented, I was unable to get them to work. The rotations, however, were confirmed as working. Licensed Codecs The following options permit you to configure the purchased license key codes for the codecs they affect. Option Notes decode_MPG2=0x12345678 License key for hardware MPEG-2 decoding decode_WVC1=0x12345678 License key for hardware VC-1 decoding Testing The following test option enables image/sound tests during boot. This is intended for manufacturer testing. test_mode Description 0 Disable test mode (default) 1 Enable test mode 202 Chapter 16 ■ Boot Memory This section summarizes configuration settings pertaining to memory. Disable GPU L2 Cache The disable_l2cache option allows the ARM CPU access to the GPU L2 cache to be disabled. This needs the corresponding L2 disabled in the kernel. disable_l2cache Description 0 Enable GPU L2 cache access (default) 1 Disable GPU L2 cache access GPU Memory (All) The gpu_mem option allows configuration of the GPU memory for all Raspberry Pi board revisions (unless gpu_mem_256 or gpu_mem_512 is supplied). gpu_mem Description gpu_mem=64 Default is 64 MB gpu_mem=128 128 MB GPU Memory (256) The gpu_mem_256 option allows configuration of the GPU memory for the 256 MB Raspberry Pi boards. When specified, it overrides the gpu_mem option setting. gpu_mem_256 Description unspecified Defined by gpu_mem option gpu_mem_256=128 128 MB (example) GPU Memory (512) The gpu_mem_512 option configures the GPU memory allocated for the 512 MB Raspberry Pi boards. When specified, it overrides the gpu_mem option setting. gpu_mem_512 Description unspecified Defined by gpu_mem option gpu_mem_512=128 128 MB (example) 203 Chapter 16 ■ Boot Boot Options Several options in this section affect the boot process. Many options pertain to the kernel being started, while others affect file systems and devices. Disable Command-Line Tags The disable_commandline_tags option permits the user to prevent start.elf from filling in ATAGS memory before launching the kernel. This prevents the cmdline.txt file from being supplied to the kernel at boot time. disable_commandline_tags Description 0 Enable ATAGS (default) 1 Disable command line in ATAGS Command Line The cmdline option allows you to configure the kernel command-line parameters within the config.txt file, instead of the cmdline.txt file. cmdline Description unspecified Command line is taken from cmdline.txt cmdline=“command” Command line is taken from parameter Kernel By default, start.elf loads the kernel from the file named kernel.img. Specifying the kernel parameter allows the user to change the file’s name. kernel Description unspecified kernel=“kernel.img” (default) kernel=“plan9.img” kernel=“plan9.img” Kernel Address This parameter determines the memory address where the kernel image is loaded into. kernel_address Description 0x00000000 Default 204 Chapter 16 ■ Boot RAM File System File The ramfsfile parameter names the file for the RAM FS file, to be used with the kernel. ramfsfile Description unspecified No RAM FS file used ramfsfile=“ramfs.file” File ramfs.file is used RAM File System Address The ramfsaddr parameter specifies where the RAM file system image is to be loaded into memory. ramfsaddr Description 0x00000000 Default address Init RAM File System This option is a convenience option, which combines the options ramfsfile and ramfsaddr. initramfs Arg 1 Arg 2 Description initramfs initram.gz 0x00800000 Example Device Tree Address The device_tree_address option defines where the device tree address is loaded. device_tree_address Description 0x00000000 Default Init UART Baud The init_uart_baud option allows the user to reconfigure the serial console to use a baud rate that is different from the default. init_uart_baud Description 115200 Default baud rate 205 Chapter 16 ■ Boot Init UART Clock The init_uart_clock parameter permits the user to reconfigure the UART to use a different clock rate. init_uart_clock Description 3000000 Default Init EMMC Clock The init_emmc_clock parameter allows the user to tweak the EMMC clock, which can improve the SD card performance. init_emmc_clock Description 100000000 Default Boot Delay The boot_delay and boot_delay_ms options allow the user to reconfigure the delay used by start.elf prior to loading the kernel. The actual delay time used is computed from the following: D = 1000 ´ b + m where • D is the computed delay in milliseconds. • b is the boot_delay value. • m is the boot_delay_ms value. boot_delay (b) Description 1 Default The boot_delay_ms augments the boot_delay parameter. boot_delay_ms (m) Description 0 Default Avoid Safe Mode A jumper or switch can be placed between pins P1-05 (GPIO 1) and P1-06 (ground) to cause start.elf to initiate a safe mode boot. If GPIO 1 is being used for some other I/O function, the safe mode check should be disabled. avoid_safe_mode Description 0 Default (check P1-05 for safe mode) 1 Disable safe mode check 206 Chapter 16 ■ Boot Overclocking According to the Raspberry Pi Configuration Settings file, Revision 14 (http://elinux.org/RPi_config.txt) the ARM CPU, SDRAM, and GPU have their own clock signals (from a PLL). The GPU core, H.264, V3D, and ISP all share the same clock. The following commands can be used to check your CPU, once you have a command-line prompt. The /proc/ cpuinfo pseudo file will give you a BogoMIPS figure: $ cat /proc/cpuinfo Processor : ARMv6−compatible processor rev 7 ( v6l ) BogoMIPS : 697.95 Features : swp half thumb fastmult vfp edsp java tls CPU implementer : 0x41 CPU architecture : 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 7 Hardware : BCM2708 Revision : 000f Serial : 00000000 f52b69e9 $ The vcgencmd can be used to read the ARM CPU clock frequency: $ vcgencmd measure_clock arm frequency (45)=700074000 $ To configure for overclocking, you start with the phase-locked loop (PLL). The PLL frequency is computed as follows: æ 2400 ö p = floor ç ÷ ( 2c ) è 2c ø where • p is the computed PLL frequency. • c is the core frequency. From this, the GPU frequency multiple m is computed from a trial GPU frequency t as follows: p m= t The value m is then rounded to the nearest even integer value, and the final GPU frequency g is computed as follows: p g= m If we take an example where the core frequency c is 500 MHz, then p is determined as follows: æ 2400 ö P = floor ç ÷ ´ ( 2 ´ 500 ) è 2 ´ 500 ø = 2000 207 Chapter 16 ■ Boot Further, if we are targeting a GPU frequency of 300 MHz, we compute m: m= 2000 = 6.666 300 The value m is rounded to the nearest even integer: m =6 The final GPU frequency becomes g= p 2000 = = 333.33 m 6 The example GPU clock is 333.33 MHz. Table 16-3 lists the standard clock profiles, as provided by the Raspberry Pi Foundation. Additionally, it is stated that if the SoC reaches temp_limit, the overclock settings will be disabled. The value of temp_limit is configurable. Table 16-3. Standard Clock Profiles Profile ARM CPU Core SDRAM Over Voltage None 700 MHz 250 MHz 400 MHz 0 Modest 800 MHz 300 MHz 400 MHz 0 Medium 900 MHz 333 MHz 450 MHz 2 High 950 MHz 450 MHz 450 MHz 6 Turbo 1000 MHz 500 MHz 500 MHz 6 Warranty and Overclocking At one time, overclocking could void your warranty. Also note that Internet forum users have reported SD card corruption when trying out overclocked configurations (though several improvements to SD card handling have been made). Be sure to back up your SD card. The following combination of parameters may set a permanent bit in your SoC chip and void your warranty. While the Raspberry Pi announcement (www.raspberrypi.org/introducingturbo-mode-up-to-50-more-performance-for-free/) speaks of overclocking without voiding the warranty, it is subject to some conditions like using the cpufreq driver. The following conditions may put your warranty in jeopardy: 208 • ver_voltage > 0, and at least one of the following: • force_turbo = 1 • current_limit_override = 0x5A000020 • temp_limit > 85 Chapter 16 ■ Boot Force Turbo Mode The documentation indicates that force_turbo has no effect if other overclocking options are in effect. By default, force_turbo is disabled. When disabled, it disables some other configuration options such as h264_freq. However, enabling force_turbo also enables h264_freq, v3d_freq, and isp_freq. force_turbo Description 0 (default) Enables dynamic clocks and voltage for the ARM core, GPU core, and SDRAM. In this mode, settings for h264_freq, v3d_freq, and isp_freq are ignored. 1 Disables dynamic clocks and voltage for the ARM core, GPU core, and SDRAM. Configuration option values h264_freq, v3d_freq, and isp_freq apply when specified. Initial Turbo The initial_turbo option is described in config.txt as “enables turbo mode from boot for the given value in seconds (up to 60).” This is somewhat confusing. What is meant is that turbo mode will be enabled after a delay of a configured number of seconds after boot. By default, if turbo mode is enabled, it is enabled immediately (after examining config.txt). The initial_turbo option allows the boot process to proceed at normal clock rates until the process has progressed to a certain point. Some people on Internet forums that experience SD card corruption from overclocking will suggest the initial_turbo option as a solution. initial_turbo Description 0 No timed turbo mode (default) 60 Maximum number of seconds after boot before enabling turbo mode Temperature Limit The temp_limit configuration option allows the user to override the default safety limit. Increasing this value beyond 85ºC voids your warranty. When the SoC temperature exceeds temp_limit, the clocks and voltages are set to default values for safer operation. temp_limit Description 85 Temperature limit in Celsius (default) > 85 Voids your warranty 209 Chapter 16 ■ Boot ARM CPU Frequency The parameter arm_freq sets the clock frequency of the ARM CPU in MHz. This option applies in non-turbo and turbo modes. arm_freq Description 700 Default ARM CPU frequency, in MHz > 700 May void warranty—check related conditions Minimum ARM CPU Frequency This option can be used when using dynamic clocking of the ARM CPU. This sets the lowest clock speed for the ARM. arm_freq_min Description 700 Default ARM CPU frequency in MHz > 700 May void warranty—check related conditions GPU Frequency The gpu_freq option determines the following other values: Parameter MHz core_freq Core frequency h264_freq H.264 frequency isp_freq Image sensor pipeline frequency v3d_freq 3D video block frequency The gpu_freq parameter has the following default value: gpu_freq Description 250 Default GPU frequency (MHz) Core Frequency The core_freq option allows the user to configure the GPU processor core clock. This parameter also affects the ARM performance, since it drives the L2 cache. core_freq Description 250 Default in MHz 210 Chapter 16 ■ Boot Minimum Core Frequency When dynamic clocking is used, this sets the minimum GPU processor core clock rate. See also the core_freq option. Like the core_freq option, this parameter affects the ARM performance, since it drives the L2 cache. core_freq_min Description 250 Default in MHz H.264 Frequency This parameter configures the frequency of the video block hardware. This parameter applies when force_turbo mode is enabled. h264_freq Description 250 Default in MHz ISP Frequency This parameter configures the image sensor pipeline clock rate and applies when force_turbo mode is enabled. isp_freq Description 250 Default in MHz V3D Frequency The v3d_freq configures the 3D block frequency in MHz. This parameter applies when force_turbo mode is enabled. v3d_freq Description 250 Default in MHz SDRAM Frequency The sdram_freq parameter allows the user to configure frequency of the SDRAM. sdram_freq Description 400 Default in MHz 211 Chapter 16 ■ Boot Minimum SDRAM Frequency When dynamic clocks are used, the sdram_freq_min allows the user to configure a minimum clock rate in MHz. sdram_freq_min Description 400 Default in MHz Avoid PWM PLL The avoid_pwm_pll configuration parameter allows the user to unlink the core_freq from the rest of the GPU. A Pi configuration note states, “analog audio should still work, but from a fractional divider, so lower quality.” avoid_pwm_pll Description 0 Linked core_freq (default) 1 Unlinked core_freq Voltage Settings The configuration parameters in this subsection configure voltages for various parts of the Raspberry Pi. Current Limit Override When supplied, the switched-mode power supply current limit protection is disabled. This can be helpful with overclocking if you are encountering reboot failures. current_limit_override Description Unspecified Default (limit in effect) 0x5A000020 Disables SMPS current limit protection Over Voltage The ARM CPU and GPU core voltage can be adjusted through the over_voltage option. Use the values shown in Table 16-4. Over Voltage Minimum The over_voltage_min option can be used when dynamic clocking is employed, to prevent the voltage dropping below a specified minimum. Use the values from Table 16-4. 212 Chapter 16 ■ Boot Table 16-4. Voltage Parameter Values Parameter Voltage Notes -16 0.8 V -15 0.825 V -14 0.85 V -13 0.875 V -12 0.9 V -11 0.925 V -10 0.95 V -9 0.975 V -8 1.0 V -7 1.025 V -6 1.05 V -5 1.075 V -4 1.1 V -3 1.125 V -2 1.15 V -1 1.175 V 0 1.2 V 1 1.225 V 2 1.25 V 3 1.275 V 4 1.3 V 5 1.325 V 6 1.35 V 7 1.375 V Requires force_turbo=1 8 1.4 V Requires force_turbo=1 Default Over Voltage SDRAM The over_voltage_sdram configuration option is a convenient way to set three options at once: • over_voltage_sdram_c: SDRAM controller voltage • over_voltage_sdram_i: SDRAM I/O voltage adjust • over_voltage_sdram_p: SDRAM physical voltage adjust Raspberry Pi documentation says the over_voltage_sdram option “sets over_ voltage_sdram_c, over_voltage_ sdram_i, over_voltage_sdram_p together.” Use the values shown in Table 16-4. 213 Chapter 16 ■ Boot SDRAM Controller Voltage Use the over_voltage_sdram_c option to set the voltage for the SDRAM controller. Use the values shown in Table 16-4. See also the over_voltage_sdram option. SDRAM I/O Voltage Use the over_voltage_sdram_i option to set the voltage for the SDRAM I/O subsystem. Use the values shown in Table 16-4. See also the over_voltage_sdram option. SDRAM Physical Voltage The over_voltage_sdram_p option adjusts the “physical voltage” for the SDRAM subsystem. Use the values shown in Table 16-4. See also the over_voltage_sdram option. cmdline.txt The cmdline.txt file is used to supply command-line arguments to the kernel. The Raspbian values supplied in the standard image are broken into multiple lines here for easier reading (note that the NOOBS distribution may show a different device for the root file system): $ cat /boot/cmdline.txt dwc_otg.lpm_enable=0 \ console=ttyAMA0,115200 \ kgdboc=ttyAMA0,115200 \ console=tty1 \ root=/dev/mmcblk0p2 \ rootfstype=ext4 \ elevator=deadline \ rootwait $ This file is provided as a convenience, since the parameters can be configured in the config.txt file, using the cmdline="text" option. When the config.txt option is provided, it supersedes the cmdline.txt file. Once the Raspbian Linux kernel comes up, you can review the command-line options used as follows (edited for readability): $ cat /proc/cmdline dma.dmachans=0x7f35 \ bcm2708_fb.fbwidth=656 \ bcm2708_fb.fbheight=416 \ bcm2708.boardrev=0xf \ bcm2708.serial=0xf52b69e9 \ smsc95xx.macaddr=B8:27:EB:2B:69:E9 \ sdhci−bcm2708.emmc_clock_freq=100000000 \ vc_mem.mem_base=0x1c000000 \ vc_mem. mem_size=0x20000000 \ dwc_otg.lpm_enable=0 \ console=ttyAMA0,115200 \ 214 Chapter 16 ■ Boot kgdboc=ttyAMA0,115200 \ console=tty1 \ root=/dev/mmcblk0p2 \ rootfstype=ext4 \ elevator=deadline \ rootwait $ Additional options can be seen prepended to what was provided in the cmdline.txt file. Options of the format name.option=values are specific to kernel-loadable modules. For example, the parameter bcm2708_fb.fbwidth=656 pertains to the module bcm2708_fb. There are too many Linux kernel parameters to describe here (entire books have been written on this topic), but some of the most commonly used ones are covered in the following subsections. Serial console= The Linux console parameter specifies to Linux what device to use for a console. For the Raspberry Pi, this is normally specified as follows: console=ttyAMA0,115200 This references the serial device that is made available after boot-up as /dev/ttyAMA0. The parameter following the device name is the baud rate (115200). The general form of the serial console option is as follows: console=ttyDevice,bbbbpnf The second parameter is the options field: Zone Description Value Raspbian Notes bbbb Baud rate 115200 Can be more than four digits p Parity n No parity o Odd parity e Even parity 7 7 data bits 8 8 data bits r RTS omitted No RTS n f Number of bits Flow control Virtual console= Linux supports a virtual console, which is also configurable from the console= parameter. Raspbian Linux specifies the following: console=tty1 215 Chapter 16 ■ Boot This device is available from /dev/tty1, after the kernel boots up. The tty parameters used for this virtual console can be listed (edited here for readability): $ sudo −i # stty −a ; swtch = ; start = ^Q; stop = ^S ; susp = ^Z; rprnt = ^R; werase = ^W; \ lnext = ^V; flush = ^O; min = 1; time = 0; −parenb −parodd cs8 hupcl −cstopb cread −clocal −crtscts −ignbrk brkint −ignpar −parmrk −inpck −istrip −inlcr \ −igncr icrnl ixon −ixoff −iuclc −ixany imaxbel iutf8 opost −o lcuc −ocrnl onlcr −onocr −onlret −ofill −ofdel \ nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok −echonl −noflsh \ −xcase −tostop −echoprt −echoctl echoke # kgdboc= The kgdboc parameter was named after the idea “kgdb over console.” This allows you to use a serial console as your primary console as well as use it for kernel debugging. The primary console, however, need not be a serial console for kgdboc to be used.27 The Raspbian image supplies this: kgdboc=ttyAMA0,115200 This allows kernel debugging to proceed through serial device /dev/ttyAMA0, which is the only serial device supported on the Raspberry Pi. root= The Linux kernel needs to know what device holds the root file system. The standard Raspbian image supplies the following: root=/dev/mmcblk0p2 This points the kernel to the SD card (mmcblk0), partition 2 (non-NOOBS distribution). See also the rootfstype parameter. The general form of the root= parameter supports three forms: 216 • root=MMmm: Boot from major device MM, minor mm (hexadecimal). • root=/dev/nfs: Boot a NFS disk specified by nfsroot (see also nfs-root= and ip=). • root=/dev/name: Boot from a device named /dev/name. Chapter 16 ■ Boot rootfstype= In addition to specifying the device holding the root file system, the Linux kernel sometimes needs to know the file system type. This is configured through the rootfstype parameter. The standard Raspbian image supplies the following: rootfstype=ext4 This example indicates that the root file system is the ext4 type. The Linux kernel can examine the device given in the root parameter to determine the file system type. But there are scenarios where the kernel cannot resolve the type or gets confused. Otherwise, you may want to force a certain file system type. Another situation is when MTD is used for the root file system. For example, when using JFFS2, it must specified. elevator= This option selects the I/O scheduler scheme to be used within the kernel. The standard Raspbian image specifies the following: elevator=deadline To find out the I/O scheduler option being used and the other available choices (in your kernel), we can consult the /sys pseudo file system: $ cat /sys/block/mmcblk0/queue/scheduler noop [deadline] cfq $ The name mmcblk0 is the name of the device that your root file system is on. The output shows in square brackets that the deadline I/O scheduler is being used. The other choices are noop and cfq. These I/O schedulers are as follows: Name Description Notes noop No special ordering of requests cfq Completely fair scheduler Older deadline Cyclic scheduler, but requests have deadlines Newest The deadline I/O scheduler is the newest implementation, designed for greater efficiency and fairness. The deadline scheduler uses a cyclic elevator, except that it additionally logs a deadline for the request. A cyclic elevator is one where the requests are ordered according to sector numbers and head movement (forward and backward). The deadline scheduler will use the cyclic elevator behavior, but if it looks like the request is about to expire, it is given immediate priority. rootwait= This option is used when the device used for the root file system is a device that is started asynchronously with other kernel boot functions. This is usually needed for USB and MMC devices, which may take extra time to initialize. The rootwait option forces the kernel to wait until the root device becomes ready. 217 Chapter 16 ■ Boot Given that the root file system is on the SD card (a MMC device), the Raspbian image uses the following: rootwait nfsroot= The nfsroot option permits you to define a kernel that boots from an NFS mount (assuming that NFS support is compiled into the kernel). The square brackets show placement of optional values: nfsroot=[server−ip:]root−dir[,nfs−options] Field Description server-ip NFS server IP number (default uses ip=) root-dir Root dir on NFS server. If there is a %s present, the IP address will be inserted there. nfs-options NFS options like ro, separated by commas When unspecified, the default of /tftpboot/client_ip_address will be used. This requires that root=/dev/nfs be specified and optionally ip= may be added. To test whether you have NFS support in your kernel, you can query the /proc file system when the system has booted: $ cat /proc/filesystems nodev sysfs nodev rootfs nodev bdev nodev proc nodev cgroup nodev tmpfs nodev devtmpfs nodev debugfs nodev sockfs nodev pipefs nodev anon_inodefs nodev rpc_pipefs nodev configfs nodev devpts ext3 ext2 ext4 nodev ramfs vfat msdos nodev nfs nodev nfs4 nodev autofs nodev mqueue From this example, we see that both the older NFS (nfs) and the newer NFS4 file systems are supported. 218 Chapter 16 ■ Boot ip= This option permits the user to configure the IP address of a network device, or to specify how the IP number is assigned. See also the root= and nfsroot= options. ip=client−ip:server−ip:gw−ip:netmask:hostname:device:autoconf Table 16-5 describes the fields within this option. The autoconf value can appear by itself, without the intervening colons if required. When ip=off or ip=none is given, no autoconfiguration takes place. The autoconfiguration protocols are listed in Table 16-6. Table 16-5. ip= Kernel Parameter Field Description Default ip-client IP address of the client Autoconfigured ip-server IP address of NFS server, required only for NFS root Autoconfigured gw-ip IP address of server if on a separate subnet Autoconfigured netmask Netmask for local IP address Autoconfigured hostname Hostname to provide to DHCP Client IP address device Name of interface to use When more than one is available, autoconf autoconf Autoconfiguration method Any Table 16-6. Autoconfiguration Protocols Protocol Description off or none Don’t autoconfigure on or any Use any protocol available (default) dhcp Use DHCP bootp Use BOOTP rarp Use RARP both Use BOOTP or RARP but not DHCP Emergency Kernel In the event that your Raspberry Pi does not boot up properly, an emergency kernel is provided in /boot as file kernel_emergency.img. This kernel includes a BusyBox root file system to provide recovery tools. Through use of e2fsck, you’ll be able to repair your normal Linux root file system. If necessary, you’ll be able to mount that file system and make changes with the BusyBox tools. 219 Chapter 16 ■ Boot To activate the emergency kernel, mount your SD card in a Linux, Mac, or Windows computer. Your computer should see the FAT32 partition, allowing you to rename files and edit configurations. Rename your current kernel.img to something like kernel.bak (you likely want to restore this kernel image later). Then rename kernel_ emergency.img as kernel.img. If you have used special configuration options in config.txt and cmdline.txt, you should copy these to config.bak and cmdline.bak, respectively. Then remove any special options that might have caused trouble (especially overclocking options). Alternatively, you can restore original copies of these two files, as provided by the standard Raspbian image download. ■■Note Your FAT32 partition (/boot) probably has about 40 MB of free disk space (for a standard Raspbian disk image). Renaming large files, rather than copying them, saves disk space. Consequently, renaming kernel images is preferred over copying. Small files like config.txt or cmdline.txt can be copied as required. The entire procedure is summarized here: 1. Rename kernel.img to kernel.bak (retain the normal kernel). 2. Rename kernel_emergency.img to kernel.img. 3. Copy config.txt to config.bak. 4. Copy cmdline.txt to cmdline.bak. 5. Edit or restore config.txt and cmdline.txt to original or safe configurations. Step 5 requires your own judgment. If you have customized hardware, there may be some nonstandard configuration settings that you need to keep (see the previous “Avoid Safe Mode” section). The idea is to simply give your emergency kernel as much chance for success as possible. Disabling all overclocking options is also recommended. ■■Caution After changes, make sure you properly unmount the SD card media (Linux/Mac) or “safely remove USB device” in Windows. Pulling the SD card out before all of the disk data has been written will corrupt your FAT32 partition, adding to your troubles. This may even cause loss of files. With the kernel exchanged and the configuration restored to safe options, it should now be possible to boot the emergency kernel. Log in and rescue. To restore your system back to its normal state, you’ll need to follow these steps: 1. Rename kernel.img to kernel_emergency.img (for future rescues). 2. Rename kernel.bak to kernel.img (reinstate your normal kernel). 3. Restore/alter your config.txt configuration, if necessary. 4. Restore/alter your cmdline.txt configuration, if necessary. At this point, you can reboot with your original kernel and configuration. 220 Chapter 17 Initialization After the Linux kernel is booted, the first executing userland process ID number (PID) is 1. This process, known as init, is initially responsible for spawning all other required processes required by the system. The init process continues to execute after the system is up, running as a daemon (in the background). It should never be terminated by the user (when attempted on Raspbian Linux, the kill request was ignored). Run Levels The init process maintains a concept of a run level for the system. The current run level can be checked at the command line: $ runlevel N 2 $ The N shown here is the previous run level that was in effect. This N means that there was no prior run level. The 2 shown at the right is the current run-level number. Raspbian Linux supports the run levels shown in Table 17-1. According to the action defined in Raspbian Linux’s /etc/inittab file, it changes to run level 2 by default (see the /etc/inittab line with the initdefault action, which is described later). If problems are encountered, such as a corrupted root file system, the run level is taken to singleuser mode (1). This allows the user at the console to repair the problem and resume the transition to a multiuser run level (normally 2) afterward. Table 17-1. Raspbian Run Levels Run Level Meaning Notes S or s Used at initial boot Reserved 0 Halt Reserved 1 Single-user mode Reserved 2 Multiuser mode Default 3 Multiuser mode 4 Multiuser mode (continued) 221 Chapter 17 ■ Initialization Table 17-1. (continued) Run Level Meaning Notes 5 Multiuser mode 6 Initiate reboot Reserved 7 Undocumented See man 8 init 8 Undocumented 9 Undocumented /etc/inittab Once the init process has begun and performed its own initialization, it starts reading from configuration file /etc/ inittab. This small file has a simple format composed of four fields, separated by colons: id:runlevels:action:process Lines beginning with a # are ignored as comments. Table 17-2 describes the four fields. Table 17-2. /etc/inittab Fields Field Name Description 1 id A unique 1- to 4-character name for the entry 2 runlevel(s) Lists the run levels for which the specified action should be performed 3 action Describes the action required 4 process Command-line text for the process inittab Action initdefault The /etc/inittab file should have one (and only one) entry, with an action named initdefault. This identifies what the initial run level should be after booting. The run level value is taken from the runlevels field of this entry. The Raspbian Linux image uses the following: # The default runlevel. id:2:initdefault: This specifies that run level 2 is entered after the Linux kernel has booted. The name in the id field is not important here and simply must be unique within the file. The process field is also ignored for this entry. If the /etc/ inittab file lacks the initdefault entry, init will ask for a run level from the console. Field 3 of the inittab line specifies an action. The possible action choices are described in Table 17-3. 222 Chapter 17 ■ Initialization Table 17-3. init Actions Action Description Notes respawn Restart whenever process terminates. wait The process is started once when the run level is entered, and init will wait for its termination. once Process is started when run level is entered. boot Executed during system boot. Ignores run levels, after sysinit entries bootwait Executed during system boot, but waits for the process to complete. Ignores run levels, after sysinit entries off This does nothing (treat as a comment). ondemand Execute upon demand: a, b, or c. initdefault Specifies the initial run level to use. sysinit Execute during system boot. No run-level change Prior to boot/bootwait Ignores run levels powerwait Execute process when power goes down. Waits for termination powerfail Execute process when power goes down. Does not wait powerokwait Execute process when power restored. powerfailnow Execute process when UPS signals near exhaustion of battery. ctrlaltdel Execute process when init sees SIGINT. kbrequest Execute process after special key press. SIGINT triggered by Ctrl-Alt-Delete. General Startup Sequence Ignoring special events like power on demand and keyboard events, the general /etc/inittab processing follows this sequence: 1. /etc/inittab is searched for the initdefault action. 2. The user is prompted at the console for a run level, if none is found in /etc/inittab or the file is missing. 3. The init process sets the run level. 4. The sysinit entries are performed. 5. The boot and bootwait entries are performed. 6. All other entries that include the established run level are performed. 223 Chapter 17 ■ Initialization Step 4: sysinit The standard Raspbian image uses the following for step 4: # Boot−time system configuration/initialization script. # This is run first except when booting in emergency (−b) mode. si::sysinit:/etc/init.d/rcS The preceding sysinit entry specifies that script /etc/init.d/rcS is to be run. This is a simple script that redirects the execution to yet another script: #!/bin/sh # # rcS # # Call all S??* scripts in /etc/rcS.d/ in numerical/alphabetical order # exec /etc/init.d/rc S From this we see that execution continues with /etc/init.d/rc with argument 1 set to S. This script is responsible for starting and stopping services on run-level changes. This particular inittab entry is used at initial boot-up and is used to invoke all startup scripts in /etc/rcS.d/S*. Each of the /etc/rcS.d/S* scripts get invoked with one argument, start. Normally, the script would invoke /etc/rcS.d/K* scripts first (kill scripts that we will discuss later), but upon initial boot, there is no prior run level. Step 5: boot/bootwait Under Raspbian Linux, there are no boot or bootwait entries to perform. Step 6: runlevel The last step of the initialization involves changing from the non-run-level N to the run level 2, which was declared by the initdefault entry. The Raspbian inittab declares that the /etc/init.d/rc script is run with a run-level argument for each of these run-level changes: l0:0:wait:/etc/init.d/rc l1:1:wait:/etc/init.d/rc l2:2:wait:/etc/init.d/rc l3:3:wait:/etc/init.d/rc l4:4:wait:/etc/init.d/rc l5:5:wait:/etc/init.d/rc l6:6:wait:/etc/init.d/rc 0 1 2 3 4 5 6 The first part of starting a new run level is to run the stop (kill) scripts at the new run level, provided that there was a previous run level. At boot time, there is no current level (it is N). So at startup, these scripts are ignored. 224 Chapter 17 ■ Initialization If, however, the system had been in single-user mode (for example) and the system was changed to run level 2, these kill scripts would be invoked: $ ls −lL /etc/rc2.d/K* −rwxr−xr−x 1 root root 2610 Jul 25 2011 /etc/rc2.d/K01lightdm −rwxr−xr−x 1 root root 6491 Jul 21 2012 /etc/rc2.d/K05nfs−common −rwxr−xr−x 1 root root 2344 Jun 15 2012 /etc/rc2.d/K05rpcbind The script /etc/init.d/rc first iterates through these kill scripts (in sort order). When the current level has a stop (kill) script, the following logic applies: 1. If the previous run level did have a matching stop (kill) script, and 2. If the previous level didn’t have a start script, 3. Then there is no need to execute the stop (kill) script. Otherwise, the corresponding kill script is necessary and is performed. At startup, or after a run-level change, the startup scripts for the new run level (2 in this example) are performed. When the current level has a start script, then the following logic applies: 1. If the previous run level also has a matching start script, and 2. The current level doesn’t have a stop (kill) script, 3. Then there is no need to stop and restart the script. Otherwise, the start script is invoked. For all run levels except 0 and 6, the action being performed by the /etc/init.d/rc script is to start services (except where kill scripts apply). Entering run level 0 (halt) or 6 (reboot) is a bit different, since the script must be stopping services. The following is an example list of startup scripts used by the Raspberry Pi when entering run level 2 after booting: $ ls −lL /etc/rc2.d/S* −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root −rwxr−xr−x 1 root root 1276 Aug 31 2012 /etc/rc2.d/S01bootlogs 4698 May 1 2012 /etc/rc2.d/S01ifplugd 995 Aug 31 2012 /etc/rc2.d/S01motd 3054 Sep 26 2012 /etc/rc2.d/S01rsyslog 714 Jun 28 2012 /etc/rc2.d/S01sudo 3169 May 10 2011 /etc/rc2.d/S01triggerhappy 3033 Jul 9 2012 /etc/rc2.d/S02cron 2832 Sep 29 2012 /etc/rc2.d/S02dbus 2148 Jun 9 2012 /etc/rc2.d/S02dphys−swapfile 1814 Dec 26 2009 /etc/rc2.d/S02ntp 4395 Dec 13 06:43 /etc/rc2.d/S02rsync 3881 Feb 24 2012 /etc/rc2.d/S02ssh 1313 Jun 30 2012 /etc/rc2.d/S04plymouth 782 Mar 16 2012 /etc/rc2.d/S04rc.local 1074 Mar 16 2012 /etc/rc2.d/S04rmnologin Like many Linux distributions, Raspbian Linux places the actual script files in the directory /etc/init.d. The names found in /etc/rc2.d, for example, are symlinks to the actual files. It should also be noted that these scripts are run in the order determined by the pair of digits following the S or K prefix. This is a natural consequence of the way the shell sorts file names when listing files. 225 Chapter 17 ■ Initialization inittab Action wait The wait init action is useful for entries that you want to run individually when the new run level is first entered. The init process will not resume with further entries until the launched process has terminated (whether launched successfully or not). Presumably, there is an implied order based on line sequence found in the file. An important attribute of this type of entry is that it is performed only once upon starting the run level. inittab Action once The once action is very similar to the wait action, except that the init process will not wait for the started process to terminate (perhaps it doesn’t). Entries marked once are started only once per entry of a given run level, but init then proceeds with immediately processing other entries. inittab Action respawn The respawn option is often used for processes that manage terminal lines (gettys). The following example is taken from the standard Raspbian /etc/inittab: # Spawn a getty on Raspberry Pi serial line T0:23:respawn:/sbin/getty −L ttyAMA0 115200 vt100 This entry is used whenever init enters run levels 2 or 3. It launches program /sbin/getty to prompt the user for login on the serial console device (/dev/ttyAMA0 in this example). Other command-line parameters help the getty program to configure the terminal and login environment. When the user logs out of his session, the getty process terminates. When init notices that the process has terminated, it starts /sbin/getty again because of the respawn action. In this way, the terminal line is readied for the next user login. ■■Caution When using the respawn action for your own application, be careful that it doesn’t fail frequently. Otherwise, init will churn by repeatedly restarting your process after it fails. You may eventually get a message on the console with init temporarily suspending the entry. This reduces the hogging of system resources from frequent respawning. But this suspension is temporary. Changing Run Levels The preceding sections outlined the startup procedure. Let’s now examine what happens when you change run levels. telinit The /sbin/telinit executable is linked to the init program file /sbin/init. This form of the command is used to inform the executing init process to request a change of run levels: # telinit x where x is the new run level to enter. The run level may be specified only as one of the choices described in Table 17-4. 226 Chapter 17 ■ Initialization Table 17-4. telinit Run Levels Level Description 0-6 Run level 0, 1, 2, 3, 4, 5, or 6 a, b, c Invoke inittab entries with a, b, or c Q or q Tell init to reexamine /etc/inittab S or s Change to single-user mode U or u Tell init to reexecute itself Any unrecognized level is silently ignored. Change of Run Level Let’s use an example to keep the references concrete. If you were in run level 1 and directed the system to change to run level 2 with # telinit 2 the following happens: 1. /etc/init.d/rc executes all K* (kill) scripts for run level 2 (the level you are changing to), with an argument of stop. 2. /etc/init.d/rc executes all S* (start) scripts for run level 2, with the argument start. 3. Except where previously noted (redundant stop and start script executions are omitted) Another way to think about this is that all K* symlinks at a particular run level identify services that should not be running at that level. Similarly, the S* symlinks identify services that should be running at that level. Single-User Mode Changing to single-user mode works the same as for any other level, except that most of the scripts are designed to be kill scripts to stop services (/etc/rc1.d/K*), rather than to start them. The concept of single-user mode is that only one user will be using the system, without unnecessary services running in the background. This run level is normally used to repair the file systems or to reconfigure the system. Halt and Reboot Changing to level 0 (halt) or 6 (reboot) requires stopping all services. As a result, in this case only the kill scripts are performed with the argument stop. In the file /usr/share/doc/sysv-rc/README.runlevels you will find this remark: In the future, the /etc/rc6.d/SXXxxxx scripts MIGHT be moved to /etc/rc6.d/K1XXxxxx for clarity. 227 Chapter 17 ■ Initialization Creating a New Service If you had a dedicated application for your Raspberry Pi, you might want to assign it to a dedicated run level, perhaps 4. In this manner, you could still perform maintenance and perhaps even development in run level 2. When it was time to start the dedicated application, you’d use telinit to change to run level 4. You could even have /etc/inittab cause a reboot directly into level 4, by the following entry: id:4:initdefault: Rebooting directly to your custom run level 4 would be useful for solar applications to handle restarts due to power fluctuations. To arrange the startup/kill scripts, you would need the following: 1. 2. Kill scripts at the following locations (symlinks to /etc/init.d/service). These apply when you change from level 4 to one of the other levels, where you don’t want the service running. a. /etc/rc2.d/KXXservice b. /etc/rc3.d/KXXservice c. /etc/rc5.d/KXXservice d. Note that single-user mode by default will not have other services left running. You will need a startup script for run level 4: a. /etc/rc4.d/SXXservice In the preceding script, XX is a sequence number (00 to 99) that positions where in the list of scripts it gets executed. Also note that the symlinks • /etc/rc2.d/KXXservice • /etc/rc2.d/SXXservice point to the same file in /etc/init.d/service. The K* symlinks are invoked with the argument stop, while the S* symlinks are invoked with start. This means that your single /etc/init.d/service script file should stop or start based on this command-line argument. The advantage of running your dedicated application from its own run level includes the following: • Less competition for CPU resources from unused daemons • Increased security by not running services that permit external login attempts • Restricted physical access—login only via the serial port console (when configured) • Automatic restart of your application after a power failure With run levels 3, 4, and 5 to work with, you can configure a mix of different dedicated application profiles. 228 Chapter 18 vcgencmd Apart from the usual Linux commands that display status, the Raspberry Pi includes a custom command named vcgencmd, which can report voltages and temperatures. This chapter documents the known features of the command. The executable file behind the command is /usr/bin/vcgencmd. vcgencmd Commands There is no man page for this command, but the list of all supported options can be displayed with the commands option. The command output has been broken over several lines for readability: $ vcgencmd commands commands="vcos, ap_output_control, ap_output_post_processing, \ pm_set_policy, pm_get_status, pm_show_stats, pm_start_logging, \ pm_stop_logging, version, commands, set_vll_dir, \ led_control, set_backlight, set_logging, get_lcd_info, \ set_bus_arbiter_mode, cache_flush, otp_dump, codec_enabled, \ measure_clock, measure_volts, measure_temp, get_config, \ hdmi_ntsc_freqs, render_bar, disk_notify, inuse_notify, \ sus_suspend, sus_status, sus_is_enabled, \ sus_stop_test_thread, egl_platform_switch, mem_validate, \ mem_oom, mem_reloc_stats, file, vctest_memmap, vctest_start, \ vctest_stop, vctest_set, vctest_get" At the time of this writing, some of these options remained undocumented. A summary list of options is itemized in Table 18-1. Table 18-1. Summary of vcgencmd Command-Line Options Option Name Argument(s) Description ap_output_control ap_output_post_processing cache_flush codec_enabled commands Flushes GPU’s L1 cache codec Reports status of codec Lists options (continued) 229 Chapter 18 ■ vcgencmd Table 18-1. (continued) Option Name Argument(s) Description disk_notify egl_platform_switch file get_config get_lcd_info Returns height, width, and depth of the display frame buffer hdmi_ntsc_freqs inuse_notify led_control measure_clock clock measure_temp measure_volts Reports frequency Reports SoC temperature device Reports voltage mem_oom Reports Out of Memory events mem_reloc_stats Reports relocatable memory stats mem_validate otp_dump pm_get_status pm_set_policy pm_show_stats pm_start_logging pm_stop_logging render_bar set_backlight set_bus_arbiter_mode set_logging Option measure_clock This firmware access option provides the user with clock rate information, according to the argument appearing after measure_clock. Valid values for are listed in Table 18-2. vcgencmd 230 measure_clock Chapter 18 ■ vcgencmd Table 18-2. Valid Arguments for the measure_clock Option Clock Description arm ARM CPU core Core dpi Display Pixel Interface emmc External MMC device h264 h.264 encoder hdmi HDMI clock isp Image Sensor Pipeline pixel Pixel clock pwm Pulse Width Modulation uart UART clock v3d Video 3D vec The following shell script is often used to list all available clocks: $ for src in arm core h264 isp v3d uart pwm emmc pixel vec hdmi dpi ; do echo −e "$src : $(vcgencmd measure_clock $src)" ; done Here is the example output: arm core h264 isp v3d uart pwm emmc pixel vec hdmi dpi : : : : : : : : : : : : frequency frequency frequency frequency frequency frequency frequency frequency frequency frequency frequency frequency (45)=700074000 (1)=250000000 (28)=250000000 (42)=250000000 (43)=250000000 (22)=3000000 (25)=0 (47)=100000000 (29)=108000000 (10)=0 (9)=163683000 (4)=0 231 Chapter 18 ■ vcgencmd Option measure_volts The measure_volts option allows the various subsystem voltages to be reported: $ for id in core sdram_c sdram_i sdram_p ; do echo −e "$id: $(vcgencmd measure_volts $id)" ; done core: volt=1.20V sdram_c: volt=1.20V sdram_i: volt=1.20V sdram_p: volt=1.23V Table 18-3 provides a legend for the output report lines. Table 18-3. Valid Device Names for measure_volts Device Description core Core sdram_c SDRAM controller sdram_i SDRAM I/O sdram_p SDRAM physical Option measure_temp The measure_temp option allows the user to retrieve the SoC temperature, in degrees Celsius. $ vcgencmd measure_temp temp=36.3 °C In this example, the relatively idle core was reported to be 36.3ºC. Option codec_enabled The codec_enabled option reports the operational status of the codecs supported by the Raspberry Pi. Valid codec names are listed in Table 18-4. The codec support can be summarized with the following command: $ for id in H264 MPG2WCV1 ; do echo −e "$id: $(vcgencmd codec_enabled $id)"; done H264: H264=enabled MPG2: MPG2=disabled WCV1: WCV1=disabled 232 Chapter 18 ■ vcgencmd Table 18-4. vcgencmd CODEC Names Name Description H264 h.264 CODEC MPG2 MPEG-2 CODEC WVC1 VC1 CODEC Option version The version option reports the GPU firmware version: $ vcgencmd version Oct 25 2012 16:37:21 Copyright (c) 2012 Broadcom version 346337 (release) Option get_lcd_info While get_lcd_info was undocumented at the time of this writing, it appears to provide LCD/monitor width and height, and pixel depth: $ vcgencmd get_lcd_info 720 480 24 Option get_config The get_config option is useful in scripts that need to query your Raspberry Pi’s configuration, as defined in /boot/config.txt. See Chapter 16 for the options that can be queried. For example, a script can query whether avoid_safe_mode is in effect: $ vcgencmd get_config avoid_safe_mode avoid_safe_mode=0 233 Chapter 19 Linux Console The Raspbian Linux console is configured (or assumed) by the kernel command line. See the console option described in Chapter 16. Available Consoles The list of consoles is available through the /proc/consoles pseudo file: $ cat /proc/consoles tty1 ttyAMA0 −WU (EC p −W− (E p ) ) 4:1 204:64 The organization and flags displayed are described in Tables 19-1 and 19-2. The major and minor numbers are confirmed in the following example session output: $ ls −l /dev/tty1 /dev/ttyAMA0 crw−rw−−−− 1 root tty 4, 1 Jan 21 00:06 /dev/tty1 crw−rw−−−− 1 root tty 204, 64 Jan 21 00:06 /dev/ttyAMA0 Table 19-1. /proc/consoles Fields Field Parameter Example Description 1 device tty1 /dev/tty1 R = read 2 operations -WU- W = write U = unblank 3 flags (EC p ) See flags in Table 19-2 4 major:minor 4:1 Device major/minor 235 Chapter 19 ■ Linux Console Table 19-2. The Meaning of Flags Displayed in Parentheses Flag Meaning E The console is enabled. C Is the preferred console. B Primary boot console. p Used for printk buffer. b Not a TTY, but is a Braille device. a Safe to use when CPU is offline. Serial Console If you wired up a serial console to your Raspberry Pi, you can use a utility such as PuTTY (http://www.chiark. greenend.org.uk/~sgtatham/putty/download.html) on your laptop or desktop computer to connect to it. The serial console sees the following first few lines at boot (long lines are edited): Uncompressing Linux... done, booting the kernel. [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Linux version 3.2.27+ (dc4@dc4–arm–01) \ (gcc version 4.7.2 20120731 (prerelease) \ (crosstool –NG linaro –1.13.1+bzr2458 – Linaro GCC 2012.08 )) \ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 [ 0.000000] CPU: ARMv6–compatible processor [410fb767] \ revision 7 (ARMv7), cr=00c5387d [ 0.000000] CPU : PIPT /VIPT nonaliasing data cache, \ VIPT nonaliasing instruction cache [ 0.000000] Machine: BCM2708 Using the dmesg command, you can see almost the same thing: $ dmesg | head −5 [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Linux version 3.2.27+ (dc4@dc4−arm−01) \ (gcc version 4.7.2 20120731 (prerelease) \ (crosstool −NG linaro −1.13.1+bzr2458 − Linaro GCC 2012.08)) \ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 [ 0.000000] CPU: ARMv6−compatible processor [410fb767] \ revision 7 (ARMv7), cr=00c5387d [ 0.000000] CPU:PIPT/VIPT nonaliasing data cache, \ VIPT nonaliasing instruction cache [ 0.000000] Machine:BCM2708 The difference is that the initial Uncompressing Linux console output is missing. Additionally, any debug messages that a new kernel might display can be capturable on a serial console. 236 Chapter 20 Cross-Compiling Embedded computers often lack the necessary resources for developing and compiling software. The Raspberry Pi is rather special in this regard since it already includes the gcc compiler and the needed linking tools (under Raspbian Linux). But while the code can be developed and built on the Raspberry Pi, it may not always be the most suitable place for software development. One reason is the lower performance of the SD card. To compile native code for the Raspberry Pi, you need a compiler and linker that knows how to generate ARM binary executables. Yet it must run on a host with a different architecture (for example, Mac OS X). Hence the reason it is called a cross-compiler. The cross-compiler will take your source code on the local (build) platform and generate ARM binary executables, to be installed on your target Pi. There are prebuilt cross-compile tools available, including the Raspberry Pi Foundation’s own tools (git://github.com/raspberrypi/tools.git), but these can be problematic for some versions of Linux. Running the cross-compiler on a different Linux release than it was built for may cause the software to complain about missing or incompatible shared libraries. But if you find that you can use a prebuilt release, it will save considerable time. In this chapter, you’ll walk through how to build your own cross-compiler. This may permit you to get the job done using your existing Linux release. Terminology Let’s first cover some terminology used in this chapter: build: Also called the local platform, this is the platform that you perform the compiling on (for example, Mac OS X). target: The destination platform, which is the Raspberry Pi (ARM) in this chapter. Let’s now consider some of the cross-compiling issues before you take the plunge. There are two main problem areas in cross-compiling: • All C/C++ include files and libraries for the Raspberry Pi (ARM) must be available on your build platform. • The cross-compiler and related tools must generate code suitable for the target platform. So before you decide that you want to build a cross-compiler environment, are you prepared to • Provide all matching C/C++ header files from the ARM platform? • Provide all ARM libraries needed, including libraries for third-party products like sqlite3 that you intend to link with? • Provide sufficient disk space for the cross-compiler and tools? 237 Chapter 20 ■ Cross-Compiling The crosstool-NG software will mitigate some of these issues. For example, the correct Linux headers are chosen by the configuration step shown later in this chapter. Disk space solves many issues by holding a copy of your Raspberry Pi’s root file system on your build platform. Simple programs won’t require this (for example, a Hello World). But software linking to libraries may require this. Even if you’re strapped for disk space, you may be able to mount the Raspbian SD card on the build platform, thus gaining access to the Raspberry Pi’s root file system. Operating System The procedure used for building a cross-compiler environment is somewhat complex and fragile. Using the crosstool-NG software simplifies things considerably. Despite this advantage, it is best to stick with proven crosscompiler platforms and configurations. You might be tempted to say, “The source code is open, and so it should work on just about any operating system.” (You might even say, “I’ll fix the problems myself.”) The reality is not quite so simple. I use the Mac Ports collection (www.macports.org) for a number of things and quickly discovered the limitations of building a crosstool-NG on Mac OS X. For example, I found that objcopy was not supported when ./configure was run for the cross-compiler. Unless you are willing to spend time on Internet forums and wait for answers, I suggest you take a more pragmatic approach—build your cross-compiling environment on a recent and stable Ubuntu or Debian environment. This chapter uses Ubuntu 14.04 LTS hosted in VirtualBox 4.3.12 (www.virtualbox.org) on a Mac OS X Mavericks MacBook Pro, running an Intel i7 processor. Current versions of Ubuntu are recommended. Ubuntu 12.10 was the version tested and used by the process documented at this link: www.kitware.com/blog/home/post/426 Host, Guest, Build, and Target At this point, a short note is in order because these terms can get confusing, especially for those performing this for the first time. Let’s list the environment terms, which will be referred to throughout the remainder of this chapter: • Host environment • Guest environment • Build/local environment • Target environment So many environments! The terms host and guest environments enter the picture when you are using a virtual machine like VirtualBox. VirtualBox is used to host another operating system on top of the one you are using. For example, you might be running Mac OS X on your laptop. In this example, the OS X environment hosts Ubuntu Linux within VirtualBox. The Ubuntu Linux operating system is thus referred to as the guest operating system. The term build (or local) environment refers to the Linux environment that is executing the cross-compiler and tools. These Linux tools produce or manipulate code for the target environment (your Raspberry Pi’s ARM CPU). Platform Limitations Many people today are using 64-bit platforms similar to my own MacBook Pro, with an Intel i7 processor. This may present a problem if you want to build a cross-compiler for the Raspberry Pi, which is a 32-bit platform. Many people building a cross-compiler on a 64-bit platform have encountered software problems building for a 32-bit platform. 238 Chapter 20 ■ Cross-Compiling For this reason, if you are using a 64-bit platform, you’ll probably want to choose a VirtualBox solution. This will allow you to run a 32-bit operating system to host the cross-compiler. On the other hand, if you are already running a 32-bit operating system, creating a native cross-compiler for the Pi is a real possibility. Without VirtualBox (Native) If you are already using a Linux development environment like Debian or Ubuntu, the term host is equivalent to the build (or local) environment. The host and guest environments are likewise equivalent, though it is probably more correct to say there is no guest operating system in this scenario. This simpler scenario leaves us with just two environments: Host/guest/build: Native environment running the cross-compiler tools Target: The destination execution environment (Raspberry Pi) Using VirtualBox (Ubuntu/Linux) If you do not have a suitable Linux environment, one can be hosted on the platform you have. You can host Linux from Windows, Mac OS X, Solaris, or another distribution of Linux. VirtualBox can be downloaded from the following: www.virtualbox.org When VirtualBox is used, the host environment is the environment that is running VirtualBox (for example, Mac OS X). The guest operating system will be Ubuntu (recommended) or Debian. This leaves us with three environments in total: Host: Or native, running VirtualBox (for example, Windows) Guest/build: Ubuntu/Debian development environment within VirtualBox Target: The destination execution environment (your Raspberry Pi) Planning Your Cross-Development Environment The main consideration at this point is normally disk space. If you are using VirtualBox, limited memory can be another factor. If you are using Linux or Mac OS X, check your mounted disks for available space (or Windows tools as appropriate): $ df −k Filesystem /dev/disk0s2 devfs map −hosts map auto_home map −static $ 1024−blocks 731734976 186 0 0 0 Used 154168416 186 0 0 0 Available 577310560 0 0 0 0 Capacity 22% 100% 100% 100% 100% Mounted on / /dev /net /home /Volumes/oth In the preceding example output, we see that the root file system has plenty of space. But your file system may be laid out differently. Symlinks can be used when necessary to graft a larger disk area onto your home directory. 239 Chapter 20 ■ Cross-Compiling If you’re using VirtualBox, create virtual disks with enough space for the Linux operating system and your cross-compiler environment. You may want to put your Linux software on one virtual disk with a minimum size of about 8–10 GB (allow it to grow larger). Allow a minimum of 10 GB for your cross-compiler environment (and allow it to grow). 9 GB is just barely large enough to host the cross-compiler tools and allow you to compile a Hello World type of program. But you must also factor in additional space for the Raspberry Linux kernel, its include files, and all other third-party libraries that you might need to build with (better still, a copy of the Raspberry Pi’s root file system). Within your development Ubuntu/Debian build environment, make sure your cross-compiler and build area are using the disk area that has available space. It is easy to glibly create a directory someplace convenient and find out later that the space that you thought you were going to use wasn’t available. Building the Cross-Compiler At this point, I’ll assume that you’ve set up and installed Ubuntu in VirtualBox, if necessary. Otherwise, you are building your cross-compiler tools on an existing Ubuntu/Debian system, with disk space sufficient for the job. We will be using the basic recipe outlined from this web resource: “Cross-Compiling for Raspberry Pi,” www.kitware.com/blog/home/post/426 Download crosstool-NG The released crosstool-NG downloads are found at this site: http://crosstool-ng.org/download/crosstool-ng/ current release: crosstool-ng-1.19.0.tar.bz2 It is normal practice to download the newest stable version of software. I am using 1.19.0 in this text because it was current at the time of writing. Staging Directory I’ll assume that you’ve symlinked to your disk area with sufficient available disk space. In other words, the symlink named ~/devel points to the development area to be used. This can be just a subdirectory if you have sufficient disk space there. In directory ~/devel, create a subdirectory named staging (~/devel/staging) and change it to the following: $ cd ~/devel # Dir is ~/devel $ mkdir staging $ cd ./staging # Dir is ~/devel/staging $ pwd /home/myuserid/devel/staging $ 240 Chapter 20 ■ Cross-Compiling Unpack the Tarball Assuming the tarball crosstool-ng-1.19.0.tar.bz2 was downloaded to your home directory, you would perform the following (change the option j if the suffix is not .bz2): $ tar xjvf ~/crosstool−ng−1.19.0.tar.bz2 . . . $ After the unpacking completes, you should have a subdirectory named crosstoolng-1.19.0 in your staging directory. Create /opt/x-tools You can choose a different location if you like, but I’m going to assume that the crosstool-NG software is going to install into /opt/x-tools. We’ll also assume your user ID is fred (substitute your own). $ sudo mkdir -p /opt/x−tools $ sudo chown fred /opt/x−tools Once your installation is complete later, you can change the ownership back to root for protection. Install Package Dependencies The crosstool-NG build depends on several packages provided by Ubuntu/Debian as optionally installed software: bison: GNU yacc flex: GNU lex subversion: Subversion source control package libtool: Library tool texinfo: Install the texinfo package gawk: GNU awk (gawk) gperf: Perfect hash function generator automake: Tool for generating GNU standards-compliant Makefiles Save time by making sure these packages are installed before proceeding to the next step. Package dependencies often change over time. Depending on your host system, you may find that additional packages (such as libncurses5-dev, for example) are also needed. If more packages are needed, the configure step usually identifies them. Configure crosstools-NG With the package dependencies installed, you are now in a position to make the crosstool-NG software: $ cd ~/devel/staging/crosstool−ng−1.19.0 $ ./configure −−prefix=/opt/x−tools If this completes without errors, you are ready to build and install the crosstool-NG software. If it reports that you are missing package dependencies, install them now and repeat. 241 Chapter 20 ■ Cross-Compiling make crosstool-ng At this point, you should have no trouble building crosstool-NG. Perform the following make command: $ cd ~/devel/staging/crosstool−ng−1.19.0 $ make This takes very little time and seems trouble free. make install Once the crosstool-NG package has been compiled, it is ready to be installed into /opt/x-tools. From the same directory: $ sudo make install If you still own the directory /opt/x-tools from earlier (recall sudo chown fred /opt/x−tools), you won’t need to use sudo in the preceding step. After make install is performed, you will have the crosstool-NG command ct-ng installed in the directory /opt/x-tools/bin. PATH To use the newly installed ct-ng command, you will need to adjust your PATH environment variable: $ PATH="/opt/x−tools/bin:$PATH" The website also indicates that you might have to unset environment variable LD_LIBRARY_PATH, if your platform has it defined. If so, then unset it as follows: $ unset LD_LIBRARY_PATH Now you should be able to run ct-ng to get version info (note that there are no hyphens in front of version in the following command). Seeing the version output confirms that your ct-ng command has been installed and is functional: $ ct–ng version This is crosstool-NG version 1.19.0 Copyright (C) 2008 Yann E. MORIN This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Cross-Compiler Configuration The command ct-ng simplifies the work necessary to configure and build the cross-compiler tool chain. From here, we are concerned with building the cross-compiler tools themselves. When that process is completed, you will have populated the cross-compiler tools into the directory /opt/x-tools/arm-unknown-linux-gnueabi. 242 Chapter 20 ■ Cross-Compiling Before ct-ng can build your cross-compiler, it must first be configured: $ cd ~/devel/staging $ ct−ng menuconfig If you get a “command not found” error message, check that the PATH variable is set properly. Paths and Misc Options When the command starts up, the menu configuration screen is presented. Press Enter, to open the Paths and Misc Options submenu. Once in the Paths and Misc Options menu, as shown next, use the cursor key to move down to Try Features Marked as Experimental. Once that line is highlighted, press the spacebar to put an asterisk inside the square brackets, to select the option (pressing space again toggles the setting). 243 Chapter 20 ■ Cross-Compiling After doing that, while in the same menu, move the cursor down to the middle entry labelled Prefix Directory and press Enter to select it. For the procedure used in this book, modify the path to the following: /opt/x-tools/${CT_TARGET} as illustrated here: Once the pathname is established, press Enter on the OK button shown. This returns you to the Paths and Misc Options menu. Then select the Exit button shown at the bottom, and press Enter again. 244 Chapter 20 ■ Cross-Compiling Target Options From the main menu, select Target Options with the cursor and press Enter to open that menu. Then choose Target Architecture and press Enter. In that menu, choose Arm and use the Select button at the bottom. This returns you to the Target Options menu. While in the Target Options menu (shown next), verify the Endianness setting by reviewing the status in brackets. It should read Little Endian. If not, enter that menu and change it to Little endian. Below the Endianness menu item is the Bitness option. It should already indicate 32-bit. If not, select it and change the setting to 32-bit. Finally, exit this submenu with the Exit button. 245 Chapter 20 ■ Cross-Compiling Operating System At the main menu again, choose Operating System and then choose Linux Kernel Version. It is best to choose the release that most closely matches the kernel that you are using (perhaps, for example, 3.10.2). Once you have chosen, exit back to the main menu. Binary Utilities At the main menu, open the Binary Utilities menu. Cursor down to Binutils Version and open that submenu: In this menu, you are presented various versions of binutils that can be used. Choose the most current stable (nonexperimental) version. Version 2.22 was chosen here. Select the version and exit back to the main menu. 246 Chapter 20 ■ Cross-Compiling C Compiler At the main menu, open the C Compiler submenu. Here it is recommended that you enable the Show Linaro Versions option. Once that is enabled, you can select the submenu Gcc Version: The preceding figure shows linaro-4.8.2013.06-1 being chosen (which I had good results with). Newer versions are always becoming available. Choose the compiler and then choose the Select button at the bottom. Then choose Exit once again to return to the main menu. 247 Chapter 20 ■ Cross-Compiling Save Configuration Unless you have a reason to change anything else, exit the menu again to cause the Save prompt to appear: Upon selecting Yes, the command exits with the following session output showing in the terminal window: $ ct−ng menuconfig IN config.gen/arch.in IN config.gen/kernel.in IN config.gen/cc.in IN config.gen/libc.in IN config/config.in # # configuration saved # At this point, it is worth mentioning that you may want to save your configuration somewhere outside the current directory. The configuration is saved in a file named .config and can be copied elsewhere. The following is a suggestion: $ cp .config ~/ct-ng.config.bak Saving the file outside the current directory will prevent accidental loss if ct-ng distclean is invoked. Build Cross-Compiler Check the ownership of /opt/x-tools. If you don’t own this directory, change the ownership now: $ sudo chown −R fred /opt/x−tools This will save you from having to execute the build process with root privileges. Now at long last, you can initiate the building of the cross-compiler: $ cd ~/devel/staging $ ct−ng build Allow a good block of time for this job. This is not something that can be pushed through in a hurry. Ideally, you can just leave the command to run and check for successful completion in an hour or so. However, it is not uncommon for different software problems to arise at this stage. I once spent an entire Saturday troubleshooting this step. If you do encounter problems, read the next section for some troubleshooting tips. 248 Chapter 20 ■ Cross-Compiling If all goes well, ct-ng compiles and installs tools into /opt/x-tools without any further interaction. In the following session, Retrieving needed toolchain components is rather brief, because this was a session rerun with the components cached somewhere. Your download times will be longer when doing this for the first time. [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] [INFO] Performing some trivial sanity checks Build started 20140103.102402 Building environment variables ================================================================= Retrieving needed toolchain components' tarballs Retrieving needed toolchain components' tarballs: done in 0.13s (at 00:04) ================================================================= Extracting and patching toolchain components Extracting and patching toolchain components: done in 3.96s (at 00:08) ================================================================= Installing GMP for host Installing GMP for host: done in 37.57s (at 00:46) ================================================================= Installing MPFR for host Installing MPFR for host: done in 18.16s (at 01:04) ================================================================= Installing PPL for host Installing PPL for host: done in 268.27s (at 05:32) ================================================================= Installing CLooG/PPL for host Installing CLooG/PPL for host: done in 6.45s (at 05:39) ================================================================= Installing MPC for host Installing MPC for host: done in 7.97s (at 05:47) ================================================================= Installing binutils for host Installing binutils for host: done in 53.52s (at 06:40) ================================================================= Installing pass -1 core C compiler Installing pass -1 core C compiler: done in 222.36s (at 10:23) ================================================================= Installing kernel headers Installing kernel headers: done in 4.54s (at 10:27) ================================================================= Installing C library headers & start files Installing C library headers & start files: done in 31.26s (at 10:58) ================================================================= Installing pass -2 core C compiler Installing pass -2 core C compiler: done in 512.54s (at 19:31) ================================================================= Installing C library Installing C library: done in 805.58s (at 32:57) ================================================================= Installing final compiler Installing final compiler: done in 484.58s (at 41:01) ================================================================= Cleaning -up the toolchain's directory Stripping all toolchain executables 249 Chapter 20 ■ Cross-Compiling [INFO] [INFO] [INFO] [INFO] [41:05] Cleaning -up the toolchain's directory: done in 3.86s (at 41:05) Build completed at 20130103.110507 (elapsed: 41:04.93) Finishing installation (may take a few seconds )... / The overall time for my build was 41 minutes (reported to be 83 minutes on a Windows 8 Intel i5 using VirtualBox). My build was performed in VirtualBox running on Mac OS X Mavericks, using the Intel i7 processor (2.8 GHz). On the same Mac, I found that the times approximately doubled when the VirtualBox disk images were located on a USB 2.0 disk drive. From these figures, you can estimate your build time. Troubleshooting The session output that you get from this build process is very terse. As such, you don’t always get a clear idea of what the real failure was. For this reason, you’ll often need to check the build.log file: $ less build.log Using less, you can navigate to the end of the build.log file by typing a capital G. One failure that frequently occurs in the beginning is a failed download. While the build process does retry downloads and tries different download methods, it can still fail. All that you need to do is to start the build again. It will download only the remaining files needed. Sometimes it will succeed on the second or third retry attempt. Sometimes a component will fail in its configuration phase. Check the build.log file first to determine precisely which component is involved. Next you will want to examine the config.log file for that particular component. For example, let’s say the isl component failed. Dive down into the .build subdirectory until you find its config.log file: $ cd .build/arm-unknown-linux-gnueabi/build/build-isl-host-i686-build_pc-linux-gnu $ less config.log Navigate to the end of config.log and work backward a few pages. Eventually, you will see text describing the command that was tried and the error message produced. In one instance, I was able to determine that the custom compiler option that I added (-fpermissive) was causing the failure. The solution then was to remove that option and try again. Some errors will occur only with certain version choices. At one time, I was receiving errors related to PPL and needed a patch to correct it. Google is your friend (the following patch is an example): http://patchwork.ozlabs.org/patch/330733/ I found that saving that patch to a file and applying it to the sources corrected the issue. Later, when I decided to start over with a different choice of compiler, this patch became unnecessary (the software was downloaded fresh again). In getting through these issues, you can simply make corrections and then rerun the ct-ng build command. It is recommended that you plan for a later rebuild of everything again (after a clean), once the problems are solved. This will ensure that you have a good build without dependency issues. If, after a correction, you run into the same problem, you may need to do a clean step first and start over. Depending on how deep you think the problem may be, choose one of the following: 250 • ct-ng clean • ct-ng distclean (Be careful; see the following text.) Chapter 20 ■ Cross-Compiling The ct-ng clean command will usually be enough, forcing the next build to start fresh. Any downloaded files and configuration will remain and are reused. The ct-ng distclean command is much more drastic, since it removes all of the downloaded content and your configuration files. I copied the .config file to .config.bak and discovered to my horror that .config.bak had been removed! So if you back up the .config file, copy it outside the current directory for safety. Above all, keep your head. It’s difficult to troubleshoot these issues if you feel time pressure or get angry over the time invested. When under time pressure, leave it for another day when you can deal with it leisurely and thoughtfully. Each redo takes considerable time. Wherever possible, eliminate the guesswork. With each problem, take a deep breath, patiently look for clues, and pay attention to the details in the error messages. Remember that line in the movie Apollo 13 : “Work the problem, people!” 251 Chapter 21 Cross-Compiling the Kernel While normally not possible on embedded platforms, it is possible to build kernels on your Raspberry Pi with its luxurious root file system. Despite this, cross-compiling on desktop systems is preferred for faster compile times. This chapter examines the procedure for building your Raspbian kernel. It is assumed that you have the cross-compiler tools and environment ready. Either the tool set built in Chapter 20 or an installed prebuilt tool chain will do. In this chapter, I assume that the cross-compiler prefix is as follows (ending in a hyphen): /opt/x−tools/arm–unknown−linux–gnueabi/bin/arm−unknown−linux−gnueabi− Substitute as appropriate, if your tools are installed differently. Image Tools According to the “RPi Buying Guide” from eLinux.org, “The way the memory addresses are arranged in the Broadcom SoC, you will need to prepare the compiled image for use.” Consequently, an image tool must be used so that the built kernel image can be modified for booting by the Raspberry Pi. ■■Note You can read more of the “RPi Buying Guide” at http://s3.amazonaws.com/szmanuals/8d4eb934fa27c2cbecd2a7f3b6922848. Let’s begin by creating and changing to a work directory: $ mkdir ~/work $ cd ~/work The tools can be downloaded from here: $ wget https://github.com/raspberrypi/tools/archive/master.tar.gz They can also be fetched from the Git repository: $ git clone --depth 1 git@github.com:raspberrypi/tools.git 253 Chapter 21 ■ Cross-Compiling the Kernel Save time with the –depth 1 option to avoid downloading older versions that you are uninterested in. The git command will produce a subdirectory named tools. After git has completed, the following additional git steps are recommended: $ rm -fr ./tools/.git $ mv tools tools-master $ tar czvf master.tar.gz # Delete unneeded .git subdirectory # Rename for consistency in this chapter # create master.tar.gz as if we downloaded it Whether you simply downloaded master.tar.gz or created it in the preceding step (after using git), unpack the tarball into /opt as follows: $ cd /opt $ sudo tar xzf ~/work/master.tar.gz This creates the subdirectory /opt/tools-master. ■■Note If you have trouble using git from VirtualBox, there may be networking issues involved (reconfiguration may correct this). The simplest workaround is to simply use git outside VirtualBox and upload the master.tar.gz file with scp. If you need to save space and you don’t need to use the other tools included, remove them: $ cd /opt/tools−master $ ls arm-bcm2708 configs mkimage pkg sysidk usbboot If you are using the cross-compiler from Chapter 20, you won’t need the arm-bcm2708 subdirectory: $ cd /opt/tools−master $ sudo rm −fr arm-bcm2708 To use the image tool, you’ll need Python installed, so install it now, if needed. Download Kernel The first thing needed is the Raspbian kernel sources. If you want the “bleeding edge” in development, the git command is the best way to acquire the source code. While you could clone the entire Linux project, this will result in a long download. The following method is suggested as a quick way to obtain the kernel release of interest from git (change 3.10.y to the release that you want to fetch): $ $ $ $ mkdir ~/work/linux cd ~/work/linux git init git fetch –depth 1 git@github.com:raspberrypi/linux.git \ rpi-3.10.y:refs/remotes/origin/rpi-3.10.y $ git checkout origin/rpi-3.10.y 254 Chapter 21 ■ Cross-Compiling the Kernel The source tarball can be fetched more easily with the wget command. Here is an example download: $ wget https://github.com/raspberrypi/linux/archive/rpi−3.10.y.tar.gz If you get an error message about an untrusted certificate (ERROR: The certificate of 'github.com' is not trusted), add the –no-check-certificate option: $ wget −−no−check−certificate \ https://github.com/raspberrypi/linux/archive/rpi−3.10.y.tar.gz In this chapter, I assume that you have downloaded the tarball. Once the download is complete, unpack the sources somewhere convenient. I also assume that you’re going to use ~/work/rasp as your working directory: $ mkdir −p ~/work/rasp $ cd ~/work/rasp $ tar xzf ~/rpi−3.10.y.tar.gz This should leave you a subdirectory named rpi-3.10.y that you can change to the following: $ cd ~/work/rasp/linux−rpi−3.10.y Edit Makefile It is possible to put the ARCH= and CROSS-COMPILE= definitions on the make command line like this: $ make ARCH=arm CROSS−COMPILE=/opt/x−tools/arm−unknown−\ linux−gnueabi/bin/arm−unknown−linux−gnueabi− However, this is tedious and error prone. You could use an alias or some other workaround, but the best approach is probably just to edit these parameters in the top-level Makefile. Using an editor of your choice, look for a line in the top-level Makefile that starts with ARCH=, as shown here: ARCH CROSS_COMPILE ?= $ (SUBARCH) ?= $ (CONFIG_CROSS_COMPILE:"%"=%) The safest thing to do is to duplicate these pair of lines and comment out the first pair, keeping them around in their original form. Then modify the second pair as shown: #ARCH #CROSS_COMPILE ?= $ (SUBARCH) ?= $ (CONFIG_CROSS_COMPILE:"%"=%) ARCH CROSS_COMPILE ?= arm ?= /opt/x−tools/arm−unknown−linux−gnueabi/bin/arm−unknown−linux−gnueabi− The CROSS_COMPILE prefix should match everything up to but not including the command name gcc shown next (edited to fit). If you’ve not already done so, edit the PATH variable so that the cross-compiler tools are searched first: PATH="/opt/x-tools/arm-unknown-linux-gnueabi/bin:$PATH" 255 Chapter 21 ■ Cross-Compiling the Kernel Now verify that your compiler is being located: $ type arm−unknown−linux−gnueabi−gcc arm−unknown−linux−gnueabi−gcc is hashed \ (/opt/x−tools/arm−unknown−linux−gnueabi/bin/arm−unknown−linux−gnueabi−gcc) make mrproper In theory, this step shouldn’t be necessary. But the kernel developers want you to do it anyway, in case something was accidentally left out of place. Keep in mind that this step also removes the .config file. So if you need to keep it, make a copy of it. $ make mrproper ■■Caution The command make mrproper cleans up everything, including your kernel .config file. You may want to copy .config to .config.bak. Kernel Config Before building your kernel, you need a configuration. The downloaded kernel source does not include your Pi’s kernel settings. If you want to build the kernel with the same configuration as the one you are using, grab your configuration from your running Pi: $ scp pi@rasp:/proc/config.gz. Then uncompress the configuration and move it into place: $ gunzip ~/work/rasp/linux−rpi−3.10.y/.config Alternatively, because there may be new options that were not used by your old kernel, you may want to start with a fresh set of default options for your kernel. Copying these defaults will give you a good starting point from which to proceed (assuming the directory ~/work/rasp/linux-rpi-3.10.y): $ cp ./arch/arm/configs/bcmrpi_defconfig .config At this point, you can modify the configuration, but for your first build, I suggest you leave it as is. Once you get a successful build and run of the kernel, you can go back with confidence and make changes. Otherwise, if the new kernel fails, you won’t know whether it was the kernel, your build procedure, or the configuration that you chose. If you downloaded your kernel from the Git repository, there is a likelihood that the first build of the kernel will fail if you copied the bcmrpi_defconfig configuration. The reason is that some of the configured modules may not be fully developed (or undergoing changes), but are enabled in the configuration for testing. For example, if an IPTables module fails to compile, you may need to disable it in the configuration. If the option is difficult to find in the menu (see make menuconfig next), it is an accepted practice to just edit the .config file. Things are often easier to find with the editor. 256 Chapter 21 ■ Cross-Compiling the Kernel make menuconfig The first time around, you should start make menuconfig and then just exit. When you decide later that you need to make configuration changes, you can either use the menu-driven approach here or edit the .config file directly. The menu-driven approach is usually best since it can guide you through the process: $ make menuconfig make Now that the configuration has been established, start the build process. If you hadn’t planned on making configuration changes, you might still be prompted with some configuration questions. To proceed without configuration changes, simply press Enter to accept the existing value for the parameter. $ make The build process takes a fair bit of time. On a MacBook Pro using an Intel i7 processor, hosting Ubuntu in VirtualBox, the process takes about 40 minutes to complete. You mileage will vary. Next, build the modules for the kernel: $ make modules Now you are ready to install the new kernel and its modules. ■■Tip If your /tmp file system is not large enough for the build, you can direct the temporary files to another directory. For example, to use ./tmp in your work area: $ mkdir ./tmp $ export TMPDIR="$PWD/tmp" Prepare Kernel Image In the subdirectory arch/arm/boot/zImage is your built kernel image: $ cd ~/work/rasp/linux−rpi−3.10.y/arch/arm/boot $ ls −l zImage −rwxr−xr−x 1 wwg wwg 3696136 2014−06−22 13:58 zImage Now let’s prepare an image that can be booted by the Raspberry Pi. The image tool seems to need to run from its own directory (otherwise, it is unable to locate the bootuncompressed.txt file). So change to the image tool’s directory and run it from there. It will create the file kernel.img in that directory, so make sure you have permissions there: $ cd /opt/tools−master/mkimage $ python /opt/tools−master/mkimage/imagetool−uncompressed.py \ ~/work/rasp/linux−rpi−3.10.y/arch/arm/boot/zImage 257 Chapter 21 ■ Cross-Compiling the Kernel $ ls −l total 3160 -rw-rw-r--rw-rw-r--rw-rw-r--rwxrwxr-x -rw-r--r-- 1 1 1 1 1 root root root root root root root root root root 157 201 32768 822 3187280 May May Jun May Jun 8 8 24 8 24 08:14 08:14 08:28 08:14 08:28 args-uncompressed.txt boot-uncompressed.txt first32k.bin imagetool-uncompressed.py kernel.img From this, we see that it creates file kernel.img, which is 3, 187, 280 bytes in size. Install Kernel Image Here I assume that you have the SD card mounted on your desktop, rather than in VirtualBox. The SD card can be mounted in VirtualBox, but this takes some special care and additional effort. See the “VirtualBox Mount of SD Card” section at the end of the chapter (if this works for you, this will be more convenient). With your SD card mounted, you can change out your kernel. It is recommended that you rename the original kernel.img file in case you want to reinstate it later. On the Mac, the session might look something like this: $ cd /Volumes/Untitled/ $ ls bootcode.bin config.txt cmdline.txt fixup.dat config.bak fixup_cd.dat $ mv kernel.img kernel.orig # Where the SD card is mounted issue.txt kernel.img kernel_cutdown.img kernel_emergency.img start.elf start_cd.elf Once the original kernel is safely renamed on the SD card, you can copy the new kernel onto it: $ scp wwg@osx-rpi:/opt/tools−master/mkimage/kernel.img /Volumes/Untitled/. wwg@osx-rpi's password: kernel.img 100% 2665KB $ sync 2.6MB/s 00:00 Here I transferred the prepared image using scp, from VirtualBox machine osx-rpi, installing the new kernel as kernel.img. You may be able to boot the new kernel without updating the modules (obviously, the new modules will not be available). Once you boot up your Pi with the new kernel, then using scp you should be able to copy your new module’s tarball to it (see the “Modules” section later). Try booting the new kernel and log in to check it (long lines edited): $ ssh pi@rasp ... $ dmesg | head ... [ 0.000000] Linux version 3.10.38 (wwg@osx-xpi) \ (gcc version 4.8.2 20130603 (prerelease) \ (crosstool −NG 1.19.0)) \ #3 PREEMPT Mon Jun 23 22:26:50 EST 2014 ... 258 Chapter 21 ■ Cross-Compiling the Kernel Here we have confirmation that the kernel was built by wwg@osx-xpi (on VirtualBox), using the crosstool-NG development tools and built on June 23. This is confirmation that the kernel is the new one that was installed. Next, of course, the modules need to be installed. Boot Failure If you see the initial colored flash screen remain on the console, this indicates that the kernel.img file failed to load/start.43 Modules The modules need to be staged somewhere, so you can transfer them to the Pi’s root file system (on the SD card). Here I’ll stage them in ~/work/modules. Specify the full pathname to the staging directory by using the INSTALL_MOD_PATH variable: $ mkdir −p ~/work/modules $ make INSTALL_MOD_PATH=$HOME/work/modules modules_install Note that $HOME is safer than the tilde (~) in the make command, since the shell may not substitute it properly. The bash shell, version 4.3.8, does seem to handle the tilde, however. After this install step completes, you will have a subtree of kernel modules deposited there. These files now need to be installed in the Pi’s root file system. Either mount the Pi’s root file system under Linux, or use the existing kernel on the Pi itself. The following shows how the modules are put into a tar file for transport to the Pi: $ $ $ . . . . $ cd ~/work/modules tar czf modules.tar.gz. tar tzf modules.tar.gz | head −4 / /modules.tar.gz /lib/ /lib/modules/ scp modules.tar.gz pi@rasp:. On the Raspberry Pi, you can install it: $ . . . . . . . $ $ tar tzf modules.tar.gz | head −7 / /modules.tar.gz /lib/ /lib/modules/ /lib/modules/3.2.27/ /lib/modules/3.2.27/modules.symbols.bin /lib/modules/3.2.27/modules.usbmap cd / sudo tar xzf ~/modules.tar.gz 259 Chapter 21 ■ Cross-Compiling the Kernel With the new modules installed, reboot your new kernel. Once the Pi boots up, log in and check whether any modules got loaded: $ lsmod Module snd_bcm2835 ... Size 0 16292 Used by Firmware From time to time, you should check to see whether new firmware is available. This code is available in binary form only. There are always two versions of the firmware available:35 Master: The current firmware used in Raspbian Next: The firmware in development, which provides GPU updates Depending on your needs, choose one of the following: $ wget−−no−check−certificate\ https://github.com/raspberrypi/firmware/archive/master.tar.gz $ wget−−no−check−certificate\ https://github.com/raspberrypi/firmware/archive/next.tar.gz Of particular interest is the bootcode.bin firmware file. There are other files like the *.dat files. It is unclear when these dat files should be replaced. These may depend on the release of the Raspbian Linux kernel. $ cd ./firmware−master/boot $ ls −l total 37248 −rw−r−−r−− .. 18693 26 −rw−r−−r−− .. 1447 26 −rw−r−−r−− .. 17764 26 −rw−r−−r−− .. 5735 26 −rw−r−−r−− .. 2260 26 −rw−r−−r−− .. 8502 26 −rw−r−−r−− .. 2800968 26 −rw−r−−r−− .. 9609864 26 −rw−r−−r−− .. 2539540 26 −rw−r−−r−− .. 569016 26 −rw−r−−r−− .. 3472580 26 Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan Jan 14:31 14:31 14:31 14:31 14:31 14:31 14:31 14:31 14:31 14:31 14:31 COPYING.linux LICENCE.broadcom bootcode.bin fixup.dat fixup_cd.dat fixup_x.dat kernel.img kernel_emergency.img start.elf start_cd.elf start_x.elf If you think you need a firmware update, copy from this subdirectory to your Raspberry Pi’s /boot directory. VirtualBox Mount of SD Card All this shuffling images around remotely using scp is a nuisance, but it gets the job done. If you are running VirtualBox, you may find that you can mount the SD card directly. This allows you to more easily update the SD card file systems, including the modules and firmware. I’ll be showing the VirtualBox procedure for a Mac, but the process is similar for Windows. 260 Chapter 21 ■ Cross-Compiling the Kernel The first step on the Mac is to determine which disk device the SD card is assigned to: $ diskutil list In my case, the SD card showed up as /dev/disk2 (this is obvious because it wasn’t there prior to inserting the SD card). Next you need to make sure that any mounted file systems from that SD card are unmounted (the Mac likes to automount everything it can). Using the diskutil command, unmount all file systems mounted from /dev/disk2: $ diskutil unmountDisk /dev/disk2 Finally (for the Mac), you need to grant permissions to VirtualBox to use the raw device. Since VirtualBox likely runs under your own login, you need to grant permissions to it. I’ll use the lazy approach here, to grant permissions to everyone on the device (the device will go away as soon as it is removed anyway): $ sudo chmod 0666 /dev/disk2 Note that once you remove the SD card, and later insert it, you will need to repeat this step. Next, you will need to locate the VBoxManage command. On the Mac you will find it here (Windows users may find it in C:\Program Files\Sun): $ cd /Applications/VirtualBox.app/Contents/MacOS You can either add that directory to your current PATH, or simply change to that directory. Then use the VBoxManage command to create a control file (*.vmdk). This control file informs VirtualBox how to access that raw device (place the *.vmdk wherever you find it convenient): $ sudo VBoxManage internalcommands createrawvmdk \ -filename /Volumes/VirtualBox/sddisk.vmdk \ -rawdisk /dev/disk2 Now enter your VirtualBox console and open the storage settings. Click the Add Hard Disk icon and select the control file you created (in the example, it was created on /Volumes/VirtualBox/sddisk.vmdk). Make sure you add this device after your current boot device. Otherwise, VirtualBox will try to boot from your SD card instead. After starting VirtualBox, you should see your new devices under Linux. In my case, the SD card devices showed up as /dev/sdb (entire SD card), /dev/sdb1 (partition 1), and /dev/sdb2 (partition 2). With this success, it is now possible to mount these partitions after creating mount points (I used ~/mnt1 and ~/mnt2): $ sudo mount /dev/sdb1 ~/mnt1 $ sudo mount /dev/sdb2 ~/mnt2 Now you can list those mount points to see the Raspberry Pi file system content. This access makes it an easy matter to install your kernel: $ cd /opt/tools−master/mkimage $ sudo mv ~/mnt1/kernel.img ~/mnt1/kernel.orig $ sudo dd if=kernel.img ~/mnt1/kernel.img # Rename original kernel # Install new kernel image Likewise, you can now update the kernel modules: $ cd ~/mnt2 $ tar xzvf ~/work/modules/modules.tar.gz # Raspberry Pi' Root file system # Unpack new modules into ~/mnt2/lib 261 Chapter 21 ■ Cross-Compiling the Kernel With the modifications completed, change out of the file system (to unbusy them) and unmount them: $ cd ~ $ sudo umount ~/mnt1 $ sudo umount ~/mnt2 If you are hosting VirtualBox on a Mac, the Mac will automount the first partition the moment that VirtualBox closes the SD card device. So be sure to undo that before pulling the SD card out (to prevent any file system corruption). You can use the Mac’s diskutil to do this for you: $ diskutil unmountDisk /dev/disk2 262 Chapter 22 DHT11 Sensor The DHT11 humidity and temperature sensor is an economical peripheral manufactured by D-Robotics UK (www.droboticsonline.com). It is capable of measuring relative humidity between 20 and 90% RH within the operating temperature range of 0 to 50°C, with an accuracy of ±5% RH. Additionally, temperature is measured in the range of 0 to 50°C, with an accuracy of ±2°C. Both values are returned with 8-bit resolution. Characteristics The signaling used by the DHT sensor is similar to the 1-Wire protocol, but the response times differ. Additionally, there is no device serial number support. These factors make the device incompatible with the 1-Wire drivers within the Linux kernel. Figure 22-1 shows a DHT11 sensor. Figure 22-1. DHT11 sensor The DHT11 sensor also requires a power supply. In contrast, the signal line itself powers most 1-Wire peripherals. The datasheet states that the DHT11 can be powered by a range of voltages, from 3 V to 5.5 V. Powering it from the Raspberry Pi’s 3.3 V source keeps the sensor signal levels within a safe range for GPIO. The device draws between 0.5 mA and 2.5 mA. Its standby current is stated as 100 mA to 150 mA, for those concerned about battery consumption. 263 Chapter 22 ■ DHT11 Sensor Circuit Figure 22-2 shows the general circuit connections between the Raspberry Pi and the DHT11 sensor. Pin 4 connects to the common ground, while pin 1 goes to the 3.3 V supply. Pin 2 is the signal pin, which communicates with a chosen GPIO pin. The program listing for dht11.c is configured to use GPIO 22. This is easily modified (look for gpio_dht11). Figure 22-2. DHT11 circuit When the Pi is listening on the GPIO pin and the DHT11 is not sending data, the line will float. For this reason, R1 is required to pull the line up to a stable level of 3.3 V. The datasheet recommends a 5 kW resistor for the purpose (a more common 4.7 kW resistor can be substituted safely). This presents less than 1 mA of load on either the GPIO pin or the sensor when they are active. The datasheet also states that the 5 kW resistor should be suitable for cable runs of up to 20 meters. Protocol The sensor speaks only when spoken to by the master (Raspberry Pi). The master must first make a request on the bus and then wait for the sensor to respond. The DHT sensor responds with 40 bits of information, 8 of which are a checksum. Overall Protocol The overall signal protocol works like this: 264 1. The line idles high because of the pull-up resistor. 2. The master pulls the line low for at least 18 ms to signal a read request and then releases the bus, allowing the line to return to a high state. 3. After a pause of about 20 to 40 ms, the sensor responds by bringing the line low for 80 ms and then allows the line to return high for a further 80 ms. This signals its intention to return data. Chapter 22 ■ DHT11 Sensor 4. Forty bits of information are then written out to the bus: each bit starting with a 50 ms low followed by: a. 26 to 28 ms of high to indicate a 0 bit b. 70 ms of high to indicate a 1 bit 5. The transmission ends with the sensor bringing the line low one more time for 50 ms. 6. The sensor releases the bus, allowing the line to return to a high idle state. Figure 22-3 shows the overall protocol of the sensor. Master control is shown in thick lines, while sensor control is shown in thin lines. Initially, the bus sits idle until the master brings the line low and releases it (labeled Request). The sensor grabs the bus and signals that it is responding (80 ms low, followed by 80 ms high). The sensor continues with 40 bits of sensor data, ending with one more transition to low (labeled End) to mark the end of the last bit. Figure 22-3. General DHT11 protocol Data Bits Each sensor data bit begins with a transition to low, followed by the transition to high, as shown in Figure 22-4. The end of the bit occurs when the line is brought low again as the start of the next bit. The last bit is marked off by one final low-to-high transition. Figure 22-4. DHT11 data bit Each data bit starts with a transition to low, lasting for 50 ms. The final transition to low after the last bit also lasts for 50 ms. After the bit’s low-to-high transition, the bit becomes a 0 if the high lasts only 26 to 28 microseconds. A 1 bit stays high for 70 ms instead. Every data bit is completed when the transition from high to low occurs for the start of the next bit (or final transition). 265 Chapter 22 ■ DHT11 Sensor Data Format Figure 22-5 illustrates the 40-bit sensor response, transmitting the most significant bit first. The datasheet states 16 bits of relative humidity, 16 bits of temperature in Celsius, and an 8-bit checksum. However, the DHT11 always sends 0s for the humidity and temperature fractional bytes. Thus the device really has only 8 bits of precision for each measurement. Presumably, other models (or future ones) provide fractional values for greater precision. Figure 22-5. DHT11 data format The checksum is a simple sum of the first 4 bytes. Any carry overflow is simply discarded. This checksum gives your application greater confidence that it has received correct values in the face of possible transmission errors. Software The user space software written to read the DHT11 sensor on the Raspberry Pi uses the direct register access of the GPIO pin. The challenges presented by this approach include the following: • Short timings: 26 to 70 ms • Preemptive scheduling delays within the Linux kernel One approach is to count how many times the program could read the high-level signal before the end of the bit is reached (when the line goes low). Then decide on 0 bits for shorter times and 1s for longer times. After some experimentation, a dividing line could be drawn, where shorter signals mean 0 while the others are 1s. The difficulty with this approach is that it doesn’t adapt well if the Raspberry Pi is accelerated. When the CPU clock is increased through overclocking, the program will tend to fail. There is also the potential for future Raspberry Pis to include CPUs with higher clock rates. The signal emitted by the sensor is almost a Manchester encoding. In Manchester encoding, one-half of the wave form is shorter than the other. This allows counting up for the first half and counting down for the second. Based on whether the counter underflows, a decision is made about the value of the bit seen. The DHT11 signal uses a fixed first half of 50 ms The bit is decided based on how long the signal remains at a high level after that. So a “bit bang” application could get a relative idea by counting the number of times it could read the low-level signal. Based on that, it can get a relative idea of where the dividing line between a short and long high-level signal is. This is the approach that was adopted by the program dht11.c. It counts the number of times in a spin loop that it can read the signal as low. On a 700 MHz nonturbo Raspberry Pi, I saw this count vary between 130 and 330 times, with an average of 292. This time period is supposed to be exactly 50 ms, which illustrates the real-time scheduling problem within a user space program. (The program did not use any real-time Linux priority scheduling.) If the sensor waveform is true, a max count of 330 suggests that the Raspberry Pi can read the GPIO pin a maximum of 330 = 6.6 reads / m s 50 266 Chapter 22 ■ DHT11 Sensor But the minimum of 130 GPIO reads shows a worst case performance of 130 = 2.6 reads / m s 50 This variability in preemptive scheduling makes it difficult to do reliable timings. I have seen the high-level bit counts vary between 26 and 378. (The interested reader can modify the code to record the counts.) If the program is able to read 6.6 times per microsecond, a 1-bit time of 70 ms should yield a count of 462. Yet the maximum seen was 378. Preemptive scheduling prevents the code from performing that many reads without interruption. The lower count of 26 represents the minimum count for 0 bits, where the line stays high for a shorter period of time. This suggests that each GPIO read is about 1 ms or longer during the 0-bit highs. The preceding information is just a crude sampling of the problem to illustrate the variability that must be grappled with in a user space program, on a multitasking operating system. Chosen Approach The program shown in this chapter uses the following general approach: 1. 2. 3. 4. Count the number of GPIO reads that report that the line is low (call it Clow). C Compute an adjustment bias B based on B = low , where D is some fixed divisor. D Compute a new count K = B + Chigh, where Chigh is the number of times the line was read as high. If the count value K > Clow, the value is considered a 1-bit; otherwise, it’s considered a 0-bit. The method is intended to at least partially compensate for the level of preemption being seen by the application program. By measuring the low read counts, we get an idea of the number of times we can sample the line at the moment. The approach is intended to adapt itself to a faster-running Raspberry Pi. Table 22-1 shows some experimental results on an idle Raspberry Pi running at the standard 700 MHz. Different divisors were tried and tested over 5-minute intervals. When the program runs, it attempts to read and report as many sensor readings as it can, tracking good reports, time-out, and error counts. The program was terminated by pressing ^C when an egg timer went off. Table 22-1. Bias Test Results Divisor Results Time-outs Errors 2 1 17 103 3 48 17 63 4 30 25 56 5 49 14 63 6 45 20 52 7 60 16 47 8 41 20 56 9 42 17 62 (continued) 267 Chapter 22 ■ DHT11 Sensor Table 22-1. (continued) Divisor Results Time-outs Errors 10 39 22 53 11 40 14 72 12 43 13 71 13 47 10 75 14 32 19 67 15 28 23 63 16 38 16 69 17 33 14 81 18 34 13 82 19 31 16 75 20 22 18 81 Using no bias at all, no successful reads result (which prompted the idea of applying a bias). Using a divisor of 2 applies too much adjustment, as can be seen by the low number of results (1). Increasing the divisor to the value 3 or more produced a much higher success rate, near 48, which is almost 10 reports per minute. Setting the divisor to 3 seems to yield the most repeatable results overall. It is uncertain from the datasheets how rapidly the sensor can be requeried. The program takes the conservative approach of pausing 2 seconds between each sensor read attempt or waiting 5 seconds when a time-out has occurred. The program reports an error when the checksum does not match. Time-outs occur if the code gets stuck waiting for the signal to go low, for too long. This can happen if the program misses a critical event because of preemptive scheduling. It sometimes happens that the high-to-low-to-high event can occur without the program ever seeing it. If the going-low event takes too long, the program performs a longjmp into the main loop, to allow a retry. The errors are reported to stderr, allowing them to be suppressed by redirecting unit 2 to /dev/null from the command line. The way that the Raspberry Pi relinquishes the sensor bus is by changing the GPIO pin from an output to an input. When configured as an input, the pull-up resistor brings the bus line high when the bus is idle (the pull-up applies when neither master or slave is driving the bus). When requested, the sensor grabs the bus and drives it high or low. Finally, when the master speaks, we configure the pin as an output, causing the GPIO pin to drive the bus. Example Run When the program dht11 is run, you should see output similar to the following: $ sudo ./dht11 RH 37% Temp 18 (Error # 1) (Timeout # 1) RH 37% Temp 18 (Timeout # 2) RH 37% Temp 18 RH 37% Temp 18 RH 37% Temp 18 268 C Reading 1 C Reading 2 C Reading 3 C Reading 4 C Reading 5 Chapter 22 ■ DHT11 Sensor (Error # 2) (Timeout # 3) (Error # 3) (Error # 4) (Error # 5) RH 37% Temp 18 (Error # 6) RH 37% Temp 18 (Error # 7) (Error # 8) (Error # 9) RH 36% Temp 19 RH 37% Temp 18 (Timeout # 4) RH 36% Temp 19 ^C Program exited C Reading 6 C Reading 7 C Reading 8 C Reading 9 C Reading 10 due to SIGINT: Last Read: RH 36% Temp 19 C, 9 errors, 4 timeouts, 10 readings Source Code The next few pages list the source code for the program. This was assembled into one compile unit by using the #include directive. This was done to save pages by eliminating additional header files and extern declarations. ■■Note The source code for gpio_io.c is found in Chapter 12. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /********************************************************************* * dht11.c: Direct GPIO access reading DHT11 humidity and temp sensor. *********************************************************************/ #include #include #include #include #include #include #include #include #include "gpio_io.c" #include "timed_wait.c" /*GPIO routines */ /*timed_wait() */ static const int gpio_dht11 = 22; static jmp_buf timeout_exit; static int is_signaled = 0; /*GPIO pin */ /*longjmp on timeout */ /*Exit program if signaled */ 269 Chapter 22 ■ DHT11 Sensor 21/* 22 * Signal handler to quit the program: 23 */ 24 static void 25 sigint_handler(int signo) { 26 is_signaled = 1; /*Signal to exit program */ 27 } 28 29 /* 30 * Read the GPIO line status: 31 */ 32 static inline unsigned 33 gread(void) { 34 return gpio_read(gpio_dht11); 35 } 36 37 /* 38 * Wait until the GPIO line goes low: 39 */ 40 static inline unsigned 41 wait_until_low(void) { 42 const unsigned maxcount = 12000; 43 unsigned count = 0; 44 45 while ( gread() ) 46 if ( ++count >=maxcount || is_signaled ) 47 longjmp(timeout_exit,1); 48 return count; 49 } 50 51 /* 52 * Wait until the GPIO line goes high: 53 */ 54 static inline unsigned 55 wait_until_high(void) { 56 unsigned count = 0; 57 58 while ( !gread() ) 59 ++count; 60 return count; 61 } 62 63 /* 64 * Read 1 bit from the DHT11 sensor: 65 */ 66 static unsigned 67 rbit(void) { 68 unsigned bias; 69 unsigned lo_count, hi_count; 70 270 Chapter 22 ■ DHT11 Sensor 71 wait_until_low(); 72 lo_count = wait_until_high(); 73 hi_count = wait_until_low(); 74 75 bias = lo_count / 3; 76 77 return hi_count + bias > lo_count ? 1 : 0 ; 78 } 79 80 /* 81 * Read 1 byte from the DHT11 sensor : 82 */ 83 static unsigned 84 rbyte(void) { 85 unsigned x, u = 0; 86 87 for ( x=0; x<8; ++x ) 88 u = (u << 1) | rbit(); 89 return u; 90 } 91 92 /* 93 * Read 32 bits of data + 8 bit checksum from the 94 * DHT sensor. Returns relative humidity and 95 * temperature in Celsius when successful. The 96 * function returns zero if there was a checksum 97 * error. 98 */ 99 static int 100 rsensor(int *relhumidity, int *celsius) { 101 unsigned char u[5], cs = 0, x; 102 for ( x=0; x<5; ++x ) { 103 u[x] = rbyte(); 104 if ( x < 4 ) /*Only checksum data..*/ 105 cs += u[x]; /*Checksum */ 106 } 107 108 if ( (cs & 0xFF) == u[4] ) { 109 *relhumidity = (int)u [0]; 110 *celsius = (int)u [2]; 111 return 1; 112 } 113 return 0; 114 } 115 116 /* 117 * Main program: 118 */ 271 Chapter 22 ■ DHT11 Sensor 119 int 120 main(int argc, char **argv) { 121 int relhumidity = 0, celsius = 0; 122 int errors = 0, timeouts = 0, readings = 0; 123 unsigned wait; 124 125 signal(SIGINT,sigint_handler); /*Trap on SIGINT */ 126 127 gpio_init(); /*Initialize GPIO access */ 128 gpio_config(gpio_dht11,Input); /*Set GPIO pin as Input */ 129 130 for (;;) { 131 if ( setjmp(timeout_exit) ) { /*Timeouts go here */ 132 if ( is_signaled ) /*SIGINT? */ 133 break; /*Yes, then exit loop */ 134 fprintf(stderr," (Timeout # %d)\n",++timeouts); 135 wait = 5; 136 } else wait = 2; 137 138 wait_until_high(); /*Wait GPIO line to go high */ 139 timed_wait(wait,0,0); /*Pause for sensor ready */ 140 141 gpio_config(gpio_dht11,Output); /*Output mode */ 142 gpio_write(gpio_dht11,0); /*Bring line low */ 143 timed_wait(0,30000,0); /*Hold low min of 18ms */ 144 gpio_write(gpio_dht11,1); /*Bring line high */ 145 146 gpio_config(gpio_dht11,Input); /*Input mode */ 147 wait_until_low(); /*Wait for low signal */ 148 wait_until_high(); /*Wait for return to high */ 149 150 if ( rsensor(&relhumidity,& celsius) ) 151 printf("RH %d%% Temp %d C Reading %d\n", relhumidity, celsius,++readings); 152 else fprintf(stderr," (Error # %d)\n",++errors); 153 } 154 155 gpio_config(gpio_dht11,Input); /*Set pin to input mode */ 156 157 puts("\ nProgram exited due to SIGINT: \n"); 158 printf("Last Read: RH %d%% Temp %d C, %d errors, %d timeouts, %d readings \n", 159 relhumidity, celsius, errors, timeouts, readings); 160 return 0; 161 } 162 272 Chapter 22 ■ DHT11 Sensor 163 /*End dht11.c */ 1 /********************************************************************* 2 * Implement a precision "timed wait". The parameter early_usec 3 * allows an interrupted select(2) call to consider the wait as 4 * completed, when interrupted with only "early_usec" left remaining. 5 *********************************************************************/ 6 static void 7 timed_wait(long sec,long usec,long early_usec) { 8 fd_set mt; 9 struct timeval timeout; 10 int rc; 11 12 FD_ZERO(&mt); 13 timeout.tv_sec = sec; 14 timeout.tv_usec = usec; 15 do { 16 rc = select (0,&mt,&mt,&mt,&timeout); 17 if ( ! timeout.tv_sec && timeout.tv_usec < early_usec ) 18 return; /*Wait is good enough, exit */ 19 } while ( rc < 0 && timeout.tv_sec && timeout.tv_usec ); 20 } 21 22 /*End timed_wait.c */ 273 Chapter 23 MCP23017 GPIO Extender Microchip’s MCP23017 provides 16 additional GPIO pins that can be purchased for as little as $1.99. The chip communicates using the I2C bus. (The companion MCP23S17 is available for SPI bus.) The I2C bus allows the chip to be remote from the Raspberry Pi, requiring only a four-wire ribbon cable (power, ground, and a pair of I2C bus lines). This chapter explores the features and limits of this peripheral. DC Characteristics When shopping for chips or interface PCBs based on a particular chip, the first thing I look at is the operating supply voltage. 5 V parts are inconvenient for the Pi because of its 3.3 V GPIO interface. Many newer devices operate over a range of voltages, which include 3.3 V. The MCP23017 supply VDD operates from an extended range of +1.8 V to +5.5 V. This clearly makes it compatible, if we power the chip from a +3.3 V source. Figure 23-1 shows the MCP23017chip pinout diagram. Figure 23-1. MCP23017 pinout 275 Chapter 23 ■ MCP23017 GPIO Extender GPIO Output Current Another factor in choosing a peripheral chip is its output drive capability. How well can the GPIO pin source or sink current? Chapter 12 notes that the Raspberry Pi’s own GPIO pins can source/sink up to 16 mA, depending on configuration. The MCP23017 chip specifications indicate that it can source or sink up to 25 mA. We still need to remember that if the MCP23017 is powered from the Raspberry Pi’s 3.3 V regulator on header P1, the total current budget must not exceed 50 mA. This budget includes the Pi’s own GPIO pin current usage. If, on the other hand, the MCP23017 is powered from a separate 3.3 V power supply, this limitation is eliminated. There are still reasons to budget current, however. The chip must not consume more than 700 mW of power. This implies a total current limit as follows: IVDD = P VDD 0.7 3.3 = 212 mA = This power figure gives us an upper current limit. However, the datasheet of the MCP23017 also lists a maximum of 125 mA for supply pin VDD . If every GPIO output is sourcing power, this leaves us with the following average pin limit: 125 mA = 7.8 mA 16 So while the output GPIO pins can source up to 25 mA, we cannot have all of them doing so simultaneously. Likewise, the datasheet lists VSS (ground) as limited to an absolute maximum of 150 mA. If every GPIO pin is an output and sinking current, the average for each output pin cannot exceed the following: 150 mA = 9.4 mA 16 Once again, while each output pin can sink up to 25 mA, we see that they cannot all do so at the same time without exceeding chip limits. This should not be discouraging, because in most applications, not all GPIO pins will be outputs, and not all will all be driving heavy loads. The occasional pin that needs driving help can use a transistor driver like the one discussed in Chapter 12. Before we leave the topic of GPIO output driving, we can apply one more simple formula to help with interface design. With the foregoing information, we can calculate the number of 25 mA outputs available: 125 mA =5 25 mA From this, it is known that four to five GPIO pins can operate near their maximum limits, as long as the remaining GPIO pins are inputs or remain unconnected. GPIO Inputs In normal operation, the GPIO inputs should never see a voltage below the ground potential VSS. Nor should they ever see a voltage above the supply voltage VDD. Yet, variations can sometimes happen when interfacing with the external world, particularly with inductive components. The datasheet indicates that clamping diodes provide some measure of protection against this. Should the voltage on an input drop below 0, it is clamped by a diode so it will not go further negative and cause harm. The 276 Chapter 23 ■ MCP23017 GPIO Extender voltage limit is listed at –0.6 V, which is the voltage drop of the clamping diode. Likewise, if the voltage goes over VDD (+3.3 V in our case), the clamping diode will limit the excursion to VDD + 0.6 V (+3.9 V). This protection is limited by the current capability of the clamping diodes. The datasheet lists the maximum clamping current as 20 mA. If pins are forced beyond their limits and the clamping current is exceeded, damage will occur. While we have focused on GPIO inputs in this section, the clamping diodes also apply to outputs. Outputs can be forced beyond their limits by external circuits like pull-up resistors. Pull-up resistors should not be attached to +5 V, for example, when the MCP23017 is operating from a +3.3 V supply. Standby Current If the MCP23017 device is not sourcing or sinking output currents, the standby current is stated as 3 mA (for 4.5 to 5.5 V operation). This operating parameter is important to designers of battery-operated equipment. Input Logic Levels Since the device operates over a range of supply voltages, the datasheet defines the logic levels in terms of the supply voltage. For example, the GPIO input low level is listed as 0.2 ´ VDD . So if we operate with VDD = + 3.3V , the input low voltage is calculated as follows: VILmax = 0.2 ´ VDD = 0.2 ´ 3.3 = 0.66V Therefore, a voltage in the range of 0 to 0.66 V is guaranteed to read as a 0 bit. Likewise, let’s calculate the input high voltage threshold, where the multiplier is given as 0.8: VIHmin = 0.8 ´ VDD = 0.8 ´ 3.3 = 2.64V Thus any voltage greater than or equal to 2.64 V is read as a 1 bit, when powered from a +3.3 V supply. Any voltage between VILmax and VIHmin is undefined and reads as a 1 or a 0, and perhaps randomly so. Output Logic Levels The output logic levels are stated differently. The datasheet simply states that the output low voltage should not exceed a fixed limit. The high level is also stated as a minimum value relative to VDD. This pair of parameters is listed here: VOLmax = 0.6 V VOH min = VDD - 0.7 V = 3.3 - 0.7 = 2.7 V 277 Chapter 23 ■ MCP23017 GPIO Extender Reset Timing The only parameter of interest for timing apart from the I2C bus is the device reset time. In order for the device to see a reset request, pin RESET must remain active (low) for a minimum of 1 ms. The device resets and places outputs into the high-impedance mode within a maximum of 1 ms. Circuit Figure 23-2 shows a circuit with two remote MCP23017 GPIO extenders connected to one I2C bus. In the figure, the power, ground, I2C data, and optional RESET and INT connections are shown connected through a six-conductor ribbon cable. This allows the Raspberry Pi to communicate remotely to peripherals in a robot, for example. Figure 23-2. MCP23017 circuit The data communication occurs over the pair of signals SDA and SCL. These are connected to the Raspberry Pi’s pins P1-03 and P1-05, respectively (GPIO 2 and 3 for Rev 2.0+). The other end of the I2C data bus is common to all slave peripherals. Each MCP23017 slave device is addressed by its individually configured A2, A1, and A0 pins. For device A, these pins are shown grounded to define it as device number 0x20 (low bits are zeroed). A1 is tied high for device B so that its peripheral address becomes 0x21. In this configuration, the Raspberry Pi will use addresses 0x20 and 0x21 to communicate with these slave devices. Lines labeled RESET and INT are optional connections. The RESET line can be eliminated if you never plan to force a hardware reset of the slaves (tie to VDD through a 10 K resistor). Usually the power-on reset is sufficient. The INT line is more desirable, since the MCP23017 can be programmed to indicate interrupts when a GPIO input has changed in value (or does not match a comparison value). The INT line is an open collector pin so that many can be tied together on the same line. However, the Pi will have to poll each peripheral to determine which device is causing the interrupt. Alternatively, each slave could provide a separate INT signal, with a corresponding increase in signal lines. 278 Chapter 23 ■ MCP23017 GPIO Extender Each MCP23017 chip has two interrupt lines, named INT A and INT B . There is the option of separate interrupt notifications for the A group or the B group of GPIO pins. For remote operation, it is desirable to take advantage of MCP23017’s ability to configure these to work in tandem, so that only one INT line is required. On the Raspberry Pi end, the GPIO pin used for the RESET line would be configured as an output and held high, until a reset is required. When activating a reset, the line must be held low for at least 1 microsecond, plus 1 more microsecond to allow for the chip reset operation itself (and possibly longer, if non-MCP23017 slaves are connected to the bus). The INT line should be connected to a GPIO input on the Pi. This GPIO input either needs to be polled by the application, or to have the GPIO configured to trigger on changes. Then the select(2) or poll(2) system calls can be used to detect when an interrupt is raised by one or more peripherals. The interrupt line, when used, should have a pull-up resistor configured (see Chapter 12 for information about internal pull-up resistors). It may be best to use an external pull-up resistor, especially for longer cable runs. To keep the sink current at 2 mA or less, the pull-up resistance used should be no lower than the following: + 3.3V 2 mA = 1650W Rpullup = A 2.2 kΩ 10% resistor will do nicely. The +3.3 V line should be powered separately from the Raspberry Pi, unless the slaves expect to drive very low currents. The main concern here is to not overload the remaining 50 mA capacity of the Pi’s +3.3 V regulated supply. See Chapter 12 about budgeting +3.3 V power. I2C Bus Throughout this chapter, we are assuming a Rev 2.0 or later Raspberry Pi. This matters for the I2C bus because the early versions wired I2C bus 0 to P1-03 and P1-05 (GPIO 0 and 1). Later this was changed to use bus 1. See Chapter 14 for more information about identifying your Pi and which I2C bus to use. If you are using an early Raspberry Pi revision, you’ll need to substitute 0 for bus number 1, in commands and in the C source code that follows. Wiring and Testing The connections to the MCP23017 are simple enough that you can wire it up on a breadboard. The first step after wiring is to determine that you can detect the peripheral on the I2C bus. But even before that, check your kernel module support. If lsmod doesn’t show these modules loaded, you can manually load them now: $ sudo modprobe i2c−dev $ sudo modprobe i2c−bcm2708 If you haven’t already done so, install i2c-tools: $ sudo apt−get install i2c−tools 279 Chapter 23 ■ MCP23017 GPIO Extender If your I2C support is there, you should be able to list the available I2C buses: $ i2cdetect −l i2c −0 unknown i2c −1 unknown bcm2708_i2c.0 bcm2708_i2c.1 N/A N/A The I2C device nodes should also appear in /dev. These nodes give us access to the I2C drivers: $ ls −l /dev/i2c* crw−rw−−−T 1 root root crw−rw−−−T 1 root root 89, 0 89, 1 Feb 18 23:53 Feb 18 23:53 /dev/i2c−0 /dev/i2c−1 The ultimate test is to see whether the MCP23017 chip is detected (change the 1 to 0 for older Pi revisions): $ sudo 0 00: 10: −− 20: 20 30: −− 40: −− 50: −− 60: −− 70: −− i2cdetect −y 1 1 2 3 4 5 −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− 6 −− −− −− −− −− −− −− −− 7 −− −− −− −− −− −− −− −− 8 −− −− −− −− −− −− −− 9 −− −− −− −− −− −− −− a −− −− −− −− −− −− −− b −− −− −− −− −− −− −− c −− −− −− −− −− −− −− d −− −− −− −− −− −− −− e −− −− −− −− −− −− −− f −− −− −− −− −− −− −− In this example, the A2, A1, and A0 pins of the MCP23017 were grounded. This gives the peripheral the I2C address of 0x20. In the session output, we see that address 0x20 was detected successfully. The i2cdump utility can be used to check the MCP23017 register: $ sudo i2cdump –y –r 0x00–0x15 1 0x20 b 0 1 2 3 4 5 6 7 8 9 a 00: ff ff 00 00 00 00 00 00 00 00 00 10: 00 00 00 00 00 00 b 00 c 00 d 00 e 00 f 00 0123456789abcdef ................ ...... Here we have dumped out registers 0x00 to 0x15 on I2C bus 1, at peripheral address 0x20, in byte mode. This was performed after a power-on reset, so we can check whether the register values match the datasheet values documented. As expected, IODIRA (register 0x00) and IODIRB (register 0x01) have the default of all 1s (0xFF). This also confirms that the registers are in BANK=0 mode (this is discussed in the following sections). All other MCP23017 registers default to 0 bits, which is also confirmed. Software Configuration The MCP23017 datasheet describes the full register complement and options available. In this chapter, we’ll concern ourselves with a subset of its functionality, which is perhaps considered “normal use.” The extended functionality is left as an exercise for you. For this chapter’s project, we’re going to do the following: 280 • Configure some GPIOs as inputs • Configure some GPIOs as outputs • Configure the group A and B inputs to signal an interrupt on any change Chapter 23 ■ MCP23017 GPIO Extender General Configuration The MCP23017 peripheral has 10 registers for the GPIO-A pins, 10 registers for the GPIO-B pins, and one shared register. In other words, there are 22 registers, with one pair of addresses referencing a common register. These registers may be accessed in banks or interleaved. We’ll use interleaved mode in this chapter, to avoid having to reset the device. Interleaved register addresses are shown in Table 23-1. These are valid addresses when the IOCON register value for BANK=0 (discussed later in this section). Table 23-1. MCP23017 Register Addresses Register A B Description IODIRx 0x00 0x01 I/O direction IPOLx 0x02 0x03 Input polarity GPINTENx 0x04 0x05 Interrupt on change control DEFVALx 0x06 0x07 Default comparison value INTCONx 0x08 0x09 Interrupt control IOCONx 0x0A 0x0B Configuration GPPUx 0x0C 0x0D Pull-up configuration INTFx 0x0E 0x0F Interrupt flags INTCAPx 0x10 0x11 Interrupt captured value GPIOx 0x12 0x13 General-purpose I/O OLATx 0x14 0x15 Output latch IOCON Register This is the first register that must be configured, since it affects how registers are addressed. Additionally, other settings are established that affect the entire peripheral. Table 23-2 illustrates the layout of the IOCON register. Setting the BANK bit determines whether we use banked or interleaved register addressing. The MCP23017 is in interleaved mode after a power-on reset. Once you set BANK=1, the register addresses change. However, once this change is made, it is impossible to tell, after a program restart, which register mode the peripheral is in. The only option is a hardware reset of the MCP23017 chip, to put it in a known state. For this reason, we’ll keep the peripheral in its power-on reset state of BANK=0. 281 Chapter 23 ■ MCP23017 GPIO Extender Table 23-2. IOCON Register Bit Meaning R W Reset Description 7 BANK Y Y 0 Set to 0 for interleaved access 6 MIRROR Y Y 0 Set to 1 to join INTA & INTB 5 SEQOP Y Y 0 Set to 0 for auto-address increment 4 DISSLW Y Y 0 Set to 1 to disable slew rate control 3 HAEN Y Y 0 Ignored: I2C always uses address 2 ODR Y Y 0 Set to 1 for open-drain INT pins 1 INTPOL Y Y 0 Set to 0 for INT active low 0 N/A 0 X 0 Ignored: reads as zero GPIO Address A 0x0A Note These access a shared register B 0x0B In the tables that follow, a Y under the R (read) or W (write) column/row indicates that you can read or write the respective value. The Reset column indicates the state of the bit after a device reset. An X indicates a “don’t care” or an undefined value when read. An N indicates no access or no effect when written. The bit MIRROR=1 is used to make INT A equivalent to INT B . In other words, GPIO A and B interrupts are reported to both pins. This allows a single pin to be used for A and B groups. Setting bit SEQOP=0 allows the peripheral to automatically increment the register address as each byte is read or written. This eliminates the need to transmit a register address in many cases. Bit DISSLW affects the physical handling of the SDA I2C bus line. HAEN is applicable only to the MCP23S17 SPI device, since addresses are always enabled for I2C devices. This project uses ODR=1 to configure the INT A pin as an open-drain pin. This allows multiple MCP23017 devices to share the same interrupt line. Use a pull-up resistor on the INT line when this is in effect. Otherwise, you may experience several sporadic interrupts. Finally, INTPOL=0 is configured so that the interrupt is active low. This is required for an open-drain connected line along with a pull-up resistor. 282 Chapter 23 ■ MCP23017 GPIO Extender OLATx Register GPIO pins are all configured as inputs after a power-on reset (or use of RESET ). Prior to configuring pins as outputs, it is usually a good idea to set the required output values. This is accomplished by writing the OLAT register, for group A or B. For this project, we’ll just write 0x00 to both OLATA and OLATB. OLATx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x14 R Y Y Y Y Y Y Y Y B 0x15 W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 OLATx Bit Value 0 Output set to 0 1 Output set to 1 GPPUx Register A given project should also define a known value for its input pull-up resistors. Setting a given bit to 1 enables a weak 100 KΩ internal pull-up resistor. This setting affects only the inputs. The pull-up resistors are configured off after a reset. In our example code, we turn them on. GPPUx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x0C R Y Y Y Y Y Y Y Y B 0x0D W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 GPPUx Bit Value 0 Pull-up resistor disabled 1 100 KW pull-up resistor enabled 283 Chapter 23 ■ MCP23017 GPIO Extender DEFVALx Register This register is associated with interrupt processing. Interrupts are produced from conditions arising from input GPIO pins only. An interrupt can be generated if the input differs from the DEFVALx register or if the input value has changed. In the project presented, we simply zero this value because it is not used when detecting changed inputs. DEFVALx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x06 R Y Y Y Y Y Y Y Y B 0x07 W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 DEFVALx Bit Value 0 Interrupt when input not 0 1 Interrupt when input not 1 INTCONx Register This register specifies how input comparisons will be made. In our project, we set all these bits to 0 so that inputs interrupt on change. INTCONx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x08 R Y Y Y Y Y Y Y Y B 0x09 W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 INTCONx Bit Value 0 Input compared against its previous value 1 Input compared against DEFCONx bit value 284 Chapter 23 ■ MCP23017 GPIO Extender IPOLx Register Bits set in this register will invert the logic sense of the corresponding GPIO inputs. In our project, we used no inversion and set the bits to 0. IPOLx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x02 R Y Y Y Y Y Y Y Y B 0x03 W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 IPOLx Bit Value 0 Read same logic as input pin 1 Read inverted logic of input pin IODIRx Register This register determines whether a given GPIO pin is an input or an output. Our project defines bits 4 through 7 as inputs, with the remaining bits 0 through 3 of each 8-bit port as outputs. IPOLx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x00 R Y Y Y Y Y Y Y Y B 0x01 W Y Y Y Y Y Y Y Y Reset 1 1 1 1 1 1 1 1 IPOLx Bit Value 0 Pin is configured as an output 1 Pin is configured as an input 285 Chapter 23 ■ MCP23017 GPIO Extender GPINTENx Register This register enables interrupts on input pin events. Only inputs generate interrupts, so any enable bits for output pins are ignored. How the interrupt is generated by the input is determined by registers DEFVALx and INTCONx. GPINTENx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x04 R Y Y Y Y Y Y Y Y B 0x05 W Y Y Y Y Y Y Y Y Reset 0 0 0 0 0 0 0 0 GPINTENx Bit Value 0 Disable interrupts on this input 1 Enable interrupts for this input For this project, we enabled interrupts on all inputs for ports A and B. INTFx Register This interrupt flags register contains the indicators for each input pin causing an interrupt. This register is unwritable. Interrupt service routines start with this register to identify which inputs are the cause of the interrupt. The DEFVALx and INTCONx registers configure how those interrupts are generated. The INTFx flags are cleared by reading the corresponding INTCAPx or GPIOx register. INTFx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x0E R Y Y Y Y Y Y Y Y B 0x0F W N N N N N N N N Reset 0 0 0 0 0 0 0 0 INTFx Bit Value 0 No interrupt for this input 1 Input has changed or does not compare 286 Chapter 23 ■ MCP23017 GPIO Extender INTCAPx Register The interrupt capture register reports the status of the inputs as the interrupt is being raised. This register is read-only. Reading this register clears the INTFx register, to allow new interrupts to be generated. When INT A is linked to INT B , both INTCAPA and INTCAPB must be read to clear the interrupt (or read the GPIOx registers). INTCAPx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x10 R Y Y Y Y Y Y Y Y B 0x11 W N N N N N N N N Reset 0 0 0 0 0 0 0 0 INTCAPx Bit Value 0 Input state was 0 at time of interrupt 1 Input state was 1 at time of interrupt GPIOx Register Reading this register provides the current input pin values, for pins configured as inputs. Reading the GPIOx register also clears the interrupt flags in INTFx. When INT A is linked to INT B , both GPIOA and GPIOB must be read to clear the interrupt (or read the INTCAPx registers). Presumably, the OLATx register is read, for pins configured for output (the datasheet doesn’t say). Writing to the GPIOx register alters the OLATx settings in addition to immediately affecting the outputs. GPIOx Register GPIO Address Bit 7 6 5 4 3 2 1 0 A 0x12 R Y Y Y Y Y Y Y Y B 0x13 W Y Y Y Y Y Y Y Y Reset X X X X X X X X R/W GPIOx Bit Value R Current input pin state is low W Write 0 to OLATx and output pin R Current input pin state is high W Write 1 to OLATx and output pin Value 0 1 287 Chapter 23 ■ MCP23017 GPIO Extender Main Program Here are some change notes for the main program: 1. If you have a pre-revision 2.0 Raspberry Pi, change line 36 to use /dev/i2c-0. 2. Change line 55 if your MCP23017 chip is using a different I2C address than 0x20 (A2, A1, and A0 grounded). 3. Change line 56 if you use a different Raspberry Pi GPIO for your interrupt sense pin. The main program is fairly straightforward. Here are the basic overall steps: 1. A signal handler is registered in line 180, so ^C will cause the program to exit cleanly. 2. Routine i2c_init() is called to open the I2C driver and initialize. 3. Routine mcp23017_init() is called to initialize and configure the MCP23017 device on the bus (only one is currently supported). 4. Routine gpio_open_edge() is called to open /sys/class/gpio17/value, so changes on the interrupt line can be sensed. This is discussed in more detail later. 5. Finally, the main program enters a loop in lines 190 to 200, looping until ^C is entered. Once inside the main loop, the following events occur: 1. Execution stalls when gpio_poll() is called. This blocks until the interrupt on GPIO 17 transitions from a high to a low. 2. The interrupt flags are read using routine mcp23017_interrupts(). They’re only reported and otherwise not used. 3. Routine mcp23017_captured() is used to read the INTCAPA and INTCAPB registers in order to clear the interrupt. 4. Finally, the routine post_outputs() reads the real-time input values and sends the bits to the outputs. Program mcp23017.c is shown here: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 288 /********************************************************************* * mcp23017.c : Interface with MCP23017 I/O Extender Chip * * This code assumes the following : * * 1. MCP23017 is configured for address 0x20 * 2. RPi’s GPIO 17 (GEN0) will be used for sensing interrupts * 3. Assumed there is a pull up on GPIO 17. * 4. MCP23017 GPA4-7 and GPB4–7 will be inputs, with pull-ups. * 5. MCP23017 GPA0–3 and GPB0–3 will be ouputs. * 6. MCP23017 signals interrupt active low. * 7. MCP23017 operating in non–banked register mode. * * Inputs sensed will be copied to outputs : * 1. GPA4–7 copied to GPA0–3 * 2. GPB4–7 copied to GPB0–3 * Chapter 23 ■ MCP23017 GPIO Extender 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "i2c_funcs.c" /* I2C routines */ /* Change to i2c 0 if using early Raspberry Pi */ static const char * node = "/dev/i2c–1"; #define GPIOA #define GPIOB 0 1 #define #define #define #define #define #define #define #define #define #define #define 0 1 IODIR IPOL GPINTEN DEFVAL INTCON IOCON GPPU INTF INTCAP GPIO OLAT 2 3 4 5 6 7 8 9 10 #define MCP_REGISTER(r,g) (((r) <<1)|(g)) cc/* For I2C routines */ static unsigned gpio_addr = 0x20; static const int gpio_inta = 17 ; static int is_signaled = 0; /* MCP23017 I2C Address */ /* GPIO pin for INTA connection */ /* Exit program if signaled * / #include "sysgpio.c" /* * Signal handler to quit the program */ static void sigint_handler(int signo) { is_signaled = 1; } : /* Signal to exit program */ 289 Chapter 23 ■ MCP23017 GPIO Extender 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 290 /* * Write to MCP23017 A or B register set: */ static int mcp23017_write(int reg,int AB,int value) { unsigned reg_addr = MCP_REGISTER(reg,AB); int rc; rc = i2c_write8(gpio_addr,reg_addr,value); return rc; } /* * Write value to both MCP23017 register sets */ static void mcp23017_write_both(int reg,int value) { mcp23017_write(reg,GPIOA,value); mcp23017_write(reg,GPIOB,value); } : /* Set A */ /* Set B */ /* * Read the MCP23017 input pins (excluding outputs, * 16–bits) : */ static unsigned mcp23017_inputs(void) { unsigned reg_addr = MCP_REGISTER(GPIO,GPIOA); return i2c_read16(gpio_addr,reg_addr) & 0xF0F0; } /* * Write 16 bits to outputs : */ static void mcp23017_outputs(int value) { unsigned reg_addr = MCP_REGISTER(GPIO,GPIOA); i2c_write16 (gpio_addr,reg_addr,value & 0x0F0F); } /* * Read MCP23017 captured values (16–bits): */ static unsigned mcp23017_captured(void) { unsigned reg_addr = MCP_REGISTER(INTCAP,GPIOA); Chapter 23 ■ MCP23017 GPIO Extender 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 return i2c_read16(gpio_addr,reg_addr) & 0xF0F0; } /* * Read interrupting input flags (16–bits) : */ static unsigned mcp23017_interrupts(void) { unsigned reg_addr = MCP_REGISTER(INTF,GPIOA); return i2c_read16(gpio_addr,reg_addr) & 0xF0F0; } /* * Configure the MCP23017 GPIO Extender : */ static void mcp23017_init(void) { int v, int_flags; mcp23017_write_both(IOCON,0b01000100); mcp23017_write_both(GPINTEN,0x00); mcp23017_write_both(DEFVAL,0x00); mcp23017_write_both(OLAT,0x00); mcp23017_write_both(GPPU,0b11110000); mcp23017_write_both(IPOL,0b00000000); mcp23017_write_both(IODIR,0b11110000); mcp23017_write_both(INTCON,0b00000000); mcp23017_write_both(GPINTEN,0b11110000); /* /* /* /* /* /* /* /* /* MIRROR=1,ODR=1 */ No interrupts enabled */ Clear default value */ OLATx=0 */ 4–7 are pull up */ No inverted polarity */ 4–7 are inputs, 0–3 outputs */ Cmp inputs to previous */ Interrupt on changes */ /* * Loop until all interrupts are cleared: */ do { int_flags = mcp23017_interrupts(); if ( int_flags != 0 ) { v = mcp23017_captured(); printf(" Got change %04X values %04X\n",int_flags,v); } } while ( int_flags != 0x0000 && !is_signaled ); } /* * Copy input bit settings to outputs : */ static void post_outputs(void) { int inbits = mcp23017_inputs(); int outbits = inbits >> 4; mcp23017_outputs(outbits); /* Read inputs */ /* Shift to output bits */ /* Copy inputs to outputs */ 291 Chapter 23 ■ MCP23017 GPIO Extender 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 printf (" Outputs: %04X\n",outbits); } /* *Main program : */ int main(int argc,char **argv) { int int_flags, v; int fd; signal(SIGINT,sigint_handler); /* Trap on SIGINT */ i2c_init(node); mcp23017_init(); /* /* Initialize for I2C */ Configure MCP23017 @ 20 fd = gpio_open_edge(gpio_inta); /* Configure INTA pin */ puts("Monitoring for MCP23017 input changes :\n"); post_outputs(); /* Copy inputs to outputs */ do { gpio_poll(fd) ; /* Pause until an interrupt */ int_flags = mcp23017_interrupts(); if ( int_flags ) { v = mcp23017_captured(); printf(" Input change: flags %04X values %04X\n", int_flags,v); post_outputs(); } } while ( !is_signaled ); /* Quit if ^C’ d */ fputc(’\n’, stdout); i2c_close(); close(fd); gpio_close(gpio_inta) ; return 0; /* Close I2C driver */ /* Close gpio17/value */ /* Unex port gpio17 */ } /* End mcp23017.c */ Module i2c_funcs.c To compile code when making use of I2C, you will need to install the libi2c development library: $ sudo apt-get install libi2c-dev 292 */ Chapter 23 ■ MCP23017 GPIO Extender The i2c_funcs.c is a small module that wraps the ioctl(2) calls into neat little I/O functions: i2c_write8(): Writes 8-bit value to MCP23017 register i2c_write16(): Writes 16-bit value to MCP23017 register i2c_read8(): Reads 8-bit value from MCP23017 register i2c_read16(): Reads 16-bit value from MCP23017 register Additionally, the open and close routines are provided: i2c_init(): Opens the bus driver for /dev/i2c-x i2c_close(): Closes the opened I2C driver The C API for these I2C functions are described in Chapter 14. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /************************************************************************* * i2c_funcs.c : I2C Access Functions *************************************************************************/ static int i2c_fd = –1; static unsigned long i2c_funcs = 0; /* Device node : /dev/i2c–1 */ /* Support flags */ /* * Write 8 bits to I2C bus peripheral: */ int i2c_write8(int addr,int reg,int byte) { struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[1]; unsigned char buf[2]; int rc; buf[0] = (unsigned char)reg; buf[1] = (unsigned char)byte; iomsgs[0].addr = (unsigned)addr; iomsgs[0].flags = 0; iomsgs[0].buf = buf; iomsgs[0].len = 2; /* MCP23017 register no. */ /* Byte to write to register */ /* Write */ msgset.msgs = iomsgs; msgset.nmsgs = 1; rc = ioctl(i2c_fd,I2C_RDWR,&msgset); return rc < 0 ? –1 : 0; } /* * Write 16 bits to Peripheral at address : */ 293 Chapter 23 ■ MCP23017 GPIO Extender 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 294 int i2c_write16(int addr, int reg, int value) { struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[1]; unsigned char buf[3]; int rc; buf[0] = (unsigned char)reg; buf[1] = (unsigned char)(( value >> 8 ) & 0xFF); buf[2] = (unsigned char)(value & 0xFF); iomsgs[0].addr = (unsigned)addr; iomsgs[0].flags = 0; iomsgs[0].buf = buf; iomsgs[0].len = 3; /* Write */ msgset.msgs = iomsgs; msgset.nmsgs = 1; rc = ioctl(i2c_fd,I2C_RDWR,&msgset); return rc < 0 ? –1 : 0; } /* * Read 8–bit value from peripheral at addr : */ int i2c_read8(int addr,int reg) { struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[2]; unsigned char buf[1], rbuf[1]; int rc; buf[0] = (unsigned char)reg; iomsgs[0].addr = iomsgs[1].addr = (unsigned)addr; iomsgs[0].flags = 0; /* Write */ iomsgs[0].buf = buf; iomsgs[0].len = 1; iomsgs[1].flags = I2C_M_RD; iomsgs[1].buf = rbuf; iomsgs[1].len = 1; /* Read */ msgset.msgs = iomsgs; msgset.nmsgs = 2; rc = ioctl(i2c_fd,I2C_RDWR,&msgset); return rc < 0 ? –1 : ((int)(rbuf[0]) & 0x0FF); } Chapter 23 ■ MCP23017 GPIO Extender 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 /* * Read 16– bits of data from peripheral : */ int i2c_read16(int addr,int reg) { struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[2]; unsigned char buf[1], rbuf [2]; int rc; buf[0] = (unsigned char)reg; iomsgs[0].addr = iomsgs[1].addr = (unsigned)addr; iomsgs[0].flags = 0; /* Write */ iomsgs[0].buf = buf; iomsgs[0].len = 1; iomsgs[1].flags = I2C_M_RD; iomsgs[1].buf = rbuf ; iomsgs[1].len = 2; /* Read */ msgset.msgs = iomsgs; msgset.nmsgs = 2; if ( (rc = ioctl(i2c_fd,I2C_RDWR,&msgset)) < 0 ) return –1; return (rbuf[0] << 8) | rbuf[1]; } /* * Open I2C bus and check capabilities : */ static void i2c_init(const char * node) { int rc; i2c_fd = open(node,O_RDWR); /* Open driver /dev/i2s–1 */ if ( i2c_fd < 0 ) { perror("Opening /dev/i2s–1"); puts("Check that the i2c dev & i2c–bcm2708 kernel modules " "are loaded."); abort(); } /* * Make sure the driver supports plain I2C I/O: */ rc = ioctl(i2c_fd,I2C_FUNCS,&i2c_funcs); assert(rc >= 0) ; assert(i2c_funcs & I2C_FUNC_I2C); } 295 Chapter 23 ■ MCP23017 GPIO Extender 139 140 141 142 143 144 145 146 147 148 /* * Close the I2C driver */ static void i2c_close(void) { close(i2c_fd); i2c_fd = –1; } /* End i2c_funcs.c : */ Module sysgpio.c The sysgpio.c module performs some grunt work in making the /sys/class/gpio17/value node available and configuring it. This node is opened for reading, so that poll(2) can be called upon it. The interesting code in this module is found in lines 89 to 106, where gpio_poll() is defined. The file descriptor passed to it as fd is the /sys/class/gpio17/value file that is • Configured as input • Triggered on the falling edge (high-to-low transition) The poll(2) system call in line 99 blocks the execution of the program until the input (GPIO 17) changes from a high state to a low state. This is connected to the MCP23017 INT A pin, so it can tell us when its GPIO extender input(s) have changed. The poll(2) system call can return an error if the program has handled a signal. The error returned will be EINTR when this happens (as discussed in Chapter 11, section “Error EINTR”). If the program detects that ^C has been pressed (is_signaled is true), then it exits, returning -1, to allow the main program to exit. A value of rc=1 is returned if /sys/class/gpio17/value has a changed value to be read. Before returning from gpio_poll(), a read(2) of any unread data is performed. This is necessary so that the next call to poll(2) will block until new data is available. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 296 /********************************************************************* * sysgpio.c : Open/configure /sys GPIO pin * * Here we must open the /sys/class/gpio/gpio17/value and do a * poll(2) on it, so that we can sense the MCP23017 interrupts. *********************************************************************/ typedef enum { gp_export = 0, gp_unexport, gp_direction, gp_edge, gp_value } gpio_path_t; /* /* /* /* /* /sys/class/gpio/export */ /sys/class/gpio/unexport */ /sys/class/gpo%d/direction */ /sys/class/gpio%d/edge */ /sys/class/gpio%d/value */ /* * Internal : Create a pathname for type in buf. */ Chapter 23 ■ MCP23017 GPIO Extender 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 static const char * gpio_setpath(int pin,gpio_path_t type,char *buf,unsigned bufsiz) { static const char *paths[] = { "export", "unexport", "gpio%d/direction", "gpio%d/edge", "gpio%d/value" }; int slen; strncpy(buf,"/sys/class/gpio/",bufsiz); bufsiz –= (slen = strlen(buf)); snprintf(buf+slen,bufsiz,paths[type],pin); return buf; } /* * Open /sys/class/gpio%d/value for edge detection */ static int gpio_open_edge(int pin) { char buf[128]; FILE *f; int fd; : /* Export pin: /sys/class/gpio/export */ gpio_setpath(pin,gp_export,buf,sizeof buf); f = fopen(buf, "w"); assert(f); fprintf(f,"%d\n",pin); fclose(f); /* Direction: /sys/class/gpio%d/direction */ gpio_setpath(pin,gp_direction,buf,sizeof buf); f = fopen(buf,"w"); assert(f); fprintf(f,"in\n"); fclose(f); /* Edge: /sys/class/gpio%d/edge */ gpio_setpath(pin,gp_edge,buf,sizeof buf); f = fopen(buf,"w"); assert(f); fprintf(f,"falling\n"); fclose(f); /* Value: /sys/class/gpio%d/value */ gpio_setpath(pin,gp_value,buf,sizeof buf); fd = open(buf,O_RDWR); return fd; } /* * Close (unexport) GPIO pin : */ 297 Chapter 23 ■ MCP23017 GPIO Extender 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 static void gpio_close(int pin) { char buf[128]; FILE *f ; /* Unexport: /sys/class/gpio/unexport */ gpio_setpath(pin,gp_unexport,buf,size of buf); f = fopen(buf,"w"); assert(f); fprintf(f,"%d\n",pin); fclose(f); } /* * This routine will block until the open GPIO pin has changed * value. This pin should be connected to the MCP23017 /INTA * pin. */ static int gpio_poll(int fd) { unsigned char buf[32]; struct pollfd polls; int rc; polls.fd = fd; polls.events = POLLPRI; do /* /sys/class/gpio17/value */ /* Exceptions */ { rc = poll(&polls,1,–1); if ( is_signaled ) return –1; } while ( rc < 0 && errno == EINTR ); (void)read(fd,buf,sizeof buf); return 0; /* Block */ /* Exit if ^Creceived */ /* Clear interrupt */ } /* End sysgpio.c */ Example Run The first time you run the program, you might encounter an error: $ ./mcp23017 Opening /dev/i2s−1: No such file or directory Check that the i2c−dev & i2c−bcm2708 kernel modules are loaded. Aborted $ 298 Chapter 23 ■ MCP23017 GPIO Extender As the program states in the error message, it is unable to open the I2C driver, because the I2C kernel modules have not been loaded. See Chapter 14 for modprobe information. The following is a successful session. After the program is started, the program pauses after issuing the message “Monitoring for MCP23017 input changes.” At this point, the program is in the poll(2) system call, waiting to be notified of an interrupt from the MCP23017 peripheral. If you open another session, you can confirm that little or no CPU resource is consumed by this. $ sudo ./mcp23017 Monitoring for MCP23017 input changes : Outputs : Input change Outputs : Input change Outputs : Input change Outputs : Input change Outputs : Input change Outputs : Input change Outputs : : : : : : : 0F0F flags 070F flags 070F flags 070F flags 070F flags 070F flags 0F0F 8000 values 70F0 8000 values F0F0 8000 values F0F0 8000 values F0F0 8000 values F0F0 8000 values 70F0 ^C $ While this was running, I carefully grounded pin 28 of the MCP28017 chip, which is input GPA7. This is reflected immediately in the message: Input change : flags 8000 values 70F0 The flags value reported as 8000 is decoded next, showing that GPA7 did indeed change in value: INTFA INTFB 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 The value reported as 70F0 is from the INTCAPx register pair: INTCAPA INTCAPB 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 This shows us that the GPA7 pin is found in the zero state at the time of the interrupt. All remaining inputs show high (0s indicate output pins). 299 Chapter 23 ■ MCP23017 GPIO Extender While I grounded the GPA7 pin only once, you can see from the session output that several events occur. This is due to the bounce of the wire as it contacts. You’ll also note that some events are lost during this bounce period. Look at the input events: 1 2 3 4 5 6 Input Input Input Input Input Input change: change: change: change: change: change: flags flags flags flags flags flags 8000 8000 8000 8000 8000 8000 values values values values values values 70F0 F0F0 F0F0 F0F0 F0F0 70F0 Each interrupt correctly shows that pin GPA7 changed. But look closely at the captured values for the inputs: 1. The captured level of the input is 0 (line 1). 2. The captured level change of the input is now 1 (line 2). 3. The next input change shows a captured level of 1 (line 3). How does the state of an input change from a 1 to a 1? Clearly what happens is that the input GPA7 changes to low but returns to high by the time the interrupt is captured. Push button, switch, and key bounces can occur often with a variety of pulse widths, in the range of microseconds to milliseconds, until the contact stabilizes (off or on). The very action of pushing a button can initiate a series of a thousand pulses. Some pulses will be too short for the software to notice, so it must be prepared to deal with this. Sometimes electronics circuits are applied to eliminate “key debouncing” so that the software will see a clean and singular event. This is what is accomplished in Chapter 29, where a flip-flop is used. Response Times You should be aware of the interrupt notification limitations provided by the poll(2) system call. The input lines could easily change faster than the Raspberry Pi can respond. Consider the process involved: 1. An input GPIO extender pin changes in value. 2. The MCP23017 device activates INT A by bringing it from a high to a low (a few cycles later). 3. The Raspberry Pi’s GPIO 17 pin sees a falling input level change. 4. The device driver responds to the GPIO pin change by servicing an interrupt and then notifies the application waiting in poll(2). 5. The application sends some I2C traffic to query the INTFA and INTFB flag registers in the MCP23017. 6. Registers GPIOA and GPIOB must also be read to clear the interrupt, involving more I/O on the I2C bus. Consequently, there is considerable delay in sensing a GPIO change and the clearing of the device interrupt. An informal test using select(2) purely for delay purposes (no file descriptors) required a minimum of approximately 150 ms on a 700 MHz Pi. The poll(2) call is likely to be nearly identical. Attempting to set smaller timed delays bottomed out near 150 ms. This suggests that the quickest turnaround for reacting to an INT signal from the MCP23017 will be 150 ms (excluding the time needed to actually service the registers in the peripheral). This means that the absolute maximum number of interrupts per second that can be processed will be 6,600. 300 Chapter 23 ■ MCP23017 GPIO Extender To estimate the effects of the IC2 bus, let’s do some additional simplified calculations. The I2C bus operates at 100 kHz on the Raspberry Pi (Chapter 14). A single byte requires 8 data bits and an acknowledgment bit. This requires about 90 ms per byte. To read one MCP23017 register requires the following: 1. The peripheral’s address byte to be sent (1 byte). 2. The MCP23017 register address to be sent (1 byte). 3. The MCP23017 responds back with 1 byte. This requires 3 ´ 90 = 270 ms, just to read one register. Add to this the following: 1. Both interrupt flag registers INTFA and INTFB must be read. 2. Both GPIOA and GPIOB registers must be read, to clear the interrupt. So, ignoring the start and stop bits, this requires 4 ´ 270 = 1.80 ms to respond to one input level change. (This also ignores the effect of multiple peripherals on the bus.) This, added to the minimum of about 150 ms overhead for poll(2), leads to the minimum response time of about 1.08 + 0.150 = 1.23 ms. This results in a practical limit of about 800 signal changes per second. Because of the response-time limitations, it is recommended that the INTCAPx register values be ignored. By the time the application can respond to a signal change, it may have changed back again. This is why the program presented uses the values read in GPIOA and GPIOB, rather than the captured values in the INTCAPx. But if your application needs to know the state at the time of the event, the INTCAPx register values are available. Some reduced I2C overhead can be attained by tuning the I/O operations. For example, with use of the auto-increment address feature of the MCP23017, it is possible to read both INTFx flags and GPIOx registers in one ioctl(2) call: T = t addr + t register + t INTFA + t INTFB + t register + tGPIOA + tGPIOB = 7 ´ 90 = 0.630 ms That approach reduces the I2C time to approximately 7-byte times. The total turnaround time can then be reduced to about 0.63 + 0.150 = 0.78 ms. 301 Chapter 24 Nunchuk-Mouse This chapter’s project is about attaching the Nintendo Wii Nunchuk to the Raspberry Pi. The Nunchuk has two buttons; an X-Y joystick; and an X, Y, and Z accelerometer. The sensor data is communicated through the I2C bus. Let’s have some fun using a Nunchuk as a pointing device for the X Window System desktop. Project Overview The challenge before us breaks down into two overall categories: • The I2C data communication details of the Nunchuk device • Inserting the sensed data into the X Window System desktop event queue Since you’ve mastered I2C communications in other parts of this book, we’ll focus more on the Nunchuk technical details. The remainder of the chapter looks at the Linux uinput API that will be used for the X-Windows interface. The final details cover a small but critical X-Windows configuration change, to bring about the Nunchuk-Mouse. Nunchuk Features The basic physical and data characteristics of the Nunchuk are listed in Table 24-1. Table 24-1. Nunchuk Controls and Data Characteristics User-Interface Features Bits Data Hardware/Chip C Button 1 Boolean Membrane switch Z button 1 Boolean Membrane switch X-Y joystick 8x2 Integers 30 kW potentiometers X, Y, and Z accelerometer 10x3 Integers ST LIS3L02 series For application as a mouse, the C and Z buttons fill in for the left and right mouse buttons. The joystick is used to position the mouse cursor. While the Nunchuk normally operates at a clock rate of 400 kHz, it works just fine at the Raspberry Pi’s 100 kHz I2C rate. 303 Chapter 24 ■ Nunchuk-Mouse ■■Note I encourage you to experiment with the accelerometer. Connector Pinout There are four wires, two of which are power and ground (some units may have two additional wires, one that connects to the shield and the other to the unused center pin). The remaining two wires are used for I2C communication (SDA and SCL). The connections looking into the cable-end connector are shown in Table 24-2. Table 24-2. Nuncheck Cable Connections SCL Gnd +3.3 V N/C SDA The Nunchuk connector is annoyingly nonstandard. Some folks have rolled their own adapters using a double-sided PCB to mate with the inner connections. Others have purchased adapters for around $6. Cheap Nunchuk clones may be found on eBay for about half that price. With the growing number of clone adapters becoming available at morecompetitive prices, there is less reason to cut off the connector. ■■Tip Beware of Nunchuk forgeries and nonfunctional units. If you do cut off the connector, you will quickly discover that there is no standard wire color scheme. The only thing you can count on is that the pins are laid out as in Table 24-2. If you have a genuine Wii Nunchuk, the listed wire colors in Table 24-3 might be valid. The column labeled Clone Wire lists the wire colors of my own clone’s wires. Yours will likely differ. Table 24-3. Nunchuk Connector Wiring Pin Wii Wire CloneWire† Description P1 Gnd White White Ground P1-25 SDA Green Blue Data P1-03 +3.3 V Red Red Power P1-01 SCL Yellow Green Clock P1-05 Clone wire colors vary! † Before you cut that connector off your clone, consider that you’ll need to trace the connector to a wire color. Cut the cable, leaving about 3 inches of wire for the connector. Then you can cut the insulation off and trace the pins to a wire by using an ohmmeter (or by looking inside the cable-end connector). Figure 24-1 shows the author’s clone Nunchuk with the connector cut off. In place of the connector, solid wire ends were soldered on and a piece of heat shrink applied over the solder joint. The solid wire ends are perfect for plugging into a prototyping breadboard. 304 Chapter 24 ■ Nunchuk-Mouse Figure 24-1. Nunchuk with wire ends Testing the Connection Once you’ve hooked up the Nunchuk to the Raspberry Pi, you’ll want to perform some simple tests to make sure it is working. The first step is to make sure your I2C drivers are loaded: $ lsmod | grep i2c i2c_bcm2708 i2c_dev 3759 5620 0 0 If you see these modules loaded, you’re good to go. Otherwise, manually load them now: $ sudo modprobe i2c−bcm2708 $ sudo modprobe i2c−dev Assuming the Raspberry Pi rev 2.0+, you’ll use I2C bus 1 (see Chapter 14 if you’re not sure). Scan to see whether your Nunchuk is detected: $ sudo i2cdetect −y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: −− −− −− −− −− −− −− −− −− −− −− −− −− 10: −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− 20: −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− 30: −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− 40: −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− 305 Chapter 24 ■ Nunchuk-Mouse 50: 60: 70: −− −− 52 −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− −− If the Nunchuk is working, it will show up in this display at address 0x52. With the hardware verified, it is time to move on to the software. Nunchuk I2C Protocol The Nunchuk contains a quirky little controller that communicates through the I2C bus. In order to know where to store bytes written to it, the first byte must be an 8-bit register address. In other words, each write to the Nunchuk requires the following: • One register address byte, followed by • Zero or more data bytes to be written to sequential locations Thus for write operations, the first byte sent to the Nunchuk tells it where to start. Any following write bytes received are written with the register address incremented. ■■Tip Don’t confuse the register address with the Nunchuk’s I2C address of 0x52. It is possible to write the register address and then read bytes instead. This procedure specifies the starting location of data bytes to be read. A quirky aspect of the Nunchuk controller is that there must be a short delay between writing the register address and reading the data. Performing the write followed by an immediate read does not work. Writing data immediately after the register address does succeed, however. ■■Note The Nunchuk uses I2C address 0x52. Encryption The Nunchuk is designed to provide an encrypted link. However, that can be disabled by initializing it a certain way. The defeat procedure is as follows: 1. Write 0x55 to Nunchuk location 0xF0. 2. Pause. 3. Write 0x00 to Nunchuk location 0xFB. The following illustrates the message sequence involved. Notice that this is performed as two separate I2C write operations: Write F0 55 Pause - Write FB 00 Once this is successfully performed, all future data is returned unencrypted. 306 Chapter 24 ■ Nunchuk-Mouse Read Sensor Data The whole point of the Nunchuk is to read its sensor data. When requested, it returns 6 bytes of data formatted as shown in Table 24-4. Table 24-4. Nunchuk Data Byte Bits Description 1 Analog stick x axis value 2 Analog stick y axis value 3 X acceleration bits 9:2 4 Y acceleration bits 9:2 5 Z acceleration bits 9:2 6 0 Z button pressed (active low) 1 C button pressed (active low) 3:2 X acceleration bits 1:0 5:4 Y acceleration bits 1:0 7:6 Z acceleration bits 1:0 Some of the data is split over multiple bytes. For example, the X acceleration bits 9:2 are obtained from byte 3. The lowest 2 bits are found in byte 6, in bits 3 and 2. These together form the 9-bit X acceleration value. To retrieve this data, we are always required to tell the Nunchuk where to begin. So the sequence always begins with a write of offset 0x00 followed by a pause: Write 00 Pause - 01 02 Read 6 bytes 03 04 05 06 The Nunchuk doesn’t allow us to do this in one ioctl(2) call, using two I/O messages. A write of 0 must be followed by a pause. Then the 6 data bytes can be read as a separate I2C read operation. If the pause is too long, however, the Nunchuk controller seems to time out, resulting in incorrect data being returned. So we must do things the Nunchuk way. Linux uinput Interface While reading the Nunchuk is fun, we need to apply it to our desktop as a mouse. We need to insert mouse events based on what we read from it. The Linux uinput driver allows programmers to develop nonstandard input drivers so that events can be injected into the input stream. This approach allows new input streams to be added without changing application code. Certainly the Nunchuk qualifies as a nonstandard input device! 307 Chapter 24 ■ Nunchuk-Mouse A problem with this uinput API is its general lack of documentation. The best information available on the Internet seems to be from these three online sources: • “Getting started with uinput: the user level input subsystem” http://thiemonge.org/getting-started-with-uinput • ”Using uinput driver in Linux- 2.6.x to send user input” http://www.einfochips.com/download/dash_jan_tip.pdf • “Types” http://www.kernel.org/doc/Documentation/input/event-codes.txt The only other source of information seems to be the device driver source code itself: drivers/input/misc/uinput.c The example program provided in this chapter can help pull all the necessary details together for you. Working with Header Files The header files required for the uinput API include the following: #include #include #include To compile code, making use of I2C, you also need to install the libi2c development library, if you have not done that already: $ sudo apt-get install libi2c-dev Opening the Device Node The connection to the uinput device driver is made by opening the device node: /dev/uinput The following is an example of the required open(2) call: int fd; fd = open("/dev/uinput",O_WRONLY|O_NONBLOCK); if ( fd < 0 ) { perror("Opening /dev/uinput"); ... 308 Chapter 24 ■ Nunchuk-Mouse Configuring Events In order to inject events, the driver must be configured to accept them. Each call to ioctl(2) in the following code enables one class of events based on the argument event. The following is a generalized example: int rc; unsigned long event = EV_KEY; rc = ioctl(fd,UI_SET_EVBIT,event); assert(!rc); The list of UI_SET_EVBIT event types is provided in Table 24-5. The most commonly needed event types are EV_SYN, EV_KEY, and EV_REL (or EV_ABS). Table 24-5. List of uinput Event Types From Header File input.h Macro Description EV_SYN Event synchronization/separation EV_KEY Key/button state changes EV_REL Relative axis mouse-like changes EV_ABS Absolute axis mouse-like changes EV_MSC Miscellaneous events EV_SW Binary (switch) state changes EV_LED LED on/off changes EV_SND Output to sound devices EV_REP For use with autorepeating devices EV_FF Force feedback commands to input device EV_PWR Power button/switch event EV_FF_STATUS Receive force feedback device status ■■Caution Do not or the event types together. The device driver expects each event type to be registered separately. Configure EV_KEY Once you have registered your intention to provide EV_KEY events, you need to register all key codes that might be used. While this seems a nuisance, it does guard against garbage being injected by an errant program. The following code registers its intention to inject an Escape key code: int rc; rc = ioctl(fd,UI_SET_KEYBIT,KEY_ESC); assert(!rc); 309 Chapter 24 ■ Nunchuk-Mouse To configure all possible keys, a loop can be used. But do not register key code 0 (KEY_RESERVED) nor 255; the include file indicates that code 255 is reserved for the special needs of the AT keyboard driver. int rc; unsigned long key; for ( key=1; key<255; ++key ) { rc = ioctl(fd,UI_SET_KEYBIT,key); assert(!rc); } Mouse Buttons In addition to key codes, the same ioctl(2,UI_SET_KEYBIT) call is used to register mouse, joystick, and other kinds of button events. This includes touch events from trackpads, tablets, and touchscreens. The long list of button codes is defined in header file linux/input.h. The usual suspects are shown in Table 24-6. Table 24-6. Key Event Macros Macro Synonym Description BTN_LEFT BTN_MOUSE Left mouse button BTN_RIGHT Right mouse button BTN_MIDDLE Middle mouse button BTN_SIDE Side mouse button The following example shows the application’s intention to inject left and right mouse button events: int rc; rc=ioctl(fd,UI_SET_KEYBIT,BTN_LEFT); assert(!rc); rc = ioctl(fd,UI_SET_KEYBIT,BTN_RIGHT); assert(!rc); Configure EV_REL In order to inject EV_REL events, the types of relative movements must be registered in advance. The complete list of valid argument codes is shown in Table 24-7. The following example indicates an intention to inject x and y relative axis movements: rc = ioctl(fd,UI_SET_RELBIT,REL_X); assert(!rc); rc = ioctl(fd,UI_SET_RELBIT,REL_Y); assert(!rc); 310 Chapter 24 ■ Nunchuk-Mouse Table 24-7. UI_SET_RELBIT Options Macro Intention REL_X Send relative X changes REL_Y Send relative Y changes REL_Z Send relative Z changes REL_RX x-axis tilt REL_RY y- axis tilt REL_RZ z- axis tilt REL_HWHEEL Horizontal wheel change REL_DIAL Dial-turn change REL_WHEEL Wheel change REL_MISC Miscellaneous Configure EV_ABS While we don’t use the EV_ABS option in this project, it may be useful to introduce this feature at this point. This event represents absolute cursor movements, and it too requires registration of intentions. The complete list of EV_ABS codes is defined in linux/input.h. The usual suspects are defined in Table 24-8. Table 24-8. Absolute Cursor Movement Event Macros Macro Description ABS_X Move X to this absolute X coordinate ABS_Y Move Y to this absolute Y coordinate The following is an example of registering intent for absolute x- and y-axis events: int rc; rc = ioctl(fd,UI_SET_ABSBIT,ABS_X); assert(!rc); rc = ioctl(fd,UI_SET_ABSBIT,ABS_X); assert(!rc); In addition to registering your intentions to inject these events, you need to define some coordinate parameters. The following is an example: struct uinput_user_dev uinp; uinp.absmin[ABS_X] = 0; uinp.absmax[ABS_X] = 1023; 311 Chapter 24 ■ Nunchuk-Mouse uinp.absfuzz[ABS_X] = 0; uinp.absflat[ABS_X] = 0; uinp.absmin[ABS_Y] = 0; uinp.absmax[ABS_Y] = 767; uinp.absfuzz[ABS_Y] = 0; uinp.absflat[ABS_Y] = 0; These values must be established as part of your ioctl(2,UI_DEV_CREATE) operation, which is described next. Creating the Node After all registrations with the uinput device driver have been completed, the final step is to create the uinput node. This will be used by the receiving application, in order to read injected events. This involves two programming steps: 1. Write the struct uinput_user_dev information to the file descriptor with write(2). 2. Perform an ioctl(2,UI_DEV_CREATE) to cause the uinput node to be created. The first step involves populating the following structures: struct input_id __u16 __u16 __u16 __u16 }; { bustype; vendor; product; version; struct uinput_user_dev { char name[UINPUT_MAX_NAME_SIZE]; struct input_id id; int ff_effects_max; int absmax[ABS_CNT]; int absmin[ABS_CNT]; int absfuzz[ABS_CNT]; int absflat[ABS_CNT]; }; An example populating these structures is provided next. If you plan to inject EV_ABS events, you must also populate the abs members, mentioned in the “Configure EV_ABS” section. struct uinput_user_dev uinp; int rc; memset(&uinp,0,sizeof uinp); strncpy(uinp.name,"nunchuk",UINPUT_MAX_NAME_SIZE); uinp.id.bustype = BUS_USB; uinp.id.vendor = 0x1; uinp.id.product = 0x1; uinp.id.version = 1; 312 Chapter 24 ■ Nunchuk-Mouse uinp.absmax[ABS_X] = 1023; /∗EV_ABS only ∗/ ... // // rc = write(fd,&uinp,sizeof(uinp)); assert(rc == sizeof(uinp)); The call to write(2) passes all of this important information to the uinput driver. Now all that remains is to request a device node to be created for application use: int rc; rc = ioctl(fd,UI_DEV_CREATE); assert(!rc); This step causes the uinput driver to make a device node appear in the pseudo directory /dev/input. An example is shown here: $ ls –l /dev/input total 0 drwxr−xr−x 2 root root drwxr−xr−x 2 root root crw−rw−−−T 1 root input crw−rw−−−T 1 root input crw−rw−−−T 1 root input crw−rw−−−T 1 root input crw−rw−−−T 1 root input crw−rw−−−T 1 root input crw−rw−−−T 1 root input 120 120 13, 64 13, 65 13, 66 13, 67 13, 63 13, 32 13, 33 Dec Dec Dec Dec Dec Feb Dec Dec Feb 31 1969 by−id 31 1969 by−path 31 1969 event0 31 1969 event1 31 1969 event2 23 13:40 event3 31 1969 mice 31 1969 mouse0 23 13:40 mouse1 The device /dev/input/event3 was the Nunchuck’s created uinput node, when the program was run. Posting EV_KEY Events The following code snippet shows how to post a key down event, followed by a key up event: 1 static void 2 uinput_postkey(int fd,unsigned key) { 3 struct input_event ev; 4 int rc; 5 6 memset(&ev,0,sizeof(ev)); 7 ev.type = EV_KEY; 8 ev.code = key; 9 ev.value = 1; 10 11 rc = write(fd,&ev,sizeof(ev)); 12 assert(rc == sizeof(ev)); 13 14 ev.value = 0; 15 rc = write(fd,&ev,sizeof(ev)); 16 assert(rc == sizeof(ev)); 17 } 313 Chapter 24 ■ Nunchuk-Mouse From this example, you see that each event is posted by writing a suitably initialized input_event structure. The example illustrates that the member named type was set to EV_KEY, code was set to the key code, and a keypress was indicated by setting the member value to 1 (line 9). To inject a key up event, value is reset to 0 (line 14) and the structure is written again. Mouse button events work the same way, except that you supply mouse button codes for the code member. For example: memset(&ev,0,sizeof(ev)); ev.type = EV_KEY; ev.code = BTN_RIGHT; ev.value = 1; /∗Right click ∗/ Posting EV_REL Events To post a relative mouse movement, we populate the input_event as a type EV_REL. The member code is set to the type of event (REL_X or REL_Y in this example), with the value for the relative movement established in the member value: static void uinput_movement(int fd,int x,inty) { struct input_event ev; int rc; memset(&ev,0,sizeof(ev)); ev.type = EV_REL; ev.code = REL_X; ev.value = x; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); ev.code = REL_Y; ev.value = y; rc = write(fd,&ev,sizeof(ev)); assert (rc == sizeof(ev)); } Notice that the REL_X and REL_Y events are created separately. What if you want the receiving application to avoid acting on these separately? The EV_SYN event helps out in this regard (next). Posting EV_SYN Events The uinput driver postpones delivery of events until the EV_SYN event has been injected. The SYN_REPORT type of EV_SYN event causes the queued events to be flushed out and reported to the interested application. The following is an example: static void uinput_syn(int fd) { struct input_event ev; int rc; 314 Chapter 24 ■ Nunchuk-Mouse memset(&ev,0,sizeof(ev)); ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); } For a mouse relative movement event, for example, you can inject a REL_X and REL_Y, followed by a SYN_REPORT event to have them seen by the application as a group. Closing uinput There are two steps involved: 1. Destruction of the /dev/input/event%d node 2. Closing of the file descriptor The following example shows both: int rc; rc = ioctl(fd,UI_DEV_DESTROY); assert(!rc); close(fd); Closing the file descriptor implies the ioctl(2,UI_DEV_DESTROY) operation. The application has the option of destroying the device node while keeping the file descriptor open. X-Window The creation of our new uinput device node is useful only if our desktop system is listening to it. Raspbian Linux’s X-Windows system needs a little configuration help to notice our Frankenstein creation. The following definition can be added to the /usr/share/X11/xorg.config.d directory. Name the file 20-nunchuk.conf: # Nunchuck event queue Section "InputClass" Identifier "Raspberry Pi Nunchuk" Option "Mode" "Relative" MatchDevicePath "/dev/input/event3" Driver "evdev" EndSection # End 20−nunchuk.conf This configuration change works only if your Nunchuk uinput device shows up as /dev/input/event3. If you have other specialized input device creations on your Raspberry Pi, it could well be event4 or some other number. See the upcoming section “Testing the Nunchuk” for troubleshooting information. Restart your X-Windows server to have the configuration file noticed. 315 Chapter 24 ■ Nunchuk-Mouse ■■Tip Normally, your Nunchuk program should be running already. But the X-Windows server will notice it when the Nunchuk does start. Input Utilities When writing uinput event-based code, you will find the package input-utils to be extremely helpful. They can be installed from the command line as follows: $ sudo apt−get install input−utils The following commands are installed: lsinput(8): List uinput devices input-events(8): Dump selected uinput events input-kbd(8): Keyboard map display This chapter uses the first two utilities: lsinput(8) and input-events(8). Testing the Nunchuk Now that the hardware, drivers, and software are ready, it is time to exercise the Nunchuk. Unfortunately, there is no direct way for applications to identify your created uinput node. When the Nunchuk program runs, the node may show up as /dev/input/event3 or some other numbered node if event3 already exists. If you wanted to start a Nunchuk driver as part of the Linux boot process, you need to create a script to edit the file with the actual device name. The affected X-Windows config file is as follows: /usr/share/X11/xord.conf.d/20-nunchuk.conf The script (shown next) determines which node the Nunchuk program created. The following is an example run, while the Nunchuk program was running: $ ./findchuk /dev/input/event3 When the node is not found, the findchuk script exits with a nonzero code and prints a message to stderr: $ ./findchuk Nunchuk uinput device not found. $ echo $? 1 316 Chapter 24 ■ Nunchuk-Mouse The findchuk script is shown here: #!/bin/bash ###################################################################### # Find the Nunchuck ###################################################################### # # This script locates the Nunchuk uinput device by searching the # /sys/devices/virtual/input pseudo directory for names of the form: # input[0_9]∗. For all subdirectories found, check the ./name pseudo # file, which will contain "nunchuk". Then we derive the /dev path # from a sibling entry named event[0_9]∗. That will tell use the # /dev/input/event%d pathname, for the Nunchuk. DIR=/sys/devices/virtual/input set_eu # Top level directory cd "$DIR" find . −type d −name 'input[0−9]∗' | ( set −eu while read dirname ; do cd "$DIR/$dirname" if [−f "name"] ; then set +e name=$(cat name) set −e if [ $(cat name) = nunchuk ] ; then event="/dev/input/$ (ls−devent[0−9]∗)" echo $event exit 0 # Found it fi fi done echo "Nunchuk uinput device not found." >&2 exit 1 ) # End findchuk Testing ./nunchuk When you want to see what Nunchuk data is being received, you can add the -d command-line option: $ ./nunchuk −d Raw nunchuk data: [83] [83] [5C] [89] [A2] [63] .stick_x = 0083 (131) .stick_y = 0083 (131) .accel_x = 0170 (368) .accel_y = 0226 (550) .accel_z = 0289 (649) .z_button= 0 .c_button= 0 317 Chapter 24 ■ Nunchuk-Mouse The first line reports the raw bytes of data that were received. The remainder of the lines report the data in its decoded form. While the raw data reports the button presses as active low, the Z and C buttons are reported as 1 in the decoded data. The value in the left column is in hexadecimal format, while the value in parenthesis is shown in decimal. Utility lsinputs When the Nunchuk program is running, you should be able to see the Nunchuk uinput device in the list: $ lsinput ... /dev/input/event2 bustype : BUS_USB vendor : 0x45e product : 0x40 version : 272 name : "Microsoft Micro soft 3−Button Mou" phys : "usb−bcm2708_usb−1.3.4/input0" uniq : "" bitsev : EV_SYN EV_KEY EV_REL EV_MSC /dev/input/event3 bustype : vendor : product : version : name : bits ev : BUS_USB 0x1 0x1 1 "nunchuk" EV_SYN EV_KEY EV_REL In this example, the Nunchuk shows up as event3. Utility input-events When developing uinput-related code, the input-events utility is a great help. Here we run it for event3 (the argument 3 on the command line), where the Nunchuk mouse device is: $ input−events 3 /dev/input/event3 bustype : BUS_USB vendor : 0x1 product : 0x1 version : 1 name : "nunchuk" bits ev : EV_SYN EV_KEY EV_REL waiting for events 23:35:15.345105: EV_KEY 23:35:15.345190: EV_SYN 23:35:15.517611: EV_KEY 23:35:15.517713: EV_SYN 318 BTN_LEFT (0x110) pressed code=0 value=0 BTN_LEFT (0x110) released code=0 value=0 Chapter 24 ■ Nunchuk-Mouse 23:35:15.833640: 23:35:15.833727: 23:35:16.019363: 23:35:16.019383: 23:35:16.564129: 23:35:16.564213: 23:35:16.564261: ... EV_KEY EV_SYN EV_KEY EV_SYN EV_REL EV_REL EV_SYN BTN_RIGHT (0x111) pressed code=0 value=0 BTN_RIGHT (0x111) released code=0 value=0 REL_X −1 REL_Y 1 code=0 value=0 The Program The code for nunchuk.c is presented on the following pages. The source code for timed_wait.c is shown in Chapter 22. We’ve covered the I2C I/O in other chapters. The only thing left to note is the difficulty of providing a smooth interface for events produced by the Nunchuk. Here are a few hints for the person who wants to experiment: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1. If the mouse moves too quickly, one major factor is the timed delay used. The timed_wait() call in line 107 spaces out read events for the Nunchuk (currently 15 ms). This also lightens the load on the CPU. Reducing this time-out increases the number of Nunchuk reads and causes more uinput events to be injected. This speeds up the mouse pointer. 2. The function curve() in line 349 attempts to provide a somewhat exponential movement response. Small joystick excursions should be slow and incremental. More-extreme movements will result in faster mouse movements. 3. The Z button is interpreted as the left-click button, while the C button is the right-click button. 4. No keystrokes are injected by this program, but it can be modified to do so. The function uinput_postkey() on line 244 can be used for that purpose. /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ nunchuk.c: Read events from nunchuck and stuff as mouse events ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "timed_wait.c" static int is_signaled = 0; static int i2c_fd = −1; static int f_debug = 0; /∗Exit program if signaled ∗/ /∗Open/dev/i2c−1 device ∗/ /∗True to print debug messages ∗/ 319 Chapter 24 ■ Nunchuk-Mouse 24 25 typedef struct { 26 unsigned char stick_x; /∗Joystick X ∗/ 27 unsigned char stick_y; /∗Joystick Y ∗/ 28 unsigned accel_x; /∗Accel X ∗/ 29 unsigned accel_y; /∗Accel Y ∗/ 30 unsigned accel_z; /∗Accel Z ∗/ 31 unsigned z_button: 1; /∗Z button ∗/ 32 unsigned c_button: 1; /∗C button ∗/ 33 unsigned char raw[6]; /∗Raw received data ∗/ 34 } nunchuk_t; 35 36 / ∗ 37 ∗ Open I2C bus and check capabilities: 38 ∗ / 39 static void 40 i2c_init(const char ∗node) { 41 unsigned long i2c_funcs = 0; /∗Support flags ∗/ 42 int rc; 43 44 i2c_fd = open(node,O_RDWR); /∗Open driver/dev/i2s−1 ∗/ 45 if ( i2c_fd < 0 ) { 46 perror("Opening/dev/i2s−1"); 47 puts("Check that the i2c−dev & i2c−bcm2708 kernel modules" 48 "are loaded."); 49 abort(); 50 } 51 52 /∗ 53 ∗ Make sure the driver supports plain I2C I/O: 54 ∗/ 55 rc = ioctl(i2c_fd,I2C_FUNCS,&i2c_funcs); 56 assert(rc >=0); 57 assert(i2c_funcs & I2C_FUNC_I2C); 58 } 59 60 /∗ 61 ∗ Configure the nunchuk for no encryption: 62 ∗/ 63 static void 64 nunchuk_init(void) { 65 static char init_msg1[] = {0xF0, 0x55}; 66 static char init_msg2[] = {0xFB, 0x00}; 67 struct i2c_rdwr_ioctl_data msgset; 68 struct i2c_msg iomsgs[1]; 69 int rc; 70 71 iomsgs[0].addr = 0x52; /∗Address of Nunchuk ∗/ 72 iomsgs[0].flags = 0; /∗Write ∗/ 73 iomsgs[0].buf = init_msg1; /∗Nunchuk 2 byte sequence ∗/ 74 iomsgs[0].len = 2; /∗2 bytes ∗/ 75 320 Chapter 24 ■ Nunchuk-Mouse 76 msgset.msgs = iomsgs; 77 msgset.nmsgs = 1; 78 79 rc = ioctl(i2c_fd,I2C_RDWR,&msgset); 80 assert(rc == 1); 81 82 timed_wait(0,200,0); /∗Nunchuk needs time ∗/ 83 84 iomsgs[0].addr = 0x52; /∗Address of Nunchuk ∗/ 85 iomsgs[0].flags = 0; /∗Write ∗/ 86 iomsgs[0].buf = init_msg2; /∗Nunchuk 2 byte sequence ∗/ 87 iomsgs[0].len = 2; /∗2 bytes ∗/ 88 89 msgset.msgs = iomsgs; 90 msgset.nmsgs = 1; 91 92 rc = ioctl(i2c_fd,I2C_RDWR,&msgset); 93 assert(rc == 1); 94 } 95 96 /∗ 97 ∗ Read nunchuk data : 98 ∗/ 99 static int 100 nunchuk_read(nunchuk_t ∗data) { 101 struct i2c_rdwr_ioctl_data msgset; 102 struct i2c_msg iomsgs[1]; 103 char zero[1] = {0x00}; /∗Written byte ∗/ 104 unsigned t; 105 int rc; 106 107 timed_wait(0,15000,0); 108 109 /∗ 110 ∗ Write the nunchuk register address of 0x00: 111 ∗/ 112 iomsgs[0].addr = 0x52; /∗Nunchuk address ∗/ 113 iomsgs[0].flags = 0; /∗Write ∗/ 114 iomsgs[0].buf = zero; /∗Sending buf ∗/ 115 iomsgs[0].len = 1; /∗6 bytes ∗/ 116 117 msgset.msgs = iomsgs; 118 msgset.nmsgs = 1; 119 120 rc = ioctl(i2c_fd,I2C_RDWR,&msgset); 121 if ( rc < 0 ) 122 return −1; /∗I /O error ∗/ 123 124 timed_wait(0,200,0); /∗Zzzz, nunchuk needs time ∗/ 125 321 Chapter 24 ■ Nunchuk-Mouse 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 322 /∗ ∗ Read 6 bytes starting at 0x00: ∗/ iomsgs[0].addr = 0x52; iomsgs[0].flags = I2C_M_RD; iomsgs[0].buf = (char ∗)data−>raw; iomsgs[0].len = 6; msgset.msgs = iomsgs; msgset.nmsgs = 1; /∗Nunchuk address ∗/ /∗Read ∗/ /∗Receive raw bytes here ∗/ /∗6 bytes ∗/ rc = ioctl(i2c_fd,I2C_RDWR,&msgset); if ( rc < 0 ) return −1; /∗Failed ∗/ data−>stick_x data−>stick_y data−>accel_x data−>accel_y data−>accel_z = = = = = data−>raw[0]; data−>raw[1]; data−>raw[2] << 2; data−>raw[3] << 2; data−>raw[4] << 2; t = data−>raw[5]; data−>z_button = t data−>c_button = t t >>=2; data−>accel_x |= t t >>=2; data−>accel_y |= t t >>=2; data−>accel_z |= t return 0; & 1 ? 0 : 1; & 2 ? 0 : 1; & 3; & 3; & 3; } /∗ ∗ Dump the nunchuk data: ∗/ static void dump_data(nunchuk_t ∗data) { int x; printf("Raw nunchuk data : "); for ( x=0; x<6; ++x ) printf("[%02X]",data−>raw[x]); putchar('\n'); printf(".stick_x printf(".stick_y printf(".accel_x printf(".accel_y printf(".accel_z = = = = = %04X %04X %04X %04X %04X (%4u)\n",data−>stick_x,data−>stick_x); (%4u)\n",data−>stick_y,data−>stick_y); (%4u)\n",data−>accel_x,data−>accel_x); (%4u)\n",data−>accel_y,data−>accel_y); (%4u)\n",data−>accel_z,data−>accel_z); Chapter 24 ■ Nunchuk-Mouse 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 printf(".z_button= %d\n",data−>z_button); printf(".c_button= %d\n\n",data−>c_button); } /∗ ∗ Close the I2C driver : ∗/ static void i2c_close(void) { close(i2c_fd); i2c_fd = −1; } /∗ ∗ Open a uinput node : ∗/ static int uinput_open(void) { int fd; struct uinput_user_dev uinp; int rc; fd = open("/dev/uinput",O_WRONLY|O_NONBLOCK); if ( fd < 0 ) { perror("Opening/dev/uinput"); exit(1); } rc = ioctl(fd,UI_SET_EVBIT,EV_KEY); assert(!rc); rc = ioctl(fd,UI_SET_EVBIT,EV_REL); assert(!rc); rc = ioctl(fd,UI_SET_RELBIT,REL_X); assert(!rc); rc = ioctl(fd,UI_SET_RELBIT,REL_Y); assert(!rc); rc = ioctl(fd,UI_SET_KEYBIT,KEY_ESC); assert(!rc); ioctl(fd,UI_SET_KEYBIT,BTN_MOUSE); ioctl(fd,UI_SET_KEYBIT,BTN_TOUCH); ioctl(fd,UI_SET_KEYBIT,BTN_MOUSE); ioctl(fd,UI_SET_KEYBIT,BTN_LEFT); ioctl(fd,UI_SET_KEYBIT,BTN_MIDDLE); ioctl(fd,UI_SET_KEYBIT,BTN_RIGHT); memset(&uinp,0,sizeof uinp); strncpy(uinp.name,"nunchuk",UINPUT_MAX_NAME_SIZE); uinp.id.bustype = BUS_USB; uinp.id.vendor = 0x1; 323 Chapter 24 ■ Nunchuk-Mouse 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 324 uinp.id.product = 0x1; uinp.id.version = 1; rc = write(fd,&uinp,sizeof(uinp)); assert(rc == sizeof(uinp)); rc = ioctl(fd,UI_DEV_CREATE); assert(!rc); return fd; } /∗ ∗ Post keystroke down and keystroke up events: ∗ (unused here but available for your own experiments) ∗/ static void uinput_postkey(int fd,unsigned key) { struct input_event ev; int rc; memset(&ev,0,sizeof(ev)); ev.type = EV_KEY; ev.code = key; ev.value = 1; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); ev.value = 0; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); } /∗ ∗ Post a synchronization point : ∗/ static void uinput_syn(int fd) { struct input_event ev; int rc; memset(&ev,0,sizeof(ev)); ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); } /∗ /∗Key down ∗/ /∗Key up ∗/ Chapter 24 ■ Nunchuk-Mouse 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 ∗ Synthesize a button click : ∗ up_down 1=up, 0=down ∗ buttons 1=Left, 2=Middle, 4=Right ∗/ static void uinput_click(int fd,int up_down,int buttons) { static unsigned codes[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT}; struct input_event ev; int x; memset(&ev,0,sizeof(ev)); /∗ ∗ Button down or up events: ∗/ for ( x=0; x < 3; ++x ) { ev.type = EV_KEY; ev.value = up_down; /∗Button Up or down ∗/ if ( buttons & (1 << x) ) { /∗Button 0, 1 or 2 ∗/ ev.code = codes[x]; write(fd,&ev,sizeof(ev)); } } } /∗ ∗ Synthesize relative mouse movement: ∗/ static void uinput_movement(int fd,int x,int y) { struct input_event ev; int rc; memset(&ev,0,sizeof(ev)); ev.type = EV_REL; ev.code = REL_X; ev.value = x; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); ev.code = REL_Y; ev.value = y; rc = write(fd,&ev,sizeof(ev)); assert(rc == sizeof(ev)); } /∗ ∗ Close uinput device : 325 Chapter 24 ■ Nunchuk-Mouse 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 326 ∗/ static void uinput_close(int fd) { int rc; rc = ioctl(fd,UI_DEV_DESTROY); assert(!rc); close(fd); } /∗ ∗ Signal handler to quit the program: ∗/ static void sigint_handler(int signo) { is_signaled = 1; } /∗ ∗ Curve the adjustment : ∗/ static int curve(int relxy) { int ax = abs(relxy); int sgn = relxy < 0 ? −1 : 1; int mv = 1; if ( ax > mv else if ( mv else if ( mv else if ( mv return mv } 100 ) = 10; ax > 65 ) = 7; ax > 35 ) = 5; ax > 15 ) = 2; ∗ sgn; /∗ ∗ Main program: ∗/ int main(int argc,char ∗∗argv) { int fd, need_sync, init = 3; int rel_x=0, rel_y = 0; nunchuk_t data0, data, last; /∗Signal to exit program ∗/ /∗abs (re lxy) ∗/ /∗sign (relxy) ∗/ /∗Smallest step ∗/ /∗Take large steps ∗/ /∗2nd smallest step ∗/ Chapter 24 ■ Nunchuk-Mouse 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 if ( argc > 1 && !strcmp(argv [1]," −d") ) f_debug = 1; /∗Enable debug messages ∗/ (void)uinput_postkey; i2c_init("/dev/i2c−1"); nunchuk_init(); signal(SIGINT,sigint_handler); fd = uinput_open(); /∗Suppress compiler warning about unused ∗/ /∗Open I2C controller ∗/ /∗Turn off encrypt ion ∗/ /∗Trap on SIGINT ∗/ /∗Open/dev/uinput ∗/ while ( !is_signaled ) { if ( nunchuk_read(&data) < 0 ) continue; if ( f_debug ) dump_data(&data); /∗Dump nunchuk data ∗/ if ( init > 0 && !data0.stick_x && !data0.stick_y ) { data0 = data; /∗Save initial values ∗/ last = data; −−init; continue; } need_sync = 0; if ( abs(data.stick_x − data0.stick_x) > 2 || abs(data.stick_y − data0.stick_y) > 2) { rel_x = curve (data.stick_x − data0.stick_x); rel_y = curve (data.stick_y − data0.stick_y); if ( rel_x || rel_y ) { uinput_movement(fd,rel_x,−rel_y); need_sync = 1; } } if ( last.z_button != data.z_button ) { uinput_click(fd, data.z_button,1); need_sync = 1; } if ( last.c_button != data.c_button ) { uinput_click(fd,data.c_button,4); need_sync = 1; } if ( need_sync ) uinput_syn(fd); last = data; } 327 Chapter 24 ■ Nunchuk-Mouse 424 425 putchar('\n'); 426 uinput_close(fd); 427 i2c_close(); 428 return 0; 429 } 430 431 /∗End nunchuk.c ∗/ 328 Chapter 25 Real-Time Clock The Dallas Semiconductor DS1307 Real-Time Clock is the perfect project for the Raspberry Pi, Model A. Lacking a network port, the Model A cannot determine the current date and time when it boots up. A 3 V battery attached to the DS1307 will keep its internal clock running for up to 10 years, even when the Pi is powered off. If you have a Model B, don’t feel left out. There is no reason that you can’t try this project too; a Model B not connected to a network could use the DS1307. DS1307 Overview The pinout of the DS1307 chip is provided in Figure 25-1. The chip is available in PDIP-8 form or in SO format (150 mils). Hobbyists who like to build their own will prefer the PDIP-8 form. Figure 25-1. DS1307 pinout A crystal is wired between pins 1 and 2 (X1 and X2). The battery powers the chip through pin 3 and flows to ground (pin 4). This keeps the clock alive while the main power is absent. When there is power, it is supplied through pin 8 (VCC). The I2C communication occurs via pins 5 and 6. Pin 7 provides an optional output clock signal or can operate as an open collector output. While you could build this circuit yourself, you can find fully assembled PCB modules using the DS1307 on eBay for as little as $2.36 (with free shipping). These are available as Buy It Now offers, so you don’t have to waste your time trying to win auctions. Just keep in mind that some are not shipped with a 3 V battery. (Check the product. The Tiny RTC I used came with a 3.6 V battery.) It is claimed that there are mailing restrictions on batteries to certain countries. So you may want to shop for suitable batteries while you wait for the mail. ■■Tip Buying a fresh battery ahead of time is recommended, as batteries often arrive exhausted. Figure 25-2 shows a PCB unit that I purchased through eBay. This unit came paired with the AT24C32 EEPROM chip. The auction was labeled “Tiny RTC I2C Modules.” You don’t have to use this specific PCB, of course. The wiring 329 Chapter 25 ■ Real-Time Clock for each chip is fairly basic and can be prototyped on a breadboard if you can’t find one. But if you do choose this PCB, a modification is required before you attach it to the Raspberry Pi. Figure 25-2. An assembled DS1307 PCB purchased through eBay ■■Caution I2C pull-up resistors R2 and R3 must be removed before wiring the PCB to the Raspberry Pi. Also, if you plan to attach the SQW/OUT output of this PCB to a GPIO input, be sure to track down and remove its pull-up resistor as well. Pins X1 and X2 These pins are for connection to a 32.768 kHz crystal. The datasheet states that the “internal oscillator circuitry is designed for operation with a crystal having a specified load capacitance (CL) of 12.5 pF.” Pin SQW/OUT This is an open-drain output from the DS1307 chip that you can choose to ignore if you like. It can be used as follows: 330 • A GPIO-like output. If you plan on wiring this to a Pi GPIO pin, be sure to remove the pull-up resistor (on PCB) first. The +5 V from the pull-up will damage the Pi. • A square wave clock output, at one of the following programmable frequencies: • 1 Hz • 4.096 kHz • 8.192 kHz • 32.768 kHz Chapter 25 ■ Real-Time Clock The datasheet lists a current rating for output when low: Parameter Symbol Logic 0 Output (IOL = 5 mA) VOL Min Typ Max Units 0.4 Volts Without more-specific information, we arrive at the conclusion that a given logic pin is capable of sinking a maximum of 5 mA (SDA). While doing so, the maximum voltage appearing at the pin is 0.4 V. This is well under the 0.8 V maximum, for the VIL voltage level of the Raspberry Pi. The datasheet indicates that the SQW/OUT pin is an open-drain output. As such, you can use a pull-up to +3.3 V or +5 V as your interface requires. It could be used to drive a small LED at 1 Hz, if the current is limited to less than 5 mA (although the datasheet doesn’t indicate the current capability of this open-drain transistor). Alternatively, it can be used to drive other external logic with a pull-up resistor. The datasheet indicates that the SQW/OUT pin can pulled as high as 5.5 V, even when VCC is lower in voltage (such as +3.3 V.) This is safe, provided that these higher voltages never connect to the Pi’s GPIO pins. Power If you’ve looked at the datasheet for the DS1307 before, you might be wondering about the power supply voltage. The datasheet lists it as a +5 V part, and by now you are well aware that the Pi’s GPIO pins operate at +3 V levels. The DC operating conditions are summarized here: Parameter Symbol Min Typ Max Units Supply voltage VCC 4.5 5.0 5.5 Volts Battery voltage VBAT 2.0 3.5 Volts It is tempting to consider that the PCB might operate at +3.3 V, given that the battery in the unit is 3 V. However, that will not work because the DS1307 chip considers a VCC lower than 1.25 × VBAT = 3.75 V to be a power-fail condition (for a typical operation). When it senses a power fail, it relies on battery operation and will cease to communicate by I2C, among other things. Power-fail conditions are summarized here: Parameter Symbol Min Typ Max Units Power-fail voltage VPF 1.26×VBAT 1.25×VBAT 1.284×VBAT Volts The note in the datasheet indicates that the preceding figures were measured when VBAT = 3 V. So these figures will likely deviate when the battery nears expiry. Given the power-fail conditions, we know that the device must be powered from a +5 V power supply. But the only connections made to the Raspberry Pi are the SDA and SCL I2C lines. So let’s take a little closer look at those and see if we can use them. 3-Volt Compatibility The SCL line is always driven by the master, as far as the DS1307 is concerned. This means that SCL is always seen as an input signal by the RTC clock chip. All we have to check here is whether the Raspberry Pi will meet the input-level requirements. Likewise, the AT24C32 EEPROM’s SCL pin is also an input only. 331 Chapter 25 ■ Real-Time Clock The SDA line is driven by both the master (Pi) and the DS1307 chip (slave). The SDA is driven from the Pi as a 3 V signal, so again we need to make certain that the DS1307 will accept those levels. But what about the DS1307 driving the SDA line? The Pi must not see +5 V signals. The DS1307 datasheet clearly states that “the SDA pin is open drain, which requires an external pull-up resistor.” The Raspberry Pi already supplies the pull-up resistor to +3.3 V. This means that the DS1307’s open drain will allow the line to be pulled up to +3.3 V for the high logic level, when the output transistor is in the off state. When the transistor is on, it simply pulls the SDA line down to ground potential. Thus with open-drain operation, we can interoperate with the Raspberry Pi. A check of the AT24C32 EEPROM datasheets leads to the same conclusion. Logic Levels How do the I2C logic levels compare between the Raspberry Pi and the DS1307? Signal Raspberry Pi DS1307 VIL £ 0.8 volts £ 0.8 volts VIH ³ 1.3 volts ³ 2.2 volts The VIL figure matches perfectly for both sides. As long as the Raspberry Pi provides a high level exceeding 2.2 V, the DS1307 chip should read high levels just fine. Given that the Pi’s pull-up resistor is connected to +3.3 V, there is very little reason to doubt problems meeting the DS1307 VIH requirement. To summarize, we can safely power the DS1307 from +5 V, while communicating between it and the Raspberry Pi at +3 V levels. The Pi already supplies pull-up resistors for the SCL and SDA lines, and these are attached to +3.3 V. If, however, you choose to use other GPIO pins to bit-bang I2C (say), you’ll need to provide these pull-up resistors (they must go to only +3.3 V). Tiny RTC Modifications In the preceding section, you saw that even though the DS1307 is a +5 V part, the SDA pin is driven by an open-drain transistor. With the Raspberry Pi tying the SDA line to +3.3 V, the highest voltage seen will be exactly that. The opendrain transistor can only pull it down to ground (this also applies to the AT24C32 EEPROM). Both chips have the SCL pins as inputs (only), which are not pulled high by the chips themselves. If you purchased a PCB like the one I used, however, be suspicious of pull-up resistors! I knew that the parts would support +3.3 V I2C bus operation before the PCB arrived in the mail. However, I was suspicious of added pull-up resistors. So when the PCB arrived, I quickly determined that the PCB did indeed include pull-up resistors connected to the +5 V supply. The extra +5 V pull-up resistors must be tracked down and removed for use with the Raspberry Pi. Checking for Pull-up Resistors There are two methods to test for pull-up resistors: a DMM resistance check and a voltage reading. I recommend that you apply them both. Since this modification is important to get correct, the following sections will walk you through the two different procedures in detail. 332 Chapter 25 ■ Real-Time Clock Performing a DMM Resistance Check Use these steps for the DMM resistance check: 1. Attach one probe of your DMM (reading kΩ) to the +5 V line of the PCB. 2. Attach the other probe to the SDA line and take the resistance reading. 3. Reverse the leads if you suspect diode action. On my PCB, I read 3.3 kΩ. Reversing the DMM leads should read the same (proving only resistance). Performing the same test with the SCL input, I also read 3.3 kΩ. Performing a Voltage Reading Do not skip this particular test. The result of this test will tell you whether your Raspberry Pi will be at risk. 1. Hook up your PCB to the +5 V supply it requires, but do not attach the SDA/SCL lines to the Pi yet. Just leave them loose for measuring with your DMM. 2. With the DMM negative probe grounded, measure the voltage seen at the PCB’s SDA and SCL inputs. If there is no pull-up resistor involved, you should see a low reading of approximately 0.07 V. The reading will be very near ground potential. On my unmodified PCB, these readings were +5 V because of the 3.3 kΩ pull-up resistors. If this also applies to your PCB unit, a modification is required. Performing a Tiny RTC Modification If you have the exact same PCB that I used, you can simply remove resistors R2 and R3 (but I would double-check with the preceding tests). These resistors are shown in Figure 25-3. Carefully apply a soldering iron to sweep them off the PCB. Make sure no solder is left, shorting the remaining contacts. I highly recommend that you repeat the tests to make sure you have corrected the pull-up problem and test for short circuits. Figure 25-3. R2 and R3 of the Tiny RTC I2C PCB 333 Chapter 25 ■ Real-Time Clock Working with Other PCB Products If you have a different PCB product, you may have optional resistors that you can leave uninstalled. Even though they may be optional, someone might have done you the favor of soldering them in. So make sure you check for that (use the earlier tests). The Adafruit RTC module (http://www.adafruit.com/products/264) is reportedly sometimes shipped with the 2.2 kΩ resistors installed. For the Raspberry Pi, they must be removed. Locating the Pull-up Resistors Even if you don’t have a schematic for your PCB product, you will need to locate the pull-up resistors. Since there aren’t many components on the PCB to begin with, they tend to be easy to locate: 1. Observe static electricity precautions. 2. Attach one DMM (kΩ) probe to the +5 V input to the PCB. 3. Look for potential resistors on the component side. 4. Locate all resistors that have one lead wired directly to the +5 V supply (resistance will read 0 Ω). These will be the prime suspects. 5. Now attach your DMM (range kΩ) to the SDA input. With the other DMM probe, check the opposite ends of the resistors, looking for readings of 0 Ω. You should find one resistor end (the other end of the resistor will have been previously identified as connected to the +5 V supply). 6. Likewise, test the SCL line in the same manner as step 5. 7. Double-check: take a resistance reading between the SDA input and the +5 V supply. You should measure a resistance of 2 to 10 kΩ, depending on the PCB manufacturer. You should get the same reading directly across the resistor identified. 8. Repeat step 7 for the SCL line. If you’ve done this correctly, you will have identified the two resistors that need to be removed. If you plan to interface the SQW/OUT pin to a Pi GPIO, you’ll want to remove the pull-up used on that as well. DS1307 Bus Speed The DS1307 datasheet lists the maximum SCL clock speed at 100 kHz: Parameter Symbol Min SCL clock frequency fSCL 0 Typ Max Units 100 kHz The Raspberry Pi uses 100 kHz for its I2C clock frequency (see Chapter 14 for more information). The specification also states that there is no minimum frequency. If you wanted to reserve the provided I2C bus for use with other peripherals (perhaps at a higher frequency), you could bit-bang interactions with the DS1307 by using another pair of GPIO pins. (Pull-up resistors to +3.3 V will be required; the internal pull-up resistors are not adequate.) That is an exercise left for you. Now that we have met power, signaling, and clock-rate requirements, “Let’s light this candle!” 334 Chapter 25 ■ Real-Time Clock RTC and RAM Address Map The DS1307 has 56 bytes of RAM in addition to the real-time clock registers. I/O with this chip includes an implied address register, which ranges in value from 0x00 to 0x3F. The address register will wrap around to zero after reaching the end (don’t confuse the register address with the I2C peripheral address). ■■Note The DS1307 RTC uses I2C address 0x68. The address map of the device is illustrated in Table 25-1. The date and time components are BCD encoded. In the table, 10s represents the tens digit, while 1s represents the ones digit. Table 25-1. DS1307 Register Map Format Address Register 7 6 0x00 Seconds CH 10s 1s 0x01 Minutes 0 10s 1s 0x02 Hours 0 24hr 10s 12hr PM 10s 1s 0 0 5 0x03 Weekday 0 0 0 0x04 Day 0 0 10s 0x05 Month 0 0 0 0x06 Year 10s 0x07 Control OUT 0x08 RAM 00 byte ... 0x3F 4 3 2 1 0 RS1 RS2 1s 1s 1s 10s 1s 1s 0 0 SQWE 0 0 ... RAM 55 byte The components of the register map are further described in Table 25-2. Bit CH allows the host to disable the oscillator and thus stop the clock. This also disables the SQW/OUT waveform output (when SQWE=1). Bit 6 of the Hours register determines whether 12- or 24-hour format is used. When in 12-hour format, bit 5 becomes an AM/PM indicator. 335 Chapter 25 ■ Real-Time Clock Table 25-2. RTC Register Map Components Bit CH Meaning 0 Clock running 1 Clock (osc) halt 24hr 0 24-hour format 12hr 1 12-hour format RS1 RS0 Meaning OUT 0 SQW/OUT = Low 0 0 1 Hz 1 SQW/OUT = High 0 1 4.096 kHz 0 SQW/OUT is OUT 1 0 8.192 kHz 1 SQW/OUT is SQW 1 1 32.768 kHz SQWE The Control register at address 0x07 determines how the SQW/OUT pin behaves. When SQWE=1, a square wave signal is produced at the SQW/OUT pin. The frequency is selected by bits RS1 and RS0. In this mode, the OUT setting is ignored. When SQWE=0, the SQW/OUT pin is set according to the bit placed in OUT (bit 7 of the control register). In this mode, the pin behaves as an open-drain GPIO output pin. Reading Date and Time When the DS1307 device is being read, a snapshot of the current date and time is made when the I2C start bit is seen. This copy operation allows the clock to continue to run while returning a stable date/time value back to the master. If this were not done, time components could change between reading bytes. The application should therefore always read the full date/time set of registers as one I/O operation. The running clock does not affect reading the control register or the RAM locations. I2C Communication The DS1307 registers and RAM can be written randomly, by specifying an initial starting register address, followed by 1 or more bytes to be written. The register address is automatically incremented with each byte written and wraps around to 0. The DS1307 slave device will ACK each byte as it is received, continuing until the master writes a stop bit (P). The first byte sent is always the peripheral’s I2C address, which should not be confused with the selected peripheral’s register address (that immediately follows). The DS1307 I2C address is always 0x68. The general form of the write message is shown here: 336 Chapter 25 ■ Real-Time Clock The DS1307 supports multibyte reads. You can read multiple bytes from the DS1307 simply by starting with an I2C start bit (S), and peripheral address sent as a read request. The slave will then serve up bytes one after another for the master. Receiving terminates when the master sends a NAK. If you want to be certain that the register address is established with a known value, you should always issue a write request first. In the preceding diagram, the write request immediately follows the start bit (S). Only the peripheral’s register address byte is written out prior to the repeating start bit (RS), which follows. After the RS bit, the peripheral address is transmitted once more to re-engage the DS1307, but this time as a read request. From that point on, the master reads bytes sequentially from the DS13017 until a NAK is sent. The final stop bit (P) sent by the master ends the exchange. This peripheral provides us with a good example of a multimessage I/O. This is demonstrated in lines 27 to 45 of the program ds1307get.c, in the upcoming pages. The entire I/O is driven by the structures iomsgs[0] and iomsgs[1]. Structure iomsgs[0] directs the driver to write to peripheral address 0x68 and writes 1 0x00 data byte out to it. This establishes the RTC’s internal register with a value of 0x00. The read request is described in iomsgs[1], which is a read from the same peripheral 0x68, for 8 bytes. (Only 7 bytes are strictly required for the date and time, but we read the additional control byte anyway.) The data structure is laid out in C terms in the file ds1307.h. An optional exercise for you is to add a commandline option to ds1307set to stop the clock and turn it on again using the ch bit (line 8 of ds1307.h). Source module i2c_common.c has the usual I2C open/initialization and close routines in it. Wiring Like any I2C project for the Pi, you’ll wire the SDA and SCL lines as follows: Pre Rev 2.0 GPIO Line Rev 2.0+ GPIO Line P1 0 SDA0 2 SDA1 P1-03 1 SCL0 3 SCL1 P1-05 The DS1307 PCB (or chip) is powered from the +5 V supply. Prior to attaching it to the Raspberry Pi, it is a good idea to power the DS1307 and measure the voltage appearing on its SDA and SCL lines. Both should measure near ground potential. If you see +5 V instead, stop and find out why. Running the Examples Since these programs use the I2C Linux drivers, make sure these kernel modules are either already loaded, or load them manually now: $ sudo modprobe i2c-bcm2708 $ sudo modprobe i2c-dev 337 Chapter 25 ■ Real-Time Clock Program ds1307set.c (executable ds1307set) is used to reset the RTC to a new date/time value of your choice. For example: $ ./ds1307set 20130328215900 2013-03-28 21:59:00 (Thursday) $ This sets the date according to the command-line value, which is in YYYYMMDDHHMMSS format. Once the RTC date has been established, you can use the executable ds1307get to read back the date and time: $ ./ds1307get 2013-03-28 22:00:37 (Thursday) $ In this case, a little time had passed between setting the date and reading it. But we can see that the clock is ticking away. If you don’t like the date/time format used, you can either change the source code or set the environment variable DS1307_FORMAT. For example: $ export DS1307_FORMAT="%a %Y-%m-%d %H:%M:%S" $ ./ds1307get Thu 2013-03-28 22:03:38 $ For a description of the date/time format options available, use this: $ man date The setting of DS1307_FORMAT also affects the display format used by ds1307set. The Ultimate Test The ultimate test is to shut down the Raspberry Pi and turn off its power. Wait a minute or so to make sure that all of the power has been drained out of every available capacitor. Then bring up the Pi again and check the date/time with the program ds1307get. Did it lose any time? The Startup Script To put the RTC to good practical use, you’ll want to apply ds1307get at a suitable point in the Linux startup sequence. You’ll need to wait until the appropriate I2C driver support is available (or can be arranged). You’ll need to develop a short shell script, using the DS1307_FORMAT environment variable in order to produce a format suitable for the console date command. To set the system date (as root), you would use this command: # date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] The startup script for doing all of this has not been provided here. I don’t want to spoil your fun when you can develop this yourself. You learn best by doing. Review Chapter 17 if you need some help. As a further hint, you’ll want to develop a script for the /etc/rc2.d directory, with a name starting with S and two digits. The digits determine where the script runs in the startup sequence (you’ll want to make sure your script runs after the system has come up far enough that I2C drivers are loaded). 338 Chapter 25 ■ Real-Time Clock Once your startup script is developed, your Raspberry Pi can happily reboot after days, even years, of being powered off, and still be able to come up with the correct date and time. ■■Note If you’re running the older Model B, where the I2C bus 0 is used instead of 1, change line 21 in ds1307set.c and line 21 in ds1307get.c. See Chapter 14 for more information. 1 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2 ∗ ds1307.h: Common DS1307 types and macro definitions 3 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ 4 5 typedef struct { 6 /∗ Register Address 0x00 : Seconds ∗/ 7 unsigned char secs_1s : 4; /∗Ones digit : seconds ∗/ 8 unsigned char secs_10s : 3; /∗Tens digit : seconds ∗/ 9 unsigned char ch : 1; /∗CH bit ∗/ 10 /∗ Register Address 0x01 : Minutes ∗/ 11 unsigned char mins_1s : 4; /∗Ones digit : minutes ∗/ 12 unsigned char mins_10s : 3; /∗Tens digit : minutes ∗/ 13 unsigned char mbz_1 : 1; /∗Zero bit ∗/ 14 /∗ Register Address 0x02 : Hours ∗/ 15 unsigned char hour_1s : 4; /∗Ones digit : hours ∗/ 16 unsigned char hour_10s : 2; /∗Tens digit : hours (24 hr mode) ∗/ 17 unsigned char mode_1224 : 1; /∗Mode bit : 12/24 hour format ∗/ 18 /∗ Register Address 0x03 : Weekday ∗/ 19 unsigned char wkday : 3; /∗Day of week (1−7) ∗/ 20 unsigned char mbz_2 : 5; /∗Zero bits ∗/ 21 /∗ Register Address 0x04 : Day of Month ∗/ 22 unsigned char day_1s : 4; /∗Ones digit : day of month (1−31) ∗/ 23 unsigned char day_10s : 2; /∗Tens digit : day of month ∗/ 24 unsigned char mbz_3 : 2; /∗Zero bits ∗/ 25 /∗ Register Address 0x05 : Month ∗/ 26 unsigned char month_1s : 4; /∗Ones digit : month (1−12) ∗/ 27 unsigned char month_10s : 1; /∗Tens digit : month ∗/ 28 unsigned char mbz_4 : 3; /∗Zero ∗/ 29 /∗ Register Address 0x06 : Year ∗/ 30 unsigned char year_1s : 4; /∗Ones digit : year (00−99) ∗/ 31 unsigned char year_10s : 4; /∗Tens digit : year ∗/ 32 /∗ Register Address 0x07 : Control ∗/ 33 unsigned char rs0 : 1; /∗RS0 ∗/ 34 unsigned char rs1 : 1; /∗RS1 ∗/ 35 unsigned char mbz_5 : 2; /∗Zeros ∗/ 36 unsigned char sqwe : 1; /∗SQWE ∗/ 37 unsigned char mbz_6 : 2; 38 unsigned char outbit : 1; /∗OUT ∗/ 39 } ds1307_rtc_regs; 40 41 /∗ End ds1307 . h ∗/ 339 Chapter 25 ■ Real-Time Clock 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ i2c_common.c : Common I2C Access Functions ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ 1 2 3 4 5 6 7 8 9 10 11 /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ds1307set.c : Set real−time DS1307 clock on I2C bus ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ static int i2c_fd = −1; static unsigned long i2c_funcs = 0; /∗ ∗ Open I2C bus and check cap abilities: ∗/ static void i2c_init(const char ∗node) { int rc; /∗Device node : /dev/ i2c−1 ∗/ /∗Support flags ∗/ i2c_fd = open(node,O_RDWR); /∗Open driver /dev/i2s−1 ∗/ if ( i2c_fd < 0 ) { perror("Opening /dev/ i 2 s −1"); puts("Check that the i2c−dev & i2c−bcm2708 kernelmodules " " are loaded . " ) ; abort(); } /∗ ∗ Make sure the driver suppor tsplain I2C I /O: ∗/ rc = ioctl(i2c_fd,I2C_FUNCS,&i2c_funcs); assert(rc >=0); assert(i2c_funcs & I2C_FUNC_I2C); } /∗ ∗ Close the I2C driver : ∗/ static void i2c_close(void) { close(i2c_fd); i2c_fd = −1; } /∗End i2c_common.c ∗/ #include #include #include #include #include #include #include 340 Chapter 25 ■ Real-Time Clock 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include #include #include #include #include "i2c_common.c" #include "ds1307.h" /∗I2C routines ∗/ /∗DS1307 types ∗/ /∗Change to i2c−0 if using early Raspberry Pi ∗/ static const char ∗node = "/dev/i2c−1"; /∗ ∗ Write [ S ] 0xB0 . . . [P] ∗/ static int i2c_wr_rtc(ds1307_rtc_regs ∗rtc) { struct i2c_rdwr_ioctl_data msgset; struct i2c_msg iomsgs[1]; char buf[sizeof ∗rtc+1] ; /∗Work buffer ∗/ buf[0] = 0x00 ; memcpy(buf+1,rtc,sizeof ∗rtc); iomsgs[0].addr = 0x68; iomsgs[0].flags = 0; iomsgs[0].buf = buf; iomsgs[0].len = sizeof ∗rtc + 1; msgset.msgs = &iomsgs[0]; msgset.nmsgs = 1; /∗Register 0x00 ∗/ /∗Copy RTC info ∗/ /∗DS1307 Address ∗/ /∗Write ∗/ /∗Register + data ∗/ /∗Total msg len ∗/ return ioctl(i2c_fd,I2C_RDWR,&msgset); } /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ Set the DS1307 real−time clock on the I2C bus : ∗ ∗ ./ds1307set YYYYMMDDHHMM[ss] ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ int main(int argc,char ∗∗argv) { ds1307_rtc_regs rtc ; /∗8 DS1307 Register Values ∗/ char buf[32]; /∗Extraction buffe r ∗/ struct tm t0, t1; /∗Unix date / time values ∗/ int v, cx, slen; char ∗date_format = getenv("DS1307_FORMAT"); char dtbuf[256]; /∗Formatted date/time ∗/ int rc; /∗Return code ∗/ 341 Chapter 25 ■ Real-Time Clock 61 /∗ 62 ∗ If no environment variable named DS1307_FORMAT, then 63 ∗ set a default date/time format. 64 ∗/ 65 if ( !date_format ) 66 date_format = "%Y−%m−%d %H:%M:%S (%A) " ; 67 68 /∗ 69 ∗ Check command line usage : 70 ∗/ 71 if ( argc != 2 | | (slen = strlen(argv[1])) < 12 || slen > 14 ) { 72 usage: fprintf(stderr, 73 "Usage : %s YYYYMMDDhhmm[ss]\n", 74 argv[0]); 75 exit(1); 76 } 77 78 /∗ 79 ∗ Make sure every character is a digit in argument 1 . 80 ∗/ 81 for ( cx=0; cx 2099 ) 97 goto usage; 98 t1.tm_year = v − 1900; 99 100 strncpy(buf,argv[1]+4,2)[2] = 0; /∗buf[] = "MM" ∗/ 101 if ( sscanf(buf,"%d",&v) != 1 || v <= 0 || v > 12 ) 102 goto usage; 103 t1.tm_mon = v−1; /∗0 − 11 ∗/ 104 105 strncpy(buf,argv[1]+6,2)[2] = 0; /∗buf[] = "DD" ∗/ 106 if ( sscanf(buf,"%d",&v) != 1 || v <= 0 || v > 31 ) 107 goto usage ; 108 t1.tm_mday = v; /∗1 − 31 ∗/ 109 342 Chapter 25 ■ Real-Time Clock 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 strncpy(buf,argv[1]+8,2)[2] = 0; /∗buf[] = "hh" ∗/ if ( sscanf(buf,"%d",&v) != 1 || v < 0 || v > 23 ) goto usage; t1.tm_hour = v; strncpy(buf,argv[1]+10,2)[2] = 0; /∗buf[] = "mm" ∗/ if ( sscanf(buf,"%d",&v) != 1 || v < 0 || v > 59 ) goto usage; t1.tm_min = v; if ( slen > 12 ) { /∗ Optional ss was provided : ∗/ strncpy(buf,argv[1]+12,2)[2] = 0; /∗buf[] = "ss" ∗/ if ( sscanf(buf,"%d",&v) != 1 || v < 0 || v > 59 ) goto usage; t1.tm_sec = v; } /∗ ∗ Check the validity of the date : ∗/ t1.tm_isdst = −1; /∗Determine if daylight savings ∗/ t0 = t1; /∗Save initial values ∗/ if ( mktime(&t1) == 1L ) { /∗t1 is modified ∗/ bad_date : printf("Argument ’%s ’ is not avalid calendar date.\n",argv[1]) ; exit(2); } /∗ ∗ If struct t1 was adjusted , then the original date/time ∗ values were invalid : ∗/ if ( t0.tm_year != t1.tm_year || t0.tm_mon != t1.tm_mon || t0.tm_mday != t1.tm_mday || t0.tm_hour != t1.tm_hour || t0.tm_min != t1.tm_min || t0.tm_sec != t1.tm_sec ) goto bad_date; /∗ ∗ Populate DS1307 registers : ∗/ rtc.secs_10s = t1.tm_sec / 10; rtc.secs_1s = t1.tm_sec % 10; rtc.mins_10s = t1.tm_min / 10; rtc.mins_1s = t1.tm_min % 10; rtc.hour_10s = t1.tm_hour / 10; rtc.hour_1s = t1.tm_hour % 10; rtc.month_10s = (t1.tm_mon + 1) / 10; rtc.month_1s = (t1.tm_mon + 1) % 10; rtc.day_10s = t1.tm_mday / 10; rtc.day_1s = t1.tm_mday % 10; 343 Chapter 25 ■ Real-Time Clock 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 rtc.year_10s = (t1.tm_year + 1900 − 2000) / 10; rtc.year_1s = (t1.tm_year + 1900 − 2000) % 10; rtc.wkday = t1.tm_wday + 1; rtc.mode_1224 = 0; /∗Weekday 1−7 ∗/ /∗Use 24 hour format ∗/ #if 0 /∗Change to a 1 for debugging ∗/ printf("%d%d−%d%d−%d%d %d%d:%d%d:%d%d (wkday %d )\n", rtc.year_10s,rtc.year_1s, rtc.month_10s,rtc.month_1s, rtc.day_10s,rtc.day_1s, rtc.hour_10s,rtc.hour_1s, rtc.mins_10s,rtc.mins_1s, rtc.secs_10s,rtc.secs_1s, rtc.wkday); #end if rc = i2c_wr_rtc(&rtc ); /∗ ∗ Display RTC values submitted : ∗/ strftime(dtbuf,sizeof dtbuf,date_format,&t1); puts(dtbuf); if ( rc < 0 ) perror("Writing to DS1307 RTC"); else if ( rc != 1 ) printf(" Incomplete write : %d msgs of 2written \n",rc); i2c_close(); return rc ==1? 0 : 4; } /∗ End ds1307set.c ∗/ /∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ds1307get.c : Read real−time DS1307 clock on I2C bus ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/ #include #include #include #include #include #include #include #include #include #include #include 344
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.4 Linearized : No Author : Create Date : 2014:10:03 00:24:18+01:00 Modify Date : 2014:08:30 12:25:12+05:30 Subject : Has XFA : No Language : EN Page Layout : TwoColumnRight Page Mode : UseOutlines Page Count : 482EXIF Metadata provided by EXIF.tools