Asterisk on an Atcom IP01


Oct 2012: I would recommend a SheevaPlug/RaspberryPi + Obi110 instead of the Atcom IP01 for the following reasons:

This article contains information on how to work with the Atcom IP01 Asterisk appliance based on a project by David Rowe. The unit I ordered came with a single FXO module so as to connect it to an analog phone line, and used David's modular BAPS packaging system (ŕ la OpenWrt) which is different from the Astfin/Switchfin solution that includes everything into a single binary image.

As of June 2009, this device uses the BlackfinOne BF532 board using a Blackfin ADSP-BF532 CPU, 64MB RAM+ 256MB NAND flash RAM + 2MB SPI Flash, and runs uCLinux (short for "Micro Controller Linux") instead of the standard Linux because the Blackfin has no Memory Management Unit (MMU). You can learn more about what the lack of MMU means and the differences between run-of-the-mill Linux and uClinux in the following articles: Differences between µClinux and Linux, Blackfin, uClinux for Linux Programmers, and Why is Malloc Different Under uClinux?.

When an application running under uClinux crashes, it might leave RAM in a poor state and it is recommended to reboot the appliance.

As the Blackfin boot ROM can't read the Linux kernel directly off the NAND, the Atcom uses a 256KB SPI flash chip (Serial Peripheral Interface) to hold the Uboot bootloader, which is able to read the NAND to copy the Linux kernel to RAM. When using "root=/dev/mtdblock0", this is a RAM-based root filesystem, while "root=/dev/mtdblock2" is the second partition in the NAND.

Note that the label of /dev/mtd0 is "ROMfs", but it's actually a device in RAM that uses the romfs filesystem as the initial ram disk, ie. this tiny RAM-based filesystem is concatenated to the kernel, so that you can safely erase and rewrite the NAND with a real, full filesystem.

FYI, "µClinux a.k.a. uClinux-dist, is a Linux distribution like any other Linux distribution, built from the Linux kernel from and assorted other packages, and software from the GNU project. Since µClinux is optimised for size, it uses more compact alternatives (busybox, uclibc, etc) than a non-embedded distribution."
Since Blackfin uClinux-dist is meant to be used with any Blackfin-based appliance, uClinux-dist-based alternatives AstFin and Switchfin had to include telephony applications such as Asterisk + Zaptel/Dahdi.

"Buildroot is a set of Makefiles and patches that allows you to easily generate a cross-compilation toolchain, a root filesystem and a Linux kernel image for your target. Buildroot can be used for one, two or all of these options, independently.
Buildroot is useful mainly for people working with embedded systems. Embedded systems often use processors that are not the regular x86 processors everyone is used to having in his PC. They can be PowerPC processors, MIPS processors, ARM processors, etc.
A compilation toolchain is the set of tools that allows you to compile code for your system. It consists of a compiler (in our case, gcc), binary utils like assembler and linker (in our case, binutils) and a C standard library (for example GNU Libc, uClibc or dietlibc)."

Note that if you use the Atcom exclusively with digital devices and make sure all SIP devices use the same codec (ie. with no need to perform translation), the Blackfin is a questionable choice since its being a DSP offers no added-value compared to more standard CPUs with an MMU, which have the advantage of requiring less or no application rewrites. In this case, consider other compact, embedded devices like Alix boards, the SheevaPlug, Buffalo (eg. WZR-HP-G300NH) or Linksys (eg. WRT54GS) routers, the Seagate FreeAgent Dockstar NAS, or even some thin clients like HP's 55xx series.

Note that Freeswitch, the alternative to Asterisk, doesn't (yet?) support Blackfin processors, although someone was able to compile and run FS on a Planex router and the uClinux-based OpenWrt firmware.

Finally, when it comes to getting help, you should know that...


Note: The MTD utilities can be installed on the workstation with "# apt-get install mtd-utils".


"The memory is arranged as an array of pages. A page consists of 256 / 512 Byte data and 8 / 16 Byte spare (out of band) area. Newer chips have 2048 Bytes data and and 64 Bytes spare area sizes. The spare area is used to store ECC (error correction code), bad block information and filesystem-dependent data. n pages build one block. The read / write access to data is on a per page basis. Erase is done on a per block basis. The commands to read / write / erase the chip is given by writing to the chip with the Command Latch Enable pin high. Address is given by writing with the Address Latch Enable pin high.

[...] UBI stores 2 small 64-byte headers at the beginning of each non-bad physical eraseblock:

This is why logical eraseblocks are smaller than physical eraseblock - the headers take some flash space.

[...] Flash reads and writes may only be done in portions of minimum input/output unit size, which depends on flash type: NAND flashes usually have 512, 2048 or 4096 byte min. I/O. unit size, which corresponds to NAND page size. NAND flashes store per-NAND page ECC codes in the OOB area, which means that whole NAND page has to be written at once to calculate the ECC code, and whole NAND page has to be read at once to check the ECC code.

[...] When working with UBI, it is important to realize that UBI stores erase counters on the flash media. Namely, each physical eraseblock has so-called erase counter header which stores the amount of times this physical eraseblock has been erased (see here). And of course, it is important not to lose the erase counters, which means that the tools you use to erase the flash and to write UBI images have to be UBI-aware. The mtd-utils repository contains the ubiformat utility which takes things right, instead of using flash_erase, dd, or nandwrite.

[...] UBIFS works on top of UBI volumes and cannot operate on top of MTD devices

Avoid formating an empty flash before running UBI on top of it, as you lose erase counters (wearing information) every time you erase the flash. Try to use UBI-aware utilities and flashing programs, eg. ubiformat /dev/mtd0

The ubinize utility uses a configuration file that describres all UBI volume(s) which the image has to contain".

Find NAND hardware information

Before flashing the NAND with a root filesystem, you'll need the following informations that are provided by the mtdinfo utility:

From those, you can compute the Logical erase block (LEB) used by Ubi(fs).



Ubi works with raw devices such as NAND, ie. those that don't have firmware to provide block-based access through FTL. UBI maps logical eraseblocks to physical eraseblocks, and provides wear-leveling and transparent I/O errors handling.

A UBI volume is a set of consecutive logical eraseblocks (LEBs). Each logical eraseblock may be mapped to any physical eraseblock (PEB). UBI volume size is specified when the volume is created and may later be changed.

UBI volumes can be static or dynamic, ie. they may be created, removed or re-sized dynamically, while MTD partitions are static.

Important UBI applications:

Adding Ubi to menuconfig

Memory Technology Device (MTD) support > UBI - Unsorted block images > <*> Enable UBI

Add support for Ubifs filesystem.

Device nodes

For Ubi(fs), it is recommended to run "mdev" and let it create device nodes dynamically instead of listing device nodes statically in device_table.txt.

  1. make config_menuconfig

    Miscellaneous Configuration > Device Nodes (Dynamic)

    BusyBox > Linux System Utilities
    [*] mdev
    [*]   Support /etc/mdev.conf
    [ ]     Support subdirs/symlinks (NEW)
    [ ]     Support command execution at device addition/removal (NEW)
    [ ]   Support loading of firmwares (NEW)
  2. vi /usr/src/uClinux-dist-2010R1-RC5/vendors/Rowetel/IP04/mdev

    # Start up file for mdev

    case $1 in
            start) echo "Starting mdev...";
            echo /sbin/mdev > /proc/sys/kernel/hotplug;
            /sbin/mdev -s;

            stop) killall -9 mdev;;
            enable) rm -f /etc/rc.d/S20mdev;
            ln -s /etc/init.d/mdev /etc/rc.d/S20mdev;;
            disable) rm -f /etc/rc.d/S20mdev;;

            *) cat <<EOF;;

    Syntax: /etc/init.d/mdev [command]
    Available commands:
            start   Start the service
            stop    Stop the service
            enable  Enable service autostart
            disable Disable service autostart
  3. vi /usr/src/uClinux-dist-2010R1-RC5/vendors/Rowetel/IP04/Makefile

    $(ROMFSINST) /etc/init.d/mdev
    $(ROMFSINST) -s /etc/init.d/mdev /etc/rc.d/S20mdev

Alternatively, here's how to create nodes manually:

mknod /dev/ubi_ctrl c 10 63
mknod /dev/ubi0 c 253 0

Upgrading just the kernel

Couldn't figure out how to get a running kernel without attached ext2 root filesystem.

First, boot up and run mtdinfo -a to check the size of the mtd1 partition

  1. ip04> set autostart
  2. ip04> tftp 0x1000000 uImage

    Note the size of the image in hexa, eg. "Bytes transferred = 3670016 (380000 hex)"
  3. ip04> nand erase clean 0x0 <size of mtd1>
  4. ip04> nand erase 0x0 <size of mtd1>
  5. ip04> nand write 0x1000000 0x0 0x380000

Important: "nand" expects numbers to be in hexa.

Creating Ubifs root filesystem

On the workstation

Compile uClinux mtdinfo

On the Atcom

  1. Download and run mtdinfo /dev/mtd2 -u
  2. Write down "Default UBI LEB size" (UBIFS_LEB_SIZE) + "Amount of eraseblocks" (UBIFS_MAX_LEB_CNT) + "Minimum I/O unit size" (UBIFS_MIN_IO_SIZE), where the total size of the partition is Eraseblock size * Amount of eraseblocks

On the workstation

  1. vi vendors/AnalogDevices/vendor.mak

    UBIFS_MIN_IO_SIZE ?= 2048
    UBIFS_LEB_SIZE    ?= 129024
    UBIFS_MAX_LEB_CNT ?= 1984
  2. vi ubi.cfg

  3. ubinize -o rootfs.ubi.img -m 2048 -p 128KiB -s 512 ./ubi.cfg
  4. mv rootfs.ubi.img /var/www

On the Atcom

  1. Boot with a RAM-based root filesystem
  2. wget -c
  3. ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img
  4. ubiattach /dev/ubi_ctrl -m 2
  5. mount -t ubifs ubi0:rootfs /mnt

    Note: "rootfs" is set in ubi.cfg

If mounted OK:

  1. umount /mnt
  2. ubidetach /dev/ubi_ctrl -m 2
  3. reboot
  4. uboot> set bootargs ubi.mtd=2 root=ubi0:rootfs rw rootfstype=ubifs

Mounting a Ubifs partition

  1. First, attach the MTD partition to Ubi: ubiattach /dev/ubi_ctrl -m 2 (2 = mtdblock2)
  2. To create /dev/ubi0: mdev -s
  3. Check Ubi infos: ubinfo /dev/ubi0 -a
  4. NOT NEEDED AFTER FIRST TIME? ubimkvol /dev/ubi0 -m -N ubifs0
  5. mount -t ubifs ubi0:rootfs /mnt
  6. umount /mnt
  7. ubidetach /dev/ubi_ctrl -m 2
  8. reboot

Do not worry about "UBIFS: recovery needed" after rebooting: /bin/reboot takes care of calling sync() before rebooting, so the Ubifs partition should be left in a stable state.

If you'd rather that uClinux unmount the Ubifs partition before rebooting, replace the default simpleinit with Busybox's init and include the "poweroff, halt, and reboot" option, More information here.


Updating to a new firmware

Tips for newbies

Here are standard variables that you can use in Makefiles to compile files as ELF FDPIC (instead of FLAT):

