Skip to content

oxidecomputer/humility

Repository files navigation

Humility

Humility is the debugger for Hubris.

Guiding principles

Production disposition

Hubris is the artifact that actually runs, and it must be allowed to be optimized in terms of size, space, and run-time; in as much as contortions are required for debuggability, they should be borne by Humility, not Hubris. As a concrete example of this, Humility operates exclusively on release builds of Hubris, relying on (unloaded) DWARF information in the binaries to make sense of the system.

Hubris-specific

Humility is Hubris-specific: it is not trying to be a generic in situ debugger, but rather specifically focused on debugging Hubris-based systems. Humility is therefore willing to encode Hubris-specific concepts like archives and tasks.

Microcontroller-specific

Debuggers must cut through abstractions, which often requires knowledge of underlying implementation detail. For Humility, this means being willing to take advantage of microcontroller-specific debug facilities where applicable. While Hubris may make decisions in the name of greater portability, Humility will generally make decisions to maximize debuggability, even where these facilities are highly specific to a particular MCU.

Device-specific

Humility is unafraid to offer device-specific functionality where that functionality is useful for system debuggability. (For example, humility i2c functions as an I2C analyzer.) That said, all device interaction uses Hubris as a proxy to actually communicate with the devices themselves (e.g., HIF); Humility does not seek to create second I/O path.

Pragmatic

Humility seeks to be useful, and therefore seeks to offer all manners of debugging: in situ, postmortem, dynamic instrumentation, static instrumentation, etc.

Operation

Humility operates by specifying a subcommand. There are options that are Humility-wide (that is, applying to every subcommand), as well as options that are specific to particular subcommands.

Probe

Humility needs to have some way of extracting information and/or controlling the microcontroller running Hubris. This is done through some variant of a debug probe, a separate microcontroller that speaks to debug-specific functionality on the target microcontroller.

For most evaluation boards, this debug probe is available on the board, and is connected to a host via USB, e.g. ST's STLink/V2 on the STM32F407 Discovery or the LPC-Link2 present on the LPCXpresso55S69. (On the Gemini board, there are two SWD headers, one for the LPC55S28 and the other for the STM32H753.)

While Humility allows for direct attachment to an on-chip debugger, doing so precludes other connections (from, for example, OpenOCD), making it too disruptive to development workflows. To allow for easier development workflows, Humility also has the option to attach via OpenOCD.

The debug probe to use is specified to Humility via the -p option (long form --probe) or the HUMILITY_PROBE environment variable, which can have the following values:

  • auto (default): Automatically determine how to attach to the microcontroller. If there is no probe found, this will default to archive.

  • usb: Attach directly via USB to a debug probe. When multiple probes are plugged in via USB, a probe index must be specified as a suffix (e.g., usb-0, usb-1, etc.) To determine which probe is which, examine the serial number in the output of humility probe.

  • vid:pid[:serial]: In some cases, the automatic algorithm may either find the wrong thing, or timeout attempting to search for non-existent probes. In these cases, it can help to explicitly set the vendor ID (VID) and product ID (PID) of the debug probe, which should be colon-delimited, e.g., 0483:374e. (Determining the VID and PID of an attached probe is platform-specific; on Linux one can use the lsusb command.) In cases where there are multiple probes with the same VID and PID, the serial number of the probe (as reported via humility probe or found in the iSerialNumber field of the USB device descriptor) can be postpended, also delimited by a colon, e.g. 0483:374e:004000343137510939383538.

  • ocd: Attach via OpenOCD, which is presumed to have the TCL interface available on localhost on port 6666 (its default).

  • jlink: Attach via Segger JLink, which is presumed to have the GDB interface available on localhost on port 2331 (its default). Note that when semihosting is being used by Hubris, the Segger JLink GDB server will become confused when Humility attaches to it -- and subsequent calls to semihosting will cause a halt. A subsequent Humility invocation will resume the target (directing semihosting output correctly to the running GDB instance), but subsequent semihosting output will again cause a halt. To recover from this condition, send an explicit ^C to the running GDB and continue from the resulting stop.

  • archive: Do not attach to a probe at all, but rather use the specified Hubris archive as the target. Those commands that operate only by reading flash (e.g., humility map) can operate in this mode, but those that operate by reading RAM (e.g., humility tasks) will fail. Commands that operate on either (e.g., humility readmem or humility readvar) will succeed or fail depending on their input.

Archive

Many Humility commands require the complete Hubris archive. This is a ZIP archive created by the build process, and includes all binaries as well as the app.toml file used to configure the Hubris archive. The archive can be found in the target for Hubris, and will end with (.zip), e.g.: /path/to/hurbis/target/demo-stm32h753-nucleo/dist/default/build-demo-stm32h753-nucleo.zip. The Hubris archive is specified via the -a option or the HUMILITY_ARCHIVE environment variable.

In the Humility examples in this documentation, unless otherwise specified, the archive will be assumed to be set via -a or HUMILITY_ARCHIVE.

Dump

Many Humility commands are able to operate postmortem on a Hubris dump, an ELF core file generated by the humility dump command. Dumps are offered in lieu of a probe and an archive and specified via the -d option (long form --dump) or the HUMILITY_DUMP environment variable.

Network

On Hubris systems that are so equipped, Humility can operate over a network in lieu of a dump or probe. When operating over a network, the archive must always be provided via -a, as well as the IP address of the target via -i (long form --ip) or the HUMILITY_IP environment variable. Note that not all commands can operate over the network, including (but not limited to) any command that stops the target or reads memory directly.

Environment

On machines that have several different connected Hubris targets, Humility can become thorny to manage. To aid this, Humility allows for environments: JSON files that define how targets can be reached and auxiliary operations that can be performed upon them. The environment file is specified via either the --environment argument or via the HUMILITY_ENVIRONMENT environment variable; a specific target within the environment is specified via the --target argument or via the HUMILITY_TARGET environment variable.

Environment file structure

The environment file contains a JSON object in which each key represents a target. The members of each target object must include probe and archive, which have the same meaning as the probe and archive as provided via the command line. For example:

{
    "lucky": {
        "probe": "0483:374e:002A00174741500520383733",
        "archive": "/gimlet/hubris/archives/lucky/build-gimlet.zip"
    },
    "sweaty": {
        "probe": "0483:374e:000D00184741500520383733",
        "archive": "/gimlet/hubris/archives/sweaty/build-gimlet.zip"
    },
    "grimey": {
        "probe": "0483:374e:003400185553500820393256",
        "archive": "/gimlet/hubris/archives/grimey/build-gimlet.zip"
    }
}

Some targets may require multiple archives. These can be specified by name. The archive to be used must be specified with the --archive-name option to humility.

{
    "lucky": {
        "probe": "0483:374e:002A00174741500520383733",
        "archive": {
            imagea: "/gimlet/hubris/archives/lucky/build-a-gimlet.zip",
            imageb: "/gimlet/hubris/archives/lucky/build-b-gimlet.zip"
        }
    },
}

The above definition -- when provided via --environment or HUMILITY_ENVIRONMENT -- would allow one to (say) run humility --target grimey tasks or humility --target lucky --image-name imagea tasks. In addition to probe and archive, one may also specify associated commands in a cmds object that contains a mapping of names to commands to execute. For example:

{
    "grimey": {
        "probe": "0483:374e:003400185553500820393256",
        "archive": "/gimlet/hubris/archives/grimey/build-gimlet.zip"
        "cmds": {
            "console": "/bin/sh -c \"grabserial.sh $(findtty.sh grimey)\"",
            "power": {
                "on": "power.sh --on grimey",
                "off": "power.sh --off grimey",
                "status": "power.sh --status grimey",
            }
        }
    }
}

These commands can be in principle accessed by any debugging command, but the humility exec command in particular allows one to execute a command against a specified target. (In the above example, one could execute humility --target grimey exec power.on.)

Commands

humility apptable

This is a deprecated command that allows for the display of the app table found in old Hubris archives; see humility manifest to understand the contents of an archive.

humility auxflash

Tools to interact with the auxiliary flash, described in RFD 311.

This subcommand should be rarely used; humility flash will automatically program auxiliary flash when needed.

humility bankerase

Erase flash in "erase block" size chunks (32 KiB) on the RoT.

Erase len is given in bytes and then rounded up to the nearest block size so that all pages containing the range are erased. Then the erased pages are overwritten with 0s, but only starting at the address given. In other words, if the address is given as 0x40001 and len as 512, flash will be erased from 0x40000 to 0x48000, but address 0x40000 will have value 0xff, and every other byte will have value 0.

humility console-proxy

Act as a proxy for the host serial console when it is jumpered to the SP.

humility counters

humility counters reads and displays any Hubris counters (as created via the counters crate and either the counters! or counted_ringbuf! macros).

For example:

$ humility -d ./hubris.core.0 counters
humility: attached to dump
gimlet_seq
|
+---> drv_gimlet_seq_server::__RINGBUF:
      TOTAL VARIANT
          1 Ice40Rails
          1 IdentValid
          1 ChecksumValid
          1 Reprogram
          1 Programmed
          1 Programming
          1 Ice40PowerGoodV1P2
          1 Ice40PowerGoodV3P3
          1 RailsOff
          1 Ident
          1 A2Status
          1 A2
        102 A1Status
          1 CPUPresent
          1 Coretype
        292 A0Status
         15 A0Power
...

If an argument is provided, only counters that have a name that contains the argument as a substring, or are in a task that contains the argument as a substring will be displayed. For example, to display every counter that has thermal in the name or the containing task:

$ humility -d ./hubris.core.0 counters thermal
humility: attached to dump
thermal
 |
 +---> task_thermal::__RINGBUF:
       TOTAL VARIANT
           1 Start
           1 ThermalMode(Auto)
           3 AutoState(Boot)
           2 AutoState(Running)
          78 ControlPwm
           2 PowerModeChanged
           6 FanAdded
IPC counters

The --ipc argument shows IPC client counters generated automatically by idol, showing the total request count for a given IPC and per-client-task breakdowns. For example:`

$ humility -d ./hubris.core.0 counters --ipc`
humility: attached to dump
drv_gimlet_hf_api::__HOSTFLASH_CLIENT_COUNTERS
 fn HostFlash::get_mux() .............................................. 6 calls
    clients:
    task host_sp_comms (0 restarts) .................... = 0 ........... = 6 ok

 fn HostFlash::set_mux() .............................................. 2 calls
    clients:
    task gimlet_seq (0 restarts) ....................... + 0 ........... + 1 ok
    task host_sp_comms (0 restarts) .................... + 0 ........... + 1 ok
                                                         ---             ---
    totals:                                              = 0 err         = 2 ok

 fn HostFlash::get_dev() .............................................. 1 calls
    clients:
    task host_sp_comms (0 restarts) .................... = 0 ........... = 1 ok


drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS
 fn Sequencer::get_state() ......................................... 2017 calls
    clients:
    task thermal (0 restarts) .......................... + 0 ........ + 1386 ok
    task power (0 restarts) ............................ + 0 ......... + 626 ok
    task host_sp_comms (0 restarts) .................... + 0 ........... + 5 ok
                                                         ---          ------
    totals:                                              = 0 err      = 2017 ok
...

When displaying counters by IPC, substring filtering is performed on the counters variable, but not on the client task name. This allows filtering the output based on the IPC interface. For example:

$ humility -d ./hubris.core.0 counters --ipc sensors
humility: attached to dump
task_sensor_api::__SENSOR_CLIENT_COUNTERS
fn Sensor::post() ................................................ 76717 calls
   clients:
   task power (0 restarts) ............................ + 0 ....... + 50300 ok
   task thermal (0 restarts) .......................... + 0 ....... + 26417 ok
                                                        ---         -------
   totals:                                              = 0 err     = 76717 ok

fn Sensor::get_reading() ......................................... 19804 calls
   clients:
   task thermal (0 restarts) ...................................... = 18101 ok
   - Err(NotPresent) ............................... + 1701 ..................
   - Err(DeviceError) ................................. + 2 ..................
                                                     ------         -------
   totals:                                           = 1703 err     = 18101 ok

fn Sensor::nodata() ............................................... 6225 calls
   clients:
   task power (0 restarts) ............................ + 0 ........ + 3536 ok
   task thermal (0 restarts) .......................... + 0 ........ + 2689 ok
                                                        ---          ------
   totals:                                              = 0 err      = 6225 ok

Instead, to show only the IPC counters recorded by specific client tasks, use the --client argument, which will filter the output counters to those recorded in tasks whose names match the provided strings. For example, to show only IPC counters recorded by the gimlet_seq task, use:

$ humility -d ./hubris.core.0 counters --ipc --client gimlet_seq
humility: attached to dump
drv_gimlet_hf_api::__HOSTFLASH_CLIENT_COUNTERS
 fn HostFlash::set_mux() .............................................. 1 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 1 ok


drv_spi_api::__SPI_CLIENT_COUNTERS
 fn Spi::exchange() ............................................... 67580 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ....... = 67580 ok

 fn Spi::write() .................................................... 530 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ......... = 530 ok

 fn Spi::lock() ....................................................... 4 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 4 ok

 fn Spi::release() .................................................... 1 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 1 ok


drv_stm32xx_sys_api::__SYS_CLIENT_COUNTERS
 fn Sys::gpio_read_input() ........................................ 16796 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ....... = 16796 ok

 fn Sys::gpio_set_reset() ............................................ 15 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 .......... = 15 ok

 fn Sys::gpio_configure_raw() ........................................ 14 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 .......... = 14 ok


task_jefe_api::__JEFE_CLIENT_COUNTERS
 fn Jefe::set_state() ................................................. 5 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 5 ok


task_packrat_api::__PACKRAT_CLIENT_COUNTERS
 fn Packrat::set_spd_eeprom() ........................................ 32 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 .......... = 32 ok

 fn Packrat::set_mac_address_block() .................................. 1 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 1 ok

 fn Packrat::set_identity() ........................................... 1 calls
    clients:
    task gimlet_seq (0 restarts) ....................... = 0 ........... = 1 ok

Multiple --client arguments may be provided, to show IPCs from any of a set of client tasks.

--client may be combined with a filter matching counter variable names, to show only the calls to specific IPC interfaces from specific tasks.

humility dashboard

Provides a captive dashboard that graphs sensor values over time. (The sensor task is required for operation; see the documentation for humility sensors for more details.)

If -o is provided, it specifies an output file for any raw sensor data graphed by the dashboard.

humility debugmailbox

The LPC55 includes an extra access port referred to as the Debug Mailbox. This allows for running a fixed set of commands to do useful things such as forcing SWD enablement and putting the chip into ISP mode without needing to touch an external pin

$ humility debugmailbox debug
Looks like a plausible debug mailbox
Reset chip successfully!
entering debug

$ humility debugmailbox isp
Looks like a plausible debug mailbox
Reset chip successfully!
entered ISP mode!

humility diagnose

This subcommand provides a "firmware engineer in a can" for scanning and reporting issues in a running system. It's mostly concerned with

  • Noticing things that seem fishy, and
  • Taking action to get good snapshots of those things.

This is application-independent logic, so it doesn't have any visibility into things the application may think are fishy -- only general behaviors at the OS level, like faults.

humility doc

Provides detailed documentation for Humility and its commands. To get documentation on Humility, run humility doc; to get documentation for a specific command (like this one!) run humility doc and specify the command name -- and run humility --help to list all commands.

humility dump

humility dump takes a dump of the attached system, writing out an ELF core file:

$ humility dump
humility: attached via ST-Link
humility: core halted
humility: dumping to hubris.core.0
humility: dumped 1.12MB in 24 seconds
humility: core resumed

A dump file name may also be specified:

$ humility dump hubris.core.`date +%s`
humility: attached via ST-Link
humility: core halted
humility: dumping to hubris.core.1600718079
humility: dumped 1.12MB in 24 seconds
humility: core resumed

The resulting dump can be used with many commands (including manifest, map, readvar, and tasks) -- and need not be run on the same machine as the debugged MCU, e.g.:

$ humility -d hubris.core.0 tasks
humility: attached to dump
system time = 94529
ID TASK                       GEN PRI STATE
 0 jefe                         0   0 recv, notif: bit0 bit1(T+71)
 1 net                          1   5 recv, notif: bit0(irq61) bit2(T+213)
 2 sys                          0   1 recv
 3 spi4_driver                  0   3 recv
 4 spi2_driver                  0   3 recv
 5 i2c_driver                   0   3 recv
 6 spd                          0   2 notif: bit0(irq31/irq32)
 7 thermal                      0   5 recv, notif: bit0(T+673)
 8 power                        0   6 recv, notif: bit0(T+351)
 9 hiffy                        0   5 wait: reply from dump_agent/gen0
10 gimlet_seq                   0   4 recv, notif: bit0
11 hash_driver                  0   2 recv
12 hf                           0   3 recv
13 update_server                0   3 recv
14 sensor                       0   4 recv, notif: bit0(T+472)
15 host_sp_comms                0   7 recv, notif: bit0(irq82) bit1
16 udpecho                      0   6 notif: bit0
17 udpbroadcast                 0   6 notif: bit31(T+86)
18 udprpc                       0   6 notif: bit0
19 control_plane_agent          0   6 recv, notif: bit0 bit1(irq37) bit2
20 sprot                        0   4 notif: bit31(T+2)
21 validate                     0   5 recv
22 vpd                          0   4 recv
23 user_leds                    0   2 recv
24 dump_agent                   0   4 wait: reply from sprot/gen0
25 idle                         0   8 RUNNING

humility etm

Enables and operates upon the Embedded Trace Macrocell (ETM) found in some ARM Cortex-M parts.

humility exec

humility exec executes a command for a target within the specified environment. The environment is specified to Humility via an argument (--environment) or an environment variable (HUMILITY_ENVIRONMENT); the target is similarly specified via an argument (--target) or an environment variable (HUMILITY_TARGET). If specified via an argument, note that both the environment and target must occur before any subcommand, e.g.:

$ humility -e /path/to/env.json -t my-target exec power.on

To list available commands, use the --list option.

For more details, see the Humliity documenation on environments.

humility extract

humility extract extracts a file from either a Hubris archive or a dump. By default, the contents of the file are sent to standard output, e.g.:

$ humility -a /path/to/my/hubris-archive.zip extract README.TXT
humility: extracting README.TXT to stdout
This is a build archive containing firmware build artifacts.

- app.toml is the config file used to build the firmware.
- git-rev is the commit it was built from, with optional dirty flag.
- info/ contains human-readable data like logs.
- elf/ contains ELF images for all firmware components.
- elf/tasks/ contains each task by name.
- elf/kernel is the kernel.
- img/ contains the final firmware images.
- debug/ contains OpenOCD and GDB scripts, if available.

To list all of the files in an archive, use the --list (-l) option:

$ humility -a /path/to/my/hubris-archive.zip extract --list
        SIZE NAME
         462 README.TXT
          46 git-rev
        5289 app.toml
        1937 chip.toml
      197456 elf/task/jefe
      208836 elf/task/sys
      288440 elf/task/i2c_driver
      309100 elf/task/spi_driver
     1059092 elf/task/net
       65156 elf/task/user_leds
       87284 elf/task/ping
       31228 elf/task/pong
      178600 elf/task/udpecho
      370756 elf/task/hiffy
      310184 elf/task/hf
      286556 elf/task/hash_driver
       17612 elf/task/idle
      201964 elf/task/rng_driver
      555820 elf/kernel
        1550 info/allocations.txt
        4195 info/map.txt
      632426 img/combined.srec
      307060 img/combined.elf
      862933 img/combined.ihex
      307200 img/combined.bin
      632426 img/final.srec
      307060 img/final.elf
      862933 img/final.ihex
      307200 img/final.bin
        1790 img/flash.ron
        1047 debug/script.gdb
        1586 debug/openocd.cfg
         235 debug/openocd.gdb

Note that the file specified is treated as a substring; if the substring matches exactly one file, it will be extracted:

$ humility -d ./hubris.core.79 extract map
humility: extracting info/map.txt to stdout
ADDRESS  END          SIZE FILE
08000000 08000298      298 target/demo-stm32h753-nucleo/dist/kernel
08000298 08004420     4188 target/demo-stm32h753-nucleo/dist/kernel
08004420 08005604     11e4 target/demo-stm32h753-nucleo/dist/kernel
08005a00 08005a58       58 target/demo-stm32h753-nucleo/dist/idle
08005c00 08005e10      210 target/demo-stm32h753-nucleo/dist/pong
08005e10 08005e88       78 target/demo-stm32h753-nucleo/dist/pong
08006000 080076f4     16f4 target/demo-stm32h753-nucleo/dist/jefe
080076f4 08007c08      514 target/demo-stm32h753-nucleo/dist/jefe
08007c08 08007c08        0 target/demo-stm32h753-nucleo/dist/jefe
08008000 08009798     1798 target/demo-stm32h753-nucleo/dist/udpecho
08009798 08009b90      3f8 target/demo-stm32h753-nucleo/dist/udpecho
08009b90 08009b90        0 target/demo-stm32h753-nucleo/dist/udpecho
08010000 08014020     4020 target/demo-stm32h753-nucleo/dist/hiffy
08014020 08015134     1114 target/demo-stm32h753-nucleo/dist/hiffy
08015134 0801574c      618 target/demo-stm32h753-nucleo/dist/hiffy
08018000 08019970     1970 target/demo-stm32h753-nucleo/dist/i2c_driver
08019970 08019ff4      684 target/demo-stm32h753-nucleo/dist/i2c_driver
08019ff4 0801a300      30c target/demo-stm32h753-nucleo/dist/i2c_driver
0801c000 0801de78     1e78 target/demo-stm32h753-nucleo/dist/spi_driver
0801de78 0801e898      a20 target/demo-stm32h753-nucleo/dist/spi_driver
0801e898 0801eca4      40c target/demo-stm32h753-nucleo/dist/spi_driver
08020000 0802a554     a554 target/demo-stm32h753-nucleo/dist/net
0802a554 0802d74c     31f8 target/demo-stm32h753-nucleo/dist/net
0802d74c 0802d7dc       90 target/demo-stm32h753-nucleo/dist/net
08040000 08041ea0     1ea0 target/demo-stm32h753-nucleo/dist/hf
08041ea0 080426a8      808 target/demo-stm32h753-nucleo/dist/hf
080426a8 080426a8        0 target/demo-stm32h753-nucleo/dist/hf
08044000 08044b8c      b8c target/demo-stm32h753-nucleo/dist/ping
08044b8c 08044d34      1a8 target/demo-stm32h753-nucleo/dist/ping
08044d34 08044d34        0 target/demo-stm32h753-nucleo/dist/ping
08046000 080478b4     18b4 target/demo-stm32h753-nucleo/dist/hash_driver
080478b4 08047f68      6b4 target/demo-stm32h753-nucleo/dist/hash_driver
08047f68 08047f68        0 target/demo-stm32h753-nucleo/dist/hash_driver
08048000 08048fcc      fcc target/demo-stm32h753-nucleo/dist/rng_driver
08048fcc 08049474      4a8 target/demo-stm32h753-nucleo/dist/rng_driver
08049474 08049474        0 target/demo-stm32h753-nucleo/dist/rng_driver
0804a000 0804a634      634 target/demo-stm32h753-nucleo/dist/sys
0804a634 0804a67c       48 target/demo-stm32h753-nucleo/dist/sys
0804a800 0804ac0c      40c target/demo-stm32h753-nucleo/dist/user_leds
0804ac0c 0804ac7c       70 target/demo-stm32h753-nucleo/dist/user_leds
20000400 20000400        0 target/demo-stm32h753-nucleo/dist/kernel
30000000 30000000        0 target/demo-stm32h753-nucleo/dist/net

