...making Linux just a little more fun! |
By Pramode C.E |
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:
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.
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 www.simputer.org.
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.
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:
minicom -m -s
Once configuration is over - just type:
minicom -m
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' .
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.
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:
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:
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
After you have reached this far, you have to run a few more commands:
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).
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).
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.
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.
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.
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:
ARCH := <lots-of-stuff>
near the top. Change it to
ARCH := arm
You need to make one more change. You observe that the Makefile defines:
AS = ($CROSS_COMPILE)as LD = ($CROSS_COMPILE)ld CC = ($CROSS_COMPILE)gcc
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:
CROSS_COMPILE = arm-linux-
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.
Once the configuration process is over, you can run
make zImage
and in a few minutes, you should get a file called `zImage' under arch/arm/boot. This is your new kernel.
I describe the easiest way to get the new kernel up and running.
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:
blob>
At the bootloader prompt, you can type:
blob> download kernel
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:
uuencode zImage /dev/stdout > /dev/ttyS1
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:
blob> boot
and the boot loader will run the kernel which you have right now compiled and downloaded.
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':
#include <linux/module.h> #include <linux/init.h> /* Just a simple module */ int init_module(void) { printk("loading module...\n"); return 0; } void cleanup_module(void) { printk("cleaning up ...\n"); }
You have to compile it using the command line:
arm-linux-gcc -c -O -DMODULE -D__KERNEL__ a.c -I/usr/local/src/linux-2.4.18/include
You can ftp the resulting `a.o' onto the Simputer and load it into the kernel by running:
insmod ./a.o
You can remove the module by running:
rmmod a
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.
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.
#include <linux/module.h> #include <linux/ioport.h> #include <linux/sched.h> #include <asm-arm/irq.h> #include <asm/io.h> 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); }
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.
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!