#Assuming the Blackfin toolchain is untarred there
export PATH:=$(PATH):/opt/uClinux/bfin-linux-uclibc/bin
export CC=$(TARGET_CROSS)gcc
export STRIP=$(TARGET_CROSS)strip
export AR=$(TARGET_CROSS)ar rcu
export RANLIB=$(TARGET_CROSS)ranlib
#Download and untar uClinux-dist for apps that need it
#Compile uClinux to get binaries
export STAGING_DIR=/usr/src/uClinux-dist/staging
export UCLINUX_LIB=/usr/src/uClinux-dist/lib
export UCLINUX_ROOT_LIB=/usr/src/uClinux-dist/root/lib
export CFLAGS=-O2 -Wall -pedantic -I$(STAGING_DIR)/usr/include
export LDFLAGS=-L$(STAGING_DIR)/usr/lib -L$(UCLINUX_LIB) -L$(UCLINUX_ROOT_LIB) add_required_libraries_here

To compile a static library:

$(AR) rcu -static -o libmylib.a mylib.o mylib2.o
#ranlib not always needed, but it doesn't hurt
$(RANLIB) libmylib.a

To compile a shared library:

$(CC) $(CFLAGS) -shared -Wl,-E,-soname, -o mylib.c

To call AutoTool's configure to compile a C application:

export PATH=$PATH:/usr/src/baps/opt/uClinux/bfin-linux-uclibc/bin
./configure --host=bfin-linux-uclibc CC=bfin-linux-uclibc-gcc AS=bfin-linux-uclibc-as CFLAGS="-O2 -Wall -ansi -pedantic -I/usr/src/uClinux-dist/linux-2.6.x -I/usr/src/uClinux-dist/staging/usr/include " LDFLAGS="$LDFLAGS -L/usr/src/uClinux-dist/staging/usr/lib" AR="bfin-linux-uclibc-ar rcu" RANLIB=bfin-linux-uclibc-ranlib

The same, to compile a C++ application:

./configure --host=bfin-linux-uclibc CPP=bfin-linux-uclibc-cpp CXX=bfin-linux-uclibc-g++ CC=bfin-linux-uclibc-gcc

Testing an image

You don't have to burn a new image just to try it and see if it works. Here's how to set things up:

  1. Now is the time to save any data out of the Atcom, in case they get removed/overwritten...
  2. On a workstation, run a TFTP server and put the image in its data directory (for Windows, you can try the open-source Tftpd32 )
  3. Connect a serial cable to the Atcom and reboot
  4. Hit any key to prevent Uboot from loading Linux, and type the following commands:

    #Disable autoloading of kernel
    set autostart
    set serverip tftpd.server.address
    set bootargs ethaddr=atcom.MAC.address root=/dev/mtdblock0 rw
    #Save params to EEPROM
    tftp 0x1000000 myimage
    bootm 0x1000000 

Important: Astfin-based images from Atcom are hard-coded to use mtd2 to save persistent data, even if you just wanted to test an image...

If the image works OK, reboot the Atcom, enter Uboot, and type the following commands to burn the image in the NAND:

nand erase clean
nand erase

set autostart
tftp 0x1000000 uImage

;tftp gives image size in "Bytes transferred": Use this info as the last parameter below, using the next 20.000 increment to make sure it fits:
nand write 0x1000000 0x0 0x300000
;alternatively, use the "filesize" variable
nand write 0x1000000 0x0 ${filesize}

set autostart yes


Switchfin is a fork of the AstFin2 project by the SwitchVoice people that compiles a full binary image of the uClinux OS, and optionally Asterisk, Dahdi and some other software (ls /usr/src/switchfin/package/).
Its makefile will take care of downloading the Blackfin toolchain, uClinux, and uClibc, and by default, generate both the image and the bootloader.

What I don't like about Switchfin:


There are three ways to update an Atcom already running Switchfin:

Creating a new image

Here's how to compile the latest source from SVN on an x86 Ubuntu 10.04 host:

  1. apt-get update
  2. apt-get upgrade (reboot with new kernel, if applicable)
  3. Install prerequisites: apt-get install autoconf automake bash binutils bison bzip2 coreutils flex gawk gcc gettext grep intltool iputils-ping libtool libz-dev linux-libc-dev liblzo2-dev liblzo2-2 libncurses5 libreadline5 libreadline5-dev libncurses5-dev ncurses-dev m4 make pax-utils pkg-config rpm texinfo zlib1g zlib1g-dev subversion mtd-utils uuid-dev uuid unzip build-essential

    Note: On Linux Mint, libreadline5-dev has been replaced with libreadline-gplv2-dev
  4. cd /usr/src
  5. svn co switchfin
  6. cd switchfin
  7. make menuconfig

    Note: Include "SpanDSP based CallerID", or libspandsp won't be built while it's expected by Asterisk
  8. make
  9. vi build_ip01/uClinux-dist/lib/libcurl/Makefile: If it refers to, change this for ; make
  10. make image: Output will be found in eg. ./build_01/image_01/ (more infos):
  11. cp build_ip01/image_ip01/uImage /tftpboot

In case you need them, binaries are located under build_ip01/image_ip01/.

Make sure a web server is running on the workstation, with its docroot set to "/tftpboot". If the Atcom is already running AstFin or Switchfin with the Asterisk GUI, just aim your browser to its web server, log on as admin/switchfin, locate Firmware Update, and copy/paste the full URL to uImage-md5 on the workstation. Reboot the Atcom, and check that it's using the new firmware.

If there's no GUI available, follow the instructions above to download the image through TFTP after copying the image in the /tftpboot on the workstation:

  1. Connect the Atcom to the workstation through the serial cable
  2. Unplug, replug the Atcom, and hit any key to prevent it from booting Linux
  3. Type the following commands (stuff in bold must be customized to fit your setup):

    setenv autostart
    setenv ipaddr
    setenv netmask
    setenv gatewayip
    setenv serverip
    setenv bootargs ethaddr=Atcom.MAC.address console=ttyBF0,115200 root=/dev/mtdblock0 rw
  4. Download the image in RAM, and check its size ("Bytes transferred = 7471104 (720000 hex)):

    tftp 0x2000000 uImage

    Note: If the Atcom can't fetch the image, unplug and replug its Ethernet cable, and give it another try.
  5. Check that the image works OK by booting it directly from RAM:

    bootm 0x2000000

    Log on as root/uClinux
  6. IF OK, redownload image and save it to EEPROM:

    nand erase clean
    nand erase
    nand write 0x2000000 0x0 0x720000
    setenv autostart yes

Note that unlike the BAPS firmware, Switchfin keeps the root filesystem in RAM and uses the NAND to save persistent files like sound files, etc. Consequently, only 40MB out of 64MB is available in RAM once Switchfin is up and running.

If you get the error "couldn't allocate a block (no free space)", it means your uImage is now to big, you need to enable "Cull unused ELF shared libraries" in the Build options, or remove some applications when running "make menuconfig" or the built files in the root filesystem. Alternatively, you can increase the space reserved for the root filesystem by editing /package/uClinux-dist/vendors/SwitchVoice/vendor.mak to change the EXT2_BLOCKS variable before running "make image".

Post-install tweakings


If you get "ping: bad address ''", check that the IP address is OK: ifconfig. If not: ifconfig eth0, and connect to the Atcom's web GUI to change its IP configuration (Admin > Network settings). Click on Reboot when prompted.

Alternatively, the network configuration can be changed by editing /etc/asterisk/rc_org.conf which Switchfin uses to overwrite /etc/network.conf at boot-time.

By default, Switchfin provides an SSHd server (dropbear), so you can also connect to the Atcom through SSH instead of the serial port



#For Central European Time
TIMEZONE = CET-1CEST,M3.5.0/2,M10.5.0/3
#For France
NTPserver =

Note: The reason those settings are located in /etc/asterisk is so they are accessible from the the Asterisk Management Interface (AMI). rc_org.conf is mapped to network.conf via the /etc/rc script.

Boot errors

If you see error messages related to dahdi/vlan "Permission denied":

chmod +x /persistent/etc/init.d/dahdi
chmod +x /persistent/etc/init.d/vlan

/persistent/etc/init.d/dahdi disable
/persistent/etc/init.d/vlan disable

rm /persistent/etc/rc.d/S55vlan

/persistent/etc/init.d/dahdi enable
/persistent/etc/init.d/vlan enable
ls -al /etc/rc.d/


Check that the problem went away


/etc/init.d/asteriskwatch calls procwatch, which reboots the host if asterisk isn't running. You can disable this while you're configuring asterisk:

/etc/init.d/asteriskwatch disable


Switchfin uses Dahdi instead of Zaptel. Its configuration file is located in /etc/dahdi/system.conf. The equivalent of zapata.conf is /etc/asterisk/chan_dahdi.conf.


To enable full logging for debugging:


How to Load u-boot in the hardware?

Can I load the uImage using the web GUI

"In the PBX GUI go to 'Firmware upgrade' (in the advanced options section) and select HTTP URL": Is it the same as the VoIPTel CE web GUI?

Can I load the uImage manually using u-boot?

Uprading an Atcom appliance that was installed using BAPS

Here's what the Switchfin tree contains after downloading the latest SVN code:

Next, running "make menuconfig" adds the following two files in the root directory:

Next, "make" will download and install the Blackfin uClibc toolchain, followed by the uClinux distribution.

Trying Switchfin 2010

  1. cd /usr/src
  2. svn co switchfin-2010R1-RC5
  3. cd switchfin-2010R1-RC5
  4. make menuconfig
  5. make
  6. make image

Cross-compiling Yate

  1. Cross-compiling: Put settings in Bash script before calling configure
  2. Make: Edit fork() -> vfork() if needed
  3. Compile
  4. Install and configure: What files are required where?
  5. Check that it works with the FXO module: Does it need Zaptel?
From the original source
  1. Install the toolchain + uclibc
  2. cd /usr/src
  3. svn checkout yate
  4. cd yate
  5. ./
  6. Create a Bash script to pass parameters to "configure":





    YATE_CONFIGURE_OPTS=--host=${TARGET} --prefix=/usr --sysconfdir=/etc --with-openssl=${STAGING_INC}/.. --with-libspeex=${STAGING_INC} --with-zlib=${STAGING_INC}/.. --enable-dahdi --disable-zaptel --disable-wpcard --disable-tdmcard --disable-wanpipe --enable-ilbc --disable-rtti --without-libpq --without-mysql --without-libgsm  --without-amrnb --with-spandsp --without-pwlib --without-openh323 --without-libqt4

  7. chmod +x myconfig.bash
  8. ./myconfig.bash
  9. make

This is a Bash script to compile Yate for ARM:

Adding Yate to Switchfin as an alternative to Asterisk

Note: By now, patches should be part of Switchfin, so this is no longer needed

  1. cd /usr/src
  2. git clone hayden-switchfin
  3. wget -O - | patch -p1
  4. make menuconfig: Check "Yate"
  5. make

BAPS as alternative to buildroot (Switch/Astfin/uClinux-dist)

The very first build of Asterisk for the BlackFin processor was a hack of OpenWRT called uCasterisk, ie. it used the same buildroot approach ("uClinux is the distribution of choice for Media and other embedded products. OpenWrt on the other hand is the distribution of choice for building a router." source)

"There are two commonly used build systems for Blackfin Asterisk, Astfin and BAPS. Astfin builds a single image containing all software, whereas BAPS is a package-based build system (like apt-get or rpm). It is easy to move between Astfin and BAPS (they both use similar Makefiles), so feel free to experiment with both." (source)

As of January 2011, when using the Makefile, you will use the 2007 version of the uClinux-dist software just to build the kernel with a few applications pre-installed, including the ipkg application which lets the user download and install packages, just like RPM and apt-get. As a result, a standard BAPS image from Rowetel is only 2MB, while a standard uClinux-dist image is about 7MB.

AstFin is a rewrite of uCasterisk. At some point, AstFin stalled and BAPS packages picked up. As of June 2010, AstFin2 is apparently headed in a different direction than just Asterisk, so some developers forked the code to Switchfin.

Here is a comparison of BAPS and AstFin2, and here is a list of BAPS packages. BAPS also comes from the OpenWrt world (ipkg).

Note that the Uboot that ships with BAPS Atcom is very compact, and doesn't include commands like "mtdparts".

The reason the BAPS software require(d) to first boot Linux entirely in RAM, copy the RAM root filesystem to NAND, and reboot is because of this bug in mkyaffs. can build different images, such as "make -f uClinux.mtd0.ip01" which is for the Atcom IP01 and has root=/dev/mtdblock0 hard-coded so it uses a RAM-based root filesystem.

Upgrading BAPS-based firmware

Here's how to upgrade an Atcom currently running a Astfin/Switchfin-based firmware to a BAPS-based firmware:

  1. Connect to the Atcom through SSH
  2. cd /persistent
  3. wget
  4. dd if=uImage_r2.mtd0.ip01 of=/dev/mtdblock1
  5. reboot

Once back in BAPS as root, the unit uses as its IP address. To have it configured through DHCP instead, see below.

Building your own BAPS uImage

Based on this article. Note that unlike other *.mk files, doesn't create an ipkg package but a Uboot-compatible, binary image that contains just the Linux kernel and a few basic applications (shell, ipkg, etc.).

  1. Install prerequisites
  2. cd /usr/src
  3. svn co baps
  4. cd baps
  5. wget -c
  6. tar xzf blackfin-toolchain-07r1.1-3.i386.tar.gz
  7. (if not starting from scratch) make -f uClinux-clean
  8. make -f uClinux
    This will download, patch, and compile the uClinux-dist source code.

    To solve a possible PATH_STR error:

    vi uClinux-dist/linux-2.6.x/scripts/mod/sumversion.c
        add "#include <limits.h>"
  9. cp uClinux-dist/images/uImage /tftpboot/uImage
    (uImage = uImage.ext2) 
  10. Reboot the Atcom and test/burn this new image as explained below
To try out new image directly
  1. ip04> set autostart
  2. ip04> setenv ipaddr
  3. ip04> setenv netmask
  4. ip04> setenv gatewayip
  5. ip04> set bootargs ethaddr=$(ethaddr) root=/dev/mtdblock0 rw
  6. ip04> setenv serverip

    serverip = address of TFTP server from which image will be dowloaded
  7. ip04> save
  8. ip04> tftp 0x1000000 uImage
  9. ip04> bootm
To save new image into NAND
  1. (In uClinux) # reboot
  2. ip04> set autostart
  3. ip04> tftp 0x1000000 uImage
  4. ip04> nand erase clean
  5. ip04> nand erase
  6. ip04> nand write 0x1000000 0x0 0x300000
  7. ip04> set bootargs ethaddr=Atcom.MAC.address root=/dev/mtdblock0 rw
  8. ip04> save
  9. ip04> reset

uClinux is running but using a RAM-based ext2 root file system (mtdblock0). To make it persistent, we must copy /root into /dev/mtdblock2 in the NAND:

  1. root:~>
  2. root:~> reboot

Next, set up u-boot to mount the root filesystem from /dev/mtdblock2 (type "print" to check what env variables are already set, if any):

  1. ip04> tftp 0x1000000 uImage
  2. ip04> set nandboot 'nboot 0x1000000 0x0'
  3. ip04> set bootcmd run nandboot
  4. ip04> set bootargs ethaddr=Atcom.MAC.address root=/dev/mtdblock2 rw
  5. ip04> set autostart yes
  6. ip04> save
  7. ip04> reset
  8. Let the Atcom reboot and load uClinux

Install packages through ipkg (repository address in /etc/ipkg.conf):

  1. root:~> ipkg update
  2. root:~> ipkg list
  3. root:~> ipkg install zaptel-ip01
  4. root:~> ipkg install asterisk-1.4.20
  5. root:~> ipkg install dropbear
  6. root:~> ipkg install ntp
  7. root:~> ipkg list_installed
  8. root:~> reboot


Building BAPS 2008

In case you previously compiled 2007, make sure you rename uClinux-dist to eg. uClinux-dist2007 and opt/uClinux to opt/uClinux2007.

  1. cd /usr/src
  2. svn co baps
  3. cd baps
  4. wget -c
  5. wget -c
  6. tar xzvf blackfin-toolchain-08r1-8.i386.tar.gz
  7. tar xzvf blackfin-toolchain-uclibc-default-08r1-8.i386.tar.gz
  8. make -f uClinux

In case you want to check how long compiling takes, edit /usr/src/baps/ thusly:

echo 'date' > time.txt

echo 'date' >> time.txt

Customizing kernel and/or applications

If some applications aren't available as ipkg packages but are available in the uClinux-dist version downloaded by the file (2007), you can customize settings this way, before compiling a new image and find the compiled files under /usr/src/baps/uClinux-dist/root:

For the kernel: cd uClinux-dist ; make linux_menuconfig

For applications: cd uClinux-dist ; make config_menuconfig

Once done, cd /usr/src/baps/ ; make -f uClinux-clean ; make -f uClinux

If the application isn't available in that old version of uClinxux-dist, download the latest from Blackfin's site and try to compile it with either the 2007 version of the toolchain or, if it doesn't work (likely) with the latest version of the toolchain, and see if the application works OK on an older uClinux kernel. If it complains of missing libraries, start by checking its inner-most Makefile and try to add the missing stuff to its LDFLAGS variable.

Things to try in BAPS

Connect the Atcom to a hub through the WAN interface, and telnet to it from a PC. By default, the Atcom is set up to use, and no username/password is required to telnet to it (to add a username + password, install the "login" package, whose default combo is root/uClinux).

Playing with ipkg

ipkg update

ipkg upgrade

ipkg list //uninstalled packages available in repo

ipkg info mypackage

ipkg install mypackage

ipkg status mypackage

ipkg list_installed //packages already installed in host

ipkg files mypackage

ipkg remove mypackage

Note: The wildcard character "*" is allowed, eg. "libstd*".

Installing DropBear (SSH server/client)
  1. ipkg install dropbear

    DropBear is launched through Inetd: cat /etc/inetd.conf ; netstat -natp
  2. Log on as root/uClinux

If you get errors in the log file:

  1. touch /var/log/lastlog
  2. touch /var/log/wtmp
To set the date/time

First, install ntp:

  1. ipkg install ntp
  2. vi /etc/init.d/ntp: Change for NTP servers close to you, eg. "" for France
  3. /etc/init.d/ntp enable

By default, time is displayed as UTC. To display the time correctly, "date" provided by Busybox 1.4.1 reads it localization through /etc/TZ, which is copied to /etc/profile and exported as environment variable by the /etc/init.d/ntp script:

For Central European Time, vi /etc/TZ to this:

  1. CET-1CEST,M3.5.0/2,M10.5.0/3
  2. reboot
  3. run "date", and check that time is displayed OK

If you can't reboot because you're running a test image in RAM, here's how to change the current date/time for your location:

  1. ntpdate
  2. export TZ=CET-1CEST,M3.5.0/2,M10.5.0/3
  3. date

More information here.

Adding CRON jobs

I couldn't get "ntpd" to work, so resorted to running ntpdate every hour through a CRON job:

  1. ipkg install cron
  2. vi /etc/config/crontab

    #BAD @hourly root /sbin/ntpdate -s -b -p 8 -u
    0 * * * * root /sbin/ntpdate -s -b -p 8 -u
  3. /etc/init.d/cron enable
  4. /etc/init.d/cron start
  5. tail -f /var/log/messages, and wait about a minute for cron to re-read its contrab automatically

By default, syslogd will output "-- MARK --" every 20mn to /var/log/messages. syslogd is actually provided by Busybox, and this version ignore /etc/syslog.conf.

  1. vi /etc/inittab

    slog:unknown:/bin/syslogd -n -m0
  2. reboot

If too much data in /var/log/messages, configure syslog to send data to remote syslogd server or /tmp (not good idea: No trace after rebooting) to save NAND.

To check network information

root:~> cat /proc/net/

To change the static IP settings

Edit /etc/init.d/network-static

To enable DHCP
  1. /etc/init.d/network-static disable
  2. /etc/init.d/network enable
  3. reboot

If the network link is down, unplug and replug the network cable that connects the Atcom to the hub/switch, and see if the unit gets an address from the DHCP. For some reason, the Atcom sometimes has its "link down".

To check the version of ucLinux

> uname -a

Linux ip04 #3 Mon Mar 10 08:53:41 CST 2008 blackfin unknown

> version

Linux release, build #3 Mon Mar 10 08:53:41 CST 2008

release 2007R1, build #13 Mon Mar 10 09:55:24 CST 2008

> cat /etc/issue

BlackfinOne BF532 v2 uClinux (

> cat /etc/firmwareversion

To change the root password
  1. perl -e 'print "crypt("yourpassword", "yoursalt")","\n"'
  2. copy/paste this new password in /etc/passwd
To transfer files to/from the Atcom

Use its FTP server by logging on as root/uClinux. wget is also installed by default.

Installing Lighttp + PHP + SQLite BAPS packages
  1. By default, the Asterisk web server is running on TCP80. To turn it off:

    vi /etc/asterisk/http.conf: enabled=no
    /etc/init.d/asterisk stop ; /etc/init.d/asterisk start
  2. To install Lighttp, PHP, and SQLite:

    ipkg install lighttpd
    ipkg install php
    ipkg install sqlite3
    ipkg list_installed
  3. Aim your browser at http://localhost/ to check that Lighttpd is up and running. You can also get information on PHP (http://localhost/test.php), and play with SQLite (http://localhost/testdb.php

    By default, Lighttpd starts with /etc/lighttpd.conf, and the document root is /www
  4. To configure Lighttp so as to use PHP for CGI calls:

    (to create a symlink in /etc/rc.d/)
    /etc/init.d/fastphp enable

    vi /etc/init.d/lighttpd: Change "-f /etc/lighttpd.conf" to "-f /etc/lighttpd-fastphp.conf"

    /etc/init.d/fastphp start

    /etc/init.d/lighttpd stop
    /etc/init.d/lighttpd start

    ps aux | grep -i php
  5. ls -al /etc/rc.d/, and make sure Lighttpd is started before the PHP FastCGI process
Installing Asterisk and Zaptel/Zapata

In case the Atcom didn't come with Asterisk preinstalled or you upgraded the image:

  1. ipkg list, and check what the latest Asterisk package is
  2. ipkg install asterisk-1.4.20
  3. ipkg install zaptel-ip01
  4. vi /etc/zaptel.conf: If not living in the US, edit as needed
  5. cd /etc/asterisk
  6. mv sip.conf sip.conf.orig
  7. mv extensions.conf extensions.conf.orig
  8. mv users.conf users.conf.orig
  9. vi sip.conf
  10. vi rtp.conf
  11. vi extensions.conf
  12. vi indications.conf
  13. vi asterisk.conf to move astlogdir to RAM-based /tmp instead of NAND-based /
  14. vi asterisk.conf to move astspooldir to RAM-based /tmp instead of NAND-based /
  15. vi /etc/init.d/asterisk

    #Killall might leave RAM in disarray
    stop) asterisk -rx "stop now";;
  16. /etc/init.d/asterisk enable
  17. /etc/init.d/asterisk start
  18. ps aux | grep -i asterisk
  19. asterisk -vvvvvvvvvvvvr
  20. sip show peers

You can edit modules.conf to avoid loading modules you don't need, eg.

noload => pbx_gtkconsole.c
noload => pbx_kdeconsole.c
noload => app_intercom.c
noload => chan_modem.c
noload => chan_modem_aopen.c
noload => chan_modem_bestdata.c
noload => chan_modem_i4l.c
load => res_musiconhold.c
noload => chan_alsa.c
noload => cdr_csv.c
noload => cdr_custom.c
noload => res_smdi.c
noload => chan_iax2.c
noload =>
noload =>
noload =>
noload => format_gsm.c
noload =>
noload =>
noload =>
noload =>
noload =>
noload =>
noload =>
noload =>
noload =>

I don't know why some modules in .c and others in .so.

By default, output from launching "asterisk -vvvc" is in reverse video, making it harder to read. To changed output to standard black text/white background, edit asterisk.conf, and add this:

Checking Asterisk

On the Atcom, run "asterisk -r" to connect to the console, and check log messages.

Connect to Asterisk from an SIP client, and dial either 2008 (play prompt) or 2020 (record your voice, and check performance).


ls -al /usr/lib/asterisk/modules/

root:~> cat /proc/modules

Managing sound files

ls -al /var/lib/asterisk/sounds/

ls -al /var/lib/asterisk/sounds/moh

Asterisk configuration files

They are located in the usual /etc/asterisk/. To restore its configuration files:

  1. root:~> ipkg update
  2. root:~> ipkg remove asterisk
  3. root:~> ipkg install asterisk
  4. root:~> reboot
Caller ID

Asterisk requires the asterisk-spandsp package to handle CallerID. To check if it's installed:

$ ipkg list_installed

If not, here's how to install it:

  1. $ /etc/init.d/asterisk stop
  2. $ ipkg remove asterisk
  3. $ ipkg install asterisk-spandsp
  4. $ reboot
Configuring Zaptel

To configure the Zaptel interface for your country, edit /etc/init.d/zaptel. Here's an example for Australia:

start) modprobe wcfxs opermode=AUSTRALIA;

