Search this site


Metadata

Articles

Projects

Presentations

Soekris net4501 GPIO on FreeBSD 7.0

I finally picked up some small parts (leds, breadboard, leads, multimeter) from Fry's to start work on my universal remote project. Yes, I know you can buy universal remotes. I want to learn more electronics, so why not use this as a starter project?

Since my Soekris box is now free of it's router duties, I can use it for this project. To do this, I'll need two pieces: an infrared receiver, and an infrared emitter. I bought an infrared emitter led today, and I just need to buy a receiver online (they're like $2).

Before getting there, I needed to learn how to drive the GPIO ports on the net4501.

It was pretty simple to do, nd after hooking up a few wires I had an LED that blinked after a few hours of reading and hacking. The code itself was trivial to write, I just had to learn how to talk to the GPIO ports.

After writing the blinking code, I decided the next step was clearly to add fading to the LED. This is commonly done with PWM (pulse-width modulation). Apple made this technique famous with its "breathing" LED lights on the monitors and laptops when the devices were in sleep mode.

At any rate, I have successfully written code that makes both the error led and the PIO5 (GPIO 0) pin "breathe".

Download glow.c

Soekris net4501 upgrade to FreeBSD 7.0

I've definitely spent 10+ hours in the past 2 days trying to get this system upgraded from 6.0 to 7.0...

Why? First, I was using the wrong power supply, so it would randomly reboot during startup (4 hours, after before I figured that one out, after compiling zillions of kernels, even trying GENERIC from 6.2, 6.3, and 7.0). Then, I couldn't get a stable system image that would boot successfully. It would halt trying to run /sbin/init. Not sure why.

I was initially making my own image with mdconfig, and rsyncing the entire system into a file-backed fs. Then I dd'd this image to my compactflash and put it in the net4501. I gave up on that after several hours, and did this instead:

  1. Bring up a new vmware instance with 2 disks. 1 800mb disk and 1 5gb disk.
  2. Install 7.0-RC1, only install kernel and base.
  3. Mount the 5gb disk (newfs /dev/sd1, mount /dev/sd1 /usr/src) and unpack the kernel sources there. Build kernel (For the soekris box).
  4. Make any necessary config changes (serial console, etc)
  5. Shutdown machine
  6. Use qemu-img to convert the vmware disk into a raw disk image
  7. dd the new image to compact flash.
  8. Rejoice. I have a working net4501 now.
In testing in qemu, I get random timeouts talking to ad0. On the soekris board, I get random timeouts to ad0. wtf :(

Boot into safe-mode, and everything seems find. (Safe mode turns off DMA, iirc)

Networking upgrade - WRT54GL

A few days ago, I noticed that for whatever reason my net4501 box was seemingly incapable of routing packets from comcast to the local lan at faster than 800KB/sec. If I removed some PF rules (such as scrubbing) I could get 900KB/sec, but even still 100% of the cpu was consumed by interrupts (as reported by top(1)).

So, I went to Fry's and picked up a WRT54GL. Got it home, installed dd-wrt on it, and am now happy. PowerBoost (Comcast's "here's lots of bandwidth for the first few seconds of your packet stream") works, and I can download at full 8mbit (1MB/sec) as I am supposed to. Sweet.

This frees up my Soekris net4501 box for new projects. Bonus :)

soekris shenanigans

Nothing quite like killing free time with more projects! I've finally managed to get this net4501 thing working again. My plan of attack this time was to use an nfs root instead of mfs root - this means I was able to build a larger system and netboot off of that rather than having to tweak a bootable image every time I wanted to make a system change. Once the system was bootable I used /stand/sysinstall to partition it and install a bootloader, then quit out. I have a script that puts pretty much all the binaries and libraries I'll need onto the main drive, but it was missing a few crucial libraries and such.

A brief list of some of the things I forgot: /usr/lib/pam_*, login(1), /libexec/ld-elf.so.1, and a few other things. After a few hours of tweaking with crap, I've got it booting off of the cf drive instead of network. Using my laptop to make packages care of FreeBSD's ports, i've got isc-dhcpd and bind9 installed. I haven't spent the time getting a ddns+dhcp configuration yet, but dhcp works. Turning ip forwarding on aswell as adding a nat rule to pf.conf and poof I have a working firewall/router.

With an excessive number of userland tools (things that make using the shell possible), the drive has 18 megs of data on it. Some libraries/binaries are not stripped, some of them, like tcsh, aren't even going to be needed when the final product is done.

A few considerations need to be made for running things on this hardware. The drive is Compact Flash which has a limited number of writes. There are a few places I needed to look at for drive writing issues: /tmp, /var, and access time changes. The latter is the easiest, simply mount / with noatime. I couldn't have /tmp being mounted from the disk, because the random access that goes on there would shorten the lifetime of the CF card. So I used mdconfig to create an 8 meg ramdisk (mdconfig -a -t malloc -s 8m) and mounted that as /tmp. As for /var, the only program I knew that wrote, often, to places in /var was syslogd, so I turned that off for the time being.

So far so good, more updates on this later as I work on it further.

soekris adventures

So for this new part-time job I've got, I'm working on a Soekris net4501. FreeBSD has some surprisingly cool support for these things thanks mostly to [email protected]'s work. Now that I've managed to get a slimmed down version of freebsd built and running (7.3meg world, 2.2 meg kernel) of a pxe boot, I've had a chance to actually play with the darned thing.

The first thing I noticed was /dev/led/error. You can do

echo 1 > /dev/led/error

and viola! The error led on the board is on. This device supports quite the array of syntax you can throw at it. For instance, I can do

echo "f1" > /dev/led/error

and the error led will start blinking. Read led(4) if you care to know more about the rest of the syntax it supports (it'll even handle morse code from running /usr/games/morse -l).

I also discovered there was support for the GPIO pins on the board, too. This is done through the same /dev/led interfaces. To enable one of the pins as a device, you fudge around with the machdep.elan_gpio_config sysctl and you'll end up with devices such as /dev/led/gpio5. Neato! More about the GPIO-specific stuff here:
http://lists.freebsd.org/pipermail/freebsd-current/2003-November/014700.html

So far so good, I've got a usable shell with most tools I use (short of gcc and gdb) in 8.7 megs.

# df -h
Filesystem    Size    Used   Avail Capacity  Mounted on
/dev/md0       19M    8.7M    8.8M    50%    /

Since it's less than 10 megs, I have it mounted in memory instead of nfs. Doesn't hurt too much, seeing as how the board has 64 megs of ram, and with everything booted and me logged in I have 26 megs free.

Speaking of disk size, /usr/bin/host is a whopping 1.1 megs. That's quite large for dynamically linked binary. However, I think it was statically linked against libbind or something silly. Either way in the final product it'll go away, shaving more disk usage off.

This project has been a grand adventure into freebsd's world build system. My whole time working on this has been me writing one makefile. The way it works is fairly slick, I think. First, it generates a 20 meg vnode-backed filesystem, then builds a bunch of things from /usr/src and installs them to that new filesystem. Once this is done, I clean out some unnecessary files like library archives (.a files), worthless things in /usr/share, etc. The kernel is handled much in the same way, doing make buildkernel in /usr/src and then plopping a new kernel.gz in /tftpboot.

The cool part is how libraries are built. The makefile builds all the necessary binaries, installs them, and then uses ldd(1) to look for library dependencies. With this list of required libraries, it builds each required library from /usr/src and installs those. To make things easier to work with, I have two other make targets that let me test the system in both a jail(8) and chroot(8). This soekris board is so cool :)