Another bit of programmable hardware: the WRTnode

I’ve got a weak spot for cheap, programmable hardware. In my junk drawer I’ve got a collection of Arduinos, Parallax Propellor boards, a couple of STM32 based ARM boards, and several Beagle Bone Blacks and Raspberry Pis. Today, another entry arrived: the WRTnode.

I’ve only had it out of the box for a few hours, and a little bit of tinkering, but here are my initial impressions.

WRTnodeA few basics first: it’s a small, cheap Linux computer. Nominally, the list price is supposed to be $25, but I ordered mine via the Amazon store and paid a bit of a premium: it cost $35, but shipped in two days via Amazon Prime. It comes in a small plastic box the size of an Altoids tin, and includes a little USB cable that allows you to chain an extra USB device to it, as well as provide power. I plugged mine into a little D-Link USB hub I had lying around. Seems to work fine.

In terms of capability, it falls somewhere between the Arduino and a Raspberry Pi. The processor is actually not ARM based, it’s an MTK MT7620N MIPS processor that runs at 580Mhz. It has a 512Mbit DDR2 RAM and 128Mbit of SPI flash ROM. This is quite a bit less than the Raspberry Pi, but it does have one cool added feature: it’s got a 300Mbit wireless networking chip on board which can do 802.11n. It also can handle USB host mode. Basically, you can think of this as the brains to a fairly reasonable wireless router. It’s a very small board, only 45mm x 50mm, and includes 23 GPIO pins, as well as JTAG and SPI.

Because of it’s rather limited memory, it can’t run full Debian. Instead, it runs the OpenWRT distribution, a small distribution which is often used on tiny embedded boxes that serve as routers. It runs BusyBox, has the tiny shell “ash”, as well as the LuCI web based configuration interface, which is based upon the uhttpd webserver.

Setting it up was pretty darned easy: I plugged the supplied USB cable into it, and the other end into my powered hub. A small blue LED comes on, and about 20 seconds later, a new wireless access point was visible called WRTnode9DDB. If you attach to that network, you are asked for a network password, which defaults to 12345678, and then you can telnet to the device, which defaults to IP address You can login as root with no password. If you run passwd you can enter a new password, and then you can use ssh to connect to it.

Screen Shot 2015-01-02 at 9.14.47 PM

Nifty! If you cat /proc/cpuinfo you can get information about the processor:

system type		: Ralink MT7620N ver:2 eco:6
machine			: WRTNODE
processor		: 0
cpu model		: MIPS 24KEc V5.0
BogoMIPS		: 398.13
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa			: mips1 mips2 mips32r1 mips32r2
ASEs implemented	: mips16 dsp
shadow register sets	: 1
kscratch registers	: 0
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

and ditto for cat /proc/meminfo:

MemTotal:          61852 kB
MemFree:           22516 kB
Buffers:            4828 kB
Cached:            17928 kB
SwapCached:            0 kB
Active:            14292 kB
Inactive:          10744 kB
Active(anon):       3772 kB
Inactive(anon):       76 kB
Active(file):      10520 kB
Inactive(file):    10668 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:          2296 kB
Mapped:             1960 kB
Shmem:              1568 kB
Slab:               6028 kB
SReclaimable:       1784 kB
SUnreclaim:         4244 kB
KernelStack:         296 kB
PageTables:          292 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       30924 kB
Committed_AS:       6948 kB
VmallocTotal:    1048372 kB
VmallocUsed:        2204 kB
VmallocChunk:    1032516 kB

OpenWRT isn’t as full featured as some Linux distributions, but it’s not bad. It includes ssh, Python and Lua. It’s got vi. It runs its own small package manager called opkg, which has a pretty good selection of precompiled packages available for install (although its good to be careful, you don’t have an infinite amount of space). Scanning the list, it’s got installation packages for lighttpd, Asterix, and a bunch of other goodies.

I haven’t had a lot of time to mess with it, but I’m fairly impressed so far. I have a feeling I’m going to miss having a C compiler/make setup on the board, but it looks to be pretty simple to cross compile to it from my main Linux box. I have already rebuilt the distribution, and will probably try flashing it sometime soon.

If you are in the market for a little machine with features like this (esp. with WiFi), it might be worth it.

My first crude DCPU-16 simulator…