root:~> ls -al /usr/doc/

-rw-r--r--    1 root     root         3142 May 31 01:56 zaptel.txt

root:~> cat /proc/zaptel/1

Adding extension to sip.conf
  1. tail /var/log/messages
  2. /etc/init.d/zaptel start
  3. vi /etc/asterisk/sip.conf

  4. /etc/init.d/asterisk start
  5. From an IP phone, connect to server with above account, and dial 1000
Writing a PHP script to handle call through Asterisk + AGI
  1. cd /var/lib/asterisk/agi-bin/
  2. vi myagiscript.php

    print "Hello, world!";
Building a new Busybox
  1. On the workstation, in /usr/src/baps, compile uClinux once to get its source tree: make -f uClinux.dist
  2. Remove object files: make -f uClinux-clean
  3. .. cd uClinux-dist, make config_menuconfig, and customize options for Busybox
  4. cd .. ; make -f
  5. If compiling went OK, you should have a new busybox in ./uClinux-dist/root/bin
  6. On the Atcom, download this file, "chmod 755 busybox" and move (not copy) it to /bin. There is no need to copy this file in /sbin, as /sbin is just a symlink to /bin
  7. In /bin, add the new symlinks, eg. "ln -s busybox unzip".

Atcom firmware

As of June 2010, Atcom provides the AstFin-based VoIPTel CE firmware (eg. IP01-0.3.7.ext2) so you can update the appliance.

