Free Telephony Project
Open Telephony Hardware

This project is a modular four port daughter card for the Blackfin STAMP. Here is a picture of the 4fx/fxsmod/fxomod boards assembled on top of a BF537 STAMP board:

STAMP & Starter Kit

Three printed circuit boards have been designed:

  1. 4fx: Is a card that plugs into the STAMP board. It has 4 RJ11 connectors, a Blackfin SPORT connector, and a SD card connector. There are four connectors on the board that can each accept a single port FXS or FXO module, much like the Digium TDM400. Each port has a LED next to it. The LED glows green if a FXS module is installed, or red if a FXO module is installed. The led is off with no module installed. 4fx boards are designed to be stacked to obtain multiple of 4 ports. Screen shot and schematic.

  2. fxsmod: Is the 25 x 50mm FXS module PCB, it implements a single FXS port based on the Silicon Labs Si3010/3201 chip set. Screen shot and schematic.

  3. fxomod: Is the 25 x 50mm FXO module PCB, it implements a single FXO port based on the Silicon Labs Si3050/3019 chip set. Screen shot and schematic.

I have blogged on the bring up of the 4fx design here and here. I find blogging hardware development a great way to document the design. Others seem to agree - these two posts are the most popular on my blog!

Design Notes

  1. The FXS and FXO port designs are straight out of the Silicon Labs data sheets for the 3050 and 3210 parts.

  2. The Xilinx chip on the 4fx is used to decode nCS signals to the 4 modules. Unfortunately we can't use the daisy chain techniques described in the data sheets to cascade chips using one chip select as the mechanism is different for the FXO and FXS chips. As we don't know what sort of module will be plugged into each position we need to use a technique (an individual chip select) that will work for both FXO and FXS chips.

  3. The Xilinx chip also also drives the LEDs. I plan to use an initial SPI byte to drive the LEDs and/or nCS lines before sending the SPI bytes to the Si Labs chips.

  4. The Xilinx chip can also be used to handle stacking boards using a daisy-chain technique similar to that described in the Si Labs data sheets, but on a board by board basis. I am still working on that bit.

  5. On the 4fx PCB the default jumper setting is to fit JMP2, JMP7, JMP12, JMP5, JMP1.

Credits

My wife Rosemary actually did a great deal of the schematic entry for the FXS module.

Jerry Zeng from Analog Devices was very helpful in checking the design and with brain storming the CPLD requirements.

Design Rule Checks

To perform a schematic DRC for the 4fx board:

[david@solomon hardware-0.3]$ gnetlist -g drc2 -o - 4fx.sch

To extract the netlist for the PCB:

[david@solomon hardware-0.3]$ gnetlist -g PCB -o 4fx-nc.net 4fx.sch
[david@solomon hardware-0.3]$ ./ncnet.pl 4fx-nc.net 4fx.net

Bill of Materials

I have posted CSV format BOM files for the 4fx, fxsmod and fxomod. Some of the suppliers are local to me here in .au, and the prices are estimates that are probably out of date. However some of the Digikey, Newark, and Farnell part numbers might be helpful.

Analog Starter Kits Assembly and Testing

Here are the instructions for assembling and testing the 2 FXO 2 FXS Kits. These instructions assume a BF537 STAMP. Contact me if you are using a 533 STAMP - a different uImage is required but apart from that there are no major differences.

Please remember that the hardware and uCasterisk software is Beta. Please email the Blackfin uCasterisk forum if you have any questions or comments.

Before you start

  1. You need a 12-15V power supply. The standard 7V STAMP power supply is not powerful enough to run the FXS cards. If you try to use the standard 7V power supply the FXS drivers won't start.

    I use a 15V laptop power supply for my work. I needed to fit a different size connector to suit the STAMP DC socket. The STAMP runs happily with a regulated DC input between between 7V and 20V. The centre connection of the socket is positive.

    Carefully check the new power supply with a multimeter before connecting to your STAMP. Check that the centre conductor is positive and that the voltage is between 12V and 20V.

  2. You need need a recent version of u-boot installed:

    U-Boot-1.1.3-ADI-R06R2 (Sep 21 2006 - 15:10:36)

    Without a recent u-boot the test code will not boot correctly:

    • You can get a recent version of u-boot here.

    • Instructions on updating u-boot are here.

    • If you upgrade u-boot on your BF537 you will also have to reset your Ethernet MAC Address, instructions for that are here.

    • After upgrading u-boot use "setenv" to set up your serverip and ipaddr, and "saveenv" to save these u-boot variables.

    Be very careful when you update u-boot, if you lose power at the wrong time or use the wrong command it is possible to kill your STAMP (requiring a JTAG cable to bring it back to life).

  3. You need some experience in using the STAMP, for example:

    • compiling uClinux-dist

    • using u-boot (say tftp-ing a uImage, "saveenv", "setenv" commands).

    • connecting your STAMP to your LAN

    • telnet-ing to your STAMP

  4. It is recommended that you have some experience in using and configuring Asterisk on x86 systems, for example configuring dial plans, SIP extensions, configuring and installing and analog telephony hardware.

  5. Obtain the test image uImage.537.2fxo2fxs and place it in your tftpboot directory on your tftp server.

  6. Do not plug a SD or MMC card into the daughter card just yet.

Assembling and Testing

4fx spacers
  1. First attach the two threaded nylon spacers (included in the kit) to the daughter card using the supplied bolts. See the picture above.

    • The longer bolt goes through the hole in the corner of the daughter card.

    • The shorter bolt goes through the large hole near the text "Port 1". To fit the shorter bolt you need to remove the Port 1 module.

    When mounted on the STAMP, the longer bolt fits through a hole on the BF537 STAMP board and helps secure the daughter card. The shorter bolt and spacer prevents the daughter board from touching the SPORT0 connector. Tighten the spacers firmly with your fingers. Don't tighten too hard to prevent damaging the board.

    Tip DO NOT attach the daughter board to the STAMP without these spacers - a short circuit will damage both boards! I speak from experience :-)
  2. Once the spacers are attached, plug the daughter board assembly into the STAMP SPORT1 connector. The tip of the long bolt should fit neatly through the hole in the corner of the STAMP.

  3. Check that the bottom on the daughter card is not touching any of the SPORT0 pins, there should be several mm clearance.

  4. On the 4fx PCB the default jumper setting is to fit only JMP2, JMP7, JMP12, JMP5, JMP1.

  5. Plug in the power supply (at least 12V as described above). Check that the STAMP boots normally.

  6. Disconnect the power. Plug an analog telephone into Port 4 (the port next to the SD card).

  7. Connect the power again to re-start the STAMP. Immediately press a key on the serial console to enter u-boot.

    At the u-boot prompt tftp the uImage, then boot the uImage:

    bf537> tftp 0x1000000 uImage.537.2fxo2fxs
    
    <snip>
             #################################################
             #################################################
    done
    Bytes transferred = 5964432 (5b0290 hex)
    bf537> bootm 0x1000000

    After about a minute of "Uncompressing Kernel Image…" the system should boot. If all is well the LEDs will light like this:

    success

    If everything is OK the serial console won't respond (the uImage version of uCasterisk disables the console while running). This will be the final few lines on the console:

    Module 3: Installed -- MANUAL FXS
    Found: Blackfin STAMP (8 modules)
    wcfxs_init_ok = 1
    Registered tone zone 0 (United States / North America)
    No entry for terminal type "dumb";
    using dumb terminal settings.

    If the LEDS don't light or you get a root prompt at the console see the Trouble Shooting section below.

    Lift the handset and you should get dial tone. Dial 2000 to get the Asterisk demo. Port 3 is extension 2001, port 4 is extension 2004. Incoming calls on the FXO ports 1 & 2 get sent to the Asterisk demo.

    If booting is successful then the serial console won't respond. You can however telnet into the STAMP (the IP is obtained via dhcp when the uImage boots) to start/stop Asterisk or change the configuration, "asterisk -r" will connect you to the running Asterisk server.

  8. To get the STAMP to boot this uImage on reset every time, try this from the u-boot prompt:

    bf537> setenv ramboot 'tftp 0x1000000 uImage.537.2fxo2fxs; bootm 0x1000000'
    bf537> setenv bootcmd 'run ramboot'
    bf537> saveenv
  9. For testing I connect Port 3 (FXS) to Port 1 (FXO) or Port 2 (FXO). Then, on a phone connected to Port 4 (FXS), I dial 2001, which is answered after a few rings by the FXO port. The FXO Ports are configured to run the Asterisk demo when answering a call.

Trouble Shooting

If the boot process is not successful, then you will probably get a root prompt on the serial console. There will be lots of text on the screen showing what happened during the boot process.

  1. If you see something like:

    ProSLIC on module 3 failed to powerup within 520 ms (0 mV only)
    
     -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM400P??

    This may mean your power supply voltage is too low. Do you have a 12V to 15V power supply connected as described above?

  2. If the STAMP hangs when booting uImage.537.2fxo2fxs, but boots from flash OK you may have the wrong u-boot version. Check your u-boot version as described above.

  3. If some of the LEDs did not light, this indicates that the STAMP couldn't auto detect the modules.

    • One possibility is that the module contacts became loose during shipping. Try carefully removing and replacing each module. You can also try cleaning the module contacts with a little solvent.

    • Make sure no SD-card is plugged in (as described above).

  4. Try compiling and downloading unittest/spi/tspi_4fx.ko, this module can be used to determine if the basic operation of the daughter card is OK. See the C source file for insmod options.

Building uCasterisk for the Analog Kits

Building uCasterisk for the analog starter kits is similar to building uCasterisk without the analog hardware.

  1. I use the latest uClinux-dist release to build uCasterisk and the latest toolchain (2006R2 RC2).

  2. The latest uCasterisk was checked out of SVN. This version has up to date drivers for the hardware.

  3. Make sure you have compiled uClinux-dist first - the zaptel drivers depend on several files that are generated by the uClinux-dist make process.

  4. Once Asterisk and the zaptel drivers have been built, use this to install and configure:

    ./scripts/install_all `hostname`
    ./scripts/config_2fxo2fxs `hostname`

    The last step installs config files to support the 2 FXO 2 FXS hardware configuration. During the last step check dmesg on the STAMP to ensure that "ztcfg" ran OK. If you don't see this:

    Registered tone zone 0 (United States / North America)
    Registered tone zone 0 (United States / North America)

    (it should appear twice) try typing:

    /var/tmp/ztcfg
  5. Then start Asterisk:

    /var/tmp/asterisk -vc
  6. At the CLI

    blackfin*CLI> zap show channels
       Chan Extension  Context         Language   MusicOnHold
    
     pseudo            internal
    
          1            incoming
          2            incoming
          3            internal
          4            internal
  7. To make your own uImage try:

    make bin

    This will create a bootable image in "images". The configuration files (for example defining the SIP settings or the dial plan) are copied from package/asterisk/files and controlled by the "bin:" target in package/asterisk/Makefile.

MMC Card Support

The Blackfin STAMP can only directly address 4M of flash. Into this flash must fit the boot loader, uClinux, and all the applications we require. This 4M limit is significant for Asterisk, due to the large number of prompts and large size of the application.

MMC card

The 4fx daughter board contains a MMC/SD card socket. MMC cards are available in sizes of up to 4GB, overcoming the Blackfin's 4M limit on directly addressable flash. The MMC card is supported from uCasterisk-0.1.7. This means you can boot your embedded Blackfin IP-PBX entirely from flash, no Host PC or tftp server required.

If you don't want to build uCasterisk yourself using the instructions below download these binaries for uImage and the MMC card files. Un-tar the MMC card files onto your MMC card, place the card in the MMC card slot, power up your BF537 STAMP, then boot your BF537 STAMP using the uImage.

Driver Design

The MMC card is connected to the same SPI bus that is used to control the analog telephony hardware (i.e. the Silicon Labs chips on the fxsmod and fxomod cards).

This leads to a problem. The wcfxs driver for the telephony hardware needs to access the SPI bus about once every 1ms using an ISR. However the SPI protocol for the MMC card sometimes requires that the MMC card "hold" the SPI bus for 50-100 ms, for example when sending a command sequence or transferring a block of data.

Thus the two drivers don't work together very well. A typical problem when they run together is the MMC driver "locks up" as command/reply sequence is interrupted by the wcfxs ISR that polls the telephony hardware using the SPI port.

The current solution to this dilema is:

  1. After booting install the MMC driver and mount the MMC filesystem.

  2. Copy all of the Asterisk files (around 10M) from the MMC card to a ram disk.

  3. Unmount the MMC file system and remove the MMC driver.

  4. Install zaptel and wcfxs and boot Asterisk.

The MMC driver is a slightly modified version of the driver developed by Hans Eklund and the team at Rubico. Configuration of this driver is described here. On my Blackfin BF537 STAMP I found that this driver wasn't working well. Some investigation with the scope showed that some extra "phantom clock" signals were sometimes being sent to the MMC card:

Phantom Clocks

Note the correct bursts of 8 clock pulses, followed by the single "phantom" clock pulse. This driver also uses the "SPI framework" for the SPI bus I/O which is a different system to the SPI access routines to that used by the ucasterisk wcfxs driver. It is possible that the SPI framework (in particular DMA-based SPI transfers at high SPI clock speeds) is the cause of the phantom clock pulses and unreliability of the MMC driver, although I haven't conclusively proven this.

As both the MMC card and the wcfxs driver need to access the SPI bus (although perhaps not at the same time as described above), it is necessary that they both use the same interface to the SPI bus hardware.

I therefore decided to modify Han's driver to use the same SPI I/O functions as the wcfxs driver, removing the SPI framework code as a precaution. This has worked well in practice, the problems with the MMC driver experienced with the SPI framework have gone away.

One disadvantage with this method is that the driver is now quite CPU intensive, as polled I/O rather than DMA is used for the transfers. This isn't a huge problem in practice - as the MMC card is just used for booting.

MMC Driver Building and Testing

The driver works almost identically to Hans' original driver described here.

  1. There is a DIP-switch (SW5) on the BF537 STAMP that (optionally) connects PF5 to another output on the STAMP (PF5 can be used to sense a push button). This switch needs to be opened to use PF5 for the SPI bus. SW5 is located next to SPORT2. All of the 4 little switches should be slid so that they are next to the 1 2 3 4 numbers (away from the tiny ON lettering). I think only one of them relates to PF5, the rest free up other GPIO pins for general purpose use as well.

  2. You need to build uClinux-dist to support the MMC driver, as per Hans' instructions. Follow the set-up instructions (kernel & user configuration options etc) on this page exactly - the modified driver uses many of the same configuration options. Note that this will actually build the original (SPI framework) MMC driver as part of the process, however we won't use it at run time.

    Note Make sure you have configured uClinux-dist to build "mke2fs" so you can format the MMC card with an ext2 filesystem using the Blackfin.
  3. Here is the MMC driver configuration I used (Customize Kernel Settings

    • Device Drivers - MMC/SD Card support):

      MMC Driver Configuration

      Note we have selected PF5 for the chip select and disabled card detection support.

      Note Make sure that the original MMC driver is compiled as a module [M] not compiled in [*] as per the screen shot above. Otherwise you will not be able to insmod the new MMC driver.
  4. Re-build uClinux-dist, the next step depends on this.

  5. The two drivers (bfsi.ko and spi_mmc_bfsi.ko) are located in the src directory of the uCasterisk tar-ball. Just type "Make" in the src directory to make the drivers.

    The only real difference using this version of the MMC driver is that you need to install the module bfsi.ko first.

    root:~> insmod bfsi.ko
    Using bfsi.ko
    root:~> insmod spi_mmc_bfsi.ko
    Using spi_mmc_bfsi.ko
    New MMC/SD card found: 241 MB | CS channel on PF5
    root:~> mount /dev/mmc /mnt
     spi_mmc: unknown partition table
    EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
    root:~> ls /mnt
    etc         sbin        var         zaptel.ko
    lost+found  usr         wcfxs.ko
    root:~>

    In the example above I had already formatted the MMC card with an ext2 filesystem and placed some files on it.

Using the MMC card to Boot uCasterisk

The boot process is a two stage process. First uClinux boots using the regular flash on the STAMP. Some instructions are added to the end of the /etc/rc file to mount the MMC card and copy files across.

Here is the current /etc/rc file:

# regular Blackfin boot stuff

hostname b537
#/bin/expand /etc/ramfs.img /dev/ram0
mount -t proc none /proc
mount -t ramfs /dev/ram0 /var
mount -t sysfs none /sys
mount -t devpts devpts /dev/pts
mkdir /var/tmp
mkdir /var/log
mkdir /var/run
mkdir /var/lock
dhcpcd &
#ifconfig eth0 192.168.1.4 up
ifconfig lo 127.0.0.1
inetd &
#cat /etc/issue
#cat /etc/motd

# mount MMC card

insmod bfsi.ko
insmod spi_mmc_bfsi.ko
mount /dev/mmc /mnt

# copy Asterisk stuff over

cp /mnt/*.ko .
cp -f /mnt/etc/zaptel.conf /etc
cp -a /mnt/etc/* /etc
cp -a /mnt/usr/* /usr
cp -a /mnt/var/* /var
cp -a /mnt/sbin/* /var/tmp

# remove MMC driver as this locks up when wcfxs is installed

umount /mnt
rmmod spi_mmc_bfsi

# now boot Asterisk

insmod zaptel.ko
insmod wcfxs.ko debug=1
/var/tmp/ztcfg
/var/tmp/asterisk -c > /dev/null < /dev/null

So we need to create a special uImage, with this rc file appended, and MMC card support enabled (as described above). We also need to write all the files we need to the MMC card.

First, you need a way to mount the MMC card on your Host PC. I have a MMC slot in my laptop, alternatively you could use a MMC card reader or even a digital camera connected to your Host via USB. Another possibility (that I haven't tried yet) is to use Blackfin & 4fx system to write to the MMC card, this would require another make file target and perhaps some clever Expect scripts.

I formatted my MMC card as an ext2 file system, this can be done on the Blackfin or your host.

I haven't tried any other file systems (like DOS or VFAT), but they might work so feel free to experiment. On my host:

root@bunny:/home/david# mkfs.ext2 /dev/mmcblk0
Tip Please be very careful with mkfs.ext2, please don't reformat your hard drive by mistake!

The next step is to make uClinux-dist & uCasterisk as per usual. Mount your MMC card on your host. The uImage and MMC files are created in one step:

[david@bunny uCasterisk-0.1.7]$ make MMCDIR=/path/to/mmc/ mmc
Tip You might find this command bombs out withe permissions errors, I found that I needed to "chmod 777 /path/to/mmc/" on my Host, as only root had write permissions to the MMC card by default.
Tip Make sure you "unmount" the MMC card before ejecting the card, as no actual writing will happen until then. My laptop actually takes about 30 seconds to complete the "unmount" - all that data has to flow through one serial bit so MMC cards aren't fast!

Place the file uCasterisk-0.1.7/images/uImage in your tftpboot directory so that your STAMP can boot this uImage file. Once you have tested it and it boots OK you can save it in the STAMP's flash using the usual procedure.

Now:

  1. Power down your STAMP.

  2. Plug the MMC card in.

  3. Power up the STAMP and interrupt the boot process to get the u-boot console.

  4. "tftp 0x1000000 uImage" and "bootm 0x1000000".

After about a minute Asterisk should boot up. There is a longish pause after the MMC card is mounted as all the files are copied over.

Small Changes

Sometimes you may just want to create a new uImage, for example after updating /etc/rc), without changing the files on the MMC card. In this case try "make MMCDIR=/tmp mmc". This avoids the need to move & mount the MMC card on the Host.

If you would like to make a small change to the files on the MMC card (for example an Asterisk configuration file), you can edit them on the Blackfin:

  1. First stop asterisk.

  2. Unload wcxfs driver and load the MMC driver:

    "rmmod wcfxs;insmod spi_mmc_bfsi.ko;mount /dev/mmc /mnt"
  3. You can then edit using vi, e.g.: "vi /mnt/etc/asterisk/extensions.conf".

  4. Don't forget to "unmount /mnt" to save your changes before rebooting.

Further Work

The main reason for the MMC card is to provide the large amount of non-volatile flash storage required for an Asterisk IP-PBX. One weakness of the current scheme is that you can't use the MMC card and Asterisk at the same time, for reasons described above. For example it would be nice to mount the MMC card permanently and read Asterisk sound & config files from it directly. The MMC card would also be a nice place to store voice mail.

However there are a few ways to improve the system:

  1. Put appropriate locks in the MMC driver to make sure the wcfxs driver can't use the SPI bus while the MMC driver is busy. This will mean that hook/ring detection won't work too well while the MMC card is in action, but that is probably OK in many cases, e.g. after changing a configuration file you will probably restart Asterisk anyway.

  2. Place the MMC card on a separate SPI bus. This could be implemented by bit-bashing out of some of the spare Xilinx CPLD pins.

  3. The assumption that the chip select line of the MMC card needs to stay asserted for many tens of ms should be checked - this was what I found by experiment but I might have messed up somewhere.

  4. The telephony chips could be placed on a different bus (for example the Si3050 can send signalling info through the TDM bus).

  5. The zaptel/wcfxs driver design could be changed to remove the 1ms SPI access requirement.

Note The IP04 design uses NAND flash which has ample storage. A removable MMC card is available as an option. On the IP04 a 2nd SPI bus for the modules can be implemented using bit bashing of PF pins, or the 2nd SPORT. See The IP04 README for more information.

Stacking Multiple 4fx Cards

The current driver supports up to two 4fx cards and 8 modules, although it would be easy to extend this. However please note that simultaneous operation of all 8 ports has not been load tested, some optimisation may be required.

You need to set the "address" of the two cards to be different using JMP10 and JMP11. You will see a small "A0" and "A1" written near these jumpers. The default setting (no jumpers) means A0=A1=0.

So to configure for 8 ports:

  1. For the top card in the stack, simply place a jumper on JMP11 to make A0=1 and A1=0. Leave the bottom board with no jumpers (the default).

  2. You need to remove J1 on one board (say the top one), which disables the clock on one of 4fx boards. Otherwise you have two 2.048MHz clock sources fighting each other. J1 is next to the little sliver 5mm square clock oscillator and has CLK written near it.