Today I'm stranded in Munich and unable to walk, so I thought it neighborly to measure the stack depth of the GoodFET's firmware in order to determine the minimal microcontroller necessary, reducing the material cost of each unit. This article ought to help those who wish to do the same.
The MSP430F1612 ($15 to $11) that I presently use is rather expensive, and a smaller, cheaper chip will likely suffice. While I don't expect the code to fit in the MSP430F2013 ($3 to $1.50), it's not unreasonable to assume that something like the MSP430F2274 ($5 to $3) would be a good choice.
To determine whether the Flash is sufficient is easy, as I can measure that by the size of the output image. make install reveals this to be 7566 bytes as of r79, which will comfortably fit in the MSP430F2254 (16KB) and 2274 (32KB) and doesn't come close to filling the 1612's 55KB of Flash.
Determining RAM usage is much more difficult, and likely better to be done in actual use than in simulation or by static analysis. I'm implementing this by adding two new commands to the Monitor application. The first, RAM_PATTERN (0x90), fills all of RAM with 0xBEEF, suiciding and resetting at the end. The second, RAM_DEPTH (0x91), measures how large this block of memory is. By running the first, then running several test cases, then running the second, I can accurately measure RAM usage, estimating the minimum required chip for the GoodFET firmware. RAM_PATTERN cannot simple be run at start because the GoodFET restarts each time a client connects.
RAM_PATTERN must know the entry point of the application in order to reset, as well as the start and end addresses of RAM. No care need be taken to avoid damaging the stack or global variables, as a reboot will obliterate and repopulate them anyways.
Looking at the linker script (trunk/firmware/ldscripts/161x.x), it can be seen that the RAM region is defined by data (rwx): ORIGIN = 0x1100, LENGTH = 0x1400, so it extends from 0x1100 to 0x2500. RAM_PATTERN simply writes 0xBEEF over this region, then calls asm("br &0xfffe") to reboot. Don't forget your pointer arithmetic: ++ on a pointer increments by the word size (2), not the integer address (1).
In any case, once these functions are working, it's a simple matter to measure RAM usage. As we know that 0x1400 bytes are available, we can fill with the pattern, then restart, then run code, and compare the number of available bytes. By the following log, you can see that 0x12b2 bytes are unused by the GoodFET firmware even after running the Chipcon test cases, or that 0x1400-0x12b2=0x14E=334 bytes of RAM are necessary.
petite% goodfet.monitor ramfill
petite% goodfet.monitor ramdepth
0x12c4 RAM bytes free.
petite% goodfet.monitor test
Performing monitor self-test.
Self-test complete.
petite% goodfet.cc test >>/dev/null
petite% goodfet.monitor ramdepth
0x12b2 RAM bytes free.
petite%
Rounding that 334 byte measurement up a bit, it still ought to fit in the MSP430F2254's 512 bytes of RAM, with a pin-compatible upgrade available for the 2274 with 1 kilobyte of RAM. For comparison, the present hardware has 5K of RAM with the MSP430F1612 and 10K with the 1611.
Note that this lean behavior is only possible because the GoodFET's firmware is very flat and uses no dynamically allocated buffers. I will be running some more tests, and if they turn out to my liking, there's a good bet that the MSP430F2274 will be the basis of the GoodFET30.
Firmware compatibility between the two chips will require more creativity than the present scheme of a wacky linker script, as they are of different families. Seeing as how plenty of memory is left over, I could write firmware which identifies its host system and configures the I/O ports so as to run on either system from a single image. I don't think that I will do this, as incompatibilities in the I/O port choices would require complication of all I/O routines that could better be handled by preprocessor directives.