Elastic Sheep

Because elasticdog was already taken

Elastic Sheep header image 1

Building and emulating a basic ARM Linux system

January 17th, 2011 · Uncategorized

Here are my notes about the process I used to build a basic ARM linux system testable with QEMU. This knowledged has been gathered from the balau82.wordpress.com blog and from a Pierre Ficheux’s article introducing BuildRoot and published in Linux Magazine special issue n°47.

Here is a summary of the environment I will use:

  • Ubuntu 10.04 development host
  • ELDK 4.2 ARM cross compilation toolchain
  • Linux kernel 2.6.37
  • BuildRoot 2010.11
  • QEMU 0.13
  • Emulated hardware target: Versatile/PB development platform

Installing a cross compilation toolchain

The Embedded Linux Development Toolkit (ELDK) contains a GCC cross-compilation toolchain and a number of pre-built target tools and libraries. It is available for ARM, PPC and PPC64 targets (Documentation and ELDK 4.2 ARM ISO).

The ELDK 4.2 toolchain is EABI (the ELDK 4.1 was OABI).

A full install of the ELDK 4.2 development tools and target components for the ARM target require about 2GB of disk space. Only installing the development tools will require just 71MB. To avoid installing the target components you need to empty the etc/rpm_arm.list file provided in the ISO distribution.

# Mount the ISO and copy its content in the current directory
$> sudo mkdir /mnt/tmp
$> sudo mount –o loop –t iso9660 arm-2008-11-24.iso /mnt/eldk42
$> cp –r /mnt/eldk42 .
$> unmount /mnt/eldk42

# Patch the rpm_arm.list file
$> cd eldk42/etc
$> mv rpm_arm.list rpm_arm.list.original
$> touch rpm_arm.list
$> cd ..

# Install the toolchain
$> sudo mkdir –p /opt/ELDK42/arm
$> ./install –d /opt/ELDK42/arm arm

The toolchain is installed in /opt/ELDK42/arm.

Cross compilation environment variables

I use a shell script to set default environment variables required to cross compile the kernel.

set_env_arm.sh

#!/bin/sh
PATH=/opt/ELDK42/arm/usr/bin:$PATH
ARCH=arm
CROSS_COMPILE=arm-linux-
export PATH ARCH CROSS_COMPILE

Execute this script before any call to the kernel makefile.

Kernel configuration and build

To use the default kernel configuration for the Versatile/PB platform and then access the configuration menu:

$> curl –O http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.37.tar.bz2
$> tar xjvf linux-2.6.37.tar.bz2
$> cd linux-2.6.37
$> ../set_env_arm.sh
$> make versatile_defconfig
$> make menuconfig

In the configuration menu, I modify the following settings:

  • Disable the module support
  • Kernel Features / Use the ARM EABI

The ARM EABI option is required because of the ELDK 4.2 toolchain configuration.

Then to build the kernel:

$> make

The resulting kernel image is in the file arch/arm/boot/zImage.

Building QEMU from the sources

Compiling QEMU from source requires the following packages to be installed in Ubuntu: zliblg-dev libsdl-dev.

$> curl –O http://wiki.qemu.org/download/qemu-0.13.0.tar.gz
$> tar xzvf qemu-0.13.0.tar.gz
$> cd qemu-0.13.0
$> ./configure --target-list=arm-softmmu --enable-sdl
$> make

The generated executable is arm-softmmu/qemu-system-arm.

To get a list of the supported machines:

$> arm-softmmu/qemu-system-arm –M ?
...
realview-pb-a8 ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9 ARM RealView Platform Baseboard Explore for Cortex-A9
versatilepb ARM Versatile/PB (ARM926EJ-S)
...

Executing the linux kernel in QEMU

The QEMU emulator is started by specifiying a machine to emulate and a Linux compressed image.

$> cd arm-softmmu
$> ./qemu-system-arm -M versatilepb –m 128M
-kernel ../../linux-2.6.37/arch/arm/boot/zImage

The-m option specifies the RAM size available for the versatilepb machine. It defaults to 16MB if not specified.

The following capture shows the kernel boot in QEMU. The kernel boot ends with a kernel panic because we don’t have provided an init filesystem.

Building a root filesystem with BuildRoot

Buildroot is a set of makefile that helps to build complete embedded Linux system. It can compiles a GCC cross-compilation toolchain, a kernel and a root filesystem with selectable applications and packages.

I already have a compiled kernel thus I will use BuildRoot to only build a basic root filesystem containing the Busybox shell. This root filesystem will be a simple compressed CPIO archive.

