Power profiling with the MSP430-JTAG-ISO-MK2

Olimex's MSP430-JTAG-ISO-MK2 has power profiling functionality which can be used from MSPDebug. When a chip is running, the debugger continuously captures current consumption and MAB (program counter) samples, which can be read and analysed.

As of 4 Oct 2012, MSPDebug contains support for the following power profiling functionality:

The driver for this device supports both raw USB and tty access, and can be used to perform firmware updates.

Firmware

After compiling a version of MSPDebug which supports power profiling (as of today, this must be a git snapshot), you will need to ensure that your debugger is running up-to-date firmware. The driver name for this debugger is olimex-iso-mk2, and the preamble displayed on startup will show the debugger version:

Olimex firmware version: 1312d04

If your firmware is older than the version shown, you'll need to update it, using the following binary image:

Update your device as follows (note that the driver also accepts the -d option if you'd prefer to use your operating system's serial driver):

$ mspdebug olimex-iso-mk2 --require-fw-update msp430_jtag_iso_mk2-01312D04.bin
MSPDebug version 0.20 - debugging tool for MSP430 MCUs
Copyright (C) 2009-2012 Daniel Beer <dlbeer@gmail.com>
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Firmware image version: 1312d04: 167936 bytes at offset 0x8000
Writing:     8192/  167936 [  4%]
...
Writing:   163840/  167936 [ 97%]
Verifying:     8192/  167936 [  4%]
...
Verifying:   163840/  167936 [ 97%]
Firmware update successful
Resetting, please wait...
Olimex firmware version: 1312d04
Resetting Olimex command processor...
Initializing FET...

Note that the reset will take a while to complete (about 15 seconds). At this point, you should have a fully functional debugger with power profiling capability.

Basic use

During startup, you should see a message like the following in the preamble:

Power profiling enabled: bufsize = 512 bytes, 55 us/sample

If so, power sampling will occur automatically each time you run the chip. Every invocation of the run command will start the sampler. As the chip runs, samples are read from the debugger and stored into a rolling buffer maintained by MSPDebug. The buffer holds a maximum of 131,072 samples (about 7 seconds worth of run-time).

At any time, you can inspect the state of the collected data with the power info command:

(mspdebug) power info
Sample granularity is 55 us
2 sessions:

Session #1: Thu Oct  4 13:49:54 2012
32921 samples (spanning 1810.655 ms)
3742.2 uA average (6775.8 uAs total charge)

Session #0: Thu Oct  4 13:49:58 2012
13990 samples (spanning 769.450 ms)
3730.1 uA average (2870.1 uAs total charge)

Sessions are numbered in reverse chronological order (0 is the most recent) and listed in forward chronological order. To reset the buffers, use the power clear command.

You can see current consumption as a function of time using the power session command, which takes as arguments a session number and an approximate granularity (in microseconds):

(mspdebug) power session 1 100000
Session #1: Thu Oct  4 13:49:54 2012
32921 samples (spanning 1810.655 ms)
3742.2 uA average (6775.8 uAs total charge)

      Time (us)    Current (uA) MAB            
------------------------------------------------
              0          3122.3 0x0000
          99990          3455.7 wait_idle+0xa
         199980          3459.9 wait_idle+0xe
         299970          3455.2 wait_idle+0xe
         399960          3457.8 wait_idle+0xe
         499950          3462.4 wait_idle+0xe
         599940          3469.5 wait_idle+0x8
         699930          4766.9 wait_idle+0xa
         799920          4879.1 pulse_led+0x14
         899910          3451.8 wait_idle+0x8
         999900          3458.0 wait_idle+0xc
        1099890          3460.3 wait_idle+0x8
        1199880          3460.3 wait_idle+0xe
        1299870          3464.2 wait_idle+0x8
        1399860          3464.2 wait_idle+0xe
        1499850          3611.1 wait_idle+0xa
        1599840          5354.9 pulse_led+0x12
        1699830          4139.0 pulse_led+0x14

The raw data can also be exported for further analysis:

(mspdebug) power export-csv 1 data.csv
Exported 32921 samples to data.csv

Profiling

The collected data is cross-referenced with the executing code in two ways. The first, and simplest way, is that the disassembler will show, for each instruction, the average current over all collected samples. It also shows a summary for the disassembled block at the end. For example:

(mspdebug) dis pulse_led 0x20
pulse_led:
    08082: 5f 42 21 00               MOV.B   &0x0021, R15
    08086: 5f d3                     BIS.B   #0x0001, R15
    08088: c2 4f 21 00               MOV.B   R15,    &0x0021
    0808c: 3f 40 c8 00               MOV     #0x00c8, R15
    08090: 3e 40 d0 07               MOV     #__wdt_clear_value+0x5d0, R14    ;; 5382.3 uA
    08094: 1e 83                     DEC     R14                              ;; 5373.8 uA
    08096: 03 43                     NOP                                      ;; 5379.4 uA
    08098: fd 23                     JNZ     pulse_led+0x12                   ;; 5377.5 uA
    0809a: 3f 53                     ADD     #__ivtbl_16+0x1f, R15            ;; 5381.6 uA
    0809c: f9 23                     JNZ     pulse_led+0xe
    0809e: 5f 42 21 00               MOV.B   &0x0021, R15                     ;; 5495.0 uA
;; Total over this block: 6722.1 uAs in 1249.9 ms (5378.0 uA avg)

(mspdebug) dis wait_idle 0x20
wait_idle:
    080ac: 3f 40 e8 03               MOV     #__wdt_clear_value+0x1e8, R15
    080b0: 3e 40 d0 07               MOV     #__wdt_clear_value+0x5d0, R14    ;; 3486.0 uA
    080b4: 1e 83                     DEC     R14                              ;; 3483.8 uA
    080b6: 03 43                     NOP                                      ;; 3485.8 uA
    080b8: fd 23                     JNZ     wait_idle+0x8                    ;; 3483.8 uA
    080ba: 3f 53                     ADD     #__ivtbl_16+0x1f, R15            ;; 3484.1 uA
    080bc: f9 23                     JNZ     wait_idle+0x4
    080be: 30 41                     RET                                      ;; 3580.8 uA
    080c0: 00 13                     RETI
    080c2: ff ff ff ff               AND.B   @R15+,  __ivtbl_16+0x1f(R15)
    080c6: ff ff ff ff               AND.B   @R15+,  __ivtbl_16+0x1f(R15)
    080ca: ff ff
;; Total over this block: 20758.3 uAs in 5957.5 ms (3484.4 uA avg)

If you have a symbol table available, you can use it to construct a profile report, which lists functions in order of power consumption:

(mspdebug) sym import power-test.elf
(mspdebug) power profile
Addr    Name               Charge (uAs)       Time (ms)    Current (uA)
------------------------------------------------------------------------
0x080ac wait_idle               20762.4          5958.7          3484.4
0x08082 pulse_led                6723.6          1250.2          5378.0