old-www/LDP/LG/issue87/pramode.html

593 lines
21 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Fun with Simputer and Embedded Linux LG #87</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="okopnik.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue87/pramode.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<!--endcut ============================================================-->
<TABLE BORDER><TR><TD WIDTH="200">
<A HREF="http://www.linuxgazette.com/">
<IMG ALT="LINUX GAZETTE" SRC="../gx/2002/lglogo_200x41.png"
WIDTH="200" HEIGHT="41" border="0"></A>
<BR CLEAR="all">
<SMALL>...<I>making Linux just a little more fun!</I></SMALL>
</TD><TD WIDTH="380">
<CENTER>
<BIG><BIG><STRONG><FONT COLOR="maroon">Fun with Simputer and Embedded Linux</FONT></STRONG></BIG></BIG>
<BR>
<STRONG>By <A HREF="../authors/pramode.html">Pramode C.E</A></STRONG>
</CENTER>
</TD></TR>
</TABLE>
<P>
<!-- END header -->
<html>
<head><title>Fun with Simputer and Embedded Linux</title></head>
<h1>Fun with Simputer and Embedded Linux</h1>
The Simputer is a StrongArm CPU based handheld device running
Linux. Originally developed by professors at the Indian
Institute of Science, Bangalore, the device has a social
objective of bringing computing and connectivity within
the reach of rural communities. This articles provides a
tutorial introduction to programming the Simputer (and similar
ARM based handheld devices - there are lots of them in the
market). The reader is expected to have some experience
programming on Linux. Disclaimer: I try to describe things
which I had done on my Simputer without any problem - if
following my instructions leads to your handheld going up
in smoke - I should not be held responsible!
<h2>Hardware/Software</h2>
<p>
The device is powered by an Intel StrongArm (SA-1110) CPU.
The flash memory size is either 32Mb or 16Mb and RAM is
64Mb or 32Mb. The peripheral features include:
<p>
<ol>
<li> USB master as well as slave ports.
<li> Standard serial port.
<li> Infra Red communication port.
<li> Smart card reader
</ol>
<p>
Some of these features are enabled by using a `docking cradle'
provided with the base unit. Power can be provided either
by rechargeable batteries or external AC mains.
<p>
Simputer is powered by GNU/Linux - kernel version 2.4.18
(with a few patches) works fine. The unit comes bundled
with binaries for the X-Window system and a few simple utility
programs. More details can be obtained from the project
home page at <a href="http://www.simputer.org">www.simputer.org</a>.
<h2> Powering up </h2>
<p>
There is nothing much to it, other than pressing the `power
button'. You will see a small tux picture coming up and
within a few seconds, you will have X up and running . The
LCD screen is touch sensitive and you can use a small `stylus'
(geeks use finger nails!) to select applications and move
through the graphical interface. If you want to have keyboard
input, be prepared for some agonizing manipulations using
the stylus and a `soft keyboard' which is nothing but a
GUI program from which you can select single alphabets and
other symbols.
<h2> Waiting for bash </h2>
<p>
GUI's are for kids. You are not satisfied till you see the
trusted old bash prompt. Well, you don't have to try a lot.
The Simputer has a serial port - attach the provided serial
cable to it - the other end goes to a free port on your
host Linux PC (in my case, /dev/ttyS1).
Now fire up a communication program (I use `minicom') -
you have to first configure the program so that it uses
/dev/ttyS1 with communication speed set to 115200 (that's
what the Simputer manual says - if you are using a similar
handheld, this need not be the same) and 8N1 format, hardware
and software flow controls disabled. Doing this with minicom
is very simple - invoke it as:
<p>
minicom -m -s
<p>
Once configuration is over - just type:
<p>
minicom -m
<p>
and be ready for the surprise. You will immediately see a
login prompt. You should be able to type in a user name/password
and log on. You should be able to run simple commands like
`ls', `ps' etc - you may even be able to use `vi' .
<p>
If you are not familiar with running communication programs
on Linux, you may be wondering what really happened. Nothing
much - it's standard Unix magic. A program sits on the Simputer
watching the serial port (the Simputer serial port, called
ttySA0) - when you run minicom on the Linux PC, you establish
a connection with that program, which sends you a login
prompt over the line, reads in your response, authenticates
you and spawns a shell with which you can interact over
the line.
<p>
Once minicom initializes the serial port on the PC end, you
can `script' your interactions with the Simputer. You are
exploiting the idea that the program running on the Simputer
is watching for data over the serial line - the program
does not care whether the data comes from minicom itself
or a script. You can try out the following experiment:
<p>
<ol>
<li> Open two consoles (on the Linux PC)
<li> Run minicom on one console, log on to the simputer
<li> On the other console, type `echo ls &gt; /dev/ttyS1'
<li> Come to the first console - you will see that the command
`ls' has executed on the Simputer.
</ol>
<h2> Setting up USB Networking </h2>
<p>
The Simputer comes with a USB slave port. You can establish
a TCP/IP link between your Linux PC and the Simputer via
this USB interface. Here are the steps you should take:
<p>
<ol>
<li> Make sure you have a recent Linux distribution - Red Hat
7.3 is good enough.
<li> Plug one end of the USB cable onto the USB slave slot in
the Simputer, then boot the Simputer.
<li> Boot your Linux PC. DO NOT connect the other end of the
USB cable to your PC now. Log in as root on the PC.
<li> Run the command `insmod usbnet' to load a kernel module
which enables USB networking on the Linux PC. Verify that
the module has been loaded by running `lsmod'.
<li> Now plug the other end of the USB cable onto a free USB
slot of the Linux PC. The USB subsystem in the Linux kernel
should be able to register a device attach. On my Linux
PC, immediately after plugging in the USB cable, I get
the following kernel messages (which can be seen by running
the command `dmesg'):
</ol>
<pre>
usb.c: registered new driver usbnet
hub.c: USB new device connect on bus1/1, assigned device
number 3
usb.c: ignoring set_interface for dev 3, iface 0, alt 0
usb0: register usbnet 001/003, Linux Device
</pre>
<p>
After you have reached this far, you have to run a few more
commands:
<p>
<ol>
<li> Run `ifconfig usb0 192.9.200.1' - this will assign an IP
address to the USB interface on the Linux PC.
<li> Using `minicom' and the supplied serial cable, log on to
the Simputer as root. Then run the command `ifconfig usbf
192.9.200.2' on the Simputer.
<li> Try `ping 192.9.200.2' on the Linux PC. If you see ping
packets running to and fro, congrats. You have successfully
set up a TCP/IP link!
</ol>
You can now telnet/ftp to the Simputer through this TCP/IP
link.
<h2> Hello, Simputer </h2>
<p>
It's now time to start real work. Your C compiler (gcc) normally
generates `native' code, ie, code which runs on the microprocessor
on which gcc itself runs - most often, an Intel (or clone)
CPU. If you wish your program to run on the Simputer (which
is based on the StrongArm microprocessor), the machine code
generated by gcc should be understandable to the StrongArm
CPU - your `gcc' should be a cross compiler. If you download
the gcc source code (preferably 2.95.2) together with `binutils',
you should be able to configure and compile it in such a
way that you get a cross compiler (which could be invoked
like, say, arm-linux-gcc). This might be a bit tricky if
you are doing it for the first time - your handheld vendor
should supply you with a CD which contains the required
tools in a precompiled form - it is recommended that you
use it (but if you are seriously into embedded development,
you should try downloading the tools and building them yourselves).
<p>
Assuming that you have arm-linux-gcc up and running, you
can write a simple `Hello, Simputer' program, compile it
into an `a.out', ftp it onto the Simputer and execute it
(it would be good to have one console on your Linux PC running
ftp and another one running telnet - as soon as you compile
the code, you can upload it and run it from the telnet console
- note that you may have to give execute permission to the
ftp'd code by doing `chmod u+x a.out' on the Simputer).
<h2> A note on the Arm Linux kernel </h2>
<p>
The Linux kernel is highly portable - all machine dependencies
are isolated in directories under the `arch' subdirectory
(which is directly under the root of the kernel source tree,
say, /usr/src/linux). You will find a directory called `arm'
under `arch'. It is this directory which contains ARM CPU
specific code for the Linux kernel.
<p>
The Linux ARM port was initiated by Russell King. The ARM
architecture is very popular in the embedded world and there
are a LOT of different machines with fantastic names like
Itsy, Assabet, Lart, Shannon etc all of which use the StrongArm
CPU (there also seem to be other kinds of ARM CPU's - now
that makes up a really heady mix). There are minor differences
in the architecture of these machines which makes it necessary
to perform `machine specific tweaks' to get the kernel working
on each one of them. The tweaks for most machines are available
in the standard kernel itself, and you only have to choose
the actual machine type during the kernel configuration
phase to get everything in order. But to make things a bit
confusing with the Simputer, it seems that the tweaks for
the initial Simputer specification have got into the ARM
kernel code - but the vendors who are actually manufacturing
and marketing the device seem to be building according to
a modified specification - and the patches required for
making the ARM kernel run on these modified configurations
is not yet integrated into the main kernel tree. But that
is not really a problem, because your vendor will supply
you with the patches - and they might soon get into the
official kernel.
<h2> Getting and building the kernel source </h2>
<p>
You can download the 2.4.18 kernel source from the nearest
Linux kernel ftp mirror. You will need the file `patch-2.4.18-rmk4'
(which can be obtained from the ARM Linux FTP site ftp.arm.linux.org.uk).
You might also need a vendor supplied patch, say, `patch-2.4.18-rmk4-vendorstring'.
Assume that all these files are copied to the /usr/local/src
directory.
<p>
<ol>
<li> First, untar the main kernel distribution by running `tar
xvfz kernel-2.4.18.tar.gz'
<li> You will get a directory called `linux'. Change over to
that directory and run `patch -p1 &lt; ../patch-2.4.18-rmk4'.
<li> Now apply the vendor supplied patch.
Run `patch -p1 &lt; ../patch-2.4.18-rmk4-vendorstring'.
</ol>
<p>
Now, your kernel is ready to be configured and built. Before
that, you have to examine the top level Makefile (under
/usr/local/src/linux) and make two changes - there will
be a line of the form:
<p>
ARCH := &lt;lots-of-stuff&gt;
<p>
near the top. Change it to
<p>
ARCH := arm
<p>
You need to make one more change. You observe that the Makefile
defines:
<p>
<pre>
AS = ($CROSS_COMPILE)as
LD = ($CROSS_COMPILE)ld
CC = ($CROSS_COMPILE)gcc
</pre>
<p>
You note that the symbol CROSS_COMPILE is equated with the
empty string. During normal compilation, this will result
in AS getting defined to `as', CC getting defined to `gcc'
and so on which is what we want. But when we are cross compiling,
we use arm-linux-gcc, arm-linux-ld, arm-linux-as etc. So
you have to equate CROSS_COMPILE with the string arm-linux-,
ie, in the Makefile, you have to enter:
<p>
CROSS_COMPILE = arm-linux-
<p>
<p>
Once these changes are incorporated into the Makefile, you
can start configuring the kernel by running `make menuconfig'
(note that it is possible to do without modifying the Makefile.
You run `make menuconfig ARCH=arm'). It may take a bit of
tweaking here and there before you can actually build the
kernel without error. You will not need to modify most things
- the defaults should be acceptable.
<p>
<ol>
<li> You have to set the system type to SA1100 based ARM system
and then choose the SA11x0 implementation to be `Simputer(Clr)'
(or something else, depending on your machine). I had
also enabled SA1100 USB function support, SA11x0 USB net
link support and SA11x0 USB char device emulation.
<li> Under Character devices-&gt;Serial drivers, I enabled SA1100
serial port support, console on serial port support and
set the default baud rate to 115200 (you may need to set
differently for your machine).
<li> Under Character devices, SA1100 real time clock and Simputer
real time clock are enabled.
<li> Under Console drivers, VGA Text console is disabled.
<li> Under General Setup, the default kernel command string
is set to `root=/dev/mtdblock2 quite'. This may be different
for your machine.
</ol>
<p>
Once the configuration process is over, you can run
<p>
make zImage
<p>
and in a few minutes, you should get a file called `zImage'
under arch/arm/boot. This is your new kernel.
<h2> Running the new kernel </h2>
<p>
I describe the easiest way to get the new kernel up and running.
<p>
Just like you have LILO or Grub acting as the boot loader
for your Linux PC, the handheld too will be having a bootloader
stored in its non volatile memory. In the case of the Simputer,
this bootloader is called `blob' (which I assume is the
boot loader developed for the Linux Advanced Radio Terminal
Project, `Lart'). As soon as you power on the machine, the
boot loader starts running - If you start minicom on your
Linux PC, keep the `enter' key pressed and then power on
the device, the bootloader, instead of continuing with booting
the kernel stored in the device's flash memory, will start
interacting with you through a prompt which looks like this:
<p>
blob&gt;
<p>
At the bootloader prompt, you can type:
<p>
blob&gt; download kernel
<p>
which results in blob waiting for you to send a uuencoded
kernel image through the serial port. Now, on the Linux
PC, you should run the command:
<p>
uuencode zImage /dev/stdout &gt; /dev/ttyS1
<p>
This will send out a uuencoded kernel image through the COM
port - which will be read and stored by the bootloader in
the device's RAM. Once this process is over, you get back
the boot loader prompt. You just have to type:
<p>
blob&gt; boot
<p>
and the boot loader will run the kernel which you have right
now compiled and downloaded.
<h2> A bit of kernel hacking </h2>
<p>
What good is a cool new device if you can't do a bit of kernel
hacking? My next step after compiling and running a new
kernel was to check out how to compile and run kernel modules.
Here is a simple program called `a.c':
<p>
<pre>
#include &lt;linux/module.h&gt;
#include &lt;linux/init.h&gt;
/* Just a simple module */
int
init_module(void)
{
printk("loading module...\n");
return 0;
}
void
cleanup_module(void)
{
printk("cleaning up ...\n");
}
</pre>
<p>
You have to compile it using the command line:
<p>
arm-linux-gcc -c -O -DMODULE -D__KERNEL__ a.c -I/usr/local/src/linux-2.4.18/include
<p>
You can ftp the resulting `a.o' onto the Simputer and load
it into the kernel by running:
<p>
insmod ./a.o
<p>
You can remove the module by running:
<p>
rmmod a
<p>
<h2> Handling Interrupts </h2>
<p>
After running the above program, I started scanning the kernel
source to identify the simplest code segment which would
demonstrate some kind of physical hardware access - and
I found it in the hard key driver. The Simputer has small
buttons which when pressed act as the arrow keys - these
buttons seem to be wired onto the general purpose I/O pins
of the ARM CPU (which can also be configured to act as interrupt
sources - if my memory of reading the StrongArm manual is
correct). Writing a kernel module which responds when these
keys are pressed is a very simple thing - here is a small
program which is just a modified and trimmed down version
of the hardkey driver - you press the button corresponding
to the right arrow key - an interrupt gets generated which
results in the handler getting executed. Our handler simply
prints a message and does nothing else. Before inserting
the module, we must make sure that the kernel running on
the device does not incorporate the default button driver
code - checking /proc/interrupts would be sufficient.
<p>
Compile the program shown below into an object file (just
as we did in the previous program), load it using `insmod',
check /proc/interrupts to verify that the interrupt line
has been acquired. Pressing the button should result in the
handler getting called - the interrupt count displayed in
/proc/interrupts should also change.
<pre>
#include &lt;linux/module.h&gt;
#include &lt;linux/ioport.h&gt;
#include &lt;linux/sched.h&gt;
#include &lt;asm-arm/irq.h&gt;
#include &lt;asm/io.h&gt;
static void
key_handler(int irq, void *dev_id, struct pt_regs *regs)
{
printk("IRQ %d called\n", irq);
}
static int
init_module(void)
{
unsigned int res = 0;
printk("Hai, Key getting ready\n");
set_GPIO_IRQ_edge(GPIO_GPIO12, GPIO_FALLING_EDGE);
res = request_irq(IRQ_GPIO12, key_handler, SA_INTERRUPT,
"Right Arrow Key", NULL);
if(res) {
printk("Could Not Register irq %d\n", IRQ_GPIO12);
return res;
}
return res ;
}
static void
cleanup_module(void)
{
printk("cleanup called\n");
free_irq(IRQ_GPIO12, NULL);
}
</pre>
<h2> Future work </h2>
<p>
A Linux based handheld offers a lot of opportunities for
serious fun - as I learn more about the device, I shall try to
share my findings with the readers.
<h2> References </h2>
<p>
<ol>
<li> <a href="http://www.simputer.org">Simputer Project</a> Home Page.
<li> <a href="http://www.simputerland.com">Simputerland</a> and
<a href="http://www.picopeta.com">PicoPeta</a> - information
about Simputer development activities from companies which
are manufacturing and marketing the product.
<li> <a href="http://www.arm.linux.org.uk">Arm Linux</a> Project Home Page
<li> <a href="http://www.lart.tudelft.nl">Lart Project</a> Home Page. Lots
of cool stuff here. You might like to check out the `Clock
Scaling' link on this site. Clock scaling allows you to
change the clock speed of the running processor on the
fly - useful for saving battery power.
</ol>
<!-- *** BEGIN author bio *** -->
<P>&nbsp;
<P>
<!-- *** BEGIN bio *** -->
<P>
<img ALIGN="LEFT" ALT="[BIO]" SRC="../gx/2002/note.png">
<em>
I am an instructor working for IC Software in Kerala, India. I would have loved
becoming an organic chemist, but I do the second best thing possible, which is
play with Linux and teach programming!
</em>
<br CLEAR="all">
<!-- *** END bio *** -->
<!-- *** END author bio *** -->
<!-- *** BEGIN copyright *** -->
<hr>
<CENTER><SMALL><STRONG>
Copyright &copy; 2003, Pramode C.E.
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 87 of <i>Linux Gazette</i>, February 2003
</STRONG></SMALL></CENTER>
<!-- *** END copyright *** -->
<HR>
<!--startcut ==========================================================-->
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="okopnik.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue87/pramode.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->