Here's how to reflash an Atcom that used the BAPS packaging system; Since this firmware doesn't support a web GUI, we'll use a serial cable to download the latest firmware from a workstation:

  1. Hook up a DB9-DB9 male-female serial cable between the workstation and the Atcom
  2. On the workstation, install a TFTP server eg. TFTPd32, copy the ext2 Atcom image in its directory, and start the TFTPd server
  3. Still on the workstation, open a terminal application with the following settings:

    Choose the right COM port, 115200 bps, 8 data bits and no parity, hardware flow control off
  4. Reboot the Atcom
  5. Hit any key to prevent it from booting, and type the following commands (you'll have to type: The serial connection is too slow and will probably drop out some characters):

    ip04>setenv autostart
    ip04>setenv ipaddr
    ip04>setenv netmask
    ip04>setenv gatewayip
    ip04>setenv serverip

    ip04>tftp 0x1000000 IP01-0.3.7.ext2

    Here, I had a networking problem, where the Atcom couldn't connect to the TFTPd server. I had to unplug and replug the Ethernet cable connecting the Atcom to the hub

    ip04>nand erase clean
    ip04>nand erase
    ip04>nand write 0x1000000 0x0 0x700000

    ip04>setenv bootargs ethaddr=$(ethaddr) console=ttyBF0,115200 root=/dev/mtdblock0 rw (NOT mtdblock2, or you'll get a kernel panic)
    ip04>setenv autostart yes
    ip04>setenv nandboot 'nboot 0x2000000 0x0'
    ip04>setenv bootcmd run nandboot

  6. Reboot the Atcom, wait for the unit to download a zillion things and reboot, and check that it boots up OK:

    root:~> uname -a
    Linux IP0x #2 Wed Jun 9 03:00:41 EDT 2010 blackfin unknown

    root:~> cat /etc/issue
    BlackfinOne BF532 v2 uClinux (

    root:~> cat /etc/version
    Rowetel/IP04 Version 3.2.0 -- Wed Jun  9 03:02:13 EDT 2010

    root:~> cat /etc/firmwareversion
  7. If you want to have a DHCP server send an IP configuration to the Atcom (and use a local NTP server pool):

    > vi /etc/network.conf


    > reboot
    > ping
  8. Aim your browser at eg., and logon as admin / atcom
  9. If you'd rather connect to the appliance through SSH, use the serial connection to set a new root password, and then aim your SSH client to the appliance


How to add SSHd, vim, Lighttpd + Lua + SQLite?, CRON?
How to upgrade from VoIPTel CE to own compiled Switchfin or Blackfin uClinux?
How to add alias ll=ls -al?


The image will include uClinux and whatever options you chose:

  1. cd /usr/src
  2. svn co astfin2
  3. cd astfin2
  4. make menuconfig
  5. make
  6. make image
  7. To update the Atcom appliance, choose one of the two images available in /usr/src/astinf2/build_xx:

Blackfin uClinux-dist

As of June 2010, and unlike Astfin/Switchfin, the uClinux-dist available directly from the Blackfin subdomain of uClinux ( doesn't support the Atcom IP01, so the only reason to work with that version is to rip software that hasn't made it to to the Astfin/Switchfin tree. There are plenty of information in the Blackfin uClinux wiki.

Here's how to add support for the Atcom IP01 and compile uClinux-dist:

  1. Download and install the toolchain:
    1. cd  /
    2. wget -c
    3. tar xjvf blackfin-toolchain-2010R1-RC4.i386.tar.bz2
    4. Add toolchain to PATH:

      export PATH=$PATH:/opt/uClinux/bfin-linux-uclibc/bin:/opt/uClinux/bfin-uclinux/bin
      echo $PATH
      which bfin-linux-uclibc-gcc

      Note: To make this persistent in Linux Mint, edit /etc/environment
  2. Download and install the uclibc library:
    1. cd /
    2. wget -c
    3. tar xjvf blackfin-toolchain-uclibc-full-2010R1-RC4.i386.tar.bz2
  3. Download and install the uClinux-dist distribution:
    1. cd /usr/src
    2. wget -c
    3. tar xjvf blackfin-linux-dist-2010R1-RC5.tar.bz2
    4. mv blackfin-linux-dist uClinux-dist-2010R1-RC5
  4. cd /usr/src/uClinux-dist-2010R1-RC5
  5. Compare /usr/src/baps/patch/vendors/Rowetel/IP04-2008/* with /usr/src/uClinux-dist-2010R1-RC5/vendors/AnalogDevices
  6. mkdir -p vendors/Rowetel/IP04
  7. cp /usr/src/baps/patch/vendors/Rowetel/IP04-2008/* vendors/Rowetel/IP04
  8. vi


    #to avoid being prompted a bazillion times when running "make menuconfig"
    #the first time

    cp vendors/Rowetel/IP04/config.device .config
    chmod u+x config/setconfig
    yes "" | config/setconfig defaults
    config/setconfig final
  9. make menuconfig
  10. make

Compiling applications for Blackfin + uClinux


Converting an application so that it'll run OK on an MMU-less CPU like the Blackfin may require making changes to its source code (fixed point DTMF, absence of fork(), dynamic memory allocation causing memory fragmentation, etc.)

Toolchains from 2010R1 and above will no longer link applications that use fork() instead of vfork() and display the following error message: "undefined reference to `_fork'". This is due to its use of AC_FUNC_FORK in If an application you are trying to compile does handle fork/vfork, ????

More information: Porting Applications to uClinux and We have no Fork.

If an application does compile and start, what other issues, if any, are to expected besides memory fragmentation and can't be solved by running a watchdog application to reboot the system every night?

In case some applications don't behave and cause memory fragmentation, a work-around solution until the application has been debugged is to use the procwatch application to keep an eye on them, and also run nightly CRON job to reboot the device.

The toolchain contains two sets of binaries: One to compile source to FLAT format, and the other, to FDPIC ELF. If you are running a lot of applications with shared libraries, FDPIC ELF is a better choice since all the read-only sections get shared among all the applications; If you are running only a few applications, choose FLAT since only the functions they actually call will be compiled into the applications.

If a FLAT binary dies with either SEGV or BUS error, try to increase the size of its stack and give it another try:

bfin-uclinux-flthdr -s 0x20000 myapp

If the error goes away, you can recompile the FLAT binary with a bigger stack, using this option: bfin-uclinux-gcc -Wl,-elf2flt="-s 0x20000" application.c

To have the stack checked at runtime, you can compile a FLAT binary with either of those options:

The Blackfin toolchain comes in three variations, two of which are used to compile software for the uClinux OS and one to run without any OS:

"The uClinux FLAT executable format, though it doesn't directly affect applications and their operations, does allow quite a few options that the usual ELF executables under Linux do not. FLAT format executables come in two basic flavors, fully relocated and a variation of position-independent code (PIC). The fully relocated version has relocations for its code and data, while the PIC version generally needs only a few relocations for its data." (source)

"Program loaders which support Position Independent Code (PIC) have been added and a new binary object code format named FLAT, which supports PIC, was created. Other program loaders, such as that for ELF, have been modified to support other formats which, instead of using PIC, use absolute references. It is then the responsibility of the kernel to fix-up these references during run time. Both methods have advantages and disadvantages. Traditionally PIC is quick and compact but has a size restriction on some architectures. The runtime fix-up technique removes this size restriction, but incurs overhead when the program is loaded by the kernel." (source)

Bottom line: To compile stand-alone applications, ie. with all their libraries compiled statically into the executable, use FLAT; If the application relies on shared libraries, use ELF.

The toolchains install by default in /opt. Each of those groups contain the following tools:

To compile C file as FLAT file: bfin-uclinux-gcc -Wl,-elf2flt hello.c -o hello

To compile C file as FDPIC: bfin-linux-uclibc-gcc hello.c -o hello

You cannot mix FLAT and FDPIC ELF: Either both the library and the executable are compiled as FLAT, or they are both compiled as FDPIC ELF.

If you get an error such as "cc1: error: unrecognized command line option "-mcpu=bf518-0.0"", make sure you are using the latest toolchain + uClibc from Blackfin.

You can use this utility to remove debugging information from FDPIC ELF binaries:

bfin-linux-uclibc-strip hello

Also, before testing a new application, make sure another, different version isn't already installed in any directory listed in PATH...

As for variables in Makefiles:

Applications that rely on AutoTools instead of a static, plain Makefile provide a file where you can check which options are available for "--enable/with" and "--disable/without".

Common variables to use in Makefile:

WARN:= -Wall -Wmissing-prototypes -Wmissing-declarations -ansi -pedantic
#Compiling files as FDPIC ELF instead of FLAT
export PATH:=$(PATH):/opt/uClinux/bfin-linux-uclibc/bin
export TARGET_CROSS:=bfin-linux-uclibc-
export CC:=$(TARGET_CROSS)gcc
export STRIP:=$(TARGET_CROSS)strip
export AR:=$(TARGET_CROSS)ar rcu
export RANLIB:=$(TARGET_CROSS)ranlib

Here's a way to call Autotools' configure:

./configure --build=i686-pc-linux-gnu --host=bfin-linux-uclibc CC=/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-gcc CFLAGS="-O2 -Wall -pedantic -I/usr/src/uClinux-dist/linux-2.6.x/include -I/usr/src/uClinux-dist/staging/usr/include" AR="/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-ar" RANLIB="/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-ranlib"

Choose either "-std=c99" or "-ansi", but not both. Some programs won't compile when using the "-ansi" switch, so try removing it and recompiling.

Use build/host/targer thusly:

./configure --build=i686-pc-linux --host=i686-pc-linux --target=bfin-linux-uclibc

Note: --target is only needed when building the toolchain. You don't need this if you use the compiled toolchain from uClinux.

In case AutoTool doesn't include checking support for malloc, you can force the malloc configure thusly:

Using AutoConf's configure, it's possible to know which settings to enable/disable by checking the configure script and the Makefile it creates.

If libtool can't find libraries the application needs for compiling, you might have to modify

When compiling an application, if some libraries aren't available in the uClinux-dist used by your firmware, it might be available in other versions of uClinux-dist.

More information:

Packaging applications with ipkg (BAPS)


  1. Download uClinux-dist and check under user/ if the application has already been ported to uClinux. If that's the case, try to extract its Makefile and compile it manually before attempting to convert it to an ipkg package

    Note that BAPS uses the 2007 version of uClinux-dist, and an application that is part of a more recent release of uClinux-dist might not compile with that 2007 version of the toolchain. OTOH, the Blackfin uClinux-dist doesn't know anything about the Atcom. YMMV. 
  2. If not part of uClinux-dist, check the application's website to see if the application could be compiled to run on an MMU-less CPU like the Blackfin. If there's no indication, give it a shot anyway to see if it compiles, and test it extensively to see if it seems to run OK without leaking memory
  3. Check existing *.mk files as reference
  4. Check the application's home website for information on compiling/installing
  5. If you get run-time issues, download the latest toolchain, and use its "ldd" to check which shared libraries the application needs, if any, and make sure those libraries are available on the Atcom
  6. Use "#!/bin/sh -x" to debug post/pre inst scripts
  7. In case ipkg complains about MD5 mismatch: rm /usr/lib/ipkg/lists/snapshots

You can check what a Makefile does using "-d" (for "details"), -n" (dry-run), and both switches can be combined: Pretty useful to figure out how the whole thing works.

As of Jan 2011, information about ipkg is no longer available from the official source (, but you can learn more from its more recent variant opkg and by reading how it's used to build packages for the OpenWrt platform.

"An Opkg package is essentially a Debian package with fewer control fields. If you know how to make a Debian package, you should be well on your way. In general, a package is an ar archive containing a control tarball (text + script), a data tarball (binaries), and a debian-binary file (which simply contains the string 2.0)" (source)

More information:

opkg-utils is no longer maintained

Compiling an application into an ipkg package

A Hello, world sample can be found at It can then be compiled thusly:

  1. Compile binary and create package
    make -f hello-package
  2. Output can be found in tmp/hello/ and the ipkg package under /usr/src/baps/ipkg/

Here's an example of a .mk file to build a BAPS package for the Lua language:

#make -f
#======== Common to all applications
export CC = $(TARGET_CROSS)gcc
export CFLAGS = -DLUA_USE_LINUX -I$(UCLINUX_DIST) -I/usr/src/uClinux-dist/staging/usr/include
#Must first compile those libraries
export LDFLAGS = -Wl,-E -L$(STAGING_DIR)/usr/lib -lm -ldl -lreadline -lhistory -lncurses
#======== Application-specific stuff
#======== Compile application
all: lua
        make -C $(LUA_DIR)
        mkdir -p $(TARGET_DIR)/bin
        cp $(LUA_DIR)/lua $(TARGET_DIR)/bin/lua
        touch $(PKG_BUILD_DIR)/.built
#======== Build ipkg package
define Package/$(PKG_NAME)
        TITLE:=Lua 5.0.2 interpreter
        Just the interpreter.
# post installation
$(eval $(call BuildPackage,$(PKG_NAME)))
lua-package: lua $(PACKAGE_DIR)/$(PKG_NAME)_$(VERSION)_$(PKGARCH).ipk

Creating and using a repository


We'll assume the build host also runs the web server that will provide users with packages:

  1. cd /usr/src/baps/ipkg
  2. ../scripts/ . > Packages
  3. Copy Packages at the root of the web server's document directory
  1. Edit /etc/ipkg.conf: src snapshots http://server
  2. ipkg update
  3. ipkg list

Using opkg instead of ipkg

Development of ipkg was abandonned around 2008, but opkg, used in the OpenWrt world, is alive and well and is compatible with ipkg.

To keep the application as small as possible, I decided to compile opkg-cl without Curl and OpenSSL. But in case you need to...

Compiling Libcurl

"Opkg by default tries to link against libcurl. If you don't have libcurl, or disable it at configure time, then you will need wget installed."

  1. Download the latest Libcurl source code
  2. CC=bfin-linux-uclibc-gcc ./configure --build=i686-pc-linux-gnu --host=bfin-linux-uclibc
  3. make
  4. If you compile opgk-cl with shared libraries, on the Atcom, copy the library to /lib

Compiling OpenSSL

Note: is 1.317.955 bytes and is 258.818, for a total of 1.576.773 bytes

OpenSSL is part of uClinux-dist, so the includes/libs should be available and you should only need to point opkg to those directories for a successful build:

  1. /usr/src/uClinux-dist-2010R1-RC5# cp staging/usr/lib/ /var/www/
  2. /usr/src/uClinux-dist-2010R1-RC5# cp ./staging/usr/lib/ /var/www/
  3. On the Atcom, copy the libraries to /lib

Compiling opkg

Here's how to build opkg-cl without Curl, OpenSSL, and GPG:

  1. svn checkout /usr/src/opkg
  2. To avoid having to use an environment variable, vi libbb/gz_open.c

    /* gz_use_vfork = (getenv("OPKG_USE_VFORK") != NULL);*/
    gz_use_vfork = 1;

    If using the 2010 toolchain, which can't be told to handle the above with a warning instead of an error.... edit gz_open.c thusly:

    #define UCLINUX 1
    /* gz_use_vfork = (getenv("OPKG_USE_VFORK") != NULL);*/
    gz_use_vfork = 1;
    #ifdef UCLINUX
        //if (gz_use_vfork) {
            *pid = vfork();
        //} else {
            *pid = fork();
  3. Add the toolchain to the PATH
  4. apt-get install glib-gettextize libglib2.0-dev libcurl4-openssl-dev libgpgme11-dev
  5. ./
  6. CC=bfin-linux-uclibc-gcc CFLAGS="-I/usr/src/uClinux-dist-2010R1-RC5/linux-2.6.x/include" LDFLAGS="-static" ./configure --disable-gpg --disable-openssl --disable-curl ac_cv_func_malloc_0_nonnull=yes --build=i686-pc-linux --host=bfin-linux-uclibc
  7. make
  8. Copy ./src/opkg-cl to the web server, and download + chmod this file from the Atcom
  9. Make sure PATH is filled with the usual suspects, eg. /bin:/usr/bin:/sbin:/usr/sbin, or you might get "pkg_run_script: package "xyz" postinst script returned status 255" when installing a package
  10. mkdir -p /usr/lib/opkg
  11. mkdir /etc/opkg
  12. vi /etc/opkg/snapshots.conf

    src snapshots
    dest root /
  13. ./opkg-cl update
  14. ./opkg-cl list

No command to list files in uninstalled package?

Packaging an application with opkg

Note: The Section field is completely ignored by opkg. You can put whatever you want here. The Architecture field is free form, it can be whatever you want, but it must match one of the arch fields specified in your conf files.

  1. mkdir /usr/src/mypackage ; cd mypackage
  2. mkdir bin ; cd bin ; vi hello.c ; bfin-linux-uclibc-gcc hello.c -o hello
  3. cd /usr/src/mypackage
  4. vi debian-binary

  5. vi control

    Package: opkg-hello (must match package name, ie. package.opk?)
    Version: 0.0.1
    Description: Sample OPKG package
    Section: cyanogenmod/applications
    Priority: optional
    Maintainer: Jiang Yio
    Architecture: all

    NO! Note: Do not leave fields empty : "Malformed package file package.opk"
  6. vi preinst

    echo "The name of this script is \"$0\"."

  7. chmod +x preinst
  8. cp preinst postinst
  9. cp preinst prerm
  10. cp preinst postrm
  11. tar czvf control.tar.gz control preinst postinst prerm
  12. tar czvfP data.tar.gz ./bin/hello
  13. ar -r package.opk debian-binary control.tar.gz data.tar.gz
  14. cp package.opk /var/www
  15. On Atcom, download and run:

    /var/tmp> wget http://server/package.opk
    /var/tmp> ./opkg-cl install package.opk
With opkg-utils

Requires Python

With OpenWrt's Makefile
To read

Creating a repository


Changing options for Busybox in BAPS

  1. Run "make -f uClinux" once so it downloads the uClinux-dist source
  2. cd uClinux-dist
  3. make clean
  4. cd uClinux-dist/user/busybox/
  5. make menuconfig, and choose options
  6. cd /usr/src/baps
  7. make -f uClinux
  8. Reboot the Atcom with this new image, and check that it works OK

Compiling iptables

As iptables relies on settings in the kernel, you'll need to recompile the kernel to enable Netfilters.

In addition, some features (eg. the "recent" Netfilter module) were added in later versions, so you might need to use a more recent release than the 2007 version of the kernel used in the BAPS firmware.

More information here.

Adding OpenVPN to BAPS uClinux

OpenVPN is a more reliable way than STUN to let remote SIP clients connect to an Asterisk server through locked-down NAT routers.

A patch is required to modify the uClinux-dist source code to include OpenVPN before rebuilding an image; We must also build OpenVPN 2.0.9 package to provide the /bin/openvpn binary that will talk to the /dev/net/tun virtual interface.

Note: Since OpenVPN requires patching the kernel and compiling/installing a package, and a VPN burns CPU cycles which would be better left to Asterisk, you might want to simply locate the VPN on your router instead.

Here's how to apply the patch, build/test a new image, compile and test the OpenVPN package, and finally burn the new image in the Atcom:

  1. cd /usr/src/baps
  2. wget
  3. patch -p0 < openvpn_package.patch
  4. make -f uClinux
  5. cp uClinux-dist/images/uImage /tftpboot/uImage
  6. On the workstation, start a TFTP server so the Atcom can download this new image
  7. On the Atcom, use a serial cable, reboot the appliance to get into the Uboot loader, and download and run the new image:

    ip04>set autostart
    ip04>set bootargs ethaddr=your:mac:address root=/dev/mtdblock0 rw
    ip04>tftp 0x1000000 uImage
  8. Check that this new image contains a character device in /dev/net/tun, write its live root filesystem to NAND (, and reboot with "root=/dev/mtdblock2 rw"
  9. On the workstation, build the OpenVPN package:

    make -f libssl
    make -f libssl-package
    make -f openvpn-package
    cp ipkg/libssl_0.9.8d-1_bfin.ipk /var/www
    cp ipkg/openvpn_2.0.9-1_bfin.ipk /var/www/
  10. From the Atcom, download and install this new package:

    cd /var/tmp
    wget -c http://workstation/libssl_0.9.8d-1_bfin.ipk
    wget -c http://workstation/openvpn_2.0.9-1_bfin.ipk
    ipkg install libssl_0.9.8d-1_bfin.ipk
    ipkg install openvpn_2.0.9-1_bfin.ipk

The package only includes a single binary /bin/openvpn, which can use configuration files but is unable to create a Certification Authority (CA) certificate and its key, and pairs of public/private keys for the server and clients. Those are needed to use OpenVPN with a Public Key Infrastructure (PKI).

Therefore, the next steps must be performed on the workstation before copying the files on the Atcom and the clients: 

  1. On the workstation:

    apt-get install openvpn
    mkdir /etc/openvpn/easy-rsa
    cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa
  2. cd /etc/openvpn/easy-rsa
  3. Create the certificates and keys:

    #Make necessary changes
    vi vars
    . ./vars


    #Use unique Common names
    ./build-key-server server
    ./build-key client1
  4. Copy certificates + keys to www so server and client can fetch them:

    cd /etc/openvpn/easy-rsa/keys
    cp ca.crt dh1024.pem server.crt server.key client1.crt client1.key /var/www
    #So web server can send files
    chmod 644 /var/www/server.key
    chmod 644 /var/www/client1.key
  5. Create a configuration file for the server:

    vi /var/www/server.ovpn

    port 1194
    proto udp
    dev tun

    ca ca.crt
    cert server.crt
    key server.key
    dh dh1024.pem

    ifconfig-pool-persist ipp.txt
    keepalive 10 120
    #Uncomment if compiled with compression
    status openvpn-status.log
    verb 3
  6. Create a configuration file for the client:

    vi /var/www/client1.ovpn

    dev tun
    proto udp
    remote <public IP to reach OpenVPN/Asterisk server> 1194
    resolv-retry infinite

    ca ca.crt
    cert client1.crt
    key client1.key

    verb 3

  7. On Atcom, download files and launch server:

    Asterisk> cd /etc/openvpn
    Asterisk> wget http://workstation/ca.crt
    Asterisk> wget http://workstation/dh1024.pem
    Asterisk> wget http://workstation/server.crt
    Asterisk> wget http://workstation/server.key
    Asterisk> chmod 600 server.key
    Asterisk> wget http://workstation/server.ovpn

    #Let's test
    Asterisk> /bin/openvpn /etc/openvpn/server.ovpn 
  8. On Windows host, install the Windows OpenVPN package, which includes a GUI, download the required files, and try to connect to OpenVPN server:

    cd c:\program files\openvpn\config
    wget http://workstation/ca.crt
    wget http://workstation/client1.crt
    wget http://workstation/client1.key
    wget http://workstation/client.ovpn

    Start OpenVPN Service
    Start OpenVPN GUI with Admin rights: Right-click on OpenVPN GUI icon > Connect

  9. If ping OK, configure SIP client to connect to Asterisk through the server's private IP used by the OpenVPN tunnel, eg., and make a call
  10. Edit Asterisk's sip.conf to add a "localnet" for the VPN:

    externip=<public IP>
    #local extensions
    #remote extensions, through VPN
  11. On Atcom, create /etc/init.d/openvpn script to start app at boot-time:

    # Start up file for OpenVPN

    case $1 in
            #--daemon not implemented
            start) openvpn --cd /etc/openvpn --config server.conf&;;
            stop) killall openvpn;;
            enable) rm -f /etc/rc.d/S60openvpn;
                    ln -s /etc/init.d/openvpn /etc/rc.d/S60openvpn;;
            disable) rm -f /etc/rc.d/S60openvpn;;
            *) cat <<EOF;;
    Syntax: /etc/init.d/openvpn [command]
    Available commands:
            start   Start the service
            stop    Stop the service
            enable  Enable service autostart
            disable Disable service autostart

    Remember to "chmod 755 openvpn"
  12. Add symlink in /etc/rc.d/: /etc/init.d/openvpn enable

Note that I couldn't get SJPhone and Qutecom to work with the VPN: Either one-way audio or couldn't even register. Ekiga could register, but couldn't dial an extension. Try XLite/EyeBeam or Zoiper instead.

More information: Switching to a software PBX and Setting up a client

Adding items to Switchfin menuconfig

  1. To add a new package to the Switchin Buildroot, start by creating a directory for the application under /package/, eg. myapp/
  2. This directory must include two files: which describes the option when you run "make menuconfig", and which contains the Makefile that will be run to download, configure, build, and install the application

    If a package lacks a file, it will not be shown as an option when running "make menuconfig" and will always be compiled and included in the image.
  3. Next, edit /package/ and add this new application.
  4. Finally, write myapp/ The contents is different depending on if the package is generic or based on Autotools.
  5. The actual source code of the application is located in build_ip01/uClinux-dist/user/ if it is part of the uClinux-dist, or in package/sources/myapp/ if you provide the application yourself.

You can tell an application uses a generic Makefile or an Autotools-based Makefile, based on whether it has a "configure" scripts, in which case it's Autotools.


Checking shared libraries

With ldd or readelf

The Blackfin toolchain already has a binary that you can run on the workstation to check which shared libraries an application depends on, if any:

On the workstation, you can run this:

find ./romfs/bin -type f -print0 | xargs -0 bfin-linux-uclibc-ldd

I failed compile ldd.c for Blackfin (either from the generic uClinux-dist distribution or from source files found through Google), but compiling Binutils went far enough to get a working readelf:

  1. cd /usr/src/uClinux-dist-2010R1-RC5/binutils-2.21
  2. CC=bfin-linux-uclibc-gcc ./configure --build=i686-pc-linux-gnu --host=bfin-linux-uclibc
  3. make
  4. cp binutils/readelf /var/www/
  5. find / -xdev -type f -print0 | xargs -0 ./readelf -d

With scanelf

uClinux provides neither ldd nor readelf, but scanelf from the pax-utils application compiles OK:

  1. wget -c
  2. tar xjvf pax-utils-0.2.2.tar.bz2
  3. cd pax-utils-0.2.2
  4. export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/uClinux/bfin-linux-uclibc/bin
  5. make CC=bfin-linux-uclibc-gcc
  6. Copy scanelf to web server
  7. Download scanelf on Blackfin appliance
  8. > ./scanelf -qn myapp

Here's a script to build a list of shared libraries, and check all the binaries recursively to find if any library is unused:

Building a smaller image

  1. Start by checking romfs/bin for applications you don't need.
  2. Next, run the script above to check that you don't uselessly pack shared libraries in /lib that aren't used by any application.
  3. Strip binaries (any drawback?)

"Hello, word" for uClinux

Here's how to install the toolchain, and compile some test files as either FLAT or FDPIC ELF binaries, manually and through a Makefile.

Setting up tools

  1. From the Blackfin uClinux site, download the two versions of the toolchain (to compile binaries as FLAT or FDPIC ELF):

    cd  /

    wget -c
    wget -c 
  2. Untar the two packages, and edit the PATH env't variable:

    tar xjvf blackfin-toolchain-2010R1-RC4.i386.tar.bz2
    tar xjvf blackfin-toolchain-uclibc-full-2010R1-RC4.i386.tar.bz2

    vi /etc/profile
    export PATH=$PATH:/opt/uClinux/bfin-uclinux/bin:/opt/uClinux/bfin-linux-uclibc/bin

    source /etc/profile
    echo $PATH

    which bfin-uclinux-gcc
    which bfin-linux-uclibc-gcc

  3. mkdir /usr/src/uclinux.test/
  4. cd /usr/src/uclinux-test/

Compiling an application 

Based on Simple Hello World Application Example

  1. vi main.c:

    #include <stdio.h>

    int main(int argc, char **argv)
        printf("Hello World\n");
        return 0;

    Save and exit
  2. To compile main.c as a FLAT executable:

    bfin-uclinux-gcc -Wl,-elf2flt main.c -o main

    file main: "BFLT executable - version 4 ram"
  3. To compile main.c as an FDPIC ELF executable:

    bfin-linux-uclibc-gcc -Wall main.c -o main
    bfin-linux-uclibc-strip main

    file main: "ELF 32-bit LSB executable, Analog Devices Blackfin, version 1 (SYSV), dynamically linked (uses shared libs), stripped"

Note: To compile source code into an object file instead of an executable, use the "-c" switch: bfin-uclinux-gcc -Wall -c main.c -o main.o

Compiling a library

First, here's the source code for the library:

void mytestfunc(void);
#include <stdio.h>
void mytestfunc(void) {
        printf("In mytestfunc\n");

Next, here's how to modify main.c to include a call to the library:

#include <stdio.h>
#include "bar.h"
int main(int argc, char **argv)
        //mytestfunc() located in libbar.a, ie. bar.c
        return 0;
FLAT static

First, let's compile the library:

bfin-uclinux-gcc -Wall -c bar.c -o bar.o
bfin-uclinux-ar rcu libbar.a bar.o
bfin-uclinux-ranlib libbar.a

Next, let's recompile main.c to include libbar.a statically:

bfin-uclinux-gcc main.c -o main -L. -lbar -Wl,-elf2flt
FDPIC ELF (static)
bfin-linux-uclibc-gcc -c bar.c -o bar.o
bfin-linux-uclibc-ar rcu libbar.a bar.o
bfin-linux-uclibc-gcc main.c -o main -L. -lbar
bfin-linux-uclibc-strip main
FDPIC ELF (shared)
bfin-linux-uclibc-gcc -c bar.c -o bar.o
bfin-linux-uclibc-gcc -shared -Wl,-soname, -o bar.o
bfin-linux-uclibc-gcc main.c -o main -L. -lbar
bfin-linux-uclibc-strip main

On the target host, a shared library must be installed in locations where the system expects to find it, eg. /lib. How to check which locations uClinux looks for shared libraries?

Compiling libraries and executables through a Makefile

If the application uses "configure", you might need to use "CROSS_COMPILE=bfin-uclinux- ./configure" and/or "CC=bfin-uclinux-gcc ./configure".

FLAT static
CROSS  = bfin-uclinux-
AR     = $(CROSS)ar
CC     = $(CROSS)gcc
RANLIB = $(CROSS)ranlib
CFLAGS       += -Wall
LDFLAGS_test  = $(LDFLAGS) -Wl,-elf2flt
LDLIBS_test   = $(LDLIBS) -L. -lbar
LIBS = libbar.a
BINS = test
all: $(LIBS) $(BINS)
libbar.a: bar.o api.o
        $(AR) rcu $@ $^
        $(RANLIB) $@
test: test.o
        $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@)
FDPIC ELF (static)
CROSS  = bfin-linux-uclibc-
AR     = $(CROSS)ar
CC     = $(CROSS)gcc
RANLIB = $(CROSS)ranlib
CFLAGS       += -Wall
LDLIBS_test   = $(LDLIBS) -L. -lbar
LIBS = libbar.a
BINS = test
all: $(LIBS) $(BINS)
libbar.a: bar.o api.o
        $(AR) rcu $@ $^
        $(RANLIB) $@
test: test.o
        $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@)
FDPIC ELF (shared)
CROSS  = bfin-linux-uclibc-
CC     = $(CROSS)gcc
CFLAGS            += -Wall  = -shared -Wl,-soname,
LDLIBS_test        = $(LDLIBS) -L. -lbar
BINS = test
all: $(LIBS) $(BINS) bar.o api.o
        $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@)
test: test.o
        $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@)

Compiling the Lua interpreter

Note: If you rarely use the Lua interpreter in interactive mode, you can save space by not including libreadline: Just edit LUA_USE_LINUX in luaconf.h.

First, update the PATH env't variable to where the toolchain is located.

Next, edit /usr/src/lua-5.1.4/src thusly:

AR= bfin-linux-uclibc-ar rcu
RANLIB= bfin-linux-uclibc-ranlib
RM=rm -f
CFLAGS=-O2 -Wall -DLUA_USE_LINUX -I$(BASE)/uClinux-dist/linux-2.6.x/include -I$(STAGING_DIR)/usr/include
LIBS= -lm -ldl
        $(MAKE) all

Compiling SQLite3

autoconf version

./configure --build=i686-pc-linux --host=bfin-linux-uclibc target=bfin-linux-uclibc CC=bfin-linux-uclibc-gcc AR=bfin-linux-uclibc-ar RANLIB=bfin-linux-uclibc-ranlib CFLAGS="-O2 -Wall -I/usr/src/baps/uClinux-dist/linux-2.6.x/include" LFLAGS=-L/usr/src/baps/uClinux-dist/lib


The command-line client sqlite3, the shared library and the static library libsqlite3.a will be found in ./.libs/

amalgamated version

Unzip the SQLite source file, and create the following Makefile:

AR=bfin-linux-uclibc-ar rcu
LDFLAGS=-Wl,-E -L$(BASE)/uClinux-dist/root/lib -L.
        @echo "No target specified."
        $(CC) $(CFLAGS) -c sqlite3.c -o sqlite.o
        $(CC) $(CFLAGS) -c sqlite3.c -o sqlite3.o
        $(AR) libsqlite3.a sqlite3.o
        $(RANLIB) libsqlite3.a
        $(CC) $(CFLAGS) $(LDFLAGS) -shared -Wl,-soname,
-o sqlite3.c
cli: static
        $(CC) -static $(CFLAGS) $(LDFLAGS) -o sqlite3 shell.c
-lsqlite3 -ldl
        -rm -rf *\.a *\.o *\.so sqlite3

Compiling LuaSQL for SQLite3

LuaSQL requires either the SQLite3 static library (libsqlite3.a) or just the object file (sqlite.o), and will generate which contains both SQLite3 and some glue to access SQLite3 from Lua:


LUA_INC= /usr/src/lua-5.1.4
LIB_OPTION = -shared -Wl,-soname,$(LIBNAME)
DRIVER_INCS = -I/usr/src/sqlite-autoconf-3070601
#DRIVER_LIBS= -L/usr/src/sqlite-autoconf-3070601/.libs -lsqlite3
DRIVER_LIBS= /usr/src/sqlite-autoconf-3070601/sqlite3.o
CFLAGS= -O2 -Wall

#assumes exported in PATH


AR= bfin-linux-uclibc-ar rcu
RANLIB= bfin-linux-uclibc-ranlib

src/$(LIBNAME): $(OBJS)
        $(CC) $(CFLAGS) $(LIB_OPTION) -o $@ $(OBJS) $(DRIVER_LIBS)

Compiling LuaSocket

Compiling lsof

lsof is not part of BAPS and Switchfin, but is available in uClinux-dist in the "Miscellaneous Applications" section.

However, it won't compile with the 2010R1-RC4 toolchain due to its use of fork(). Incidently, "netstat -natp" will display the name of the program that opened the port.

Compiling applications with MPU

While the Blackfin has no MMU, it offers a Memory Protection Unit (MPU) so that an application won't access RAM that doesn't belong to it.

Compiling Samba

Samba 3.0.25a is part of uClinux-dist, and here's how to compile a more recent release:


To check the version: smbd -V

To check where smbd expects to find smb.conf:

smbd -b | grep CONFIGFILE

Compiling Busybox

Some options you might want to enable:

Using Busybox's init instead of simpleinit

By default, uClinux-dist uses simpleinit (in Core Applications), instead of the one provided by Busybox. You might want to use Busybox's init so that you use its poweroff/halt/reboot which unmount partitions before rebooting.

Busybox uses a different format for /etc/inittab. Here's an example:

# /etc/inittab
# Copyright (C) 2001 Erik Andersen <>
# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
# Format for each entry: <id>:<runlevels>:<action>:<process>
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run
# Startup the system
console::sysinit:/bin/sh /etc/rc
# Set up a console shell
#Using "console" prevents use of job control, eg. CTRL+c
#console::respawn:/bin/login -f root
#Check which tty is in your kernel command line
ttyBF0::respawn:/bin/login -f root
# Misc services
null::respawn:/sbin/inetd -f
null::respawn:/sbin/watchdog -F -T 20 -t 10 /dev/watchdog
# Logging junk
null::sysinit:/bin/touch /var/log/messages
null::respawn:/sbin/syslogd -n -m 0
null::respawn:/sbin/klogd -n
# Stuff to do for the 3-finger salute
# Stuff to do before rebooting
null::shutdown:/bin/killall klogd
null::shutdown:/bin/killall syslogd
null::shutdown:/bin/umount -a -r


Choose a file format for shared libraries: Shared FLAT, FDPIC ELF. Read how to create libraries.



What is difference between host, build, and target?

--build=i686-linux-gnu --host=blackfin-unknown-linux-gnu

How to remove unneeded Asterisk modules?

There's no sure-fire way to check which modules Asterisk need. Here's how to investigate:

  1. Configure Asterisk to log messages
  2. Start Asterisk with enough -d and -v, and watch for error messages
  3. vi /etc/asterisk/modules.conf


    (load modules you think you need)
  4. Repeat until Asterisk stops complaining about missing modules.

What files do I need for a minimal Asterisk?

Use "readelf -d" to check which shared libraries a binary needs.

If you'd rather run readelf on the Atcom rather than on the workstation,

This is what you need when using SIP and Dahdi:

Read this:

To locate dependency errors, edit logger.conf full => notice,warning,error,debug,verbose

How to monitor the connection to a VoIP provider for quality?

FreeSwitch can be used for this. Does Asterisk offer this feature?

Busybox's ping doesn't stop with CTRL+c

Make sure /etc/inittab uses the "tty" mentionned in the kernel command line instead of "console". More information here.

How to restart an application that crashed?


How to check network performance?

Compile and install iperf on a workstation and the Atcom to stress-test the network part.

Simple TCP test

On the server: iperf -s

On the client: iperf -c server.ip -t 30 -i 1

Simple UDP test

On the server: iperf -s -u

On the client: iperf -c server.ip -u -b 4m -t 30 -i 1

Multiple UDP threads

On the client: iperf -c server.ip -u -b 4m -t 30 -i 1 -P 4

Bigger MTU

On the client: iperf -c server.ip -w 128k -t 30 -i 1 -P4

Finding biggest MTU supported by network

On the server: iperf -s -m

On the client: iperf -c server.ip

On the server, check the line that says "MSS size XXXX bytes"

Checking VoIP performance

Datagrams are 32-byte long and the MTU buffer is 128k:

On the server: iperf -s -u -l 32 -w 128k

On the client: iperf -c server.ip -u -b 1m -l 32 -w 128k -i 1

Upload, and then download data

On the client: iperf -c server.ip -t 30 -i 1 -r

Upload and download data simultaneously

On the client: iperf -c server.ip -t 30 -i 1 -d

Why two versions of the toolchain?

Eg. bfin-uclinux-readelf vs. bfin-linux-uclibc-readelf?

Try compiling FLAT + FDPIC ELF hello, world, and try apps on them to see

Which version of uClibc does uClinux-dist include?

$ printf '#include \n__UCLIBC_MAJOR__ __UCLIBC_MINOR__ __UCLIBC_SUBLEVEL__\n' | bfin-uclinux-gcc -E - | tail -1

DHCP client crashes at reboot -> Busybox's udhcpc

Patching dm9000.c didn't help, so I dumped the default DHCP client and used udhcpc provided by Busybox.

Here's the init.d script to be called at boot time:

OPTIONS="-R -a -S -T 3 -A 1 -t 3"
INT="-i eth0"
PID="-p /var/run/"
SCRIPT="-s /etc/simple.script"
case $1 in
        start) rm -f /var/run/;
               udhcpc $OPTIONS $INT $PID $SCRIPT;;

/etc/simple.script can be found here.

To ask udhcpc to renew its lease run "killall -USR1 udhcpc ; tail /var/log/messages".

How to check Switchfin patches

  1. cd /usr/src
  2. svn co switchfin
  3. cd switchfin
  4. find ./package/ -name "*\.patch"

Does Uboot know about the NAND partitions?

No, it's up to you to provide correct offset/length to match the partition settings in the NAND driver compiled in the kernel.

Generally speaking, what patches are required to run Linux apps on uClinux?

  1. svn co http://server/somedistro somedistro
  2. grep .patch package/* -rs | grep -v .svn

How to find what shared libraries are needed?

On the workstation

find ./romfs/bin/ -executable -type f -print0 | xargs -0 bfin-linux-uclibc-readelf -d | egrep "File|library"

On the Atcom

Note: Make sure Busybox supports "-xdev"

find /bin -xdev -type f -perm +111 -print0 | xargs -0 ./readelf -d

How to find unused libraries?

for n in romfs/lib/*.* romfs/usr/lib/*.*; do du -sh $n; nn=`basename $n`; find romfs/ -type f -print0 | xargs -0 grep -l $nn | grep -v $n | grep -v | wc -l; done

Alternatively, run "make menuconfig", and in the "uClinux Distribution Configuration > Blackfin build options" menu, enable "Cull unused ELF shared libraries", ie. CONFIG_INSTALL_ELF_TRIM_LIBS.

When installing new applications that use shared libraries, you'll have to check that they are available in /lib or /usr/lib.

What are the different files in ./images/ or build_ipXX/image_ipXX?

If you just want to upgrade the kernel in the NAND, use vmImage.

Images are compiled through Mfg/Board/Makefile, which calls vendors/AnalogDevices/vendor.mak.

More information in uClinux-dist Compiled Images

"init: exec rc failed"

Things to try/check:

  1. romfs/bin: Is there a symlink sh->(the shell)?
  2. Try either the BusyBox init or the stand-alone Core Applications init
  3. If you get "Bad inittab entry at line 11", check ./user/inetd/Makefile: The Busybox init seems unable to process the simple inittab format used by the stand-alone init "ttyline:termcap-entry:getty-command". Try  "inetd::sysinit:/sbin/inetd". Also, the stand-alon e init will process /etc/rc first and then execute the lines found in /etc/inittab
  4. "can't execute '/etc/rc.d/S10network': Permission denied": chmod 755 /etc/init.d/network

Kernel stuck at "Starting Kernel at = "

Make sure you compiled uClinux for the ADSP-BF532 CPU.

The Hush shell lacks some features

If some features are missing when running the Hush shell (no path completion through TAB, no command history through the up arrow, etc.), check the Busybox > Busybox Settings > Busybox Library Tuning section in "make config_menuconfig".

How to monitor applications?

I think there is a standard Unix application that can monitor if another application is running.  It might even be in uClinux-dist.  Can't recall it's name......

Is RAM fred when an application ends?

Not all RAM is freed immediately after an application ends, as VFS file buffers, network buffers, kernel data structures, etc. can linger in RAM for a while.

Worse, some kernel threads, kernel modules, and service daemons won't exit and free memory allocated until you force a reboot.

So it's a good idea to 1) run a watchdog to check for memory leaks, and 2) schedule a nightly reboot to make sure unused memory is returned to the kernel.

How to check SVN version of downloaded source?


BAPS ignores my settings

When compiling a new kernel with BAPS and, it can happen that the script rewrite configuration files and ignore your settings such as when compiling Netfilter/iptables in the kernel image.

Looks like it's done by copying patch/vendors/Rowetel/IP04/config.linux-2.6.x into uClinux-dist/vendors

A solution is to compile uClinux once the usual way (make -f uClinux), and modify to add your own, simpler target:

        ./src/zeropad uClinux-dist/images/uImage uClinux-dist/images/uImage_r2.ip08 0x20000
uClinux: $(UCLINUX_DIR)/.unpacked ./src/zeropad
    mkdir -p $(UCLINUX_DIR)/vendors/Rowetel/IP04/
    cp -af patch/vendors/* $(UCLINUX_DIR)/vendors
    $(MAKE) -C $(UCLINUX_DIR) Rowetel/IP04_config
    ./src/zeropad uClinux-dist/images/uImage uClinux-dist/images/uImage_r2.ip08 0x20000

FXO is acting funny

If you make a lot of use of FXO/Zaptel during tests, it might act funny after a while, either displaying error messages (eg. "chan_zap.c:6406 ss_thread: Got event 18 (Ring Begin)..." instead of handling the call), or not making/answering calls at all.

In this case, just reboot the Atcom and see if this solves the problem.

How to convert sound files from WAV to Ulaw?

Two easy solutions:

On the workstation, use "sox". If you need to convert a whole directory:

for i in *.wav; do sox $i -r 8000 -c 1 $(basename $i .wav).gsm resample -ql; done

On the Atcom, enter the Asterisk CLI and use this command:

ip04*CLI> file convert /var/tmp/myfile.wav /var/tmp/myfile.ulaw

Zaptel sometimes goes berzerk

After making a bunch of test calls, Zaptel stops reporting an incoming call:

root:~> /etc/init.d/asterisk stop
root:~> /etc/init.d/zaptel stop
rmmod: wcfxs: Resource temporarily unavailable
rmmod: bfsi: Resource temporarily unavailable
rmmod: zaptel: Resource temporarily unavailable
rmmod: oslec: Resource temporarily unavailable

Must wait a little while before being able to stop/start Zaptel and Asterisk.

[modules.conf] .c instead of .so

Samples on the Net use the .so extension, while the default modules.conf in the Atcom uses .c, using "noload" with a .c extension doesn't work, and renaming all items from .c to .so causes Asterisk to start... and die. You'll have to try each line separately until you know which module can be safely renamed from .c to .so.

Call files aren't handled by Asterisk

This is due to a bug in Yaffs2 not updating the timestamp on parent directories. Upgrade uClinux and see if the bug is gone.

If you can't upgrade, edit /etc/asterisk/asterisk.conf so that the spool directory is located in /var/tmp, and edit /etc/init.d/asterisk so that the start) part contains this:

if [ ! -d /var/tmp/asterisk/outgoing ]
        mkdir -p /var/tmp/asterisk/outgoing

[BAPS] Why two Ethernet devices?

root:~> ifconfig

eth0      Link encap:Ethernet  HWaddr 00:09:45:56:72:9B

          inet addr:  Bcast:  Mask:


          RX packets:10 errors:0 dropped:0 overruns:0 frame:0

          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000



eth0:9    Link encap:Ethernet  HWaddr 00:09:45:56:72:9B

          inet addr:  Bcast:  Mask:



Why use "asterisk -f &"?

-f : Foreground. Starts Asterisk but does not fork as a background daemon.

What are local files?

Asterisk only handles callfile when restarted

Moving a callfile to Asterisk's outgoing/ directory while Asterisk is already running doesn't trigger a call: A call will only occur if Asterisk is stopped, the file moved, and Asterisk restarted. uClinux has inotify enabled. No idea as to the cause of this problem.

Alternative ways to have Asterisk auto-dial out:

Fails compiling the Asterisk 1.4.4 package

"The existing menuselect.makeopts file did not specify that 'app_flash' should not be included.  However, either some dependencies for this module were not found or a conflict exists."

  1. cd asterisk-1.4.4/ ; rm menuselect.makeopts
  2. cd ..; make -f asterisk-package

Fails compiling the Asterisk 1.4.20 package

This .mk file actually downloads Asterisk

  1. cd asterisk- ; rm menuselect.makeopts
  2. vi pbx/ael/ael_lex.c
  3. cd ..; make -f asterisk-package

How to stress-test Asterisk?

What is the recommended way to stop Asterisk?

Instead of "kill", try "asterisk -rx "stop now".

How to enable Asterisk message logging

It might not be enabled by default, so you won't see any Asterisk-related messages in /var/log/messages.

Provided you have a syslogd server running:

  1. vi /etc/asterisk/logger.con

    syslog.local0 => notice,warning,error
  2. Connect to Asterisk with "asterisk -vvvvvvvvvr"
  3. Tell Asterisk to reload its configuration with "logger reload"
  4. Exit console, and check "tail -f /var/log/messages"

How to restart crashed/rogue applications?

What solution is available to restart an application that crashed, or is causing memory fragmentation and must be restarted so uClinux can reorganize RAM?

How to disable LD_DEBUG?

env -u LD_DEBUG didn't work. Had to reboot

What modules do I really need?

By default, Asterisk loads all the modules located in /usr/lib/asterisk/modules/, unless told otherwise in modules.conf.

The problem is that there doesn't seem to be away to be positive a module is required or not for your Asterisk server to work OK, but here are modules you can problably avoid loading without a problem:

Using Asterisk' mini web server

By default, Asterisk supports a basic web server. Its configuration is located in /etc/asterisk/http.conf, and its docroot is /var/lib/asterisk/static-http/.

Note that documents can be reached through http://srv/static/.

Making sense of MTD

The Atcom uses the MTD device file to access the NAND flash memory.

Check the dmesg for a bit of information about MTD partitions:

Creating 1 MTD partitions on "RAM":
0x00000000-0x00300000 : "ROMfs"
uclinux[mtd]: set ROMfs:EXT2  to be root filesystem
Generic platform RAM MTD, (c) 2004 Simtec Electronics
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 2 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00800000 : "linux kernel"
0x00800000-0x10000000 : "file system"

In addition to two partitions in the NAND to contain a kernel and a persistent root filesystem, respectively, the kernel creates another MTD object in RAM to hold the RAM-based root filesystem attached to the kernel:

> cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00300000 00001000 "ROMfs"

mtd1: 00800000 00020000 "linux kernel"

mtd2: 0f800000 00020000 "file system"

"ROMfs" contains the RAM-based root filesystem that you can use to boot a new Atcom appliance before writing this root filesystem onto the /dev/mtdblock2 partition in the NAND.

How to access NAND from uClinux?

If the MTD commands are included, you'll need to either build an ipkg package or recompile a root filesystem or image to include the MTD applications.

What are entrypoints in "mount"?

When running mount, some of the entry points refer to kernel data structures, not physical devices.

What is /etc/index.html?

Alias ll='ls -al'?

How to check the hardware?

root:~> cat /proc/cpuinfo

root:~> cat /proc/meminfo

How to save space?

Replace FTPd + TelnetD with SSHd?

Remove DHCPd?

Remove Inetd?

Remove IPTables?

Remove rsh and rshd?

Remove rcp?

Remove unneeded Asterisk modules?


root:~> ls -al home/httpd/

drwxr-xr-x    1 500      500          2048 Mar  9  2008 .

drwxr-xr-x    1 500      500          2048 Mar  9  2008 ..

drwxr-xr-x    1 500      500          2048 Mar  9  2008 cgi-bin

What is OpenIPPbx?

Wiki by Atcom:

What is SwitchVoice?

"It was sometime in spring 2006 when a small Bulgarian group (now part of SwitchVoice Ltd.) started the BlackFin One project. It was a flexible general purpose Blackfin BF532 based development board. Both the schematics and PCB layout was open to the public which made the project pretty popular that time. The platform was ideal for SMB VOIP applications and it was first David Rowe (Rowetel) who saw its potential. David had already developed the 4FX (FXS/FXO interface card) and it was only a matter of months before we get complete analog BPX (IP04) ready. At that time we all were working as perfect team. We got great contribution from Mark who pointed the team to “build root” way of maintaining of the software (Astfin). Since then all of our Blackfn based products are Astfin driven and we are the major Astfin 2.1 contributor.

One year after we started the BlackFin One project, part of the Bulgarian team joined with Mark created a company uCpbx Ltd. The team under uCpbx Ltd. entity has developed family of Analog and Digital (PRI &BRI ) VoIP Appliances based on Blackin and Freescale PowerQUICC CPUs. Many external telecom. projects have been successfully designed as well.

During second half of 2009 the core development team decided to take a course for spin-out and this way avoid the management redundancy uCpbx Ltd. has created among the years.

The result is SwitchVoice Ltd. !"



Books and Tutorial