FeatureImage7

Chapter 5: Practical Beagle Board Programming

Chapter 5: Practical Beagle Board Programming

/Chapter 5: Practical Beagle Board Programming
Chapter 5: Practical Beagle Board Programming2019-01-22T23:01:10+01:00

Introduction

This is the chapter web page to support the content in Chapter 5 of the book: Exploring BeagleBone – Tools and Techniques for Building with Embedded Linux. The summary introduction to the chapter is as follows:

This chapter describes several different programming options for the Beagle boards, including scripted and compiled languages. An LED flashing example is provided in all of the languages so that you can investigate each language’s structure and syntax. The advantages and disadvantages of each language are discussed along with example uses. The chapter then focuses on the C/C++ programming languages, describing their principles, and why object-oriented programming (OOP) is appropriate and necessary for the development of scalable embedded systems applications. Finally, the chapter details how you can interface directly to the Linux kernel using the GNU C library. A single chapter can only scratch the surface on this topic, so this one focuses on physical programming tasks, which are required throughout the remainder of this book.

Learning Outcomes

After completing this chapter, you should be able to:

  • Describe the multitude of issues that would impact on your choice of programming languages to use in building applications for the Beagle platform.
  • Write basic scripting language program code on your board that interfaces to the on-board LEDs.
  • Compare and contrast scripting, hybrid, and compiled programming languages, and their application to the embedded Linux applications.
  • Write C code examples that interface to the Beagle board’s on-board LEDs.
  • Wrap C code in C++ classes to provide greater program structure.
  • Write advanced C/C++ code that is capable of interfacing to Linux operating system commands.
  • Write C/C++ modules that can be called directly from Python.

Source Code Examples

As described in the book, here are source code examples for flashing a sysfs-mapped user LED using different languages with markup highlighting. Essentially, each code example is performing the same task. The code appears to become more complex as you move across the tabs (moving from left to right), but the functionality that is available in the code examples is also enhanced (e.g., the OOP examples are applied to all LEDs rather than a single LED). Note: these code examples, and all code on this website, are pulled live from the exploringBB GitHub repository.

Additional Materials

A Further Note on Setting the BBB CPU Frequency

There is a short section on “Setting the BBB CPU Frequency” in the book (First Edition in particular). This note provides some additional information, and was prompted by reader questions, which was integrated into the Second Edition. As described, the ondemand governor sets the CPU frequency depending on the current demand. If the CPU frequency is currently 300MHz and the average CPU usage between governor samplings is above the threshold (called the ‘up_threshold’) then the CPU frequency will be automatically increased. The ‘up_threshold’ can actually be adjusted using sysfs as follows:

If you decide that you would like to change the default operation of the BeagleBone you can do so by editing the file /etc/init.d/cpufrequtils and changing the entry GOVERNOR="ondemand" to a different governor, such as conservative, userspace, powersave or performance. For example, you could set it to high-performance mode using the settings:

See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt for more information on the governors.

Accessing Environment Variables in a C/C++ Program

It can be useful to access environment variables from within your C/C++ programs — for example, you could determine the user’s home directory location, the shell type, or the user’s path settings. To achieve this there are two different ways that are presented in the code example, Listing 5.A1 below and in /chp05/extras/environment/environment.cpp:   Listing 5.A1: A C++ example to access the available environment variables

When this is built and then executed on the BBB it will result in the following output:

System Uptime by Reading /proc/uptime

Here is an example to use /proc to read a system state, which is the system up-time in this example. This can be performed from other languages including sandboxed languages, such as Java. However, as discussed in the book, care must be taken in reading /proc entries as they can change their state as you are reading them (i.e., reads may not be atomic).

Listing 5.A2: An example to determine the system uptime using /proc entries

You can execute this example as follows and it will give the output (yes, really five days!) :

This example works by parsing the /proc/uptime entry. You can view this directly, where the first value is the uptime in seconds. The second is the idle time in seconds.

You could use a similar framework to parse other /proc file entries, such as:

The /proc file system provides useful information about the system, and using it you can even change configuration settings. For example, while logged in as root, you can change the IP forwarding state:

Just remember that you may have difficulty with the non-atomic nature of these file entries — it is much safer to use the system call framework that is described on pages 195-197.

Using a System Call to use the chmod command

Towards the end of the chapter, in the section on “GLIBC and Syscall” there is a reference to a source code example (/chp05/syscall/callchmod.cpp). The example uses the syscall() function to set the permissions of a file called “test.txt” in the repository directory to be rwxrwxrwx. This could also be performed using the chmod() function, which is defined in sys/stat.h. Type man 2 chmod for more information.

Listing 5.A3: A Linux example that uses syscall() to change file access permissions

You can reset the permissions of the test.txt file by typing chmod 644 test.txt. So, for example:

Tracing System Calls

One command that is very useful in helping you to understand what system calls your application is performing is the strace command. You can execute your application using the strace command, which then provides a full trace of the system commands and signals that your application performs. For example, we can install strace on the BBB and then test it on a simple “hello world” C program as follows:

Each command is shown in the form of a function call, where the return value from each function call is displayed on the right-hand side of the equals symbol. For example, towards the bottom of this output you can see the line: write(1, “Hello world!”, 12Hello world!) = 12 which writes to a file descriptor and results in the output on the Linux terminal. You can use man 2 write to get further information about this system call:

The first argument is the file descriptor, which refers to a file. It is 1 in this case, which refers to the standard output, stdout (0 is stdin, and 2 is stderr). The second argument is the buffer pointer to the string data. The third argument is the number of bytes to write to the file that is described by the file descriptor. In this case the value will be read as 12. The return value of 12 above for ssize_t indicates that 12 bytes were successfully written to the standard output (stdout).  A value of zero would indicate that nothing was written, and a value of -1 would indicate that there was an error.

Clearly, the strace command is a valuable tool in understanding what is happening “under the hood” on Linux systems when you develop programs that interact with the operating system.

External Resources

External Web Sites

Errata

  • None as yet in this edition

Recommended Books on the Content in this Chapter

         

71 Comments

  1. TB December 17, 2014 at 9:38 pm - Reply

    Loc: 4761. Just a brief point of clarification. In the paragraph on the BBB governors, the text says this:

    “The default governor is ondemand, which will dynamically switch CPU frequencies if the BBB reaches 95% of the CPU load.”

    Does that mean 95% of *full* CPU load? Seems to make sense that way, but I’m not sure that I’m not missing something, so I just thought I would ask for clarification.

    Thanks.

    • Derek December 18, 2014 at 1:06 pm - Reply

      Yes, the ondemand governor sets the CPU frequency depending on the current demand. If the CPU frequency is currently 300MHz and the average CPU usage between governor samplings is above the threshold (called the ‘up_threshold’) then the CPU frequency will be automatically increased. The ‘up_threshold’ can actually be adjusted using sysfs:


      root@beaglebone:/sys/devices/system/cpu/cpufreq/ondemand# ls -l
      total 0
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 ignore_nice_load
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 io_is_busy
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 powersave_bias
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 sampling_down_factor
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 sampling_rate
      -r--r--r-- 1 root root 4096 Dec 18 12:59 sampling_rate_min
      -rw-r--r-- 1 root root 4096 Dec 18 12:59 up_threshold
      root@beaglebone:/sys/devices/system/cpu/cpufreq/ondemand# cat up_threshold
      95
      root@beaglebone:/sys/devices/system/cpu/cpufreq/ondemand# echo 90 > up_threshold
      root@beaglebone:/sys/devices/system/cpu/cpufreq/ondemand# cat up_threshold
      90

      See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt for more information on the governors. Derek.

      • TB December 18, 2014 at 2:38 pm - Reply

        Ah, I see… If the CPU load reaches the current up_threshold value, then the CPU frequency gets increased–and you can tweak that to be increased at different relative percentages of full load, as you demonstrate here. Very nice.

        Thanks for the clarification.

  2. TB December 18, 2014 at 1:16 am - Reply

    Very interesting benchmarks, Derek. I was especially interested to see the difference between the C and C++ versions of the “n-body” program. I was somewhat surprised to see that the C version (n-body.cpp) was nearly 6 seconds faster, despite being being compiled with g++.

    $ g++ --version
    g++ (Debian 4.6.3-14) 4.6.3
    =====================
    $ time ./n-body 5000000
    -0.169075164
    -0.169083134

    real 0m33.547s
    user 0m33.074s
    sys 0m0.023s
    =====================
    $ time ./n-body2 5000000
    -0.169075164
    -0.169083134

    real 0m39.098s
    user 0m38.543s
    sys 0m0.025s
    =====================

    Since the n-body.cpp file was built with g++ (but is basically just C code), I went ahead and copied it to a new file with a .c extension (foo.c) and then built it with gcc with the same -O3 optimization level. I had to link the math library manually of course, but here is that result:

    $ time ./foo 5000000
    -0.169075164
    -0.169083134

    real 0m33.772s
    user 0m33.287s
    sys 0m0.021s
    =====================

    Interesting. I guess you’d expect gcc and g++ to generate comparable object code given the same basic C source code, but I expected to see more of a difference actually. That being said though, maybe there is a slight discrepancy because I built the gcc version, but ran the g++ executables as found in the binaryARMhf/ directory.

    So I learned something!

  3. TB December 18, 2014 at 1:19 am - Reply

    Oops…that was supposed to be gcc version 4.6.3, not the g++ version. That’s the same of course, but I ran your executable files for those–as I could not get the n-body2.cpp file to build with g++ on my machine, due to a bunch of errors.

    • Derek December 18, 2014 at 1:23 pm - Reply

      Yes, the n-body2.cpp version needs C++11 support, which is only available (with experimental support) in g++ 4.7 and almost full support in g++ 4.8.1. If memory serves me correct, I cross-compiled the n-body2.cpp program using my desktop computer and transferred the ARM-hf binary to my BeagleBone (covered in Chapter 7). I have made the binary available in /chp05/performance/binaryARHhf. Once g++ 4.7 is available for the BeagleBone, the n-body2.cpp program can be built on it using the call:
      g++ -std=c++11 n-body2.cpp -o n-body2

      See https://gcc.gnu.org/projects/cxx0x.html for details of the gcc/g++ support for C++11.

      • TB December 18, 2014 at 2:42 pm - Reply

        Right. I ran both the binaries in that directory, and then compared them to one I generated myself, using gcc. Because the n-body.cpp code is basically just C code, I built it using gcc 4.6.3-14. I was simply curious to see whether or not there would be a difference in execution time between two binaries generated with two compilers (your g++, my gcc) from the same source code.

  4. TB December 19, 2014 at 1:24 am - Reply

    Loc 5188: In the paragraph on header files, you mention that the angular brackets () indicate a standard rather than user-defined header file, and that user-defined header files. While it’s a technicality, this is not entirely correct. Rather the represents include files to be located in the standard system search paths, while the ” ” syntax indicates an include file that is located in the directory containing the file naming the header. There is nothing to say that you cannot simply drop a new version of stdio.h (for instance) into your project if desired, simply by pasting it into the project’s directory and enclosing it in quotation marks. Not that this is something one would normally do–but it is entirely possible.

    So it’s a small point I realize, but the vs ” ” really has more to do with the path searched by the pre-processor to located the named file…rather than who wrote it.

    • Derek December 19, 2014 at 12:20 pm - Reply

      Thanks, good point and I agree fully with your description. I will leave it as is because (as you pointed out) it is correct according to best practice.

  5. TB December 19, 2014 at 3:08 am - Reply

    Loc 5355: “The function sizeof(c) returns the size of the type of the variable in bytes.”

    Although it does return the size of its argument in bytes, sizeof() is a unary operator…not a function. It works at compile time.

    • Derek December 19, 2014 at 12:23 pm - Reply

      Oops! Thanks for spotting that — adding to the list of errata.

  6. TB December 19, 2014 at 5:42 am - Reply

    Loc 5573: In your Listing 5-15 code example, third line, your comment is inaccurate. The “#include ” type of syntax is used to include the C++ equivalent of a C header–not the C header itself. For that you’d simply use “#include “.
    ********************************************************
    Ref: http://www.cplusplus.com/reference/clibrary/
    ********************************************************
    It’s picky, I know. But since you went to the trouble of pointing out the little details (awesome, by the way!, I thought it worth mentioning. Call it a weakness.

    • TB December 19, 2014 at 5:54 am - Reply

      I should add that (from what I’ve read) the C++ equivalent of those C headers often do contain some C++-specific changes, so they are not necessarily the same file(s) simply renamed. As I recall, there are often namespace issues and some template-specific changes in the C++ versions–and indeed a quick review of some of the StackOverflow forum discussions seems to agree.

    • Derek December 19, 2014 at 12:30 pm - Reply

      Thanks. That is a very fair point. I have added a clarification to the list of errata.

  7. TB December 20, 2014 at 4:30 am - Reply

    Loc 5837: Where you discuss the virtual keyword, the text states… “It should always be there (except for the constructor), unless you know that there will definitely be no child class.”
    ******************************************************
    The problem I see with that statement is that you might in fact WANT the exact same behavior in the child class, as it has in the parent class. In other words–your child class is intended to use the inherited method as-is without overriding it, and therefore there would be no need for the “virtual” keyword (as it won’t be overriden). Frankly, I don’t mark a function virtual unless I am going to override it in a derived class. I know there is a bit of a performance hit by using it (as you mentioned in the chapter), but I honestly don’t remember how much of a hit. But it seems to me that in the vast majority of inheritance relationships, you won’t ever be overriding a given method, and instead will want the child class method to simply do what the parent class method has been implemented to do. So in such cases I wonder why you’d use “virtual” at all?

    • Derek December 20, 2014 at 4:17 pm - Reply

      The problem really arises when you make your code available for others to use. For example, I build the GPIO class in Chapter 6 so that anyone can replace the behavior of one of the methods with a method of their own design (they can even still call my method within the new method). If the method was non-virtual then it may not be possible to correctly override it (e.g., if I only made my code available as a library). I believe that it is a good rule-of-thumb that you should always use virtual methods unless you are absolutely sure that there will not be a child class that is written by you or someone else. There is a performance hit, but it is very small compared to the hassle it may cause. In fact, languages like Java have removed the ability to create non-virtual functions as a principle of design (although Java does provide a final keyword, which enforces that even a non-virtual method can be written in the child class).

      • TB December 20, 2014 at 10:14 pm - Reply

        I see. That seems reasonable then. And I have been doing a bit of research on this today, since I posted that last night. Apparently the consensus is that the CPUs of today are easily able to overcome any such hit to performance–and in fact, a compiler might well be smart enough to notice that the function is NOT being overridden…and make it a static call. So in light of this information, then I guess I can see why it wouldn’t necessarily be a game-changer in terms of performance. I will say that a number of people in the forums seemed to point out that if the virtual function(s) was (were) being called LOTS of times, say maybe in a loop, then the performance hit *would* be significant. So in such a case it would seem better not to use virtual. However I wouldn’t think that would apply to this code all that much. I am just getting started in chapter 6 now, so I haven’t really played with the code just yet.

  8. TB December 20, 2014 at 4:59 am - Reply

    Loc 5879: In the section on /proc, in this sentence… “A program that is executed with superuser privileges can read or write files in /proc.”
    ***********************************************
    Actually in my Debian installation in the BBB, the permissions are such that you don’t have to be superuser to read the file at all–it works just fine as user. Also, although the files in /proc are owned by root (and group root as well), none of them seem to have the write flag set. Therefore I am not sure you could write to them either…even as root. Is the behavior different on your machine Derek? I have to admit that I’ve never tried to *write* to one of /proc’s files–but I sure have read them a whole bunch of time. And it works very well as normal user.

    • Derek December 20, 2014 at 4:40 pm - Reply

      Interesting point that I cut short (I think I could have written 1,000 pages for this book but it would have been too expensive!). Yes, most entries have user-level read access, but there are a few that do not. For example: cat /proc/vmallocinfo will only work as the superuser. In relation to write access, have a look at /proc/sys which allows you to configure the parameters of a running system. If you look at the entries in /proc/sys/kernel you will see many configurable options that have root write permissions only.

      For example, the Linux kernel can act as a watchdog to detect soft and hard lockups (See Chapter 10). A hard lockup is a bug that causes the CPU to loop in kernel mode for more than 10 seconds (10 seconds by compile-time default). You can configure your system to reboot after such a hard lockup ( See: https://www.kernel.org/doc/Documentation/lockup-watchdogs.txt). So, to discover and set this value we could use:


      root@beaglebone:/proc/sys/kernel# ls watchdog_thresh
      watchdog_thresh
      root@beaglebone:/proc/sys/kernel# more watchdog_thresh
      10
      root@beaglebone:/proc/sys/kernel# echo 15 > watchdog_thresh
      root@beaglebone:/proc/sys/kernel# more watchdog_thresh
      15

      Note: I’m not recommending that you do this, it’s just a relatively easy example!

      You might also use a write to send data from a userspace program to a loadable kernel module (LKM), which is running in kernel space.

      • TB December 20, 2014 at 10:19 pm - Reply

        Very cool! I do note that there are indeed a few files in that directory, with root access only. Very interesting stuff…

        Linux is unbelievably cool!

  9. TB December 20, 2014 at 5:22 am - Reply

    Loc 5915: In the section on syscalls, it says “You can call functions like chmod…”
    ************************************
    Isn’t chmod a Linux program and not a function? On my machine, I get this:
    $ which chmod
    /bin/chmod
    ************************************
    I tried to go look at the “..chp05/syscall/callchmod.cpp” file you mention in the text, but no such file exists in that directory. Also, find cannot locate the file anywhere in the book’s project files.

    • TB December 20, 2014 at 5:31 am - Reply

      Ah…interesting! Man1 tells me that it’s a program–but man 2 actually shows me that it is also a function! So I stand corrected! A good example of how one should always try checking a different section of the man pages. For anyone who (like me) has trouble remembering which section numbers represent which class of manual pages, here’s a helpful summary on the Wikipedia page for man pages:
      ************************************
      http://en.wikipedia.org/wiki/Man_page
      ************************************
      The other comment about the “callchmod.cpp” file being missing is still valid though–I cannot find it in the book’s project files as downloaded 5-6 days ago. (I also just did a git pull, but there have been no interim additions.)

    • Derek December 20, 2014 at 4:42 pm - Reply

      Well spotted! That example was missing. I have just pushed a new version to the GitHub repository and I will add a note above shortly that includes the code.

    • Derek December 20, 2014 at 4:46 pm - Reply

      That is a very useful point. The man pages have sections when there is a command version and a system call. Just to add on to your response, here is the result of a call to get the man page for the system call.

      root@beaglebone:~# man 2 chmod
      CHMOD(2) Linux Programmer's Manual CHMOD(2)

      NAME
      chmod, fchmod - change permissions of a file

      SYNOPSIS
      #include

      int chmod(const char *path, mode_t mode);
      int fchmod(int fd, mode_t mode);

      Feature Test Macro Requirements for glibc ...

      Whereas a call to man chmod(or man 1 chmod) would give:

      root@beaglebone:~# man chmod
      CHMOD(1) User Commands CHMOD(1)

      NAME
      chmod - change file mode bits

      SYNOPSIS
      chmod [OPTION]... MODE[,MODE]... FILE...
      chmod [OPTION]... OCTAL-MODE FILE...
      chmod [OPTION]... --reference=RFILE FILE...

      DESCRIPTION
      This manual page documents the GNU version of chmod. chmod changes the
      file mode bits of each given file according to mode, which can be
      either a symbolic representation of changes to make, or an octal number
      representing the bit pattern for the new mode bits...

      • TB December 20, 2014 at 10:22 pm - Reply

        Right. I first ran “which chmod” and lo and behold, it returned the path. Then I ran “man chmod” (section 1 by default), it seemed to confirm that it was simply a command. Then I went to the link you posted, which is essentially man (2)…and there was the chmod() function! So then I ran “man 2 chmod” on my machine, and BAM! There it was.

        Oops!

  10. Greg December 21, 2014 at 8:43 pm - Reply

    There is a minor typo in the code for listing 5-11 (downloaded from github).
    The string in the first printf
    “The variable has rvalue %d and the lvalue %p.\n”

    The listing in the book (kindle) is correct:
    “The variable has value %d and the address %p.\n”

    • Derek December 22, 2014 at 1:59 pm - Reply

      Thanks Greg. That is now fixed. Derek.

      • Greg December 22, 2014 at 7:13 pm - Reply

        The source code is good, the supplied executable (pointers) remains the same.
        Easy enough to compile and overwrite it! Good to go.

  11. Greg December 21, 2014 at 10:26 pm - Reply

    Hmmm, can’t get the build script to run correctly in makeLEDmulti. It is not creating the symbolic links. It seems like the bash script should have some sort of loop to cause the if statements to execute. This is from “Writing Your Own Multi-call Binary”.
    The script is running to completion, but there is no output for when the links are created.

    I’m really enjoying working through the code examples. I’ve toyed with C in the past, but never had the motivation to really use it. Seeing stuff happen in the physical world after running a script is really great! I’m excited about C++ too, I think I can get it.

    • Derek December 22, 2014 at 2:13 pm - Reply

      Thanks Greg. I think that I have just fixed it. Can you “git pull” the repository and see if it works? The code in the build script checks to see if the links already exist otherwise there will be errors if you try to create links that already exist. The links themselves should not have been pushed to the Git repository.

      Thanks for the feedback. Yes, C/C++ are really great when you get the hang of them. Hopefully there are enough examples littered throughout the book to get you going with hardware interfacing. Some of the C++ structures are difficult to get used to (e.g., in Chapter 6), but the important thing is that you know how to use the classes that I write — you can always modify them later when you are confident with them.

      • Greg December 22, 2014 at 7:25 pm - Reply

        All good. The only quirk was that I had to su root otherwise the LED would not respond. I had cloned the code into a user account I had created earlier. I’m getting some much needed git repository exercise.

        This website is well designed, easy to use. I like the supplementary videos as well. The e-book plus the extras is a great deal. I’m putting the hardcopy on my shopping list as well, nice work!

        • Derek December 22, 2014 at 10:31 pm - Reply

          Thanks Greg!

          • Greg January 8, 2015 at 2:24 am

            The hardcopy arrived today! I’ve only done a quick scan; the typography and binding appears first class. Diagrams and images are nice and sharp. Looks great!

          • Derek January 8, 2015 at 2:37 am

            Thanks Greg — great to hear. I’m still waiting for my copy! Derek.

  12. Evert Jan December 27, 2014 at 11:27 pm - Reply

    You write in de second paragraph after Listing 5-6 and Listing 5-7 that argv[0] contains the name and full path used to execute the application. That’s confusing because when you put the following in your program as last line printf(argv[0]) you get:
    #include
    // exampleArgv, a program to show the content of argv[0]
    int main(int argc, char *argv[]){
    printf(argv[0]);
    return 0;
    }
    The result of this program is:
    root@beaglebone:/var/lib/cloud9/WorkingSpace# ./exampleArgvc
    ./exampleArgvcroot@beaglebone:/var/lib/cloud9/WorkingSpace#

    I thougt that you ment the name of the program and the path where it is stored. But that is not right because when you add the line printf(“\n”); after printf(argv[0]); you get :
    root@beaglebone:/var/lib/cloud9/WorkingSpace# ./exampleArgvc
    ./exampleArgvc
    root@beaglebone:/var/lib/cloud9/WorkingSpace#

    i know now that there are better ways to print argv[0]. My misunderstanding is because i am not a native english speaker.
    By the way my mail name comes from the dutch translation of Lord Havelock Vetinari from the Discworld from Terry Pratchett.

    • Derek December 28, 2014 at 6:59 pm - Reply

      Hi Evert, args[0] shows the full path and executable name that is used to execute the program. Your code is perfect but here is a C++ version too (just for your reference):

      When it is executed, you will see the following:

      molloyd@beaglebone:~/tmp$ g++ testargs.cpp -o testargs
      molloyd@beaglebone:~/tmp$ ./testargs
      The first argument is ./testargs
      molloyd@beaglebone:~/tmp$ cd /
      molloyd@beaglebone:/$ /home/molloyd/tmp/testargs
      The first argument is /home/molloyd/tmp/testargs

      So, when you execute it from the same directory no path will appear, but if you execute if from a different directory (like / in this case) then the full path that is used to execute the program will appear. Hope that helps, Derek.

      • Evert Jan December 29, 2014 at 5:25 pm - Reply

        Yes i did understand that, the confusion came up because i didn’t translate it good and in the first version of the program i did forget the \n token, so the cursor stayed on the same line from the output and my linux prompt was printed after it. So i learned two things, read and translate good and inspect your code well before you compile and execute. I am happy with this book, it gives me a reason to play with the beagle bone by learning c++ with it.In the proces i’m translating the book in dutch to, facsinating.

  13. Greg December 28, 2014 at 5:05 pm - Reply

    Here’s another small point of confusion. This is just prior to listing 5-17: “You can open this file /usr/include/arm-linux-gnueabihf/sys/syscall.h”. This file actually includes asm/unistad.h. So the include includes an include!

    So it looks like that full path to the sytem call numbers is:

    /usr/include/arm-linux-gnueabihf/asm/unistad.h

    I need to do some learning to understand how gcc and g++ search to find include files.
    Apparently /usr/include/arm-linux-gnueabihf is a default search path.

    • Derek December 28, 2014 at 8:44 pm - Reply

      Thanks Greg. You are perfectly correct — the actual numbers are in /asm/unistd.h on the BeagleBone, but I think it best that people search for them via /sys/syscall.h as this is consistent across all flavours/architectures. For example, it is /usr/include/sys/syscall.h on my desktop installation.

      On the default path for g++. Yes, if you type:

      molloyd@beaglebone:~$ g++ -v
      Using built-in specs.
      COLLECT_GCC=g++
      COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapper
      Target: arm-linux-gnueabihf
      Configured with: ../src/configure -v --with-pkgversion='Debian 4.6.3-14' ... --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
      Thread model: posix
      gcc version 4.6.3 (Debian 4.6.3-14)

      You will see that the target value is set at arm-linux-gnueabihf. If no include path is specified then gcc/g++ will automatically search the “user/include/target” path (or “user/target/include”, and /usr/include, and /usr/local/include). Hope that helps, Derek.

      • Greg December 30, 2014 at 3:14 pm - Reply

        OK, I understand, I was suspecting architecture dependencies.

        Also thanks for the clarification on the paths and using g++ -v option.

        I’ve been pushing forward a bit, and while nothing about embedded Linux seems difficult, there are buckets of details!
        I’m enjoying the challenge a lot.

  14. Evert Jan December 30, 2014 at 10:27 am - Reply

    In the Paragraph just before listing 5-10 you wrote: “The BBB has a 32-bit microcontroller, so….”. I understand what you mean, but is “The BBB has a 32-bit microprocessor, so…” not more correct? I know that i “zout op slakken leg” as we say in dutch, but that is just the difference between Arduino and the BBB.

    • Derek December 30, 2014 at 3:58 pm - Reply

      Thanks Evert, I will add that to the list of errata. That is a typo for sure. Derek.

  15. Kerry December 31, 2014 at 11:36 pm - Reply

    There are some tinyURLs that send me off to Comedy Central and a “Page Not Found” error, such as tiny.cc/ebb501 and tiny.cc/ebb502.

    One thing I struggle with is the concept of hardware access being represented as a file. I guess I tend to think of a file as a package of data with a name and that resides on a disk or in memory. It isn’t obvious to me how writing to a file causes something to happen in the hardware. I’m used to poking registers in an FPGA and stuff like that, and I assume something like that is going on under the hood. What is the mechanism that connects a “file” to the hardware? (Did I miss something in an earlier chapter? I did get bogged down in the Linux file system description – I’m not sure I was completely conscious at the the time I read it…)

    Great book, by the way! I’m in chapter 5 and looking forward to more good stuff!

    • Derek January 1, 2015 at 4:36 pm - Reply

      Hi Kerry, Thanks for that — they seem to be working now. Can you please check? I wonder if there is a stray ‘.’ included in some of the URLs.

      Yes, sysfs is unusual and takes time to get used to if you are familiar with other embedded systems. Chapter 6 describes it in more detail — in particular how you can adjust its behavior using device tree overlays. Linux maps the kernel space to the user space using several RAM-based file systems, such as sysfs, procfs, configfs and debugfs. Because they are RAM based, the performance is not too bad, and they do provide a reasonably straightforward interface that does provide some consistency from system to system (unlike raw memory addressing). The implementation is buried deep in Linux and the best document to study is from kernel.org: https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt

      Thank for the feedback! Derek.

      • Kerry January 1, 2015 at 6:38 pm - Reply

        I should have mentioned that I’m reading the Kindle version of the book (purchased from Amazon) on my iMac with the Kindle app, so I’m not sure what it means to check the links again without somehow downloading a revised version from Amazon. FWIW, it does the same thing using the Kindle Cloud Reader in Chrome.

        • Derek January 1, 2015 at 8:18 pm - Reply

          Hi Kerry, It is possible the the Kindle reader has introduced a period at the end of the URL. If this is the case, are you able to manually remove the period from the end of the URL (i.e., change tiny.cc/ebb501. to tiny.cc/ebb501 within the reader)? I tried to create links with periods to fix this problem but I am not permitted by tiny.cc. I have sent a request to Wiley to look into this as the manually typed links appear to be working correctly. Derek.

          • Kerry January 2, 2015 at 12:15 am

            Weirdness happens when I try to copy and paste a link – what follows below is the pasted link, complete with an extra space in the URL itself:

            tiny.cc/ ebb501

            Molloy, Derek (2014-12-05). Exploring BeagleBone: Tools and Techniques for Building with Embedded Linux (Kindle Location 5880). Wiley. Kindle Edition.

            Manually typing the links works, so I need to stop being lazy and just type the links, which I suppose is sort of the point of having tiny URLs in the first place.

          • Derek January 2, 2015 at 12:32 am

            Thanks Kerry. Yes, I had the printed version in mind when I decided to use the URL format as it is very difficult to manually key some URLs (e.g., YouTube). I should also be able to fix them if the source materials move. Derek.

  16. Vidal January 11, 2015 at 9:54 pm - Reply

    Dear Derek

    In listing 5-16, the methods (or functions, correct ?) could not be defined INSIDE the class definition???

    Thanks
    Vidal

    • Derek January 11, 2015 at 10:24 pm - Reply

      Hi Vidal, unlike Java where it is necessary, it is bad practice to do this in C++ as it does not allow for separate compilation. Separate compilation allows large projects to be compiled efficiently, part by part, with the C++ header files describing the code that is contained in libraries (I do this in the book for the classes in Chapter 6, 8, 9 etc in order to create a library). The libraries need not be compiled each time you build your project. This is important — for example, imagine that you just built the Linux kernel and then realised that you made a typo — without separate compilation you would have to re-build every single line of code. With it, you only have to compile (and then link) the classes that are affected by your change. Derek.

  17. Phil February 22, 2015 at 5:59 am - Reply

    re: makeLED.c
    Is it possible to access GPIO pins using the above .c example? Only published way to access the GPIO seems to be the python library.
    Thanks,
    Phil

    • Derek February 22, 2015 at 11:08 am - Reply

      Hi Phil, yes, I have written an advanced gpio C/C++ version and it is described in detail in Chapter 6. Kind regards, Derek.

  18. Trevor February 27, 2015 at 7:15 pm - Reply

    When I try and run the python version of the LED code, I keep getting command not found. Not sure why this is. I typed everything in nano by hand and everything looks right but I don’t even think the BB is even trying to run through the program. Not sure what I am doing wrong.

    Also I can not get the code for the book from github. I type everything in and all I get back is authentication failed. I have a github account.

    • Derek February 28, 2015 at 9:52 pm - Reply

      Hi Trevor, it sounds like you have several problems there. If you cannot clone the GitHub repository then it is likely a network configuration problem and I am guessing that you are using Internet-over-USB. If you are, you could try a fixed-line Internet connection or go through the steps on sharing your Internet connection on page 28 and the note on page 43.

      On the script not being executable. Yes, chmod needs to be applied to some scripts before they are executable, particularly if you type them in yourself. A non-executable version of the script will not have the x flag set. Set the x flag and execute the script as follows:

      Kind regards, Derek.

  19. EvertJan Henken March 7, 2015 at 12:46 pm - Reply

    Derek,

    I try to understand your explanation after listing 5-12 pointer array.c. The program works, i tried it. But i can’t understand why. I googled for pre- and post increment, and found a lot:
    y = ++x; // y==4, x==4
    y = x++; // y==3, x==4,
    I think i understand now pre- and post increment, but now i try to understand what happens in the line of code (*(p++))++; and i don’t understand what is happening after the code is compiled, i can’t what the steps are with i and p. The program works, but i can’t reason why ++(*(++p); gives the wrong result. I understand that it has to do with pre- and post-incrementing and the precedence of operations. I think i have to stick with (*p)++; p++; or ++(*p); ++p; .

    • EvertJan Henken March 8, 2015 at 1:26 pm - Reply

      Derek,
      I think i know now what happens in the line (*(p++))++; , p++ increases the pointer, but returns the value of the pointer before the increase and that wil be used to increase the value where the pointer points to. Therefor also the first element of the array wil be increased. Is this right?

      with regards
      Evert Jan Henken

    • Derek March 8, 2015 at 1:53 pm - Reply

      Hi Evert, yes, you have captured there one of the most important parts of the discussion — keep it simple, and use parentheses when working with pointers!

      You have captured the difference between pre- and post-increment perfectly. When you write:

      That is equivalent to writing:

      However, when you write:

      That is equivalent to writing:

      So, you achieve a different outcome, which you have stated.

      The expression (*(p++))++ is complex, mainly because of the rules of precedence. We can write this as follows:

      is equivalent to:

      Importantly the inner ++ is what is written on the next line. This the post-increment operation. If you follow the logic for (*(++p))++ we can write it as:

      is equivalent to:

      This will increment the pointer before increasing the value-at the pointer. This is dangerous in this case as it will increase the value of the memory address after the end of the array. I hope that helps! Derek.

      • EvertJan Henken March 9, 2015 at 8:37 am - Reply

        Hi Derek,
        Thanks for your response, but i think the 6 and 8 line of aren’t right because p = p+1 is not the same as p = p++ because in the former you add 1 to the pointer and in the latter you add 4 to the pointer. With p++ you wil increase the pointer, and it is an int dereference pointer, so he has to increase to the next integer value which are 4 bytes.

        • EvertJan Henken March 9, 2015 at 8:43 am - Reply

          I made a mistake, p = p++; is not right, it has to be just p++; or p = p+4.

        • Derek March 9, 2015 at 8:12 pm - Reply

          Hi Evert, No, they are actually equivalent. When you create a pointer, the dereference type of the pointer defines what a +1 is in terms of bytes. For example, on the BBB if you define int *p; the compiler uses the dereference type size (e.g., 4 bytes in this case) to manipulate the pointer. If you declare char *p; then the pointer will only move by one byte on a ++ or +1 manipulation. You can see this in a short code example:

          Which gives the output when executed:

          You can see that the pointer moved by 4 bytes after each pointer operation. Hope that helps! Derek.

  20. EvertJan Henken March 7, 2015 at 3:07 pm - Reply

    Derek,
    I decided to try some more so i rewritten your program to this:
    int main(int argc, char **argv)
    {
    int x[5] = { 100, 200, 300, 400, 500 };
    int *p = &x[0], i=0;
    printf(“The adress of the pointer before the loop is: %p\n”,p);
    printf(“%d times executed the expression (*(p++)++ .\n”,i);
    for (i=0; i<5; i++){
    (*(p++))++;
    printf("%de iteration of the loop.\n", i+1);
    printf("The adress of the pointer is now: %p\n",p);
    printf("The value of x[%d] is: %d\n", i,x[i]);
    printf("The pointer points to the value: %d\n", *p);
    }
    return 0;
    }
    The result is:
    pi@rpibp-1 ~/projects/ch05 $ ./testpointer
    The adress of the pointer before the loop is: 0xbec4e494
    0 times executed the expression (*(p++)++ .
    1e iteration of the loop.
    The adress of the pointer is now: 0xbec4e498
    The value of x[0] is: 101
    The pointer points to the value: 200
    2e iteration of the loop.
    The adress of the pointer is now: 0xbec4e49c
    The value of x[1] is: 201
    The pointer points to the value: 300
    3e iteration of the loop.
    The adress of the pointer is now: 0xbec4e4a0
    The value of x[2] is: 301
    The pointer points to the value: 400
    4e iteration of the loop.
    The adress of the pointer is now: 0xbec4e4a4
    The value of x[3] is: 401
    The pointer points to the value: 500
    5e iteration of the loop.
    The adress of the pointer is now: 0xbec4e4a8
    The value of x[4] is: 501
    The pointer points to the value: 4.

    I understand why the last value to which the pointer points is 4, this because he points now outside the array. I still don't understand why the right elements of the array get incremented.
    When i use ++(*(++p); instead, The first element of the array wil not increment and stays 100. I have a slight idea why, but i can't explain it in detail.

    • EvertJan Henken March 8, 2015 at 7:39 am - Reply

      Derek,
      I now know why with ++(*(++p); the first element of the array stays unchanged, it is because in this line you first increment the adres of the pointer and then the value where he points to, so the second element of the array wil be incremented and not the first.

  21. Brett March 11, 2015 at 10:36 pm - Reply

    Derek,
    Love your book. It’s just fantastic and I may use it for a text book next Spring when I again teach my department’s instrumentation course — I’ll focus on embedded devices. What you’ve written is great and I was happy to see the material in Chapter 13. But you stop a bit short of where I was hoping you’d go, namely directly using more of the power of the cpu (at least as much as the BBB allows). For example, by directly addressing registers in the cpu, one could obtain exquisite — and very fast — control over the pwm functions of the cpu, particularly if one did this via the PRU-ICSS. That is, do not use the bios calls, but go into assembly language so the PRU-ICSS can directly access the appropriate PWM registers. For many of my applications this would be extremely useful. I’ve got much of this worked out but, as you know, the AM335x is a really sophisticated chip (roughly 200 pages on PWM alone!) and getting the register settings correct is driving me a bit batty. So my question is, do you plan to write a follow-up book in which you pick up where Chapter 13 leaves off?

    • Derek March 12, 2015 at 11:17 pm - Reply

      Thanks Brett — I appreciate your support! Yes, I would have loved to spend more time on the PRU-ICSS but I had agreed 430 pages and was well over that! I’ll continue to add more content to the chapter web page as I develop it (I’ll have to look at real-time DAC soon), but I’ll have to be honest, I hadn’t considered using the PRU-ICSS quite the way that you have suggested. I can see certainly see the use for controlling PWM, but with the complexity of the AM335x and the (quite) limited set of instructions available on the PRU-ICSS it is going to be hard work! I’ll have to have a look into it though. Another book is off the cards for the moment (on any topic) until I catch up with myself. I wrote this book late at night after I settled my kids in bed and it was hard keeping up with everything in work the next day. I’ll keep adding content to the chapter web pages as I develop it — maybe it will all end up in Revision 2! Kind regards, Derek.

  22. Robert P. J. Day April 15, 2015 at 11:36 am - Reply

    p. 152, “+AgressiveOpts” -> “+AggressiveOpts”, no?

    • Derek April 15, 2015 at 6:41 pm - Reply

      Thanks. Yes it should be +AggressiveOpts — adding it to the list of errata, Derek.

  23. Robert P. J. Day April 15, 2015 at 1:02 pm - Reply

    The script “restoreDefaultLEDs” doesn’t have the execute bit(s) set, is this deliberate?

    • Derek April 15, 2015 at 6:43 pm - Reply

      Hi Robert, Unfortunately I keep losing the executable bits and I don’t know why — I think it is possibly the GitHub Windows client, but I cannot be certain. I will fix that. Thanks, Derek.

  24. vidal April 18, 2015 at 4:03 pm - Reply

    Hi Derek
    I am running a test code in c++ to blink a led at GPIO1_12 , using fet and a resistor from gate to ground, then when disconected i am sure the led is off.
    At the end the pin is adjusted to 0, and obviously the led is turned off.
    But, just after unexport the pin, it goes high.
    Am I missing some adjust ??

  25. Catfang June 2, 2015 at 10:40 pm - Reply

    Great book, really enjoying it so far! You included Java in your performance testing but left out C#/Mono. Any reason why? It would be great to see how C#/Mono performs next to Java on the BBB.

    • Derek June 3, 2015 at 1:33 am - Reply

      Thanks! The C#/Mono MCS 3.2.8 (with mcs -optimize+ -platform:arm) is a factor of 2.47, which is approximately the same as Node.js. However, it may be possible to further optimize the build. Also, the performance of Node.js on the BeagleBone is exceptional — I’m not sure how it was optimized so well. No significant reason for leaving it out (other than page space) — I would also like to have covered Haskell, Lua and Ruby! Kind regards, Derek.

Leave A Comment Cancel reply

Exploring BeagleBone

This is the companion site for the book “Exploring BeagleBone: Tools and Techniques for Building with Embedded Linux” by Derek Molloy. The site structures and contains all of the digital media that is described in the book. Each chapter in the book links to an individual web page, which can be accessed using the menu on the top right-hand side of this page when you close this menu. For details of the book itself, click here.

Recent Works

Latest from Derek Molloy YouTube Channel

Oops, something went wrong.