A few days ago, I mentioned that @notch, the creator of Minecraft, had a new idea for a space game that he was beginning to work on. One of the features of this game is that your spaceship would be controlled by a simulated computer that you could program. He released a preliminary specification for the 16 bit machine called DCPU-16. I like writing things like this, so I spent a couple of hours and hacked the simple core of one together. It doesn’t yet properly count cycles, but it does implement the basic instruction set, and executes the sample program that he provided in the notes. As yet, he hasn’t specified how things like I/O will work (I suspect some of the type 0 reserved opcodes will be used), so it’s not of much use, but it might serve as the basis for others to explores.

Addendum: The example program implements a simple loop with the target :loop, but I suspect the bottom of the loop should be an IFE rather than an IFN instruction, otherwise, the loop simple exits on the first iteration.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>

 * An implementation of Notch's DCPU-16 specification, version 1.1
 * Written by Mark VandeWettering.

/* this has to be 16 bits, because we aren't going to mask increments
 * and decrements.
typedef unsigned short Word ;
#define MEMSIZE (65536)
Word R[8] = {0, 0, 0, 0, 0, 0, 0, 0} ;
Word PC = 0 ;
Word SP = 0 ;
Word O = 0 ;
Word W = 0 ;
unsigned long cycles = 0L ;

#define OP(w)                   ((w)&(0xF))
#define FIELDA(w)               (((w)>>4)&(0x3F))
#define FIELDB(w)               (((w)>>10)&(0x3F))

unsigned char *Rn[] = { "A", "B", "C", "X", "Y", "Z", "I", "J"} ;

DecodeSRC(Word v)
    Word EA ;
    if (v < 0x8) {
        return R[v] ;
    } else if (v < 0x10) {
        return M[R[v&0x7]] ;
    } else if (v < 0x18) {
        EA = M[PC++] ;
        EA += R[v&0x7] ;
        return M[EA] ;
    } else if (v < 0x20) {
        switch (v) {
        case 0x18:
            return M[SP++] ;
        case 0x19:
            return M[SP] ;
        case 0x1a:
            return M[--SP] ;
        case 0x1b:
            return SP ;
        case 0x1c:
            return PC ;
        case 0x1d:
            return 0 ;
        case 0x1e:
            return M[M[PC++]] ;
        case 0x1f:
            return M[PC++] ;
            abort() ;
    } else if (v < 0x40) {
        return v - 0x20 ;
    abort() ;

Word *
DecodeDST(Word v)
    Word EA ;
    Word *T ;
    if (v < 0x8) {
        return R+v ;
    } else if (v < 0x10) {
        return M+(v&0x7) ;
    } else if (v < 0x18) {
        EA = M[PC++] ;
        EA += R[v&0x7] ;
        return M + EA ;
    } else if (v < 0x1f) {
        switch (v) {
        case 0x18:
            return M+(SP++) ;
        case 0x19:
            return M+SP ;
        case 0x1a:
            return M+(--SP) ;
        case 0x1b:
            return &SP ;
        case 0x1c:
            return &PC ;
        case 0x1d:
            return &W ;
        case 0x1e:
            return M+PC++ ;
        case 0x1f:
            return &W ;
            abort() ;
    } else if (v < 0x40) {
        return &W ;
    abort() ;

SkipArg(Word arg)
    if (arg >= 0x10 && arg < 0x18)
        return 1 ;
    if (arg == 0x1e)
        return 1 ;
    if (arg == 0x1f)
        return 1 ;
    return 0 ;

    Word I = M[PC++] ;
    Word A = FIELDA(I) ;
    Word B = FIELDB(I) ;
    PC += SkipArg(A) ;
    PC += SkipArg(B) ;

#define DEBUGPRINTF(x)          

    Word I ;
    Word T ;
    Word B ;
    Word * A ;
    uint32_t a, b ;

    I = M[PC] ;
    PC ++ ;

    if (OP(I) != 0)
        A = DecodeDST((I>>4)&0x3f) ;
    B = DecodeSRC((I>>10)&0x3f) ;
    switch (OP(I)) {
    case 0x0:
        switch (((I)>>4)&0x3F) {
        case 0x01:
            /* JSR */
            DEBUGPRINTF("... JSR") ;
            /* Push the PC on the stack */
            M[--SP] = PC ;
            PC = B ;
            break ;
            abort() ;
        break ;
    case 0x1:   
        /* SET */
        DEBUGPRINTF("... SET\n") ;
        *A = B ;
        break ;
    case 0x2:   
        /* ADD */
        DEBUGPRINTF("... ADD\n") ;
        a = *A ;
        b = B ;
        *A = (a + b) ;
        O = (a + b) >> 16 ;
        break ;
    case 0x3:
        /* SUB */
        DEBUGPRINTF("... SUB\n") ;
        a = *A ;
        b = B ;
        *A = (a - b) ;
        O = (a - b) >> 16 ;
        break ;
    case 0x4:
        /* MUL */
        DEBUGPRINTF("... MUL\n") ;
        a = *A ;
        b = B ;
        *A = (a * b) ;
        O = ((a * b)>>16) ;
        break ;
    case 0x5:
        /* DIV */
        DEBUGPRINTF("... DIV\n") ;
        a = *A ;
        b = B ;
        if (b == 0) {
            *A = O = 0 ;
        } else {
            *A = a / b ;
            O = ((a<<16)/b) ;
        break ;
    case 0x6:
        /* MOD */
        DEBUGPRINTF("... MOD\n") ;
        a = *A ;
        b = B ;
        if (b == 0)
            *A = 0 ;
            *A = a % b ;
        break ;
    case 0x7:
        /* SHL */
        DEBUGPRINTF("... SHL\n") ;
        a = *A ;
        b = B ;
        *A = a << b ;
        O = (a << b) >> 16 ;
        break ;
    case 0x8:
        /* SHR */
        DEBUGPRINTF("... SHR\n") ;
        a = *A ;
        b = B ;
        *A = a >> b ;
        O = (a << 16) >> b ;
    case 0x9:
        /* AND */
        DEBUGPRINTF("... AND\n") ;
        *A &= B ;
        break ;
    case 0xa:
        /* BOR */
        DEBUGPRINTF("... BOR\n") ;
        *A |= B ;
        break ;
    case 0xb:
        /* XOR */
        DEBUGPRINTF("... XOR\n") ;
        *A ^= B ;
        break ;
    case 0xc:
        /* IFE */
        DEBUGPRINTF("... IFE\n") ;
        if (*A == B) Skip() ;
        break ;
    case 0xd:
        /* IFN */
        DEBUGPRINTF("... IFN\n") ;
        if (*A != B) Skip() ;
        break ;
    case 0xe:
        /* IFG */
        DEBUGPRINTF("... IFG\n") ;
        if (*A > B) Skip() ;
        break ;
    case 0xf:
        /* IFB */
        DEBUGPRINTF("... IFB\n") ;
        if ((*A & B) != 0) Skip() ;
        break ;
    DEBUGPRINTF("\n") ;

Word prog0[] = {
    /* 0000 */ 0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d,
    /* 0008 */ 0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
    /* 0010 */ 0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a,
    /* 0018 */ 0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000,
} ;
    int i ;
    printf("... PC=0x%04X SP=0x%04X ", PC, SP) ;
    for (i=0; i<8; i++)
        printf("%s=0x%04X ", Rn[i], R[i]) ;
    printf("O=0x%04X\n", O) ;

    printf("... DCPU-16 simulator.\n") ;
    printf("... version 1.0, written by Mark VandeWettering\n") ;
    printf("... loading %d words of program ...", sizeof(prog0)/sizeof(prog0[0])) ;

    int i ;
    for (i=0; i<sizeof(prog0)/sizeof(prog0[0]); i++) {
        M[i] = prog0[i] ;
    printf("done.\n\n") ;

    for (i=0; i<20; i++) {
        execute() ;

Xv6, a simple Unix-like teaching operating system

I like operating systems. My first exposure to Unix was a revelation. Unix was a complex operating system that provided useful facilities for programmers, and it wasn’t written in assembler and locked away: it was written in C (the same language that you use to write ordinary programs for Unix) and it was understandable.

This was enhanced by The Lions Commentary on Sixth Edition Unix. It’s a brilliant commentary, clearly describing the source code for the Sixth Edition Unix. It filled a gap in the practical learning of operating systems for a generation of students.

But, well, it’s aging. It’s hard to use the Sixth Edition code, because it’s written for a PDP-11, in an archaic dialect of C, and well… we can do better.

Luckily, that’s what MIT thought too. They created an ANSI C version of the Sixth Edition Unix, compiled it for the x86 architecture in a way that could be run under the QEMU or BOCHS emulator. Here’s the page:

Xv6, a simple Unix-like teaching operating system

It’s less than 8K lines of C, under the MIT license. Seems like the kind of thing that could prove useful: bookmarked for future perusal.

FreeBSD 8.0 is released…

I’ve been a long time fan of FreeBSD, going all the way back to the days (and used regular BSD going back even further). Today, I still have a server which runs FreeBSD, as well as another desktop which is running Ubuntu. Which one I prefer is not really something I choose to argue (or even spend much time thinking about) but I did notice that FreeBSD 8.0 was just released.

FreeBSD 8.0-RELEASE Release Notes.

San Jose Mercury News – Google unveils mobile-phone software strategy

San Jose Mercury News – Google unveils mobile-phone software strategy

the big news is that Google has gone generic, offering free software to anyone who wants it under the relaxed terms of an open-source license, which will allow developers to view the source code for that software. This also means there will not be a “gPhone,” or any sort of phone with the Google brand on it.

“Today’s announcement is more ambitious than any single ‘Google Phone’ that the press has been speculating about,” Google Chief Executive Eric Schmidt said in a statement. “Our vision is that the powerful platform we’re unveiling will power thousands of different phone models.”

The MINIX 3 Operating System

How did I miss this? Minix, the small OS designed by professor Andrew Tanenbaum to teach operating systems concets, is now in its 3.0 revision. From their webpage:

MINIX 1 and 2 were intended as teaching tools; MINIX 3 adds the new goal of being usable as a serious system on resource-limited and embedded computers and for applications requiring high reliability.

Neat. I’ll have to check it out.

SLAX Linux Live, with some questions

Previously I’ve mentioned my appreciation for both Knoppix and Damn Small Linux, both fairly cute LiveCD versions of Linux. The problem is that Damn Small Linux can be just a little bit too small, and Knoppix can be a bit slow to boot, and can seem a bit bloated. Enter SLAX, a LiveCD which is designed to fit on those little 8cm CD blanks that can hold around 185 megabytes. I tried it out this weekend, and it seemed great: slick, fast to boot, has all the stuff I needed except for one: it doesn’t seem to detect any wireless card that I have for my laptop.

I currently have:

  • A Belkin F5D7010 802.11g card
  • A Belkin F5D6020 802.11b card
  • A Dell Truemobile 1150 802.11b card

Neither Belkin card autodetects. For some reason, when the Dell card is inserted, it locks up my machine (all three cards work just fine in Windows). Anyone have any clue what the deal is for setting up wireless in Slax?

Oh, and my laptop seems to run significantly hotter when running Linux. Any clues as to what I could do ACPI wise to make it run cooler?

‘Cool it, Linus’ – Bruce Perens

Over on the Register, there is an article on the ongoing row between Linus Torvalds, Andrew Tridgell, author of the Samba software you’ll find as part of many operating system distributions, and Larry McVoy, CEO of Bitkeeper software, the proprietary revision control software which is used to help maintain order in the Linux kernel source tree.

It’s turning into quite a tiff, and Bruce Perens has weighed in and asking for cooler heads to prevail.

The problem is as far as I can tell, entirely Linus’ fault. He made what must be viewed as an incredibly short sighted decision: to use a propietary product as a key element in open source development. It’s a bad idea, for a number of reasons.

First of all, proprietary software is managed by commercial entities. They are allowed to sign NDAs, they can purchase and sublicense proprietary technology and they go out of business. When such a company goes out of business, there is no guarantee that the software which you are using will continue to be available. Putting the long term viability of your open source project at risk in this way is wreckless.

Secondly, if your goal is to promote open source software promote open source software by sleeping in the bed you’ve made. If the open source alternatives aren’t as good as the proprietary ones, then through your weight behind new or existing projects to improve by using them. Linus wrote:

“So I think open source tends to become technically better over time (but it does take time), but I don’t think it’s a moral imperative.” he writes.

The real issue is of course not whether it is a moral imperative, but rather do most people who would work on such a project view it as better to use and improve open source tools which can be made available to all, or to simply use the best tool available, despite it being against the principles which supposedly you began writing open source software to espouse?

Lastly, Linus simply didn’t take the feelings of a large subset of kernel developers into account. For projects which rely on volunteer labor, that’s just dumb.

I’ve used cvs for years, and spearheaded its use within a couple of different organizations. It’s got its flaws, but it is open, and available, and I’m willing to wait until other open source code revision systems have features which make it profitable for me to change. In my career I’ve used SCCS, RCS, CVS, Perforce and subversion, and will probably use some more before it’s all over. For my own personal work, work that I care about, I’ll choose open alternatives every single time.

VIA Technologies, Inc. releases Linux video driver source

VIA Technologies, Inc. has made code for their ProSavage, ProSavage DDR and Unichrome drivers available over at

Of particular interest to the growing number of Linux enthusiasts and customers utilizing VIA EPIA mainboards, is the source for the S3 Graphics UniChrome family display driver for version 2.6.x kernels. The UniChrome family display driver supports the VIA CLE266 and the new VIA CN400 Digital Media chipsets featured on the popular VIA EPIA M series and VIA EPIA SP series mainboards respectively, and will provide developers with the flexibility to autonomously incorporate support for latest applications based on VIA hardware.

Perhaps my Ubuntu machine will at long last be able to play DVDs at a reasonable speed.

Sarge vs. The Hoary Hedgehog? ran an interesting article about the synergy and tension beween Ubuntu Linux and classic . Ian Murdoch had this to say…

Sarge vs. The Hoary Hedgehog?

But Ian Murdoch, Debian’s founding father, does not believe Ubuntu’s popularity bodes well for Debian-based distros.

“If anything, Ubuntu’s popularity is a net negative for Debian,” Murdoch told “It’s diverged so far from Sarge that packages built for Ubuntu often don’t work on Sarge. And given the momentum behind Ubuntu, more and more packages are being built like this. The result is a potential compatibility nightmare.”

Murdoch argues that if Ubuntu were truly compatible with Debian, all of the energy going into it could be directed at Sarge and toward getting it released, which is what would really benefit the Debian developer ecosystem as a whole.

“I understand what the Ubuntu folks are trying to do, and they’re doing lots of good work that will eventually find its way into Debian,” Murdoch said. “But what we really need right now as a community is for Sarge to be released.

“In that respect, Ubuntu’s popularity is more harmful than helpful.”

Ian, you are missing the point. I suppose that isn’t really surprising, since the reason that Ubuntu exists at all is because Debian has lost its way.

The reason that Ubuntu exists is actually pretty simple: no existing distribution had the features that people wanted. Among things that people want but have not received are:

  • regular releases
  • modern updates to windowing software and applications
  • excitement! A sense that things are really moving.

Yes, the guys behind Ubuntu could have tried to work within Debian. But they would be forced to participate in what seems like an incredibly bloated, lethargic, unresponsive behemoth. Sarge has been years in the making, and is still at least months away from being ready to ship. The current “stable” release of Debian was first released in January of 2002 for pity’s sake.

And another pet peeve of mine: installation. Debian has the most quirky, oddball install of any popular distribution I’ve found. With Ubuntu, you download an iso, burn it, boot it, answer a couple of questions, and you are done.

Ubuntu should hurt Debian. Debian has seemingly worked at dispersing excitement and enthusiasm rather than generating it. It seems always to be looking backwards, rather than forwards. Some people think that is important, but for a project that relies upon the enthusiasm and excitement of volunteers, it doesn’t seem like a viable strategy.

New Release of Ubuntu Linux

The 5.04 version of Ubuntu Linux is freshly released, and is now running on my test machine. I must admit, I am really, really impressed by how quickly Ubuntu has become a mature and useful operating system. Things that are most impressive to me:

  • It only takes up one ordinary CD blank. Yes, one. Yes, it doesn’t include everything in the universe, but it does include a very nice Gnome based desktop, and all the applications that get installed by default look like they are part of one seamless distribution.
  • The Synaptic/apt package manager stuff works simply. Almost childishly so. It would be very easy for almost anyone to keep an Ubuntu system up to date.
  • Ubuntu is committed to be free. Not just open, but actually free.
  • Ubuntu is dedicated to providing high quality multi-lingual support. As an American, I know it’s unfashionable for me to say so, but that’s pretty cool.

There are a couple of small caveats: my system has a Savage chipset videocard (actually, built onto the motherboard) and the DRI stuff that makes playback of dvds and the like fast is not yet ported into this release, so it doesn’t as yet make the best DVD player. But I’m really happy with it. If you are bored with your older, staler distributions, think about giving Ubuntu a try.

Addendum: There is a review of the new Ubuntu release on

Addendum^2: Don’t like Gnome? Prefer KDE? Then what you are looking for is Kubuntu.

First Bootable (Barely) itsyBSD .ISO file

I’ve got a very simple LiveCD of FreeBSD booting off of CDROM. If you are brave, you can surf over to and download the iso image, burn it to CD and give it a try. It doesn’t install anything to any hard disks, so nothing can be hurt by giving it a try, but as usual, no warranties are granted. Try it at your own risk.

It’s got a number of problems, but I should iron them out over the next few days.