Embedded Control Systems for Intelligent Mechanics - Assignments
Table of Contents
Practical Information

BeagleBoard (source: Wikipedia)
The assignments can be carried out on the Ubuntu Gnu/Linux PCs in the Robot Lab, C300, first floor. You should be able to log in with your s-number. Working through each assignment should take no longer than 3 hours. Please report any problems such as non-working commands or problems with the robots on the course mailing list, but be sure to adhere to the Netiquette. Try to formulate smart questions and give efficient answers, keeping in mind that communication is a skill which is also being evaluated.
The embedded system used throughout the assingnments is the BeagleBoard-xM.
While the first two assignments can be carried out on any modern Linux computer, the later ones depend on specific tools which are setup in the Robot Lab.
Assignment 1: The Command Line
The purpose of this first assignment is to familiarize yourself with an essential concept of embedded systems: the command line. The command line provides a low level but yet powerful interface to the system. Especially in embedded system development it is often the only way to interact with the system. The FLOSS command line book gives a excellent introduction. It is suggested to read at least to Chapter Commands. Of course you should use further information where necessary.
After reading the basic introduction, you should be able to answer (or quickly find out the answer to) the following questions:
- which methods exist of getting help on the command line?
- what do
pwd,ls,cddo? - what is the difference between an absolute and relative path?
- which information does
ls -ldisplay? - what does the
filecommand do? - how can you find a file located somewhere in a directory?
- what do
ps,top,killdo? - what does mounting mean?
- what are environment variables and how can they be set and shown?
- What is the
$PATHenvironment variable used for?
Final note: throughout the assignments commands to be executed will be
prefixed with a $ sign as for example:
$ whoami
Assignment 2: Editors
The goal of this assignment to become familiar with an advanced editor which is suitable for programming. The FLOSS command line book has a general introduction to editors and especially to the vi editor, which we suggest you to get familiar with. The reason for this is that vi is available even on very small and resource limited embedded systems including the beagle board.
After this introduction you should know how:
- the two modes of vi and how to switch between them
- how to open new or existing files
- how to move around and how to insert text
- how exit with or without saving the changes made
Next step is to write a small shell script. Shell scripts are very useful to automate tasks instead of repeatively entering the same commands. An introduction can be found in the FLOSS book. A very thorough guide to shell scripting (using the Bash shell) can be found in the Advanced Bash Scripting Guide. The following is an example of a script which checks if the internet connection is up and prints the result:
1: #!/bin/bash 2: 3: ping -w3 -c 1 -q google.be &> /dev/null 4: 5: if [ $? -eq 0 ]; then 6: echo "internet up" 7: else 8: echo "internet down" 9: fi
The first line indicates that this script is to be executed with the
bash shell, which is the most common shell today. The real program
starts in line 3. This line executes the ping(1)
command, which checks wether a computer on a network is
responding. Lookup the arguments on the ping(1) manpage. The &>
line redirects the output of ping to /dev/null, which is a garbage
bin for data. This is done so that when the script is run only the
desired message and not the output of the ping command is shown.
In line 5 it is checked if the ping was successful or
not. For this the special variable $? is used, which always
contains the return value of the last command executed. $? is
compared to the value 0 which commonly indicates success. If this is
true a positive status message is output in line 6. In
case the check was not true, the else branch is entered and a
negative message printed. The last line (which is if spelled
backwards) ends the if block.
Store the script in a file (up.sh). Next we need to make the
script file executable. This can be done by setting the x
(executable) bit on the file:
$ chmod +x up.sh
and run it:
$ ./up.sh internet up
Assignment 3: Compiling and Makefiles
The purpose of this assignment is to introduce the concept of compilation and the associated make tool. After this assignment you should know:
- the structure of a simple C program
- How to compile C program
- How a basic Makefile looks like
- How to debug a C program using gdb
- What the strip command does
Compilation
We start using the following simple C program:
1: #include <stdlib.h> 2: #include <stdio.h> 3: 4: int main(int argc, char **argv) 5: { 6: int a = 4711; 7: printf("hello world: %d\n", a); 8: return(EXIT_SUCCESS); 9: }
We start by explaining the program. The first two lines 1
and 2 make available some standard program functions which
have been defined in different files. Line 4 defines the
main function, which is called when the program is started. The code
between the parentheses are two arguments which contain the values
which were given when the program was started on the command line. The
statement in line 6 create a variable a and
assigns the value 4711 to it. In line 7 the printf
function os called (which is defined in the stdio.h library we
included in line 2). Finally in line 8 the
program returns from the main function and thereby end the
execution. It reports that everything went OK by returning
EXIT_SUCCESS (which is defined in stdlib.h)
Store the program in a file (hello_world.c). It can then be compiled
with the following command:
$ gcc hello_world.c -o hello_world
Running it produces the intended output.
$ ./hello_world hello world: 4711
Questions:
- Note the
./before the file. What happens if it is omitted? Why? - What do the
file(1)and the theldd(1)command report when run on the compiled program? - What is the size of the binary?
Makefiles
Next we extend the program with a loop:
#include <stdlib.h> #include <stdio.h> int main(int argc, char **argv) { int i; for(i=0; i<10; i++) { printf("hello world: %d\n", i); } return(EXIT_SUCCESS); }
Now instead of running the gcc command again we write a Makefile. Take a very quick look at the make(1) manpage to get an idea what this tool does.
The Makefile for our hello_world.c program will contain the
following in a file called Makefile:
1: hello_world: hello_world.c 2: gcc hello_world.c -o hello_world
Important: line 2 begins with a tab!
The meaning of this file is the following: in order to build the
target hello_world (the target is the name before the ':') the
command in the second line needs to be executed. The file
hello_world.c after the : in the first line is a prerequisite,
which means that the target hello_world depends on this
file. Effectively this allows the make program to examine when the
prerequisite last changed and to invoke the compilation only when it
is necessary.
Now the program can be simply compiled by executing:
$ make gcc hello_world.c -o hello_world
which compiles the program. Running make again
$ make
make: `hello_world' is up to date.
is not recompiled because make detects that the hello_world program
is up to date because none of its dependencies (the hello_world.c
file in our case) have changed.
Assignment 4: Debugging techniques
There exist several ways to debug a C/C++ program. A simple and
therefore often used way is to add printf statements print the
values of variables and to identify where things go wrong. A more
powerful approach is to use a debugger such as gdb(1). Quickly take a
look at the gdb(1) manpage DESCRIPTION section to get an idea.
In order to use gdb, a program needs to be compiled with debugging
information. This is done by providing the -g switch to the gcc
compiler.
hello_world: hello_world.c
gcc -g hello_world.c -o hello_world
The following shows a sample debugging session with gdb:
1: gdb hello_world 2: GNU gdb (GDB) 7.2-debian 3: Copyright (C) 2010 Free Software Foundation, Inc. 4: License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 5: This is free software: you are free to change and redistribute it. 6: There is NO WARRANTY, to the extent permitted by law. Type "show copying" 7: and "show warranty" for details. 8: This GDB was configured as "x86_64-linux-gnu". 9: For bug reporting instructions, please see: 10: <http://www.gnu.org/software/gdb/bugs/>... 11: Reading symbols from /home/mk/work/Schulungen/ELI/hello_world/hello_world...done. 12: (gdb) break main 13: Breakpoint 1 at 0x4004f3: file hello_world.c, line 8. 14: (gdb) run 15: Starting program: /home/mk/work/Schulungen/ELI/hello_world/hello_world 16: Breakpoint 1, main (argc=1, argv=0x7fffffffd0c8) at hello_world.c:8 17: 8 for(i=0; i<10; i++) { 18: (gdb) n 19: 9 printf("hello world: %d\n", i); 20: (gdb) n 21: hello world: 0 22: 8 for(i=0; i<10; i++) { 23: (gdb) n 24: 9 printf("hello world: %d\n", i); 25: (gdb) n 26: hello world: 1 27: 8 for(i=0; i<10; i++) { 28: (gdb) print i 29: $2 = 1 30: (gdb) continue 31: Continuing. 32: hello world: 5 33: hello world: 6 34: hello world: 7 35: hello world: 8 36: hello world: 9 37: 38: Program exited normally. 39: (gdb) quit
Some of the more important commands (Note: all commands can be
abreviated, e.g. b instead of break )
help <command>get some helprunruns (i.e. starts) a program- breakpoints
break xsets a breakpoint on x, where x can be for instance a function or a line number as followsb hello_world.c:10;info breaklist all breakpointsdel break 1deletes breakpoint number 1
listshow the source codewhereshow where the program is currently executing- TUI mode: text user face mode. Sometimes it is nice to see the
source code while debugging. TUI (=text user interface) does
this. It can started while running gdb by pressing the command
sequence
Ctrl-x a(this means pressing theCtrland thexkey together, then releasing both and pressing theakey. It can be exited again by repeating the same sequence. infoallows to inspect the system. E.g.info regishows the current content of the cpu registers.print- Advancing the program
nextruns the next line, but does not enter functionsstepexecutes the next line and does enter functionsfinishexecutes until the end of the current functioncontinuecontinue program execution until reaching a breakpoint or the end of program.
Further information can be found in the gdb user manual.
Assignment 5: Version control
Making use of version control tools is essential for any professional software development by facilitating tracking of change. Although many different version control systems exist, all can be roughly divided into two categories: centralized or distributed. The centralized ones such as subversion or cvs store all changes in a central repository, while with the distributed version control systems like mercurial or git there is no such central storage. Instead each developer has an individual copy of the whole repository (disk space is cheap nowadays!). The following gives a short introduction to git, which is one of the most widely used versions control systems. It assumes that git is installed.
The steps carried out are:
- retrieving an existing repository
- examining its history
- examining changes
- storing the changes.
git overview
The first step is to retrieve (also called "to check out" a local
copy of the remote repository. With git this is done with the
clone command:
$ mkdir src/ $ cd src/ $ git clone http://git.mech.kuleuven.be/~u0062335/traffic_control.git Cloning into traffic_control... remote: Counting objects: 97, done. remote: Compressing objects: 100% (94/94), done. remote: Total 97 (delta 56), reused 0 (delta 0) Receiving objects: 100% (97/97), 17.52 KiB, done. Resolving deltas: 100% (56/56), done.
After this you have a local copy of the source code of the virtual
traffic light in the traffic_control directory. Change to it and
examine the history.
$ cd traffic_control $ git log
This shows the history of the repository starting from latest
changes at the top. Pressing q will exit the pager. The gitk
program provides a fancier, graphical overview of the
history. Simply run it in the traffic_control directory.
Next step is to make some changes. Edit any of the files, e.g. the README. A summary of the current changes can be obtained with the git status command:
$ git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # #modified: README # no changes added to commit (use "git add" and/or "git commit -a") $
This shows that the README file has been modified.
A more detailed description of the changes with respect to the base
version is shown by using the git diff command:
$ git diff
The output has the following meaning: Lines starting with a minus have been removed while lines with a plus have been added. Assuming we are content with the changes made we now want to permanently store them in the repository. This is called commiting the change. Don't worry about commiting a nonsense change, we can check out a fresh copy later.
The following command will store all local changes (the -a
flag). You will be asked to enter a message describing the
change. It is important to choose good commit messages for you and
others to be able to understand later what was the purpose of the
change. (Side note: the editor program opened is defined (among
others) by the EDITOR environment variable, so you might want to set
it to your preferred editor export EDITOR=vi beforehand)
$ git commit -a
Now you should be able to see your change using git log or gitk.
Some remarks
- git is not considered to be intuitive to the newcomer. Especially the staging area, for instance explained here, can be confusing.
- git does not replace making backups: as a git directory is self contained, removing the checked out directory erases all history.
- Find out how to create a new git repository starting from some existing files. This does not have to be source code, git can be useful for tracking changes to any text documents.
For more information consult the exhaustive git documentation.
Assignment 6: cross development
Cross compilation
In the last session we compiled a program to be executable on our local computer (commonly called host system) which probably contains an AMD or Intel CPU. However our target embedded system, the BeagleBoard, contains a ARM CPU which is quite different. Therefore any program which must run on the Beagle Board needs to be compiled specifically for this architecture.
In general there are two possible ways to do this:
- By compiling a program on the beagle board itself. This is called native compilation.
- By compiling the program on the host system, but with a compiler which generates executable programs for a different CPU. Because of this asymmetry this process is called cross compilation
The following figure shows the two approaches:
Depending on the situation both approaches are usefull. Generally the cross development approach has the advantage that the development can take place on the host system opposed to the restricted embedded target. We will explore both approaches.
A cross compilation environment is already installed on the lab PCs
under opt/eldk-4.2. You can check that it is available in your PATH
by writing arm- in a terminal window and hitting tab twice:
$ arm-linux-gnueabi- arm-linux-gnueabi-addr2line arm-linux-gnueabi-elfedit arm-linux-gnueabi-gcov-4.4 arm-linux-gnueabi-ranlib arm-linux-gnueabi-ar arm-linux-gnueabi-g++ arm-linux-gnueabi-gprof arm-linux-gnueabi-readelf arm-linux-gnueabi-as arm-linux-gnueabi-g++-4.4 arm-linux-gnueabi-ld arm-linux-gnueabi-size arm-linux-gnueabi-c++filt arm-linux-gnueabi-gcc arm-linux-gnueabi-nm arm-linux-gnueabi-strings arm-linux-gnueabi-cpp arm-linux-gnueabi-gcc-4.4 arm-linux-gnueabi-objcopy arm-linux-gnueabi-strip arm-linux-gnueabi-cpp-4.4 arm-linux-gnueabi-gcov arm-linux-gnueabi-objdump $ arm-linux-gnueabi-
This shows the various tools which form the cross development
toolchain. They resemble the tools which are available on the host
platform but use the prefix arm-linux-. As we will see this allows
to quickly switch between cross and host development.
In order to cross compile our hello world program, all we need to do
is to extend our Makefile. The original version looks like this:
hello_world: hello_world.c
gcc hello_world.c -o hello_world
We extend it like this.
CC=$(CROSS_COMPILE)gcc
hello_world: hello_world.c
${CC} -g hello_world.c -o hello_world
Important: remember that the space before ${CC} is one tab!
The first line sets the variable CC to the value of the
CROSS_COMPILE environment variable plus the string gcc. The result
is then used as the compiler command. This way, if we don't set the
CROSS_COMPILE environment variable the compiler used will be the
standard gcc, so the program will be compiled for the host system as
before. But if we set CROSS_COMPILE to the value arm-linux- then
the cross compiler will be used so the program can run on the embedded
board.
$ make CROSS_COMPILE=arm-linux-gnueabi-
arm-linux-gcc -Wall -g hello_world.c -o hello_world
Some questions:
- What happens if we run the program?
- What does the
filecommand report when run the executable?
Connecting to the target system
For testing a program we need to transfer it to the embedded system
and the run it there. For doing this we will use the two tools scp
and ssh. The first allows to securely copy files across a network.
The second allows to access a remote system by means of a command line
interface.
First let's connect with ssh to the beagle board (ip address is 192.168.10.65). The first time you might get a message about the RSA fingerprint, which you should verify to be sure that you are connecting to the right embedded board (and not to a fake system a malicious user has setup)
If the fingerprint is
ab:6d:2a:ef:15:24:68:40:c7:ad:7a:4e:55:26:67:19 everything is ok and
you can accept the key by typing yes. Next you will be promted for
the password, which is ecs.
pma-robot-youbot /home/mk $ ssh ecs@192.168.10.65 The authenticity of host '192.168.10.65 (192.168.10.65)' can't be established. RSA key fingerprint is ab:6d:2a:ef:15:24:68:40:c7:ad:7a:4e:55:26:67:19. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.10.65' (RSA) to the list of known hosts. ecs@192.168.10.65's password: Linux beagle1 2.6.37-x2 #1 SMP PREEMPT Wed Feb 2 20:59:40 UTC 2011 armv7l GNU/Linux Ubuntu 10.10 Welcome to Ubuntu! * Documentation: https://help.ubuntu.com/ The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. ecs@beagle1:~$
Now we are remotely connected to the beagle board with the familar
command line interface. We can verify this is an ARM Processor based
Linux with the uname command:
ecs@beagle1:~$ uname -a Linux beagle1 2.6.37-x2 #1 SMP PREEMPT Wed Feb 2 20:59:40 UTC 2011 armv7l GNU/Linux
Next step is to create a folder with your s-number to which your program can be copied. Because everybody is logged in using the same username care needs to be taken to not interfere with each other.
ecs@beagle1:~$ mkdir s0202242 ecs@beagle1:~$
Next we switch to a terminal of the host system and copy our the
cross compiled program using the scp tool to the newly created
directory on the beagle board:
$ scp hello_world ecs@192.168.10.65:/home/ecs/s0202242/ # replace this with your s-number! ecs@192.168.10.65's password: hello_world 100% 6258 6.1KB/s 00:00 $
Next change to the directory and check the file was really copied there…
ecs@beagle1:~$ cd s0202242 ecs@beagle1:~/s0202242$ ls hello_world
… and run it:
ecs@beagle1:~/s0202242$ ./hello_world hello world: 4711 ecs@beagle1:~/s0202242$
Congratulations! You just successfully ran a program which was cross compiled for an embedded system.