$> curl –O http://buildroot.uclibc.org/downloads/buildroot-2010.11.tar.bz2
$> tar xjvf buildroot-2010.11.tar.bz2
$> cd buildroot-2010.11.tar.bz2
$> make menuconfig

I set the following options:

  • Target Architecture: arm
  • Target Architecture Variant: arm926t
  • Target ABI: EABI
  • Toolchain/Kernel Headers: 2.6.36.x (I could specify a path to my kernel sources)
  • Package Selection for the Target/Busybox 1.17.x
  • Target Fileystem Options/cpio the root filesystem and Compression method: gzip

Some dependencies you may need to install in Ubuntu: g++ flex msgfmt(gettext) patch subversion.

To start the BuildRoot execution (with optional V=1 to enable the verbose mode):

$> make V=1

BuildRoot automatically download the required source packages from their original servers, applies patches if necessary and compile them. It then builds a filesystem with the built packages installed.

Executing the kernel with the BuildRoot root filesystem

$> cd qemu-0.13.0/arm-softmmu
$> ./qemu-system-arm -M versatilepb –m 128M
-kernel ../../linux-2.6.37/arch/arm/boot/zImage
–initrd ../../buildroot-2010.11/output/images/rootfs.cpio.gz

The initrd option specifies a filesystem image to load as the initial ram disk. During boot the kernel will mount this ram disk as its root filesystem and look for an init executable to start. In our case the init executable is provided by Busybox.

Here a capture of the result. I am able to loginp as root and then do a ls on the root of the filesystem.

Quitting QEMU when the mouse has been grabbed

The QEMU graphical window can grab the mouse pointer to interact with the virtual machine display. Ctrl-Alt should exit the mouse grab but in my case (QEMU executed by Ubuntu emulated by OS X/VMWare Fusion) it does not work so I am unable to get back the mouse when I want to end my session.

So I use the console accessed through Ctrl-Alt-2 and the quit command.

compat_monitor0 console
QEMU 0.13.0 monitor - type 'help' for more information
(qemu) quit

→ 9 CommentsTags:···

Linux ARM emulation articles

October 4th, 2010 · Uncategorized

I have begun learning about Linux with embedded ARM targets.

Here is a good set of links to learn the basics of building a kernel and how to boot it in the QEMU virtual machine:

→ No CommentsTags:··

The PSGroove effect

September 3rd, 2010 · Uncategorized

I was surprised to discover yesterday a strange traffic spike on my blog. A lot of people suddenly looking for atmega32u4 and Teensy all over the world. I thought it was a back to school effect, the AVR becoming part of the curriculum of engineering school maybe ;)

It appears that the Teensy is used as a dongle for a jailbreaking hack of the PS3. Now PJRC is out of stock and someone is selling bare AT90USB62 on Ebay for 25$! It is just crazy!

→ 1 CommentTags:

Teensy2 USB WAV player – Part 2

June 29th, 2010 · Uncategorized

[Update Jan 6th, 2011 / An error in the capacitor unit (pF instead of nF) has been fixed in the schematics]

Long overdue post in my USB WAV player implementation series. Let’s go !

General architecture

Here are the main software building blocks of the application:

The left side is the USB Mass Storage implementation based on the LUFA library. It is enabled if the user press a predefined button at power-on (see Part 1).

The right side is the WAV playback application and its related blocks.

  • The Player block offers a high-level API to control the playback of files,
  • The Wav parser contains some simple WAV-header parsing code to determine what are the sampling rate and number of channels of a file; it also helps to locate the audio data start in the file,
  • The Dac block implements the digital to analog conversion to output sound to a speaker.

DAC block

The DAC block converts digital samples to an analog signal using Pulse-Width Modulation (PWM) and a low-pass RC filter.

The PWM is generated from the Timer4 of the ATMEGA32U4 in Fast PWM mode with an 8-bit resolution. Using OCR4A and OC4B we can produce two independent PWM signals.

The PWM clock is set to the highest possible value (PeripheralClock / 256 = 187500 Hz) to avoid a fundamental harmonic close to the audio signal. The RC filter has a cut-off frequency of about 22kHz corresponding to the Nyquist frequency for the 44.1kHz sampling rate.

Two buffers of 8-bit samples (mono or stereo) are used as input. An interrupt triggered by Timer0 at the sampling rate (8kHz, 16kHz, 44.1kHz) read samples for one buffer and update the Timer4 output compare registers. When the end of one buffer is reached, the routine switch to the other one and trigger and End Of Buffer interrupt.

The End Of Buffer interrupt by Timer0 by writing a 0 output compare value. In OCR0B. This immediately raise the TIMER0_COMPB_vect interrupt. As its priority is lower than TIMER0_COMPA_vect, it will not block the sample transfer while being served by the Wav player block (The idea has been borrowed from LadyAda WaveHc library)

The double buffer mechanism allows the Wav player block to refill one buffer while the other one is copied to the PWM generation. It can be viewed as a particular implementation of a circular buffer.

Player block

Here is the WAV player API:

  • player_start
  • player_stop
  • player_pause
  • player_resume

When started, the player parse the WAV header from a file then fill its buffers and start the DAC block. Subsequent data copy from the file to buffer are handled in the End Of Buffer interrupt:

When no more data can be read from the file, the End Of File callback is called to notify the client application. This callback is provided by the client when calling the Player_start API (notify_eof).

The routine also performs the sample conversion if the file contains 16-bit samples.

Player performance

The following sampling rate are currently supported: 8kHz, 16kHz, 22.05kHz and 44.1kHz. Mono and stereo files can be played. As the DAC plays only 8-bit samples, 16-bit per sample files are converted to 8-bit samples when reading from the audio file.

The playback has been successfully tested with files up to 44.1kHz 16-bit mono files with a 16MHz clock. With 44.1kHz 16-bit stereo files, underflows are happening (To be investigated later to see if it can be supported with some optimization…)

The circuit

The audio outputs are connected to an active amplifier through a stereo jack connector. Capacitors are placed after the RC filters to remove the DC components of the analog signal.

A stereo potentiometer allows to control the level of both audio channels.

Here is the circuit schematic:

Demo applications

I coded two demo applications to illustrate possible use cases:

  • Shuffle: the application automatically plays the files in the root directory of the SD card. When the button 0 is pushed, the application randomly plays the next file.
  • Trigger: the playback of a predefined file is assigned to each push-button.

As the playback is fully handled with interrupts, the mainloop in those demos is only responsible for the push-button polling and to start/stop the playback depending on the use case.

Testing the demos

Go in the apps/shuffle or apps/trigger subdirectory and type make.
Upload the resulting hex file with the Teensy loader.
Copy some WAV file to an SD card root directory and power-on the hardware.

Here is the result:

Shuffle playback demo

Button-triggered playback demo

Source code

The source code and demo binaries can be downloaded from bitbucket.org.

Source: http://bitbucket.org/elasticsheep/teensy2-usb-wavplayer/

Archive: http://bitbucket.org/elasticsheep/teensy2-usb-wavplayer/get/V2.zip

Binaries: shuffle-ref-V2.hextrigger-ref-V2.hex

To my few readers

Any comment is welcome: if you learned something, if the code has been useful to a project of yours or if there is an error, leave a message ;)

→ 11 CommentsTags:·····

Macbook pro french keyboard with Ubuntu 9.10

May 7th, 2010 · Uncategorized

After having installed Ubuntu 9.10 in a virtual machine, I have wasted two days wrestling with the keyboard layout configuration (where is the | ? where are the { and the @ ? Arghh !!!). I was almost on the verge of switching permanently to a Terminal.app ssh session connected to the VM ;) .

So after so much googling and poking in the preferences, here are the bits to remember for the next installation, in french and in english for my international readership. My MBP model is a MacBook Pro 2,2. The VM is VMWare Fusion 3.

English version

Disable the VMWare Fusion remapping: Preferences/Keyboard and Mouse, Disable “Enable key remapping for language”.

In Ubuntu, go to System/Preferences/Keyboard/Layouts:

  • Choose the Generic 105-key (Intl) PC keyboard model (DON’T use Apple/Macbook Pro !!!)
  • Add the layout: France Macintosh layout.
  • Layout Options:
    • Alt/Win key behavior: Control is mapped to Win key
    • Key to choose 3rd level: Left Alt (to enable access to | and ~).

En français

Désactiver le remapping clavier de VmWare Fusion: Préférences/Clavier et Souris, désactiver “Activer le mappage de touche pour les langues”.

Dans Ubuntu, aller dans le menu Système/Préférences/Clavier/Agencements:

  • Modèle du clavier: PC générique 105 touches (Ne pas utiliser Apple/MacbookPro !!!)
  • Ajouter l’agencement: France-Apple Macintosh
  • Options de l’agencement:
    • Comportement des touches Alt/Logo: La touche Ctrl est obtenue avec la touche Logo.
    • Touche sélectionnant le troisième niveau: Alt Gauche (Pour atteindre | et ~).

It looks like the Alt key is now missing, but I don’t need it for the moment.

→ 7 CommentsTags:···