Schon mal drüber nachgedacht?

Fahrradcomputer

2 Kommentare

What? A self made bike speedo?

„This guy must be crazy!“, many people cry, if they here that I spend my leisure time on my own bike speedo since years. Actually the first version was finished, when I was in school („Technisches Gymnasium der Werner-Siemens-Schule“), where I got in touch with microcontrollers the first time. It had a PIC16F84 and a 2×8 character LC-Display. A very sad time, I somehow lost the source code – (pure assembly language). Since I once proved my ability to implement a division algorithm on an 8 bit architecture only using bitshift, addition and substraction operations, I stopped working on that ddevice. Now, I’m left with the hardware, not showing anything. But that is history. I came up with new requirements:

  • 320 x 240 pixel TFT with a touchscreen
  • CPU: Hynix (now magnachip, oh no, they were sold again: ABOV) hms7202 (ARMv4, ARM720T core)
  • an extensionboard with chargecontroller and a few sensors like air pressure for barometric hight measurement, temperature, battery voltage,… (schematic and layout will follow)
  • everything running Linux and showing OpenStreetMaps

So, I admit, that I did not build the complete hardware on my own. I took a CPU board equipped with 64 MB RAM, an ethernet controller (CS8900) and some other interface electronics. It’s a Future Unit from Kurz Industrieelektronik in Remshalden, Germany.

A project with similar aims can be found at obico.de.

Hardware

Altimeter

To calculate the altitude I designed the following extension, connected to the I2C bus (emulated with GPIO ports):

For the ADS1100 I wrote a linux kernel module to read the analog value in high resolution via /sys interface. This is read by my SmartEiffel application with the class ADS1100. Using the formula

pressure (kPa) = exp((log(1 – 22.5498e-6 * altitudeMeters) * 5.256)) * seaLevelPressure

(Source: http://davidbray.org/onewire/baro2030.html)

I calculate the altitude from the measured pressure. During development I found the following sites useful:

http://www.csgnetwork.com/pressurealtcalc.html (Pressure Altitude Calculator)
http://www.wetteronline.de/ because they publish air pressure data.

Software

Bootloader

The first piece of software executed is the bootloader, for which I first used the LDBoot from hynix, but as this does crazy things with the mmu (actually it enables it ;-) I switched over to U-Boot (version 1.1.1-hynix2-svn Nov 6 2005 – 21:19:43 – at least that is what is printed on boot). The patches come from http://www.pengutronix.de/software/hynix/download/uboot/ but I also stored them here (just in case).

To get the uboot binary (for which I have no glue how I got it compiled) I used the JTAG tool from the Openwince project, but of cause I had to teach it how to deal with my hardware. See patch here. To flash the thing I use the jtag-script
cable parallel 0x378 WIGGLER
detect
initbus h7202
eraseflash 0x0 4
flashmem 0x0 uboot

kernel

Once we have the boot loader, the hardest part is done and we can configure and build a kernel. As I do this using buildroot, I do not explain the steps to get a uImage. To download the uImage boot the system with a serial console connected and read:
U-Boot 1.1.1-hynix2-svn (Nov 5 2005 - 00:50:22)

U-Boot code: 41FE0000 -> 41FF73FC BSS: -> 41FFB12C
RAM Configuration:
Bank #0: 40000000 64 MB
Flash: 16 MB
*** Warning – bad CRC, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 1
press any key and get a command prompt. Enter:
erase 0x40000 0x1fffff
loadb 0x40000000
“Ctrl-\ c” to escape from kermit
send path/to/uImage
connect # reconnect to uboot console
cp.b 0x40000000 0x40000 ${filesize}

erasing the flash (between addresses in range 0x40000 – 0x1fffff may need adjustment in other setups) also the kernel load address 0x40000000 shall be a valid RAM address.

Feel free to look at http://kernelnewbies.org/KernelHacking-HOWTO/Debugging_Kernel.

Application

The application to show speed data and the maps is written in the programming language Eiffel. I should say SmartEiffel, as I do not use the ECMA crap which destroyed the langauge.

In the first step I was just parsing the OSM xml file to get the map data. As this limits the size of the map to some hundred ways (due to the parsing time on startup) I decided to give sqlite a try. I wrote a small converter to parse the XML and store it into a sqlite database. Using the eiffel sqlite wrapper from EWLC this went quite well but running the thing on the target showed, that getting the data from sqlite is way slower then parsing XML ;-( One could surely improve the db schema and everything, but I do not expect to gain a factor > 10, which is what I need. The next try will probably be some non-SQL embedded DB like BerkleyDB.

When I first tried to use the sqlite library (built by buildroot) I got a segfault on startup of my application. Disabling the threadsafe option for sqlite solved the problem.

Graphics

I use the framebuffer device driver of linux and a SmartEiffel application on top of that. This means I have to do some nasty graphic stuff on my own. Thing like „drawing a line“ or „managing windows“. For text rendering I did not go into details and just use freetype. Some links I used for this:
Antialiasing for line drawing (because plain Bresenham does not give „ahh“ and „oohhho“ sounds when you show your app to friends):
http://courses.ece.uiuc.edu/ece390/archive/archive-f2000/mp/mp4/anti.html

Todo:

my /etc/TZ looks like the following:
CET-1CEST-2
which seems to set the timezone info for uclibc to something like Europe/Berlin or CET/MEZ.
Once upon a time I will (probably find time to support the new display background whatever backend for the HMS7202)

Toolchain

To get a working toolchain (gcc, libraries and also a root filesystem) I use buildroot.


Here are some old notes, evolved during the last years…

Toolchain

using crosstool (version 0.38 from http://kegel.com/crosstool/) I generated a working toolchain with

#!/bin/sh
set -ex
TARBALLS_DIR=/armroot/downloads
RESULT_TOP=/opt/crosstool
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES=“c,c++“
export GCC_LANGUAGES
unset LD_LIBRARY_PATH

# Really, you should do the mkdir before running this,
# and chown /opt/crosstool to yourself so you don’t need to run as root.
mkdir -p $RESULT_TOP

# Build the toolchain. Takes a couple hours and a couple gigabytes.

eval `cat arm.dat gcc-3.4.4-glibc-2.3.5.dat` sh all.sh –notest
echo Done.

u-boot

to flash the first version of uboot, I used a wiggler with jtag from openwince. build the kernel with
make uImage
open kermit with script:
set line /dev/ttyS0
set speed 115200
set carrier-watch off
set handshake none
set flow-control none
robust
set file type bin
set file name lit
set rec pack 1000
set send pack 1000
set window 5
connect
now you are connected to the serial console, now switch on the device
press any key to get a uboot-console
erase #erase flash, good values are: 0x40000 0x1fffff
loadb 0x40000000
„Ctrl-\ c“ to escape from kermit
send path/to/uImage
connect # reconnect to uboot console
cp.b 0x40000000 0x40000 ${filesize}
bootm 0x40000

H7202-cpufreq Patch

linux-2.6.13-hnx3-h7202-cpufreq.diff
this patch enables cpufreq support for the h7202 (needs hnx3 patch from Pengutronix), Since I do not have access to a H7201 I cannot test it there, but it feels, as it could work there, too.
I’m planning to use SLOW mode to reduce the power consumption.
It thought of 1. just adding other (half) frequencies to the cpufreq driver or 2. implementing it in a different module. Both don’t satisfy me completly. Is there another place to do this? Any ideas where to implement this are welcome!

MMC Support for the h7202

By browsing the kernel tree and the web, I found:
* two patches from magnachip, both containing a MMC driver (using DMA)
* in summer 2004 I tried to use a version of the mmc driver with kernel 2.4.19 and succeded more or less after removing the use of DMA, but it was very slow and buggy
* in linux/drivers/mmc is a driver for MMC support of the AMBA PL181 standard
* the MMC hardware in the HMS7202 is NOT compliant with PL181
* probably I’ll try to implement a mmc driver from scratch with use of the mmc-core in linux/drivers/mmc (or adapt the mmci – the PL181 implementation)

I2C support

I use a few I2C devices (tmeperature sensor DS1621, a few ADCs ADS1100), therefore I’ve adapted a bit-banging I2C driver for usage at GPIO PortE. Details will follow. (or ask me) for the ads1100 chip try this.

Packages

zlib

cd /armroot/usr/src
wget http://switch.dl.sourceforge.net/sourceforge/libpng/zlib-1.2.3.tar.bz2
tar -jxvf zlib-1.2.3.tar.bz2
cd zlib-1.2.3
#now set path to use arm-unknown-linux-gcc as gcc
export PATH=/opt/crosstool/gcc…/…/…/bin
./configure –prefix=/armroot/usr –shared
make
make install

dropbear ssh server

get it from http://matt.ucc.asn.au/dropbear/dropbear.html
./configure –prefix=/armroot/usr –target=arm-unknown-linux-gnu –host=arm-unknown-linux-gnu –build=i686-pc-linux-gnu –with-zlib=/armroot/usr
make
to run it /dev/random must be readable, this means, that you have to add enough entropy sources for your system. For details see http://matt.ucc.asn.au/dropbear/dropbear.html.

Hardware monitoring

Since I use a few sensors to measure battery voltage and temperature I want to user lm_sensors (version 2.10) which depends on libsysfs (see http://linux-diag.sourceforge.net/Sysfsutils.html).
Intall it with:
./configure –prefix=/armroot/usr –target=arm-unknown-linux-gnu –host=arm-unknown-linux-gnu –build=i686-pc-linux-gnu
make
make install
cd lm_sensors-2.10.0
I changed the Makefile to look like this.
make user (didn’t work fine for me)
arm-unknown-linux-gnu-gcc -shared -Wl,-soname,libsensors.so.3 -o lib/libsensors.so.3.1.0 lib/data.lo lib/general.lo lib/error.lo lib/chips.lo lib/proc.lo lib/access.lo lib/init.lo lib/sysfs.lo lib/conf-parse.lo lib/conf-lex.lo -lc -lm -lsysfs -L/armroot/usr/lib
make user
make user_install This is my sensors.conf for the given hardware.

Softfloat vs. Hardfloat

If you want to read more about softfloat, hardfloat and what to use read here.