[fusion_builder_container backgroundcolor=”no” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”0px” paddingbottom=”0px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”1″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Introduction[/fusion_title][fusion_text columns=”” column_min_width=”” column_spacing=”” rule_style=”default” rule_size=”” rule_color=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=””]
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.
[/fusion_text][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”3_5″ layout=”3_5″ last=”no” spacing=”yes” background_color=”” background_image=”” background_repeat=”no-repeat” background_position=”left top” border_size=”0px” border_color=”” border_style=”” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” class=”” id=”” min_height=”” hover_type=”none” link=”” border_position=”all”][fusion_text columns=”” column_min_width=”” column_spacing=”” rule_style=”default” rule_size=”” rule_color=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=””]
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.
[/fusion_text][/fusion_builder_column][fusion_builder_column type=”2_5″ layout=”2_5″ last=”yes” spacing=”yes” background_color=”” background_image=”” background_repeat=”no-repeat” background_position=”left top” border_size=”0px” border_color=”” border_style=”” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” class=”” id=”” min_height=”” hover_type=”none” link=”” border_position=”all”][fusion_text][toc][/fusion_text][fusion_sharing tagline=”Share this page:” tagline_color=”” title=”Exploring BeagleBone: Chapter 1″ link=”http://exploringbeaglebone.com/chapter1/” description=”” pinterest_image=”” icons_boxed=”” icons_boxed_radius=”4px” box_colors=”” icon_colors=”” tooltip_placement=”” backgroundcolor=”” class=”” id=”” /][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_separator style_type=”shadow” top_margin=”” bottom_margin=”20″ sep_color=”#9b9b9b” icon=”” width=”” class=”” id=”” /][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container backgroundcolor=”no” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”0px” paddingbottom=”0px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”1″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Source Code Examples[/fusion_title][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container hundred_percent=”yes” overflow=”visible”][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_text columns=”” column_min_width=”” column_spacing=”” rule_style=”default” rule_size=”” rule_color=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=””]
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.
[/fusion_text][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_tabs design=”classic” layout=”horizontal” justified=”yes” backgroundcolor=”” inactivecolor=”” bordercolor=”” class=”” id=””][fusion_tab title=”Bash” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”Perl” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”Python” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”Node.js” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”Java” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”C” icon=”fa-git-square”]
[/fusion_tab][fusion_tab title=”C++” icon=”fa-git-square”]
[/fusion_tab][/fusion_tabs][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container backgroundcolor=”” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”20px” paddingbottom=”20px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”1″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Additional Materials[/fusion_title][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_tagline_box backgroundcolor=”” shadow=”yes” shadowopacity=”0.70″ border=”0″ bordercolor=”” highlightposition=”top” content_alignment=”left” link=”” button=”” linktarget=”_self” modal=”” button_size=”” button_type=”” button_shape=”” buttoncolor=”default” title=”A Further Note on Setting the BBB CPU Frequency” description=”” margin_top=”” margin_bottom=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=”” animation_type=”” animation_direction=”down” animation_speed=”0.1″ animation_offset=””]
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:
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
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:
molloyd@beaglebone:/etc/init.d$ more cpufrequtils ... ENABLE="true" GOVERNOR="performance" MAX_SPEED="1000" MIN_SPEED="0"
See https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt for more information on the governors.
[/fusion_tagline_box][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Accessing Environment Variables in a C/C++ Program[/fusion_title][fusion_text] 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:
root@beaglebone:~/exploringBB/chp05/extras/environment# ./build root@beaglebone:~/exploringBB/chp05/extras/environment# ./environment TERM=xterm SHELL=/bin/bash SSH_CLIENT=192.168.7.1 32084 22 SSH_TTY=/dev/pts/2 USER=root ... HOME=/root LOGNAME=root SSH_CONNECTION=192.168.7.1 32084 192.168.7.2 22 ************************************************** The user shell is: /bin/bash The user path is: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[/fusion_text][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]System Uptime by Reading /proc/uptime[/fusion_title][fusion_text]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!) :
/chp05/proccall$ ./readUptime Starting the read uptime program The system up time is 7287.43 minutes. It was idle for 7116.69 minutes, or 97.6571%
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.
/proc# cat uptime 431875.38 421711.26
You could use a similar framework to parse other /proc file entries, such as:
/proc# cat interrupts … /proc# cat version Linux version 3.8.13-bone41 (root@imx6q-sabrelite-1gb-1) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Tue Mar 4 22:51:47 UTC 2014 /proc# cd net /proc/net# cat arp IP address HW type Flags HW address Mask Device 192.168.1.4 0x1 0x2 14:da:e9:d8:24:74 * eth0 /proc/net# cat sockstat sockets: used 171 TCP: inuse 3 orphan 0 tw 0 alloc 8 mem 1 UDP: inuse 5 mem 3 UDPLITE: inuse 0 RAW: inuse 0 FRAG: inuse 0 memory 0
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:
/proc/net# cd /proc/sys/net/ipv4 /proc/sys/net/ipv4# ls … ip_forward tcp_orphan_retries ip_local_port_range tcp_reordering … /proc/sys/net/ipv4# cat ip_local_port_range 32768 61000 /proc/sys/net/ipv4# cat ip_forward 0 /proc/sys/net/ipv4# echo "1" > ip_forward /proc/sys/net/ipv4# cat ip_forward 1
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.
[/fusion_text][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Using a System Call to use the chmod command[/fusion_title][fusion_text]
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
/* A Linux chmod system call example * Written by Derek Molloy for the book "Exploring BeagleBone: Tools and * Techniques for Building with Embedded Linux" by John Wiley & Sons, 2014 * ISBN 9781118935125. Please see the file README.md in the repository root * directory for copyright and GNU GPLv3 license information. */ #include<gnu/libc-version.h> #include<sys/syscall.h> #include<sys/types.h> #include<sys/stat.h> #include #include using namespace std; int main(){ //gnu_get_libc_version() returns a string that identifies the //glibc version available on the system. cout << "The GNU libc version is " << gnu_get_libc_version() << endl; cout << "Calling chmod using a system call:" << endl; int ret = syscall(SYS_chmod, "test.txt", 0777); cout << "The return value is " << ret << endl; cout << "Reset the permissions using: chmod 644 test.txt" << endl; return 0; }
You can reset the permissions of the test.txt file by typing chmod 644 test.txt. So, for example:
root@beaglebone:~/exploringBB/chp05/syscall# ls -l total 28 -rw-r--r-- 1 root root 70 Dec 20 15:54 build -rwxr-xr-x 1 root root 7272 Dec 20 15:54 callchmod -rw-r--r-- 1 root root 931 Dec 20 15:54 callchmod.cpp -rw-r--r-- 1 root root 7388 Dec 20 15:54 syscall -rw-r--r-- 1 root root 1345 Dec 20 15:54 syscall.cpp -rw-r--r-- 1 root root 0 Dec 20 15:54 test.txt root@beaglebone:~/exploringBB/chp05/syscall# ./callchmod The GNU libc version is 2.13 Calling chmod using a system call: The return value is 0 Reset the permissions using: chmod 644 test.txt root@beaglebone:~/exploringBB/chp05/syscall# ls -l test.txt -rwxrwxrwx 1 root root 0 Dec 20 15:54 test.txt root@beaglebone:~/exploringBB/chp05/syscall# chmod 644 test.txt root@beaglebone:~/exploringBB/chp05/syscall# ls -l test.txt -rw-r--r-- 1 root root 0 Dec 20 15:54 test.txt root@beaglebone:~/exploringBB/chp05/syscall#
[/fusion_text][fusion_separator style_type=”shadow” top_margin=”” bottom_margin=”20″ sep_color=”#9b9b9b” icon=”” width=”” class=”” id=”” /][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container backgroundcolor=”” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”20px” paddingbottom=”20px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”1″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Tracing System Calls[/fusion_title][fusion_text]
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:
root@beaglebone:~/# sudo apt-get install strace Reading package lists... Done … root@beaglebone:~/tmp# more test.c #include < stdio.h > int main(void){ printf("Hello world!"); return 0; } root@beaglebone:~/tmp# gcc test.c -o test root@beaglebone:~/tmp# strace ./test execve("./test", ["./test"], [/* 18 vars */]) = 0 brk(0) = 0x11000 uname({sys="Linux", node="beaglebone", ...}) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fae000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=83872, ...}) = 0 mmap2(NULL, 83872, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6f7e000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\rn\1\0004\0\0\0"..., 512) = 512 lseek(3, 895780, SEEK_SET) = 895780 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1360) = 1360 lseek(3, 895340, SEEK_SET) = 895340 read(3, "A2\0\0\0aeabi\0\1(\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 51) = 51 fstat64(3, {st_mode=S_IFREG|0755, st_size=897140, ...}) = 0 mmap2(NULL, 906528, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6ea0000 mmap2(0xb6f78000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd8) = 0xb6f78000 mmap2(0xb6f7b000, 9504, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6f7b000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fad000 set_tls(0xb6fad800, 0xb6faded8, 0xb6fb1048, 0xb6fad800, 0xb6fad138) = 0 mprotect(0xb6f78000, 8192, PROT_READ) = 0 mprotect(0xb6fb0000, 4096, PROT_READ) = 0 munmap(0xb6f7e000, 83872) = 0 fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fac000 write(1, "Hello world!", 12Hello world!) = 12 exit_group(0) = ? root@beaglebone:~/tmp#
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:
WRITE(2) Linux Programmer's Manual WRITE(2) NAME write - write to a file descriptor SYNOPSIS #include < unistd.h > ssize_t write(int fd, const void *buf, size_t count);
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.
[/fusion_text][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container backgroundcolor=”no” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”0px” paddingbottom=”0px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”1″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]External Resources[/fusion_title][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]External Web Sites[/fusion_title][fusion_text]
- My EE402 Object-oriented Programming Course Notes: ee402.eeng.dcu.ie
[/fusion_text][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container backgroundcolor=”no” backgroundimage=”” backgroundrepeat=”no-repeat” backgroundposition=”left top” backgroundattachment=”scroll” video_webm=”” video_mp4=”” video_ogv=”” video_preview_image=”” overlay_color=”” video_mute=”yes” video_loop=”yes” fade=”no” bordersize=”0px” bordercolor=”” borderstyle=”” paddingtop=”0px” paddingbottom=”0px” paddingleft=”0px” paddingright=”0px” menu_anchor=”” equal_height_columns=”no” hundred_percent=”no” class=”” id=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Errata[/fusion_title][fusion_text columns=”” column_min_width=”” column_spacing=”” rule_style=”default” rule_size=”” rule_color=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=””]
- None as yet in this edition
[/fusion_text][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_title size=”2″ content_align=”left” style_type=”single solid” sep_color=”” class=”” id=””]Recommended Books on the Content in this Chapter[/fusion_title][fusion_text][amazon asin=0321563840&template=Iframe Image] [amazon asin=0321334876&template=Iframe Image] [amazon asin=0131103628&template=Iframe Image] [amazon asin=0470147628&template=Iframe Image] [amazon asin=0954161793&template=Iframe Image] [amazon asin=1593272200&template=Iframe Image][/fusion_text][/fusion_builder_column][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding_top=”” padding_right=”” padding_bottom=”” padding_left=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”no” center_content=”no” min_height=”none” last=”no” hover_type=”none” link=”” border_position=”all”][fusion_sharing tagline=”Share This Story, Choose Your Platform!” tagline_color=”” title=”” link=”” description=”” pinterest_image=”” icons_boxed=”” icons_boxed_radius=”4px” box_colors=”” icon_colors=”” tooltip_placement=”” backgroundcolor=”” class=”” id=”” /][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]
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.
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.
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.
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++.
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:
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!
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.
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.
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.
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.
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.
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.
Oops! Thanks for spotting that — adding to the list of errata.
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.
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.
Thanks. That is a very fair point. I have added a clarification to the list of errata.
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?
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).
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.
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.
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:
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.
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!
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.
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.)
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.
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.
Whereas a call to man chmod(or man 1 chmod) would give:
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!
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”
Thanks Greg. That is now fixed. Derek.
The source code is good, the supplied executable (pointers) remains the same.
Easy enough to compile and overwrite it! Good to go.
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.
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.
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!
Thanks Greg!
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!
Thanks Greg — great to hear. I’m still waiting for my copy! Derek.
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.
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:
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.
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.
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.
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:
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.
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.
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.
Thanks Evert, I will add that to the list of errata. That is a typo for sure. Derek.
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!
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.
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.
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.
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.
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.
Dear Derek
In listing 5-16, the methods (or functions, correct ?) could not be defined INSIDE the class definition???
Thanks
Vidal
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.
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
Hi Phil, yes, I have written an advanced gpio C/C++ version and it is described in detail in Chapter 6. Kind regards, Derek.
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.
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.
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; .
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
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.
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.
I made a mistake, p = p++; is not right, it has to be just p++; or p = p+4.
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.
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.
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.
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?
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.
p. 152, “+AgressiveOpts” -> “+AggressiveOpts”, no?
Thanks. Yes it should be +AggressiveOpts — adding it to the list of errata, Derek.
The script “restoreDefaultLEDs” doesn’t have the execute bit(s) set, is this deliberate?
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.
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 ??
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.
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.