Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Continuum

An event driven kernel in machine code for the MSP430FR5969, with its own assembler, a cycle counting simulator and a charge balance taken from the data sheet.

Everything here is built from scratch: the assembler, the simulator and the kernel itself. No vendor toolchain, no SDK. Whatever can be checked against an independent implementation is checked against one.

The target is a temperature logger that samples once an hour, keeps five years of readings in FRAM and is read out over the serial port once a month. It spends 99.99 percent of its life asleep, which makes the idle current the only number that really matters.

Status

Part Scope State
Assembler 3 instruction formats, all addressing modes, 20 emulated instructions 38 of 38 against mspdebug
Simulator cycle counting, Timer_A0, RTC_B, LPM3.5 with reset, ADC12, eUSCI, FRAM cache 13 of 13 against mspdebug
Energy model data sheet SLAS704G, no estimates complete
Kernel 2224 bytes, tickless, ADC driver, serial interface runs in the simulator
Hardware MSP-EXP430FR5969 LaunchPad not yet measured
sh run-all-checks.sh

Eleven stages, all green. sh check-status.sh prints one line per stage if you only want to know what passes.

Requirements: python3, plus mspdebug and msp430mcu for the two cross checks against an independent implementation.

The numbers

mean current 0.257 µA
of which idle 5508 of 5556 µAs, or 99.1 percent
storage reach 44032 samples, 1835 days, 5.02 years
CR2032, calculated 97 years
CR2032, in practice 10 to 15 years, limited by the cell

The last two lines are the point. A CR2032 loses about one percent of its 220 mAh per year to self discharge, which works out at 251 nA. The circuit draws about as much as the cell loses on its own, so the cell gives up long before the electronics do. Below roughly a quarter of a microamp, saving current stops buying runtime.

The one register that mattered

LFXTDRIVE in CSCTL4 sets the drive level of the 32 kHz crystal oscillator, and it resets to level 3, the most expensive one. Waking from LPM3.5 is a reset, so the field comes back at level 3 every single time.

Level Load capacitance Oscillator LPM3.5 total
0 3.7 pF 180 nA 250 nA
1 6.0 pF 185 nA 255 nA
2 9.0 pF 225 nA 295 nA
3 12.5 pF 330 nA 400 nA

Of the 250 nA the data sheet quotes for LPM3.5, 180 nA is this oscillator alone. The LaunchPad schematic gives Y4 as a 7.0 pF part, which needs level 1 at most. The kernel never wrote the field, so it ran at level 3 and paid 145 nA for nothing, more than a third of the whole budget.

The kernel now finds the lowest level the crystal tolerates at cold start, records it in FRAM and applies it on every start, with a short check against a note that no longer holds. check-crystal.py measures the result: 0.402 µA down to 0.257 µA.

Documentation

Kernel design sleep paths, tickless timing, calling convention, why LPM3.5 ends in a reset
Energy the model, the crystal, what optimisation gained and where it stopped
Serial readout the button window, the commands, the full dump
Storage one byte per sample, position as timestamp, gap marking
Hardware power supply, jumpers, what the board adds
Bugs found six real defects, none of which showed up in normal operation
Part survey why this chip and not one of the twenty alternatives

Files

File Contents
kernel.s the kernel
assembler.py assembler, emits machine code and TI-Text
simulator.py cycle counting simulator with peripherals and charge balance
energy.py energy model from the data sheet
decode.py reads the sample store, converts raw values to degrees
benchmark.py kernel in the simulator, forecasts, comparisons
parts.py part comparison for this workload
storage.py reach and resolution of the sample store
battery.py, radioisotope.py power source comparisons
addresses.py memory map, read from the assembler symbol table
profiler.py, profiler-detail.py cycles per routine and per instruction
trace.py single steps through the kernel
check-*.py the checks; run-all-checks.sh runs the eleven that gate

check-status.sh runs only the eleven stages of the suite. The other check-*.py files are diagnostic tools that print what happened rather than pass or fail, and they are not part of the gate.

What is open

Verification on real hardware. The simulator works from data sheet figures. Whether reality follows is a question for EnergyTrace on the actual board. Three assumptions are worth checking first: the button on P4.5, the baud rate modulation value 0x92, and the crystal startup time.

Board leakage. The supercapacitor sits in its own power domain and is disconnected from the factory, the debugger can be isolated at J13, and the target current is measurable at J9. What remains in the target domain is the chip, the crystal, two LEDs on driven pins and two buttons. That should be clean, but it has not been measured.

Clock source at run time. The crystal runs continuously, even when only short waits are pending, where the VLO would be cheaper. Switching between them founders on the crystal startup time of several hundred milliseconds.

Licence

MIT, see LICENSE.

About

Event driven kernel in machine code for the MSP430FR5969, with its own assembler, cycle counting simulator and data sheet based energy model

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages