Moving on from my previous post (in which I muttered sullenly about brain-dead
packaging of software for Linux), I began hacking on my Chronos proper tonight.
Read on for some juicy tidbits.
The first order of business was to set up a toolchain targeting MSP430. Since
I’m running Arch on my primary development system,
it was a simple matter to build
gcc-msp430 from the AUR.
With that, I was ready to try compiling things. I assumed (correctly) that the
provided firmware would not build on GCC without modification, but a little
googling pointed me to OpenChronos,
which effectively takes the stock firmware, makes it build with any of several
compilers (TI’s compiler included with CCS,
and GCC). Come to think of it, LLVM
has an experimental MSP430 backend that might be interesting to try out.
One git checkout and an invocation of make later, and I was staring at a
screenful of errors. “How auspicious,” I thought. The first part of the fix was
easy– I simply needed msp430-libc for some of the more specialized functions
that don’t map well into straight C- things like interrupt handling (which is in
msp430-libc’s signal.h for some reason) or machine-specific delays.
The remaining compilation errors after grabbing libc were rather more
troublesome, however. There were two main classes of problem.
- Uses of types at some specific bit-width (such as
uint16_t). These were
easily resolved by strategic inclusion of stdint.h, but I’m not very happy
with how I had to do it. Spraying header inclusions all over the source code is
a poor way to fix things.
- Large delay constants. There were two cases in the radio control code which
adjusted the microcontroller’s voltage regulator, which then requires a
rather long delay before the system can be considered stable again. The solution
in code is simply to delay for as many as ~800000 clock cycles. Normally that
wouldn’t be a problem, but some of the delay constants were larger than the
input type to the
__delay_cycles function could hold. My hacky solution was to
split those into two calls of half the length, which seemed to work out OK.
After a while to figure out the compilation problems, I was able to build a
firmware image. After the struggles I had with unpacking TI’s sample code and
demo applications, it was fortunately painless to actually run them. I just
ensured I had Tcl/Tk installed and ran the Chronos Control Center application.
Putting the Chronos itself into WBSL (Wireless BootStrap Loader) mode and
clicking a few times was easy, and I quickly got my new firmware image flashed
onto the CC430.
Preparing for mods
Now that I had a known-working toolchain, it was time to get to work actually
implementing some of the toy features I wanted to add. Since the single most
interesting feature of the hardware is the radio (although the low-power
capabilities of the MSP430 are quite shiny as well), I set out to see how I
could communicate with the watch from my PC.
One of the USB dongles that comes packaged with the Chronos is a USB wireless
access point, basically just a CC1111 (6801 core with USB and RF transciever). I
understand that earlier revisions of the demo applications didn’t include source
code for the software running on the CC1111, but the current release includes
it. Some people had taken a bit of trouble to reverse-engineer the
but that alone isn’t very useful documentation. With that in mind, I set out to
document for myself how to communicate with the RF access point and go through
that to talk to the Chronos.
Setting up communications is easy, fortunately. The CC1111 is programmed to
enumerate as a USB CDC, so one must only open the virtual serial port it creates
with a 115200 bps baud rate with 8 data bits and 1 stop bit. (If that’s not
terse enough for you: 115200 baud, 8n1.)
With virtual serial communications up, the upper-level protocol is rather easy-
it consists of packets of at least 3 bytes each, where the first one is always
0xFF. Byte 2 provides a command ID, and byte 3 specifies the total packet size,
including the overhead (so the minimum valid size is 3). Anything more in the
message is interpreted based on the command ID.
There are a number of command IDs defined, but only a few that are of particular
interest. In the hopes that somebody else will find it useful, I include my raw
notes on the command bytes below.
As a little bit of context, the system can run on either of two different radio
protocols. TI’s SimpliciTI is a protocol designed mainly for communication
between low-power nodes in a network, while BlueRobin is a radio protocol
developed by IAR Systems, notable with the Chronos because it allows
communication with a heart rate
monitor developed by BMi
Dumps 32-bit product ID into the usb buffer
returns system_status (some file-scope var?)
Turns off bluerobin
Start bluerobin (set a flag, actually), stop simpliciti if that's going
== simpliciti RX
Start simpliciti, stop bluerobin if that's going
Dump the 4 bytes from the simpliciti_data buffer to USB
also mark simpliciti data as read
If no pending data, usb_buffer[PACKET_BYTE_FIRST_DATA] = 0xFF
copy packet from USB to simpliciti buffer and flag for tx ready
1-byte payload packet out, = var simpliciti_sync_buffer_status
copy simpliciti_data buffer out to USB
Flag to turn off simpliciti
flag to start WBSL, turn off bluerobin/simpliciti if active
stop wbsl, turn off LED
copy back var wbsl_status
copy back var wbsl_packet_flag or WBSL_ERROR if wbsl is off
copy back max number of bytes allowed in wbsl payload
set wbsl_packet_flag to WBSL_PROCESSING_PACKET
deocode packet and spew it to the 430
write a byte to the access point's Flash memory
first data byte is the value to write
second and third are address, little-endian (2 is lsb, 3 => msb)
must be in test mode (precede this with BM_INIT_TEST)
(Command and system status constants are defined in
Knowing all the commands, it’s pretty easy to pull out the useful ones.
BM_START_SIMPLICITI makes the access point switch into SimpliciTI mode, and
sending BM_SYNC_START allows direct communication through the radio link with
This is as far as I’m going to go with this adventure for today, but there’s
more to come in the coming days (hopefully, assuming my motivation holds out).
This is just preliminary documentation– I’m hoping to create a more formal set
of documents providing a whirlwind overview of how to get hacking on the
Chronos, but I feel this is an excellent start.