If the substring matches more than one file, the command will fail and the matching files will be displayed:

$ humility -d ./hubris.core.79 extract toml
humility extract failed: "toml" matches multiple files: app.toml, stm32h7.toml

To redirect output to a particular file, use the --output (-o) option.

To dump the entire archive, leave the file unspecified. (Note that extracting the entire archive requires the specification of an output file to prevent accidental blasts of binary content to the console.)

humility flash

Flashes the target with the image that is contained within the specified archive (or dump). As a precautionary measure, if the specified archive already appears to be on the target, humility flash will fail unless the -F (--force) flag is set. Because this will only check the image ID (and not the entire image), humility flash can be optionally told to verify that all of the program text in the image is on the device by specifying -V (--verify). Similarly, if one wishes to only check the image against the archive (and not flash at all), specify -C (--check).

This attempts to natively flash the part within Humility using probe-rs, but for some parts or configurations, it may need to use OpenOCD as a child process to flash it. If OpenOCD is required but not installed (or isn't in the path), this will fail. If OpenOCD is used, temporary files are created as part of this process; if they are to be retained, the -R (--retain-temporaries) flag should be set. To see what would be executed without actually executing any commands, use the -n (--dry-run) flag. Should use of OpenOCD need to be forced (that is, should probe-rs flashing fail), the -O (--force-openocd) flag can be used. That said, OpenOCD should generally be discouraged; the disposition is to extend probe-rs to support any parts that must be flashed via OpenOCD.

If the specified archive includes auxiliary flash data and the new image includes a task with the AuxFlash API, two slots of auxiliary flash will be programmed after the image is written. See RFD 311 for more information about auxiliary flash management.

humility gdb

This command launches GDB and attaches to a running device.

By default, the user must be running openocd or pyocd in a separate terminal.

The --run-openocd option automatically launches openocd based on the openocd.cfg file included in the build archive.

When using pyocd, it must be launched with the --persist option, because humility gdb connects to it multiple times (once to check the app id, then again to run the console).

humility gimlet

humility gimlet contacts a (recent firmware version) Gimlet over the management network and extracts certain live diagnostic information.

$ humility gimlet --ip fe80::0c1d:9aff:fe64:b8c2%en0 read-seq-regs

For a complete list of subcommands, use humility gimlet --help.

humility gpio

humility gpio allows for GPIO pins to be set, reset, queried or configured on STM32 targets. Commands:

  • --set (-s): Sets a pin (sets it high)
  • --reset (-r): Resets a pin (sets it low)
  • --toggle (-t): Toggles a pin (sets it high if low, low if high)
  • --input (-i): Queries the state of a pin (or all pins if no pin is specified)
  • --configure (-c): Configures a pin

Set, reset, toggle

To change the state of a pin (or pins), specify the pin (or pins) and the desired command. For example, to toggle the state on pin 14 on port B:

$ humility gpio --toggle --pins B:14
humility: attached via ST-Link V3
[Ok([])]

To set pins B:0, B:14 and E:1:

$ humility gpio --set --pins B:0,B:14,E:1
humility: attached via ST-Link V3
[Ok([]), Ok([]), Ok([])]

To reset pin E:1:

$ humility gpio --reset --pins E:1
humility: attached via ST-Link V3
[Ok([])]

Input

To get input values for a particular pin:

$ humility gpio --input --pins B:0,B:14,E:1
humility: attached via ST-Link V3
B:0  = 1
B:14 = 1
E:1  = 0

To get input values for all pins, leave the pin unspecified:

$ humility gpio --input
humility: attached via ST-Link V3
Pin       0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
-----------------------------------------------------------------------
Port A    0   0   1   0   0   0   0   0   0   0   0   0   0   1   1   1
Port B    1   0   0   0   1   0   0   0   0   0   0   0   0   0   1   0
Port C    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port D    0   0   0   0   0   0   0   0   1   1   0   0   0   0   1   0
Port E    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port F    1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port G    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port H    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port I    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port J    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
Port K    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

Configure

To configure a pin, the configuration should be specified as a colon-delimited 5-tuple consisting of:

  • Mode: Input, Output, Alternate, or Analog
  • Output type: PushPull or OpenDrain
  • Speed: Low, Medium, High, or VeryHigh
  • Pull direction: None, Up, or Down
  • Alternate function: one of AF0 through AF15

For example, to configure pin 5 on port A as a push-pull output:

$ humility gpio -c Output:PushPull:High:None:AF0 -p A:5

humility hash

Uses the hash task to hash sequences. The following are all equivalent:

$ humility hash --digest -s abc
$ humility hash --digest -x 61,62,63
$ echo -n abc > abc.txt ; humility hash --digest -f abc.txt
$ hash -i --update -s 'a' ; hash --update -s 'bc' ; hash --finalize

Note that --update can also take a filename as a parameter.

humility hiffy

humility hiffy allows for querying and manipulation of hiffy, the HIF agent present in Hubris. To list all Idol interfaces present in Hubris, use the -l (--list) option, optionally specifying a filter for tasks or interface names if so desired:

$ humility hiffy -l user_leds
humility: attached via ST-Link
INTERFACE                    TASK
UserLeds                     user_leds
  |
  +--> UserLeds.led_on
  |       index                       usize
  |       <ok>                        ()
  |       <error>                     LedError
  |
  +--> UserLeds.led_off
  |       index                       usize
  |       <ok>                        ()
  |       <error>                     LedError
  |
  +--> UserLeds.led_toggle
          index                       usize
          <ok>                        ()
          <error>                     LedError

To enlist the Hubris agent to call a particular interface and operation, use -c (--call), using -a (--arguments) to indicate any arguments, e.g.:

$ humility hiffy -c UserLeds.led_toggle -a index=0
humility: attached via ST-Link
UserLeds.led_toggle() = ()

To view the raw HIF functions provided to programmatic HIF consumers within Humility, use -L (--list-functions).

humility host

humility host pretty-prints host state, which is sent to the SP over IPCC.

It is only functional on a Gimlet SP image.

humility host last-panic

Pretty prints the value of LAST_HOST_PANIC

humility: attached to dump
humility: reading LAST_HOST_PANIC
humility: fixing up trimmed initial data
ipd_cause:   IPCC_PANIC_CALL
ipd_error:   0
ipd_cpuid:   58
ipd_thread:  0xfffff78811079c20
ipd_addr:    0x0
ipd_pc:      0xfffffffff7ee48b8
ipd_fp:      0xfffff78811079a50
ipd_rp:      0x0
ipd_message: I/O to pool 'oxp_410e4dfb-b4d1-4d73-8c39-077bf436da3a' appears to be hung.
ipd_stackid: 16
stack trace:
  vdev_deadman+0x108          (0xfffffffff7ee48b8)
  vdev_deadman+0x43           (0xfffffffff7ee47f3)
  spa_deadman+0x84            (0xfffffffff7ed54d4)
  cyclic_softint+0xe1         (0xfffffffffc03e061)
  cbe_low_level+0x20          (0xfffffffffbc0c3f0)
  av_dispatch_softvect+0x72   (0xfffffffffbcc9d12)
  apix_dispatch_softint+0x35  (0xfffffffff7c92545)
  switch_sp_and_call+0x15     (0xfffffffffbc818c5)
  apix_do_softint+0x5a        (0xfffffffff7c925ba)
  apix_do_interrupt+0x2bf     (0xfffffffff7c9306f)
  _interrupt+0xc3             (0xfffffffffbc00233)
  i86_mwait+0x12              (0xfffffffffbc81042)
  cpu_idle_mwait+0x14b        (0xfffffffffbc5131b)
  cpu_idle_adaptive+0x19      (0xfffffffffbc50f39)
  idle+0xa8                   (0xfffffffffbc96c88)
  thread_start+0xb            (0xfffffffffbc838bb)
ipd_dataidx: 0
ipd_data:    [0; 256]

humility host boot-fail

Pretty-prints the contents of LAST_HOST_BOOT_FAIL

$ humility host boot-fail
humility: attached to dump
humility: reading LAST_HOST_BOOT_FAIL
[0; 4096]

humility i2c

On platforms that have I2C support, humility i2c can be used to scan a bus, scan a device, read a register, or write a register. Its usage will be specific to the board being examined; to specify a controller use the -c, to specify a port (if necessary), use -p; to specify a mux and segment (if necessary), use -m.

For example, on a Gimletlet, here is a scan of controller I2C3, revealing one device at address 0x48:

$ humility i2c -s -c 3
humility: attached via ST-Link

Device scan on controller I2C3:

    R = Reserved   - = No device   \o/ = Device found   X = Timed out

ADDR     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf
0x00       R   R   R   R   R   R   R   R   -   -   -   -   -   -   -   -
0x10       -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
0x20       -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
0x30       -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
0x40       -   -   -   -   -   -   -   - \o/   -   -   -   -   -   -   -
0x50       -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
0x60       -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
0x70       -   -   -   -   -   -   -   -   -   -   -   -   R   R   R   R

To scan that device, specify its address via -d:

$ humility i2c -s -c 3 -d 0x48
humility: attached via ST-Link

Register scan for device 0x48 on I2C3:

      - = No register        ! = No device        X = Timed out

ADDR  0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf
0x00   0b  c8  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0x10   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0x20   0b  c8  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0x30   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0x40   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0x50   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0x60   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0x70   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0x80   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0x90   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0xa0   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0xb0   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0xc0   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0xd0   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00
0xe0   00  00  80  00  20  00  05  00  49  80  05  cb  00  00  00  00
0xf0   00  00  00  00  00  00  00  00  6c  00  06  00  00  00  00  00

(This device is an ADT7420 temp sensor.) To look at a particular register, elide -s and specify the register of interest via -r:

$ humility i2c -c 3 -d 0x48 -r 0xb
humility: attached via ST-Link
Controller I2C3, device 0x48, register 0xb = 0xcb

To write a value to a register, specify the -w flag, along with the value to write, e.g. (for the ADT7420), the MSB of the THIGH register:

$ humility i2c -c 3 -d 0x48 -r 0x4 -w 0x1f
humility: attached via ST-Link
Controller I2C3, device 0x48, register 0x4 = 0x1f

Note that if registers are not writable, the write will (generally) be silently discarded by the device; it can be useful to read the register after writing it to confirm that the value is as expected:

$ humility i2c -c 3 -d 0x48 -r 0x4
humility: attached via ST-Link
Controller I2C3, device 0x48, register 0x4 = 0x1f

To determine the last mux and segment to be enabled on a particular controller/port, use --lastmux (-l):

$ humility i2c -b front --lastmux
humility: attached via ST-Link V3
last selected mux/segment for I2C2, port F: mux 3, segment 2

humility ibc

Interface to BMR491 power regulator

This regulator is present on Gimlet and Sidecar PCAs. Right now, humility ibc only exposes one subcommand: black-box.

humility ibc black-box allows you to read out the blackbox log from the power converter. This can be used to debug previous faults. The log is stored in non-volatile memory, so it should be persistent through power loss.

Here's an example:

$ humility ibc black-box
humility: attached to 0483:374e:001B00083156501320323443 via ST-Link V3
FAULT EVENT
  EVENT_INDEX:        0
  TIMESTAMP           0x000a3747 = 18 hr, 35 min, 51.1 sec
  EVENT_ID            0x0000
  STATUS_WORD         0x0010
    0x0010: Output overcurrent fault
  STATUS_IOUT         0x80
    0x80: Iout Overcurrent Fault
  STATUS_MFR          0x00
  V_IN                0xf84f = 39.500V
  V_OUT               0x6000 = 12.000V
  I_OUT               0x0075 = 117.000A
  TEMPERATURE         0x0023 = 35.000°C
FAULT EVENT
  EVENT_INDEX:        1
  TIMESTAMP           0x000a3751 = 18 hr, 35 min, 52.1 sec
  EVENT_ID            0x0001
  STATUS_WORD         0x0001
    0x0001: System event
  STATUS_MFR          0x01
    0x01: INPUT_LOW_EVENT
  V_IN                0xf83c = 30.000V
  V_OUT               0x0000 = 0.000V
  I_OUT               0x0000 = 0.000A
  TEMPERATURE         0x0000 = 0.000°C
FAULT EVENT
  EVENT_INDEX:        2
  TIMESTAMP           0x2809e751 = 777 day, 11 hr, 22 min, 48.1 sec
  EVENT_ID            0x0002
  STATUS_WORD         0x0001
    0x0001: System event
  STATUS_MFR          0x02
    0x02: CANCEL_EVENT
  V_IN                0xf86b = 53.500V
  V_OUT               0x5f00 = 11.875V
  I_OUT               0x0000 = 0.000A
  TEMPERATURE         0x0012 = 18.000°C
FAULT EVENT
  EVENT_INDEX:        3
  TIMESTAMP           0x50099751 = 1554 day, 4 hr, 9 min, 44.1 sec
  EVENT_ID            0x0003
  STATUS_WORD         0x0001
    0x0001: System event
  STATUS_MFR          0x02
    0x02: CANCEL_EVENT
  V_IN                0xf86b = 53.500V
  V_OUT               0x6000 = 12.000V
  I_OUT               0x0000 = 0.000A
  TEMPERATURE         0x0020 = 32.000°C
LIFECYCLE EVENT
  EVENT_INDEX:        24
  TIMESTAMP           0xffef8ad0 = 4969 day, 18 hr, 41 min, 12.0 sec
  EVENT_ID            0x0680
  STATUS_WORD         0x0001
    0x0001: System event
  STATUS_MFR          0x04
    0x04: CLR_EVENT
  V_IN                0xf86b = 53.500V
  V_OUT               0x5f00 = 11.875V
  I_OUT               0x0000 = 0.000A
  TEMPERATURE         0x001a = 26.000°C
LIFECYCLE EVENT
  EVENT_INDEX:        25
  TIMESTAMP           0xffef8bd4 = 4969 day, 18 hr, 41 min, 38.0 sec
  EVENT_ID            0x0681
  STATUS_WORD         0x0001
    0x0001: System event
  STATUS_MFR          0x05
    0x05: ERASE_OVFL_EVENT
  V_IN                0xf860 = 48.000V
  V_OUT               0x5f00 = 11.875V
  I_OUT               0x0000 = 0.000A
  TEMPERATURE         0x001b = 27.000°C

The log doesn't appear to be completely reliable, especially with respect to timestamps, so take it with a grain of salt and with the datasheet close at hand. For example, the machine in the example above had not be up for 777 days (or, for that matter, for 4,969).

humility itm

humility itm consumes data from the Instrumentation Trace Macrocell (ITM) present in many ARM Cortex-M variants. ITM is problematic in many dimensions: it is lossy; it requires knowledge of the target's clocking to configure properly; it relies on functionality (SWO/SWV) that is often buggy in chip debuggers; it isn't present everywhere (Cortex-M0+ in particular doesn't have ITM). So in general, ITM isn't what Hubris programmers should be looking for: those developing code and wishing to see if and how that code is executed should prefer ring buffers to ITM-based instrumentation. (See the documentation for humility ringbuf for details.)

That said, ITM remains the best way to get certain messages from the Hubris kernel (e.g., boot and panic messages); use humility itm -ea to enable ITM and attach to the connected device. For example, if running with the ping task, one will see messages from jefe restarting it:

$ humility -a /path/to/my/hubris-archive.zip itm -ea
humility: attached via ST-Link
humility: core halted
humility: core resumed
humility: ITM synchronization packet found at offset 6
Task #7 Divide-by-zero
Task #7 Memory fault at address 0x0
Task #7 Divide-by-zero

humility jefe

Humility allows for some (well-defined) manipulation of tasks via jefe, the Hubris supervisor. By default, jefe will carry out a configured set of responses if tasks fault -- restarting them unless configured otherwise. The policy that governs Jefe's response to task failure is called the disposition. While debugging, it can be useful to change Jefe's disposition on a particular task, so that the task will not automatically restart on fault. This is done with the -H/--hold option:

$ humility jefe --hold ping
humility: attached via ST-Link
humility: successfully changed disposition for ping

This doesn't make any immediate changes to the task, but merely updates a table inside jefe. When the task next faults, it will not be restarted, e.g.:

$ humility tasks ping
humility: attached via ST-Link
system time = 26597
ID TASK                 GEN PRI STATE
 8 ping                 121   4 FAULT: divide by zero (was: ready)

This can be particularly useful to couple with either humility dump or humility tasks -sl:

$ humility tasks -sl ping
humility: attached via ST-Link
system time = 103879
ID TASK                 GEN PRI STATE
 8 ping                 121   4 FAULT: divide by zero (was: ready)
   |
   +--->  0x200065b0 0x0802a05e task_ping::divzero
                     @ /home/bmc/hubris/task/ping/src/main.rs:24
          0x20006600 0x0802a0fe userlib::sys_panic
                     @ /home/bmc/hubris/sys/userlib/src/lib.rs:678
          0x20006600 0x0802a0fe main
                     @ /home/bmc/hubris/task/ping/src/main.rs:35

To change the disposition of a task (back) to be restarted, use the --release/-r flag:

$ humility jefe --release ping
humility: attached via ST-Link
humility: successfully changed disposition for ping

--release undoes the effect of --hold. If the task is parked at a fault, it will be restarted immediately. Otherwise just the disposition will be updated and the task will be left alone.

If you would like to cause a task to restart, use the --start/-s flag. This will restart a running task immediately, and will re-run a held task without releasing the hold. This means the task will still be caught at the next fault, giving you a way of precisely trying an operation again.

To inject a fault into a task, use the --fault/-f flag. This will cause jefe to use Kernel Trickery(tm) to inject a fault into the target task, and also switch its disposition to "held" so you can inspect the result. The injected fault has a dedicated type to make clear that the fault originated outside of the task:

$ humility jefe --fault pong
humility: attached via ST-Link
humility: successfully changed disposition for pong
$ humility tasks pong
humility: attached via ST-Link
system time = 191227
ID TASK                 GEN PRI STATE
 7 pong                   0   3 FAULT: killed by jefe/gen0 (was: recv, notif: bit0)
   |
   +--->  0x200063b8 0x08028c0a userlib::sys_recv_stub
                     @ /home/bmc/hubris/sys/userlib/src/lib.rs:288
          0x20006400 0x080280ac userlib::sys_recv
                     @ /home/bmc/hubris/sys/userlib/src/lib.rs:236
          0x20006400 0x080280ba main
                     @ /home/bmc/hubris/task/pong/src/main.rs:13

As with tasks held by --hold, use --release/-r to set the task back to normal, or --start/-s to run it once but catch the next fault.

humility lpc55gpio

The LPC55-equivalent of humility gpio, allowing for GPIO pins to be set, reset, queried or configured on LPC55 targets. Commands:

  • --set (-s): Sets a pin (sets it high)
  • --reset (-r): Resets a pin (sets it low)
  • --toggle (-t): Toggles a pin (sets it high if low, low if high)
  • --input (-i): Queries the state of a pin (or all pins if no pin is specified)
  • --configure (-c): Configures a pin
  • --direction (-d): Configure the direction of a pin

Set, reset, toggle

To change the state of a pin (or pins), specify the pin (or pins) and the desired command. For example, to toggle the state on pin PIO0_17:

$ humility lpc55gpio --toggle --pins PIO0_17
humility: attached via CMSIS-DAP
[Ok([])]

To set pins PIO0_15, PIO0_16 and PIO0_17:

$ humility lpc55gpio --set --pins PIO0_15,PIO0_16,PIO0_17
humility: attached via CMSIS-DAP
[Ok([]), Ok([]), Ok([])]

To reset pin PIO0_17:

$ humility lpc55gpio --reset --pins PIO0_17
humility: attached via CMSIS-DAP
[Ok([])]

Input

To get input values for a particular pin:

$ humility lpc55gpio --input --pins PIO0_10,PIO0_11,PIO1_0
humility: attached via CMSIS-DAP
PIO0_10 = 0
PIO0_11 = 1
PIO1_0 = 0

To get input values for all pins, leave the pin unspecified:

$ humility lpc55gpio --input
humility: attached via ST-Link V3
humility: attached to 1fc9:0143:12UNOSLDXOK51 via CMSIS-DAP
PIO0_0 = 0
PIO0_1 = 0
PIO0_2 = 0
PIO0_3 = 0
PIO0_4 = 0
PIO0_5 = 1
PIO0_6 = 0
PIO0_7 = 0
PIO0_8 = 0
PIO0_9 = 1
PIO0_10 = 0
PIO0_11 = 1
PIO0_13 = 0
...

Configure, direction

To configure a pin, the configuration should be specified as a colon-delimited 6-tuple consisting of:

  • Alternate function: one of Alt0 through Alt9
  • Mode: NoPull, PullDown, PullUp, or Repeater
  • Slew: Standard or Fast
  • Invert: Disable, or Enabled
  • Digital mode: Analog or Digital
  • Open drain: Normal or OpenDrain

Note that the direction of the pin should also likely be configured; this is done via the --direction option, specifying either Input or Output. For example, to configure pin PIO0_17 to be an output:

$ humility lpc55gpio -c Alt0:NoPull:Standard:Disable:Digital:Normal -p PIO0_17
humility: attached via CMSIS-DAP
[Ok([])]
$ humility lpc55gpio -p PIO0_17 --direction Output
humility: attached via CMSIS-DAP
[Ok([])]

humility lsusb

humility lsusb will show you Humility's view of the USB devices available on the system, to help you choose probes and/or diagnose permissions issues.

humility manifest

humility manifest displays information about the Hubris archive. It does not connect at all to a Hubris target to operate. In addition to archive-wide attributes, humility manifest displays the features enabled for each task, as well as any device toplogy information present in the archive, e.g.:

$ humility manifest
     version => hubris build archive v1.0.0
     git rev => 753a57169eba699e73ee59e0cf5345eb1d6e1ae2-dirty
       board => nucleo-h743zi2
        name => demo-stm32h753-nucleo
      target => thumbv7em-none-eabihf
    features => h743, itm
  total size => 140K
 kernel size => 30K
       tasks => 12
                ID TASK                SIZE FEATURES
                 0 hiffy              42.9K h743, stm32h7, itm, i2c, gpio, qspi
                 1 jefe                6.7K itm
                 2 i2c_driver          9.8K h743
                 3 spi_driver         10.7K spi3, h743
                 4 hf                  8.6K h743
                 5 rcc_driver          4.7K h743
                 6 gpio_driver         5.8K h743
                 7 usart_driver        5.9K h743
                 8 user_leds           5.5K stm32h7
                 9 pong                4.7K
                10 ping                5.2K uart
                11 idle                0.1K
   i2c buses => 1 controller, 1 bus
                C PORT MODE NAME          DESCRIPTION
                2 F    init -             -

humility manifest can operate on either an archive or on a dump.

humility map

One common pathology in Hubris tasks is a fault induced when a task attempts to access a memory address outside of its designated regions. (This can happen, for example, because the task attempted to access device memory that was not allocated to it in the build description, because it exceeded the device memory allocated to it, or because it allocated the memory allocated to it, e.g., because of a stack overflow.) humility tasks can be useful to see this happening; a non-zero generation count will indicate that a task has been restarted -- and the log message from jefe will indicate the specific address, e.g.:

$ humility itm -ea
humility: attached via OpenOCD
humility: core halted
humility: core resumed
humility: TPIU sync packet found at offset 1
humility: ITM synchronization packet found at offset 12
Task #7 Memory fault at address 0x200028fc
Task #7 Memory fault at address 0x200028fc
^C

To better understand the memory that a task is trying to access, one can run the humility map command, which shows the memory regions that have been mapped into tasks, in address order:

$ humility -a ~/hubris/target/demo/dist/build-demo.zip map
humility: attached via OpenOCD
DESC       LOW          HIGH          SIZE ATTR   ID TASK
0x08004864 0x08010000 - 0x08017fff   32KiB r-x---  0 jefe
0x08004884 0x08018000 - 0x08019fff    8KiB r-x---  1 rcc_driver
0x080048a4 0x0801c000 - 0x0801ffff   16KiB r-x---  2 usart_driver
0x080048c4 0x08020000 - 0x08023fff   16KiB r-x---  3 user_leds
0x080048e4 0x08024000 - 0x08025fff    8KiB r-x---  4 ping
0x08004904 0x08026000 - 0x08027fff    8KiB r-x---  5 pong
0x08004924 0x08028000 - 0x080280ff     256 r-x---  6 idle
0x08004944 0x0802a000 - 0x0802bfff    8KiB r-x---  7 oh_no
0x08004964 0x0802c000 - 0x0802dfff    8KiB r-x---  8 oh_no2
0x08004874 0x20001000 - 0x200013ff    1KiB rwx---  0 jefe
0x08004894 0x20001400 - 0x200017ff    1KiB rwx---  1 rcc_driver
0x080048b4 0x20001800 - 0x20001bff    1KiB rwx---  2 usart_driver
0x080048d4 0x20001c00 - 0x20001fff    1KiB rwx---  3 user_leds
0x080048f4 0x20002000 - 0x200021ff     512 rwx---  4 ping
0x08004914 0x20002400 - 0x200027ff    1KiB rwx---  5 pong
0x08004934 0x20002800 - 0x200028ff     256 rwx---  6 idle
0x08004954 0x20002900 - 0x200029ff     256 rwx---  7 oh_no
0x08004974 0x20002a00 - 0x20002aff     256 rwx---  8 oh_no2
0x08004824 0x40004400 - 0x400047ff    1KiB rw-d--  2 usart_driver
0x08004844 0x40020000 - 0x400203ff    1KiB rw-d--  2 usart_driver
0x08004854 0x40020c00 - 0x40020fff    1KiB rw-d--  3 user_leds
0x08004834 0x40023800 - 0x40023bff    1KiB rw-d--  1 rcc_driver

(In this case, task 7, oh_no, has overflowed its stack -- which we can see from the map output has been sized to only 256 bytes.)

humility monorail

humility monorail exposes commands to interact with the management network switch and PHYs. It is for management of the management network, and can therefore only be run on two images:

  • app/sidecar/app.toml running on Sidecar hardware
  • app/gimletlet/app-vsc7448.toml, running on a Gimletlet which is attached to a VSC7448 dev kit (VSC5627EV) via SPI. This setup is non-trivial; if you find yourself with a dev kit, talk to Matt about how to wire it up.

Use humility monorail -h to see help, or humility monorail status for a bird's-eye view of the ports.

humility monorail read

The read subcommand allows you to read a register from the VSC7448 switch IC. Registers can be specified in a few ways, but most of the time, you'll want to execute a read by register name:

$ export HUMILITY_TARGET=sidecar
$ humility monorail read DEV1G[0]:DEV_RST_CTRL
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
humility: Reading DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL from 0x71040000
DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL => 0x100000
  bits |    value   | field
 21:20 | 0x1        | SPEED_SEL
    12 | 0x0        | PCS_TX_RST
     8 | 0x0        | PCS_RX_RST
     4 | 0x0        | MAC_TX_RST
     0 | 0x0        | MAC_RX_RST

It's not necessary to use the fully qualified TARGET:GROUP:REGISTER form; any unambiguous subset will work (e.g. in the example above, we used DEV1G[0]:DEV_RST_CTRL instead of the full DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL). If your register name is not unambiguous, an error will be printed.

Register names can be found in the vsc7448-pac crate, which is automatically generated from Microchip's C SDK header files.

It's also possible to execute reads by raw address:

$ humility monorail read 0x71040000
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
humility: Reading DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL from 0x71040000
DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL => 0x100000
  bits |    value   | field
 21:20 | 0x1        | SPEED_SEL
    12 | 0x0        | PCS_TX_RST
     8 | 0x0        | PCS_RX_RST
     4 | 0x0        | MAC_TX_RST
     0 | 0x0        | MAC_RX_RST
humility monorail write

Modifies a register in the VSC7448 switch. Note that there is no checking of read/write vs read-only registers; good luck!

humility monorail info

The info subcommand looks up info on a register in the VSC7448 switch IC. This command is offline, meaning it does not require an attached system.

$ humility monorail info HW_QSGMII_CFG
Register HSIO:HW_CFGSTAT:HW_QSGMII_CFG
Register address: 0x71460170
  bits |    field
    13 | E_DET_ENA
  11:0 | FLIP_LANES
    14 | SHYST_DIS
    12 | USE_I1_ENA

If you provide a value as the final argument, it will decode the register and pretty-print a table:

$ humility monorail info HW_QSGMII_CFG 0x2000
Register HSIO:HW_CFGSTAT:HW_QSGMII_CFG
Register address: 0x71460170
Register value: 0x2000
  bits |    value   | field
    14 | 0x0        | SHYST_DIS
    13 | 0x1        | E_DET_ENA
    12 | 0x0        | USE_I1_ENA
  11:0 | 0x0        | FLIP_LANES
humility monorail status

Prints a table showing the status of every port in the system, along with their PHY (if present). The -p argument allows you to specify a subset of ports, e.g.

$ humility monorail status -p40,41,42,43,44,45
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
PORT | MODE    SPEED  DEV     SERDES  LINK |   PHY    MAC LINK  MEDIA LINK
-----|-------------------------------------|-------------------------------
 40  | QSGMII  100M   1G_16   6G_14   up   | VSC8504  down      down
 41  | QSGMII  100M   1G_17   6G_14   up   | VSC8504  down      up
 42  | QSGMII  100M   1G_18   6G_14   up   | VSC8504  down      down
 43  | QSGMII  100M   1G_19   6G_14   up   | VSC8504  down      down
 44  | QSGMII  1G     1G_20   6G_15   up   | VSC8562  up        up
 45  | QSGMII  1G     1G_21   6G_15   up   | VSC8562  up        up
humility monorail dump

Dumps an entire top-level target on the VSC7448, e.g. DEV1G[0]

$ humility monorail dump DEV1G[0]
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
Dumping target DEV1G[0] (0x71040000 -> 0x710400a0)
DEV1G[0]:DEV_CFG_STATUS:DEV_RST_CTRL    0x00100000
DEV1G[0]:DEV_CFG_STATUS:DEV_STICKY    0x00004000
DEV1G[0]:DEV_CFG_STATUS:DEV_DBG_CFG    0x00000800
DEV1G[0]:DEV_CFG_STATUS:DEV_PORT_PROTECT    0x00000000
DEV1G[0]:DEV_CFG_STATUS:EEE_CFG    0x0011940a
DEV1G[0]:DEV_CFG_STATUS:PTP_CFG    0x00400000
DEV1G[0]:DEV_CFG_STATUS:PTP_EVENTS    0x00000000
...

This subcommand is rather fragile; large targets may overflow the HIF return stack, and it's possible to access invalid registers.

humility monorail mac

Prints the MAC table of the VSC7448 switch. This table shows which MAC addresses have be learned on each port.

$ humility monorail mac
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
Reading 3 MAC addresses...
 PORT |        MAC
------|-------------------
   18 | 0e:1d:23:88:1a:3b
   41 | 0e:1d:7f:c3:07:31
   48 | 0e:1d:15:70:3d:bb
humility monorail counters

Prints or resets (with -r) counters for a port on the VSC7448.

$ humility monorail counters -p48
humility: attached to 0483:374f:002A001C4D46500F20373033 via ST-Link V3
Packet counters: (port 48)
  Receive:
    Unicast:   0
    Multicast: 1049
    Broadcast:  0
  Transmit:
    Unicast:   0
    Multicast: 2099
    Broadcast:  0
humility monorail phy

Subcommand to interact with PHYs on a per-port basis. Supports read, write, info, and dump sub-subcommands, which behave similarly to the commands to interact with VSC7448 registers.

PHY register names are also found in the vsc7448-pac crate.

humility net

humility net exposes commands to interact with the management network from the client's perspective.

(It is the counterpart to humility monorail, which interacts with the management network from the switch's perspective.)

It is fully functional on

  • Gimlet
  • Sidecar
  • PSC
  • gimletlet-mgmt These PCAs have the KSZ8463 switch + VSC85x2 PHY which is our standard management network interface.

humility net ip

The ip subcommand works on any image with network functionality, and prints the MAC and IPv6 address of the board. Note that on boards with multiple ports, this is the lowest MAC / IPv6 address.

humility net mac

This subcommand prints the MAC table from the KSZ8463 switch. It is functional on the boards listed above and the Gimletlet (when the NIC daughterboard is installed)

humility net status

This subcommand shows the status of the management network links. It is only functional on the fully supported boards listed above.

humility net counters

This subcommand shows the internal counters on the management network links. It is only functional on the fully supported boards listed above. In addition, the MAC-side counters are only supported on the VSC8562, not the VSC8552; this is indicated with -- in the relevant table positions.

humility openocd

This command launches OpenOCD based on the config file in a build archive, which then allows one to connect with either GDB or directly via telnet. If the intention is to only run GDB, note that humility gdb --run-openocd will both run OpenOCD and run a foreground GDB that is connected to it.

humility pmbus

Operates on PMBus devices in the system. To list all PMBus devices, use --list (-l):

$ humility pmbus --list
C P  MUX ADDR DEVICE        RAILS
3 H  -   0x24 tps546b24a    V3P3_SP_A2
3 H  -   0x26 tps546b24a    V3P3_SYS_A0
3 H  -   0x27 tps546b24a    V5_SYS_A2
3 H  -   0x29 tps546b24a    V1P8_SYS_A2
3 H  -   0x5a raa229618     VDD_VCORE, VDD_MEM_ABCD
3 H  -   0x5b raa229618     VDDCR_SOC, VDD_MEM_EFGH
3 H  -   0x5c isl68224      VPP_ABCD, VPP_EFGH, V1P8_SP3
4 F  -   0x10 adm1272       V54_FAN
4 F  -   0x14 adm1272       V54_HS_OUTPUT
4 F  -   0x25 tps546b24a    V0P96_NIC_VDD_A0HP
4 F  -   0x67 bmr491        V12_SYS_A2

To query a particular device, specify the device by its I2C identity (controller/port, segment, address):

$ humility pmbus -d 0x67 -c 4 -p f
0x01 OPERATION                 0x84
0x02 ON_OFF_CONFIG             0x18
0x10 WRITE_PROTECT             0x00
0x19 CAPABILITY                0xb0
0x20 VOUT_MODE                 0x15
0x21 VOUT_COMMAND              0x6000 = 12.000V
0x22 VOUT_TRIM                 0x0000 = 0.000V
0x23 VOUT_CAL_OFFSET           0xffb4 = 31.963V
0x24 VOUT_MAX                  0x7333 = 14.400V
0x25 VOUT_MARGIN_HIGH          0x699a = 13.200V
0x26 VOUT_MARGIN_LOW           0x5666 = 10.800V
0x27 VOUT_TRANSITION_RATE      0x9b02 = 0.094V/ms
0x28 VOUT_DROOP                0xe800 = 0.000mV/A
...

In the unusual case that a device is unknown to the system (that is, it does not appear in humility manifest), you can force a particular PMBus driver by using --driver (-D).

For the common case of devices known to the system, you can specify a device by name if it matches a single device in the system (e.g., humility pmbus -d bmr491). In lieu of specifying a device, you can specify a rail via --rail (-r), e.g.:

$ humility pmbus --rail VDD_MEM_EFGH
humility: attached via ST-Link V3
0x00 PAGE                      0x01 = 1
0x01 OPERATION                 0x48
0x02 ON_OFF_CONFIG             0x16
0x04 PHASE                     0x00 = 0
0x07 ZONE_CONFIG               0xfefe
0x08 ZONE_ACTIVE               0x0000
0x10 WRITE_PROTECT             0x00
0x19 CAPABILITY                0xd4
0x20 VOUT_MODE                 0x40
0x21 VOUT_COMMAND              0x04ce = 1.230V
0x22 VOUT_TRIM                 0x0000 = 0.000V
0x23 VOUT_CAL_OFFSET           0x0000 = 0.000V
0x24 VOUT_MAX                  0x05dc = 1.500V
0x25 VOUT_MARGIN_HIGH          0x03b1 = 0.945V
0x26 VOUT_MARGIN_LOW           0x0357 = 0.855V
0x27 VOUT_TRANSITION_RATE      0x09c4 = 0.025V/μs
0x28 VOUT_DROOP                0x0014 = 0.200mV/A
...

You can specify a command (or commands) to run with --command (-C); this can be useful when paired with the --verbose (-v) flag to deconstruct a particular command result:

$ humility pmbus -r VDD_MEM_ABCD --command STATUS_WORD --verbose
humility: attached via ST-Link V3
0x79 STATUS_WORD               0x0000
     |
     | b15    0b0 = no fault                 <= OutputVoltageFault
     | b14    0b0 = no fault                 <= OutputCurrentFault
     | b13    0b0 = no fault                 <= InputFault
     | b12    0b0 = no fault                 <= ManufacturerFault
     | b11    0b0 = POWER_GOOD set           <= PowerGoodStatus
     | b10    0b0 = no fault                 <= FanFault
     | b9     0b0 = no fault                 <= OtherFault
     | b8     0b0 = no fault                 <= UnknownFault
     | b7     0b0 = no fault                 <= Busy
     | b6     0b0 = power is not off         <= Off
     | b5     0b0 = no fault                 <= OutputOvervoltageFault
     | b4     0b0 = no fault                 <= OutputOvercurrentFault
     | b3     0b0 = no fault                 <= InputUndervoltageFault
     | b2     0b0 = no fault                 <= TemperatureFault
     | b1     0b0 = no fault                 <= CMLFault
     | b0     0b0 = no fault                 <= NoneOfTheAbove
     +-----------------------------------------------------------------------

You can also write a PMBus command with --write (-w), which allows for for particular fields to be written, e.g.:

$ humility pmbus -r VDD_VCORE -w OPERATION.MarginFaultResponse=ActUpon
humility: attached via ST-Link V3
humility: I2C3, port H, dev 0x5a, rail 0: successfully wrote OPERATION

It should go without saying that this should be done carefully!

To get specific help on what fields may be written and the legal values for those fields, use --commandhelp (-H):

$ humility pmbus -r VDD_VCORE --commandhelp OPERATION
0x01 OPERATION
     | b7     OnOffState                     <= On/off state
     |        0b0 = Off                      <- output off
     |        0b1 = On                       <- output on
     | b6     TurnOffBehavior                <= Power down behavior
     |        0b0 = Clear                    <- powers down immediately
     |        0b1 = Set                      <- powers down based on TOFF_DELAY
     | b5:4   VoltageCommandSource           <= Source of output voltage
     |        0b00 = VOUT_COMMAND            <- set by VOUT_COMMAND
     |        0b01 = VOUT_MARGIN_LOW         <- set by VOUT_MARGIN_LOW
     |        0b10 = VOUT_MARGIN_HIGH        <- set by VOUT_MARGIN_HIGH
     |        0b11 = AVS_VOUT_COMMAND        <- set by AVSBus
     | b3:2   MarginFaultResponse            <= Margin fault response
     |        0b01 = Ignore                  <- ignore margin faults
     |        0b10 = ActUpon                 <- act upon margin faults
     | b1     TransitionControl              <= Transition control
     |        0b0 = Clear                    <- not set
     |        0b1 = Set                      <- set
     +-----------------------------------------------------------------------

To get a summary of all PMBus rails in the system, use --summarize (-s):

$ humility pmbus --summarize
humility: attached via ST-Link V3
DEVICE      RAIL               PG? #FLT       VIN      VOUT      IOUT    TEMP_1
tps546b24a  V3P3_SP_A2           Y    0   11.969V    3.311V    0.404A  33.500°C
tps546b24a  V3P3_SYS_A0          Y    0   11.969V    3.309V    1.457A  36.250°C
tps546b24a  V5_SYS_A2            Y    0   11.969V    4.982V    0.518A  36.000°C
tps546b24a  V1P8_SYS_A2          Y    0   11.984V    1.797V    3.316A  34.750°C
raa229618   VDD_VCORE            Y    0   11.990V    1.181V   53.200A  40.000°C
raa229618   VDD_MEM_ABCD         Y    0   11.990V    1.224V   28.600A  41.000°C
raa229618   VDDCR_SOC            Y    0   11.950V    0.890V   18.200A  42.000°C
raa229618   VDD_MEM_EFGH         Y    0   11.950V    1.223V   27.400A  43.000°C
isl68224    VPP_ABCD             Y    0   11.950V    2.500V    0.400A  40.000°C
isl68224    VPP_EFGH             Y    0   11.950V    2.499V    0.500A  30.000°C
isl68224    V1P8_SP3             Y    0   11.950V    1.796V    1.600A   0.000°C
adm1272     V54_FAN              Y    4    0x088c    0x088c    0x0810  30.452°C
adm1272     V54_HS_OUTPUT        Y    4    0x088c    0x088b    0x092e  30.690°C
tps546b24a  V0P96_NIC_VDD_A0HP   Y    0   11.984V    0.955V    3.074A  37.500°C
bmr491      V12_SYS_A2           Y    1   53.625V   11.995V   19.250A  35.750°C

Note that for some devices, it is not possible to get accurate voltage and current readings from pmbus alone, as knowledge of how the device is integrated into a larger system is required to interpret raw values. For these devices, the raw value is provided (as in the adm1272 output, above); to get the interpreted value, use humility power instead (which has the added advantage of displaying all power rails in the systemn, not just PMBus devices.)

humility pmbus can use two different mechanisms to perform PMBus actions, selected by the --agent command-line argument.

  • --agent=i2c uses direct construction and execution of raw I2C commands. This only works when connected to the target via a debugger.
  • --agent=idol uses Idol operations, which can be executed over the network. This could also be used (in theory) when connected with a debugger; in practice, the Idol operations have a larger encoding compared to raw I2C operations, so the HIF program may not fit.
  • --agent=auto (the default) selects i2c if we're connected with a debugger or idol if we're connected over the network.

In practice, allowing humility pmbus to select the agent is almost always what you want.

humility power

humility power displays the values associated with power rails, displaying output voltage, output current, input voltate, input current, and temperature. Not all measurements are available for all rails; if a measurement is not provided for a given rail, "-" is printed. To specify which rails are displayed, use the --rails option. If a rail can provide a given measurement, but that measurement is unavailable (say, due to being in a power state whereby the rail is not powered), "x" is displayed. Some rails can determine current by output phase; to display these, use the --phase-current option.

humility powershelf

humility powershelf allows for remotely dumping the state of the PSC power shelves.

This command is currently hard-coded to support only the MWOCP68, and it dumps 50+ properties described in the ACAN-114 application note. It will only dump the properties from a single shelf+rail combination, so seeing properties of all 6 shelves requires calling this command 6 time (with indices 0 through 5).

humility probe

humility probe attempts to infer as much about the hardware state as it can, e.g.:

$ humility probe
humility: attached via ST-Link
humility:        probe => STLink V3, VID 0483, PID 374e
humility: probe serial => 003700303137511139383538
humility:         core => Cortex-M7
humility: manufacturer => STMicroelectronics
humility:         chip => STM32H7, revision 0x2003
humility:       status => executing
humility:  debug units => CSTF(x2) CTI(x2) DWT ETM FPB ITM SCS SWO TMC TPIU
humility:         CSTF => 0x5c004000, 0x5c013000
humility:          CTI => 0x5c011000, 0xe0043000
humility:          DWT => 0xe0001000
humility:          ETM => 0xe0041000
humility:          FPB => 0xe0002000
humility:          ITM => 0xe0000000
humility:          SCS => 0xe000e000
humility:          SWO => 0x5c003000
humility:          TMC => 0x5c014000
humility:         TPIU => 0x5c015000
humility:   ITM status => TRCENA enabled, TCR disabled, TER=0x0
humility:           R0 => 0x20006000
humility:           R1 => 0x20006000
humility:           R2 => 0x0
humility:           R3 => 0x0
humility:           R4 => 0x0
humility:           R5 => 0x0
humility:           R6 => 0x0
humility:           R7 => 0x0
humility:           R8 => 0x0
humility:           R9 => 0x0
humility:          R10 => 0x0
humility:          R11 => 0x0
humility:          R12 => 0x0
humility:           SP => 0x20006100
humility:           LR => 0x802404f
humility:           PC => 0x8024052
humility:         xPSR => 0x61000000
humility:          MSP => 0x20000f48
humility:          PSP => 0x20006100
humility:          SPR => 0x7000000

If provided a Hubris archive, humility probe will display any register contents symbolically, e.g.:

$ humility -a ~/hubris/target/demo/dist/build-demo.zip probe
humility: attached via ST-Link
humility:        probe => STLink V2-1, VID 0483, PID 374b
humility: probe serial => 066DFF383032534E43132614
humility:         core => Cortex-M4
humility: manufacturer => STMicroelectronics
humility:         chip => STM32F40x/STM32F41x, revision 0x1007
humility:  debug units => DWT ETM FPB ITM SCS TPIU
humility:       status => executing
humility:          ITM => TRCENA enabled, TCR enabled, TER=0x3
humility:           R0 => 0x0
humility:           R1 => 0x0
humility:           R2 => 0x1
humility:           R3 => 0x20001bd4
humility:           R4 => 0x20001bd4
humility:           R5 => 0x801d988
humility:           R6 => 0xb004
humility:           R7 => 0x20001bf0
humility:           R8 => 0x40004400
humility:           R9 => 0x1
humility:          R10 => 0x0
humility:          R11 => 0xffff
humility:          R12 => 0x0
humility:           SP => 0x20001ba8
humility:           LR => 0x801c12b   <- main+0xef
humility:           PC => 0x801d290   <- sys_recv_stub+0x1e
humility:         xPSR => 0x61000000
humility:          MSP => 0x20000f48
humility:          PSP => 0x20001ba8
humility:          SPR => 0x7000000

humility qspi

humility qspi manipulates (and importantly, writes to) QSPI-attached flash in Hubris. To read the device identifier, use the --id (-i) option:

$ humility qspi -i
humility: attached via ST-Link V3
DeviceIdData {
    manufacturer_id: Micron(0x20)
    memory_type: 3V(186)
    memory_capacity: 33554432
    uid_n: 16
    # If a Micron device:
    ext_device_id: 0b1000100
        2nd device generation,
        Standard BP scheme,
        HOLD#/RESET#=HOLD
        Additional HW RESET# is available,
        Sector size is Uniform 64KB,
    device_configuration_info: 0
    uid: [9a, ec, 0b, 00, 19, f9, ff$, 39, 00, be, 69, 97, f4, a2]
}
[Ok([20, ba, 19, 10, 44, 0, 9a, ec, b, 0, 19, f9, ff, 39, 0, be, 69, 97, f4, a2])]

To write an image from a file, use the --writefile (-W) option:

$ humility -W ./milan-spew-115k2-2dpc-0.4.1-dataeye.bin
humility: attached via ST-Link V3
humility: erasing 16777216 bytes...
humility: ... done
humility: flashed 16.00MB in 5 minutes

If writing similar images, it is much faster to write only those blocks that differ. To perform a differential write, use the --diffwrite (-D) option:

$ humility qspi -D ./milan-spew-115k2-2dpc-0.4.1.bin
humility: attached via ST-Link V3
humility: erasing 65536 bytes...
humility: ... done
humility: hashed 16.00MB, wrote 64.00KB in 16 seconds

To read, write or hash a particular region, use the --read (-r), --write (-w), or --hash (-H) respectively -- giving the address via --address (-a) and the number of bytes via --nbytes (-n). For example, to read 128 bytes from address 0x120000:

$ humility qspi -r -a 0x120000 -n 128
             \/  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00120000 | 24 50 53 50 ee 7a 31 28 10 00 00 00 20 cd 48 20 | $PSP.z1(.... .H
0x00120010 | 00 00 00 00 40 04 00 00 00 30 12 00 00 00 00 00 | ....@....0......
0x00120020 | 01 00 00 00 00 54 01 00 00 40 12 00 00 00 00 00 | .....T...@......
0x00120030 | 03 00 00 00 00 54 01 00 00 a0 13 00 00 00 00 00 | .....T..........
0x00120040 | 08 00 00 00 40 ea 01 00 00 00 15 00 00 00 00 00 | ....@...........
0x00120050 | 09 00 00 00 40 06 00 00 00 f0 16 00 00 00 00 00 | ....@...........
0x00120060 | 0a 00 00 00 40 06 00 00 00 00 17 00 00 00 00 00 | ....@...........
0x00120070 | 0b 00 00 00 ff ff ff ff 01 00 00 00 00 00 00 00 | ................

To get the SHA256 hash for that same region:

$ humility qspi -H -a 0x120000 -n 128
humility: attached via ST-Link V3
120000..000080: 4d07112733efe240f990fad785726c52de4335d6c5c30a33e60096d4c2576742

By default, Hubris reserved sector 0 (the lowest 64 KiB) of QSPI for its own internal bookkeeping. To override this, use the --write-sector0 flag; this is required for erases and writes that would otherwise modify sector 0, as well as bulk erase.

humility readmem

humility readmem allows one to read a specified range of memory:

$ humility readmem 0x00011b00
humility: attached via DAPLink
humility: reading at 0x11b00 for 256 bytes
             \/  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00011b00 | 00 0f 1a bf 81 54 bc f1 01 0f d0 bd 02 44 bc f1 | .....T.......D..
0x00011b10 | 02 0f 51 70 00 d1 d0 bd 91 70 d0 bd 69 00 01 00 | ..Qp.....p..i...
0x00011b20 | 04 00 00 00 04 00 00 00 17 01 01 00 6b 00 01 00 | ............k...
0x00011b30 | f1 00 01 00 65 78 70 6c 69 63 69 74 20 70 61 6e | ....explicit pan
0x00011b40 | 69 63 00 00 3c 1f 01 00 49 00 00 00 0a 00 00 00 | ic..<...I.......
0x00011b50 | 09 00 00 00 76 69 76 61 20 65 6c 20 6a 65 66 65 | ....viva el jefe
0x00011b60 | 0a 54 61 73 6b 20 23 20 50 61 6e 69 63 21 0a 00 | .Task # Panic!..
0x00011b70 | 61 1b 01 00 06 00 00 00 67 1b 01 00 08 00 00 00 | a.......g.......
0x00011b80 | 20 42 61 64 20 53 79 73 63 61 6c 6c 20 55 73 61 |  Bad Syscall Usa
0x00011b90 | 67 65 20 0a 61 1b 01 00 06 00 00 00 80 1b 01 00 | ge .a...........
0x00011ba0 | 13 00 00 00 93 1b 01 00 01 00 00 00 20 53 74 61 | ............ Sta
0x00011bb0 | 63 6b 20 6f 76 65 72 66 6c 6f 77 20 61 74 20 61 | ck overflow at a
0x00011bc0 | 64 64 72 65 73 73 20 30 78 00 00 00 61 1b 01 00 | ddress 0x...a...
0x00011bd0 | 06 00 00 00 ac 1b 01 00 1d 00 00 00 93 1b 01 00 | ................
0x00011be0 | 01 00 00 00 20 4d 65 6d 6f 72 79 20 66 61 75 6c | .... Memory faul
0x00011bf0 | 74 20 61 74 20 61 64 64 72 65 73 73 20 30 78 00 | t at address 0x.

If an argument is present, it is the number of bytes to read:

$ humility readmem 0x00011d00 100
humility: attached via DAPLink
humility: reading at 0x11d00 for 100 bytes
             \/  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00011d00 | 20 62 6f 75 6e 64 73 3a 20 74 68 65 20 6c 65 6e |  bounds: the len
0x00011d10 | 20 69 73 20 20 62 75 74 20 74 68 65 20 69 6e 64 |  is  but the ind
0x00011d20 | 65 78 20 69 73 20 30 30 30 31 30 32 30 33 30 34 | ex is 0001020304
0x00011d30 | 30 35 30 36 30 37 30 38 30 39 31 30 31 31 31 32 | 0506070809101112
0x00011d40 | 31 33 31 34 31 35 31 36 31 37 31 38 31 39 32 30 | 1314151617181920
0x00011d50 | 32 31 32 32 32 33 32 34 32 35 32 36 32 37 32 38 | 2122232425262728
0x00011d60 | 32 39 33 30                                     | 2930

Both arguments can be in either hex, decimal, octal or binary (addresses and contents will always be printed in hex):

humility readmem 0o216401 0b110
humility: attached via DAPLink
humility: reading at 0x11d01 for 6 bytes
              0 \/  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0x00011d00 |    62 6f 75 6e 64 73                            |  bounds

The length argument can have an optional size suffix. Note that "k" is used to to denote the SI kilobytes (that is, 1000 bytes); if one wishes to have a multiples of 1024 bytes (a kibibyte), "KiB" should be used instead.

To display as half-words (16-bits) use -h; to display as words (32-bits) use -w. (The addresses must be 2-byte and 4-byte aligned, respectively.)

$ humility readmem -w 0x20000000 0x40
humility: attached via DAPLink
humility: reading at 0x20000000 for 64 bytes
                   \/        4        8        c
0x20000000 | 00000001 20000180 0000000b 00005020 | ....... .... P..
0x20000010 | 00000002 200001f0 00838042 00000000 | ....... B.......
0x20000020 | 00004db8 00004dc8 00004d28 00004d28 | .M...M..(M..(M..
0x20000030 | 00004d28 00004d28 00004d28 00004d28 | (M..(M..(M..(M..

A frequent use of readmem is to read peripheral memory; as a convenience, a peripheral name can be used in lieu of an address, provided that an archive or dump is also specified:

$ humility -a ~/hubris/target/gemini-bu/dist/build-gemini-bu.zip readmem -w i2c4
0x30
humility: attached via ST-Link
                   \/        4        8        c
0x58001c00 | 000000f7 00020490 00008000 00008000 | ................
0x58001c10 | 10c0ecff 00000000 00000021 00000000 | ........!.......
0x58001c20 | 00000000 00000080 00000000 00000000 | ................

Note that reading some peripheral memory may have side effects!

It can also be useful to interpret memory contents symbolically; to do this, provide a dump or achive and specify the -s option, e.g.:

$ humility  -a ~/hubris/target/gemini-bu-rot/dist/build-gemini-bu-rot.zip readmem -s 0x20004b30 0x40
humility: attached via DAPLink
0x20004b30 | 0x20004bdc
0x20004b34 | 0x0000000a <- __EXCEPTIONS+0x2
0x20004b38 | 0x80000000
0x20004b3c | 0x00002e2e <- syscall_entry+0xcf6
0x20004b40 | 0x00000000
0x20004b44 | 0x0003c2e3 <- spi:main+0x5b
0x20004b48 | 0x0003ceda <- spi:sys_send_stub+0xe
0x20004b4c | 0x01000000
0x20004b50 | 0x00000000
0x20004b54 | 0x00000000
0x20004b58 | 0x00000000
0x20004b5c | 0x00000000
0x20004b60 | 0x00000000
0x20004b64 | 0x00000000
0x20004b68 | 0x00000000
0x20004b6c | 0x00000000

humility readvar

humility readvar allows one to read a global static variable. To list all such variables, use the -l option:

$ humility readvar -l
humility: MODULE             VARIABLE                       ADDR       SIZE
humility: kernel             CORE_PERIPHERALS               0x20000000 1
humility: kernel             CURRENT_TASK_PTR               0x20000018 4
humility: kernel             DEVICE_PERIPHERALS             0x20000001 1
humility: kernel             FAULT_NOTIFICATION             0x20000004 4
humility: kernel             IRQ_TABLE_BASE                 0x20000010 4
humility: kernel             IRQ_TABLE_SIZE                 0x20000014 4
humility: kernel             TASK_TABLE_BASE                0x20000008 4
humility: kernel             TASK_TABLE_SIZE                0x2000000c 4
humility: kernel             __EXCEPTIONS                   0x08000008 56
humility: kernel             __INTERRUPTS                   0x08000040 620
humility: kernel             __RESET_VECTOR                 0x08000004 4
humility: adt7420            TEMPS_BYMINUTE                 0x2000b848 17288
humility: adt7420            TEMPS_BYSECOND                 0x20008000 14408

To read a variable, specify it:

$ humility readvar CURRENT_TASK_PTR
humility: attached via ST-Link
CURRENT_TASK_PTR (0x20000018) = Some(NonNull<kern::task::Task> {
        pointer: 0x20000558 (*const kern::task::Task)
    })

humility rebootleby

Recovers an LPC55 target by reflashing the CFPA, CMPA, and bootleby image. This will not work if the target has a locked CMPA or SWD access has been disabled!

!!! Using this can be dangerous and should be undertaken with caution

humility registers

humility registers displays the registers from either a live system or a dump, e.g.:

$ humility registers
humility: attached via ST-Link V3
   R0 = 0x00000000
   R1 = 0x0000000a
   R2 = 0x80000000
   R3 = 0x00000000
   R4 = 0x00000000
   R5 = 0x0000f406
   R6 = 0x00002711
   R7 = 0x20000310
   R8 = 0x00000000
   R9 = 0x00000000
  R10 = 0x20000f68
  R11 = 0x00000001
  R12 = 0x200002b4
   SP = 0x200002e8
   LR = 0x0800414f
   PC = 0x08004236
  PSR = 0x4100000f <- 0100_0001_0000_0000_0000_0000_0000_1111
                      |||| | ||         |       |           |
                      |||| | ||         |       |           + Exception = 0xf
                      |||| | ||         |       +------------ IC/IT = 0x0
                      |||| | ||         +-------------------- GE = 0x0
                      |||| | |+------------------------------ T = 1
                      |||| | +------------------------------- IC/IT = 0x0
                      |||| +--------------------------------- Q = 0
                      |||+----------------------------------- V = 0
                      ||+------------------------------------ C = 0
                      |+------------------------------------- Z = 1
                      +-------------------------------------- N = 0

  MSP = 0x200002e8
  PSP = 0x20011ab0
  SPR = 0x01000001 <- 0000_0001_0000_0000_0000_0000_0000_0001
                            |||         |         |         |
                            |||         |         |         + PRIMASK = 1
                            |||         |         +---------- BASEPRI = 0x0
                            |||         +-------------------- FAULTMASK = 0
                            ||+------------------------------ CONTROL.nPRIV = 1
                            |+------------------------------- CONTROL.SPSEL = 0
                            +-------------------------------- CONTROL.FPCA = 0

FPSCR = 0x00000000

If an archive is provided or if displaying registers from a dump, the symbol that corresponds to register's value (if any) is displayed, e.g.:

$ humility -d ./hubris.core.81 registers
humility: attached to dump
   R0 = 0x00000000
   R1 = 0x0000000a
   R2 = 0x80000000
   R3 = 0x00000000
   R4 = 0x00000000
   R5 = 0x0000f406
   R6 = 0x00002711
   R7 = 0x20000310 <- kernel: 0x20000000+0x310
   R8 = 0x00000000
   R9 = 0x00000000
  R10 = 0x20000f68 <- kernel: DEVICE_PERIPHERALS+0x0
  R11 = 0x00000001
  R12 = 0x200002b4 <- kernel: 0x20000000+0x2b4
   SP = 0x200002e8 <- kernel: 0x20000000+0x2e8
   LR = 0x0800414f <- kernel: write_str<cortex_m::itm::Port>+0xd
   PC = 0x08004236 <- kernel: panic+0x36
  PSR = 0x4100000f <- 0100_0001_0000_0000_0000_0000_0000_1111
                      |||| | ||         |       |           |
                      |||| | ||         |       |           + Exception = 0xf
                      |||| | ||         |       +------------ IC/IT = 0x0
                      |||| | ||         +-------------------- GE = 0x0
                      |||| | |+------------------------------ T = 1
                      |||| | +------------------------------- IC/IT = 0x0
                      |||| +--------------------------------- Q = 0
                      |||+----------------------------------- V = 0
                      ||+------------------------------------ C = 0
                      |+------------------------------------- Z = 1
                      +-------------------------------------- N = 0

  MSP = 0x200002e8 <- kernel: 0x20000000+0x2e8
  PSP = 0x20011ab0 <- pong: 0x20011800+0x2b0
  SPR = 0x01000001 <- 0000_0001_0000_0000_0000_0000_0000_0001
                            |||         |         |         |
                            |||         |         |         + PRIMASK = 1
                            |||         |         +---------- BASEPRI = 0x0
                            |||         +-------------------- FAULTMASK = 0
                            ||+------------------------------ CONTROL.nPRIV = 1
                            |+------------------------------- CONTROL.SPSEL = 0
                            +-------------------------------- CONTROL.FPCA = 0

To display a stack backtrace, use the --stack (-s) option:

$ humility -d ./hubris.core.81 registers --stack
humility: attached to dump
   R0 = 0x00000000
...
  R10 = 0x20000f68 <- kernel: DEVICE_PERIPHERALS+0x0
  R11 = 0x00000001
  R12 = 0x200002b4 <- kernel: 0x20000000+0x2b4
   SP = 0x200002e8 <- kernel: 0x20000000+0x2e8
        |
        +--->  0x20000318 0x08004236 rust_begin_unwind
               0x20000330 0x08000558 core::panicking::panic_fmt
               0x20000358 0x08000ad8 core::panicking::panic
               0x20000390 0x08003ba6 kern::arch::arm_m::safe_sys_tick_handler
               0x20000390 0x08003ba6 kern::arch::arm_m::SysTick::{{closure}}
               0x20000390 0x08003ba6 kern::arch::arm_m::with_task_table
               0x20000390 0x08003bb0 SysTick

   LR = 0x0800414f <- kernel: write_str<cortex_m::itm::Port>+0xd
...

To additionally display floating point registers on platforms that support floating point, use the --floating-point (-f) option.

humility rencm

Query the Renesas 8A3400X ClockMatrix part -- or process a trace from Renesas configuration software.

humility rendmp

humility rendmp allows for querying, dumping and flashing the Renesas Digital Multiphase family of voltage regulators.

Like humility pmbus, a device can be specified in terms of an address (which requires the further specification of a controller and port) or a PMbus rail.

To view the number of NVM OTP slots that remain, use the --slots option:

$ humility rendmp -b mid -d 0x5a --slots
humility: attached via ST-Link V3
humility: RAA229618 at I2C3, port H, dev 0x5a has 28 slots available

To determine the OTP CRC, use the --crc option. Note that an entirely unprogrammed part generally has a CRC of 0:

$ humility rendmp -b mid -d 0x5a --crc
humility: attached via ST-Link V3
humility: RAA229618 at I2C3, port H, dev 0x5a has CRC 0x00000000

To flash a part (that is, to program its one-time programmable non-volatile memory), specify the HEX file as generated by the Renesas PowerNavigator. Note that this file specifies the address of the device; mismatches are not permitted, e.g.:

$ humility rendmp -b mid -d 0x5b --flash ./raa229618-0x5a.hex
humility: attached via ST-Link V3
humility rendmp failed: image specifies address to be 0x5a; can't flash 0x5b

Specify the proper device to flash:

$ humility rendmp -b mid -d 0x5a --flash ./raa229618-0x5a.hex
humility: attached via ST-Link V3
humility: 28 NVM slots remain
humility: flashing 2871 bytes
humiility: flashed 2.80KB in 4 seconds
humility: bank 0: bank written successfully
humility: flashed successfully after 246 ms; power cycle to load new configuration

To check a configuration, specify the image and the --check option:

$ humility rendmp -b mid -d 0x5c -f ./isl68224-0x5c.hex --check
humility: attached via ST-Link V3
humility: 27 NVM slots remain
humility: image CRC (0x841f35a5) matches OTP CRC

The Renesas voltage regulators include a black box which stores fault information. This can be queried using the --blackbox subcommand, specifying a device (I2C) address to pick a specific power converter:

$ humility rendmp --blackbox --device=0x5b
humility: attached to 0483:374f:000C001F4D46500F20373033 via ST-Link V3
rail0 uptime: 0 sec
rail1 uptime: 0 sec
controller fault: 0
rail0 fault: 00000000000000000000000000000000 ()
rail1 fault: 00000000000000000000000000000000 ()
phase fault uc: 00000000000000000000000000000000 ()
phase fault oc: 00000000000000000000000000000000 ()
adc fault uc: 00000000000000000000000000000000 ()
adc fault oc: 00000000000000000000000000000000 ()
rail0 status: 0000000000000000 ()
rail1 status: 0000000000000000 ()
status cml: 00000000 ()
status mfr: 00000000 ()
rail1 status vout: 00000000 ()
rail0 status vout: 00000000 ()
rail1 status iout: 00000000 ()
rail0 status iout: 00000000 ()
rail1 status temperature: 00000000 ()
rail0 status temperature: 00000000 ()
rail1 status input: 00000000 ()
rail0 status input: 00000000 ()

     | RAIL 0  | RAIL 1
-----|---------|-----------
VIN  | 0.00 V  | 0.00 V
VOUT | 0.000 V | 0.000 V
IIN  | 0.00 A  | 0.00 A
IOUT | 0.0 A   | 0.0 A
TEMP | 0°C     | 0°C
controller read temperature: 0°C

 PHASE | TEMPERATURE | CURRENT
-------|-------------|----------
 0     | 0°C         | 0.0 A
 1     | 0°C         | 0.0 A
 2     | 0°C         | 0.0 A
 3     | 0°C         | 0.0 A
 4     | 0°C         | 0.0 A
 5     | 0°C         | 0.0 A
 6     | 0°C         | 0.0 A
 7     | 0°C         | 0.0 A
 8     | 0°C         | 0.0 A
 9     | 0°C         | 0.0 A
 10    | 0°C         | 0.0 A
 11    | 0°C         | 0.0 A
 12    | 0°C         | 0.0 A
 13    | 0°C         | 0.0 A
 14    | 0°C         | 0.0 A
 15    | 0°C         | 0.0 A
 16    | 0°C         | 0.0 A
 17    | 0°C         | 0.0 A
 18    | 0°C         | 0.0 A
 19    | 0°C         | 0.0 A

(In the example above, there have been no faults so the blackbox is empty)

To check individual phases for errors, use the --phase-check subcommand: