[sipp] type=friend context=internal host=192.168.1.20 port=6000 user=sipp canreinvite=no disallow=all allow=ulaw
uCasterisk (you-see-Asterisk) is a set of scripts, makefiles and patches to build Asterisk for uClinux. The target is the Blackfin BF533 STAMP board, although it should be portable to other uClinux platforms.
uCasterisk in one part of a project to build a completely open telephony platform. Both the hardware and the software are freely available under the GPL.
The uCasterisk port was derived from the OpenWRT port of Asterisk developed by Brian Capouch, and uses a similar set of scripts derived from the cross compilation tool Buildroot.
As far as I know there are two other ports of Asterisk to embedded hardware (OpenWRT and Gumstix). These ports run in a regular Linux environment on embedded hardware that supports a Memory Management Unit (MMU). The difference with uCasterisk is that it runs in a uClinux environment, i.e. on embedded processors without a MMU.
This opens up the use of Asterisk on a variety of other processors; e.g. the Blackfin which has some nice features like DSP capability, low cost, and ease of interfacing to hardware.
The main challenge with the port to uClinux was that uClinux doesn't support shared libraries (at least not in the way regular Linux does) and Asterisk uses LOTs of shared libraries. I worked around this using GNU libtool (which can emulate shared libraries) and some patches to the Asterisk .so loader. The result is that all of the shared libraries are statically linked but Asterisk is tricked into thinking they are .so's. Not quite as good as the real thing (e.g. you need to shut down uCasterisk to add/remove a module), but it seems to work fine.
Despite the static linking, the footprint on the Blackfin is still fairly small, e.g. my current build is about 2.4M for Asterisk which includes a bunch of shared libs (without any sound files).
I have also written about porting multithreaded apps to uClinux here.
Note
|
I am a mainly a hardware/DSP guy so bending the Buildroot scripts and Asterisk Makefile to my will was a stretch for me - I apologise in advance for the mess I have made - please feel free to suggest of help with improvements. |
To test uCasterisk I have been using SIPp. The information in this section might also be useful to other Asterisk newbies who would like to use SIPp for testing, as it took me a few hours to work out how to configure Asterisk and SIPp.
I actually found this really interesting as I hit a few memory management issues related to the differences between Linux and uClinux. This meant I had to research how memory management works for multi-threaded apps on uClinux. For the interest of others I have written a short article on my blog to explain the techniques I used.
Note
|
I would like to thank the Blackfin kernel developers for their efforts - I have found that the 2005R4 RC2 kernel is much more stable, and elegantly kills my apps when they misbehave rather than allowing the kernel to panic. I would also like to say that the support from the Blackfin community is just great. |
Initially I found that uCasterisk would fall over after a few hundred SIP calls, often crashing uClinux. However after gaining some understanding of uClinux memory management, and upgrading the Blackfin uClinux kernel to 2005R4 RC2, it is now much more stable, for example a recent test on a BF533 STAMP executed 500,000 SIP calls over a 12 hour period.
Unfortunately after about 15 simultaneous calls I tend to run out of memory (I only have 64 MByte available on my STAMP BF533 due to a silicon bug). Asterisk seems to require around 2 MByte per call, and without a MMU I need to allocate the worst-case amount of physical memory to each thread. The CPU load at a rate of 10 new calls per second is 20% (measured with top) so at this stage I am memory limited rather than CPU limited.
If anyone has any ideas on how I could reduce per-thread memory usage of Asterisk, please email me you thoughts.
Sometime I would like to research the memory usage further to see if this can be improved, but as a first pass it is sufficient for my needs (SOHO IP-PBX with say 4 FXO ports). I suspect with some tweaking and extra memory a T1-span could be handled by the Blackfin.
The test configuration is:
SIPp is running on a regular Linux box connected to a BF533 STAMP running uCasterisk 0.1.3 over a LAN.
SIPp makes a call to an internal asterisk extension (numbered 2005), that answers the call and does nothing.
SIPp then hangs up after 0.5 of a second (500ms).
SIPp repeats this at a call rate of 10 calls per second.
Here is the sip.conf file I used. Declaring the host IP allows SIPp to make calls without needing to register:
[sipp] type=friend context=internal host=192.168.1.20 port=6000 user=sipp canreinvite=no disallow=all allow=ulaw
This is the extension logic from extensions.conf:
[internal] ; dummy extension just for testing exten => 2005,1,Answer exten => 2005,2,Wait(2) exten => 2005,3,Hangup
And this is the SIPp command line I use on the Linux box used to generate calls (bf533 is the hostname of my BF533 STAMP board).
./sipp -sn uac -d 500 -s 2005 bf533 -l 10
I haven't tried any codecs (e.g. GSM) yet. I am not sure how fast and codecs written in C will run if not optimised for the target processor. The trick is to get inner loops running in internal memory - processor specific optimisation may be required for good performance. However with some assembler optimisation it should be possible to make the codecs very efficient.
For example commercial versions of G729 are available for the Blackfin, they run in about 22 MIPs (i.e. 10-20 channels could run in real time). If you need more MIPs, we can always add another Blackfin, they are only five bucks each!
uCasterisk Blackfin BF533 source: uCasterisk-x.y.z.tar.gz
uCasterisk Blackfin BF533 binary: uCasterisk-x.y.z-bf533.tar.gz
== Parsing '/etc/asterisk/iaxprov.conf': Found -- Loaded provisioning template 'default' [chan_sip.so] => (Session Initiation Protocol (SIP)) == Parsing '/etc/asterisk/sip.conf': Found == SIP Listening on 0.0.0.0:5060 == Using TOS bits 0 == Registered channel type 'SIP' (Session Initiation Protocol (SIP)) == Registered application 'SIPDtmfMode' == Parsing '/etc/asterisk/enum.conf': Found == Parsing '/etc/asterisk/extconfig.conf': Found == Parsing '/etc/asterisk/logger.conf': Found Asterisk Event Logger restarted == Parsing '/etc/asterisk/manager.conf': Found == Parsing '/etc/asterisk/enum.conf': Found == Parsing '/etc/asterisk/rtp.conf': Found == RTP Allocating from port range 10000 -> 20000 Asterisk Ready. *CLI> stop now Beginning asterisk shutdown.... Executing last minute cleanups Asterisk cleanly ending (0). root:/var/tmp> uname -r 2.6.12.1-BFIN-2005R3 root:/var/tmp>
Read the configuration section.
On the host PC:
tar xvzf uCasterisk-0.1.3.tar.gz cd uCasterisk-0.1.3
In the file .config check that:
BR2_TOOLCHAIN_DIR="/opt/uClinux/bfin-uclinux/bin" BR2_KERNEL_SOURCE="/opt/uClinux-dist/linux-2.6.x"
point to your toolchain and target kernel sources. Then:
make
will download, patch, and make all the different packages you need. See the top level Makefile for other useful options.
To downloading and install (host):
./scripts/install_all `hostname`
where hostname above is the hostname of your Blackfin STAMP target.
To start Asterisk (target):
cd /var/tmp ./asterisk -vvvc
Note
|
The procedure above downloads to the RAM file system. I haven't worked out how to store uCasterisk permanently in flash yet - the BF533 STAMP only has 4MByte flash so space could be a problem. The hardware designs we are working on provide extra flash storage. |
To just compile asterisk (say after making a few mods):
make TOPDIR=$(pwd) -C package/asterisk compile
Then to just download asterisk:
./scripts/dltarget build-bfin-uclinux/asterisk-1.0.9/asterisk `hostname`
Sample conf files are stored in packages/asterisk/files, these are standard Asterisk conf files with the following configurations added at the end of each file:
sip.conf: An IpDialog SIP Phone 2 (SIP protocol) iax.conf: An iaxComm Windows softphone (IAX2 protocol)
extensions.conf:
2003: The iaxComm soft phone 2004: The SIP phone 2005: A dummy phone that answers, waits one second and hangs up
Tip
|
The easiest way to test (no hardware required apart from target system) is to download the iaxcomm soft phone and try to dial 2005; Asterisk should answer, wait one second, then hang up. The next easiest way is to download the iaxComm softphone. |
I have generated a binary for those who would like to test uCasterisk on their STAMP board without any compiling. The configuration information (uClinux verison etc) used to generate this binary is here.
On the host:
gunzip uCasterisk-0.1-bf533.tar.gz
Download uCasterisk-0.1-bf533.tar to target /var/tmp, e.g. using tftp or ftp. We have to download to /var/tmp as the executable is too large to download to other parts of the STAMP filesystem (e.g. usr/bin doesn't have enough room).
On the target:
cd /var/tmp tar xvf uCasterisk-0.1-bf533.tar cd ipkg/asterisk cp -a etc/* /etc cp -a usr/* /usr cp -a var/* /var cd ../.. chmod u+x asterisk ./asterisk -vvvc
The make files can automatically generate patches against the standard asterisk and zaptel tar balls. Perform your edits in the build-bfin-uclinux/asterisk-1.0.9 or build-bfin-uclinux/zaptel-1.0.9.1 directory.
Then type:
make asterisk-make-patches
to generate the patch files, which are stored in the package directory.
In channels sub-dir iax2-parser.c was renamed iax2_parser.c, and iax2-provision.c was renamed iax2_provision.c to support the static linking using libtool (it's a long story). This messes up the patching, as diff thinks these files are new. Oops.
Also, in the zaptel package I renamed zaptel.c to zaptel1.c as I couldn't work out how to build a kernel module from two source files when one of them had the same name as the output .ko file. I am sure there is a better way to do this. Can anyone please tell me how?
I am currently using the 2005R4 RC2 kernel and the December 2005 release of Uboot. On my Blackfin BF533 STAMP (V1.2 hardware) target:
root:/var/tmp> uname -r 2.6.12.1-BFIN-2005R4
I am currently using the 2005R4 toolchain (bfin-gcc-3.4.05r4-6.i386.rpm). On my host Linux box:
[root@solomon uCasterisk-0.1.3]# which bfin-uclinux-gcc /opt/uClinux/bfin-uclinux/bin/bfin-uclinux-gcc
Change:
BR2_TOOLCHAIN_DIR="/opt/uClinux/bfin-uclinux/bin" BR2_KERNEL_SOURCE="/opt/uClinux-dist/linux-2.6.x"
in uCasterisk-x.y/.config if your tools and kernel sources are installed in a different location.
Tip
|
Stay up to date with the Blackfin uClinux kernels/toolchain - it is definitely worth it as they are improving rapidly. |
I think these lines in uCasterisk-x.y/.config:
BR2_ARCH="bfin-uclinux" BR2_TOOLCHAIN_DIR="/opt/uClinux/bfin-uclinux/bin"
define the architecture. I would be interested to know if uCasterisk works on other architectures.
Here is a short description of each directory. For more information on Buildroot check out the Buildroot site.
build-bfin-uclinux: is where each of the packages is built using the Blackfin cross compiler. The Buildroot scripts untars each package, apply patches, then builds the package under build-bfin-uclinux. This directory is created dynamically and is not part of the uCasterisk tar ball.
staging-bfin-uclinux: For some packages there is an option "install" step where package components are installed in staging-bfin-uclinux for use by other packages. For example when ncurses is built its header files are installed in staging-bfin-uclinux/usr/include and libncurses.a is installed in staging-bfin-uclinux/usr/lib. This directory is also created dynamically and is not part of the uCasterisk tar ball.
package: Contains the top level Makefile for each package that gets built for uCasterisk. Also contains patches, and configuration files. This is where most of the cleverness of the Buildroot system lies, for example the top level Makefile sets up the appropriate tool chain for the build before calling the regular package make file.
dl: Contains tar-balls of packages downloaded from the web. These are automatically fetched the first time the build process is run.
scripts: Useful scripts supporting the Buildroot process and testing on the Blackfin target hardware.
asciidoc: CSS stylesheets used to control AsciiDoc formatting
The build process works like this:
The top level Makefile calls the package Makefiles for each package.
Each package Makefile downloads the tar-ball, un tars it, patches it, configures and builds it, and optionally "installs" the package in the staging directory.
After all the dependant packages are built, eventually Asterisk gets built.
Some current behaviour quirks:
1/ When running at a high verbose debug level, asterisk dies under high call load. In this case many messages are being sent to the console. Some sort of console buffer or stack overflow problem perhaps?
2/ There is still a possible small memory leak, free memory reduced by about 1M over a 12 hour/500k SIP calls. Possibly some random reduction due to uClinux memory management or some cumulative data still being written to /var/log.