Documentation style guide

Bridle documentation is written in two formats:

  • doxygen for API documentation

  • RST for conceptual documentation

RST style guide

See Zephyr’s Documentation Guidelines for a short introduction to RST and, most importantly, to the conventions used in Zephyr. More information about RST is available in the reStructuredText Primer as part of the original Sphinx Documentation, and about the Sphinx documentation framework in the Li-Pro.Net Sphinx Primer.

The Bridle documentation follows the Zephyr style guide, and adds a few more restrictive rules:

  • Headings use sentence case, which means that the first word is capitalized, and the following words use normal capitalization.

  • Do not use consecutive headings without intervening text.

  • For readability reasons, start every sentence on a new line in the source files and do not add line breaks within the sentence. In the output, consecutive lines without blank lines in between are combined into one paragraph.

    Note

    For the conceptual documentation written in RST, you can have more than 80 characters per line. The requirement for 80 characters per line applies only to the code documentation written in doxygen.

Diagrams

You can include Message Sequence Chart (MSC) diagrams in RST by using the … t.b.d.

You can include Message Sequence Chart (MSC) diagrams in RST by using the .. msc:: directive and including the MSC content, for example:

.. msc::
   hscale = "1.3";
   Module,Application;
   Module<<Application      [label="nemo_connect() returns successfully"];
   Module>>Application      [label="NEMO_LAB_TRANSPORT_CONNECTED"];
   Module>>Application      [label="NEMO_LAB_USER_ASSOCIATION_REQUEST"];
   Module<<Application      [label="nemo_user_associate()"];
   Module>>Application      [label="NEMO_LAB_USER_ASSOCIATED"];
   Module>>Application      [label="NEMO_LAB_READY"];
   Module>>Application      [label="NEMO_LAB_TRANSPORT_DISCONNECTED"];

This will generate the following output:

msc {
hscale = "1.3";
Module,Application;
Module<<Application      [label="nemo_connect() returns successfully"];
Module>>Application      [label="NEMO_LAB_TRANSPORT_CONNECTED"];
Module>>Application      [label="NEMO_LAB_USER_ASSOCIATION_REQUEST"];
Module<<Application      [label="nemo_user_associate()"];
Module>>Application      [label="NEMO_LAB_USER_ASSOCIATED"];
Module>>Application      [label="NEMO_LAB_READY"];
Module>>Application      [label="NEMO_LAB_TRANSPORT_DISCONNECTED"];
}

Kconfig

Kconfig options can be linked to from RST by using the :option: domain:

:option:`CONFIG_DEBUG`

Breathe

The Breathe Sphinx plugin provides a bridge between RST and doxygen.

The doxygen documentation is not automatically included in RST. Therefore, every group must be explicitly added to an RST file.

Example of how to include a doxygen group
.. doxygengroup:: nemo_lab_transport
   :project: bridle
   :members:

Note

Including a group on a page does not include all its subgroups automatically. To include subgroups, list them on the page of the group they belong to.

The Breathe documentation contains information about what you can link to.

To link directly to a doxygen reference from RST, use the following Breathe domains:

  • Function: :cpp:func:

  • Structure: :c:type:

  • Enum (i.e. the list): :cpp:enum:

  • Enumerator (i.e. an item): :cpp:enumerator:

  • Macro: :c:macro:

  • Structure member: :cpp:member:

Note

The :cpp:enum: and :cpp:enumerator: domains do not generate a link due to Breathe issue #437. As a workaround, use the following command:

:cpp:enumerator:`ENUM_VALUE <DOXYGEN_GROUP::ENUM_VALUE>`

Special Roles

Bridle provides its own predefined roles for specific formatting, which are then later interpreted and rendered accordingly by the style sheets of the various output formats. The available roles are specified in the doc/bridle/roles.txt file. The classes declared therein must then be defined accordingly for HTML in the CSS files below doc/_static/css.

The following table shows just a few examples.

reStructuredText

rendered result

description

:rd:`normal red`

normal red

inline colorization in normal weight

:i:`italic`

italic

inline italic style

:ign:`italic green`

italic green

inline colorization in italic style

:b:`bold`

bold

inline bold weight

:bbl:`bold blue`

bold blue

inline colorization in bold weight

:s:`strikethrough`

strikethrough

inline strikethrough decoration

:syl:`strikethrough yellow`

strikethrough yellow

inline colorization in strikethrough decoration

:u:`underline`

underline

inline underline decoration

:uwt:`underline white`

underline white

inline colorization in underline decoration

:rst:`:program:\`honkomat\``

:program:`honkomat`

inline syntax highlighting for reStructuredText

:python:`from pathlib import Path`

from pathlib import Path

inline syntax highlighting for Python

:c:`int sum(int a, int b);`

int sum(int a, int b);

inline syntax highlighting for C/C++

:devicetree:`zephyr,code = <INPUT_KEY_ENTER>;`
:devicetree:`chosen { zephyr,display = &st7789v_240x135; };`
zephyr,code = <INPUT_KEY_ENTER>;
chosen { zephyr,display = &st7789v_240x135; };

inline syntax highlighting for Devicetree

:hwftlbl:`4㎆`
:hwftlbl:`OTA`

4㎆ OTA

hardware feature label for a common purpose

:hwftlbl-btn:`RST`
:hwftlbl-btn:`USR`

RST USR

hardware feature label for a button and switch purpose

:hwftlbl-kbd:`QWERTY`
:hwftlbl-kbd:`NUM`

QWERTY NUM

hardware feature label for a keyboard and number pad purpose

:hwftlbl-mse:`3KEY`
:hwftlbl-mse:`BALL`

3KEY BALL

hardware feature label for a mouse and track ball purpose

:hwftlbl-joy:`DIG`
:hwftlbl-joy:`DYN`

DIG DYN

hardware feature label for a joystick purpose

:hwftlbl-ctr:`EQU`
:hwftlbl-pot:`VOL`

EQU VOL

hardware feature label for a controller and regulator purpose

:hwftlbl-tmp:`T`
:hwftlbl-hty:`H`
:hwftlbl-prs:`P`
:hwftlbl-mtr:`THP`
:hwftlbl-wts:`WTS`
:hwftlbl-voc:`VOC`
:hwftlbl-hzd:`BIOHZD`
:hwftlbl-rar:`RAY`
:hwftlbl-sat:`GNSS`
:hwftlbl-cps:`9-DOF`
:hwftlbl-lgt:`UV/ALS`
:hwftlbl-wtc:`RTC`
:hwftlbl-stw:`ALARM`

T H P THP WTS

VOC BIOHZD RAY

GNSS 9-DOF UV/ALS

RTC ALARM

hardware feature label for a measuring and sensor purpose

:hwftlbl-led:`ERR`
:hwftlbl-led:`USR`

ERR USR

hardware feature label for a lamp and signal purpose

:hwftlbl-cam:`CMOS`
:hwftlbl-cam:`CCD`

CMOS CCD

hardware feature label for a camera and video purpose

:hwftlbl-mic:`MIC`
:hwftlbl-mic:`LINE-IN`

MIC LINE-IN

hardware feature label for a microphone and line-in purpose

:hwftlbl-spk:`PIEZO`
:hwftlbl-spk:`LINE-OUT`

PIEZO LINE-OUT

hardware feature label for a speaker, buzzer and line-out purpose

:hwftlbl-hdp:`AUX`
:hwftlbl-hdp:`LINE-OUT`

AUX LINE-OUT

hardware feature label for a headphone and line-out purpose

:hwftlbl-scr:`OLED`
:hwftlbl-scr:`HDMI`

OLED HDMI

hardware feature label for a screen and display purpose

:hwftlbl-dsk:`TF`
:hwftlbl-dsk:`microSD`

TF microSD

hardware feature label for a storage and disk purpose

:hwftlbl-flp:`3½‟`
:hwftlbl-flp:`5¼‟`
:hwftlbl-flp:`8‟`

3½‟ 5¼‟ 8‟

hardware feature label for a storage and floppy purpose

:hwftlbl-con:`USB-C`
:hwftlbl-con:`10Base-T`

USB-C 10Base-T

hardware feature label for a connector purpose

:hwftlbl-bat:`LiPo/Fe`
:hwftlbl-bat:`NiCd/Mh`

LiPo/Fe NiCd/Mh

hardware feature label for a battery purpose

:hwftlbl-cpt:`SRV`
:hwftlbl-prt:`INK`

SRV INK

hardware feature label for a computer and printer purpose

:hwftlbl-cld:`MQTT`
:hwftlbl-net:`LAN`

MQTT LAN

hardware feature label for a cloud and network purpose

:hwftlbl-sys:`3.3V(PS)`
:hwftlbl-sys:`3.3V(EN)`

3.3V(PS) 3.3V(EN)

hardware feature label for a system and control purpose

:hwftlbl-vdd:`5V/300㎃`
:hwftlbl-vdd:`3.3V/500㎃`
:hwftlbl-vdd:`3.3V(OUT)`

5V/300㎃

3.3V/500㎃ 3.3V(OUT)

hardware feature label for a power and voltage distribution purpose

:hwftlbl-dbg:`UF2`
:hwftlbl-dbg:`SWD`
:hwftlbl-dbg:`JTAG`

UF2 SWD JTAG

hardware feature label for a debug and development purpose

:hwftlbl-pio:`20`
:hwftlbl-pwm:`16`
:hwftlbl-pcm:`1`
:hwftlbl-dac:`2`
:hwftlbl-adc:`4`
:hwftlbl-i2s:`1`
:hwftlbl-i2c:`1`
:hwftlbl-spi:`2`
:hwftlbl-hsi:`2`
:hwftlbl-can:`2`
:hwftlbl-uart:`2`
:hwftlbl-usart:`2`
:hwftlbl-mmc:`1`
:hwftlbl-sdc:`1`
:hwftlbl-tfc:`1`
:hwftlbl-csi:`1`
:hwftlbl-dsi:`1`
:hwftlbl-dpp:`1`
:hwftlbl-tsi:`1`

20 16 1

2 4

1 1 2 2

2 2 2

1 1 1

1 1 1 1

hardware feature label for a function and interface purpose

  • Total number of PIO (Parallel In-/Output)

  • Total number of PWM (Pulse-Width Modulation)

  • Total number of PCM (Pulse-Code Modulation)

  • Total number of DAC (Digital-to-Analog Converter)

  • Total number of ADC (Analog-to-Digital Converter)

  • Total number of I2S (Inter-IC Sound)

  • Total number of I2C (Inter-Integrated Circuit)

  • Total number of SPI (Serial Peripheral Interface)

  • Total number of HSI (High-Speed Synchronous Serial Interface)

  • Total number of CAN (Controller Area Network)

  • Total number of UART (Universal Asynchronous Receiver-Transmitter)

  • Total number of USART (Universal Synchronous and Asynchronous Receiver-Transmitter)

  • Total number of MMC/SD/TF (Multi-Media-/Secure-Digital-Card or TransFlash)

  • Total number of CSI (Camera Sensor Interface, e.g. MIPI)

  • Total number of DSI (Display Serial Interface, e.g. MIPI)

  • Total number of DPP (Display Parallel Port, e.g. RGB444/HS/VS/CLK)

  • Total number of TS (Touch-Screen Interface)

:rpi-pico-gnd:`GND`
:rpi-pico-vdd:`VSYS`

GND

VSYS

Raspberry Pi Pico signal line label special purpose

  • Total number of GND (Ground potential)

  • Total number of VSYS (Voltage level of System)

:rpi-pico-sys:`RUN`
:rpi-pico-swd:`SWCLK`

RUN

SWCLK

Raspberry Pi Pico signal line label special purpose

  • Total number of RUN (Reset)

  • Total number of SWCLK (Serial Wire Clock)

:rpi-pico-pio:`GPIO28`
:rpi-pico-pwm:`PWM12`
:rpi-pico-adc:`ADC_CH2`

GPIO28

PWM12

ADC_CH2

Raspberry Pi Pico signal line label special purpose

  • Total number of GPIO28 (General Purpose I/O line 28)

  • Total number of PWM12 (PWM output line 12)

  • Total number of ADC_CH2 (ADC input channel 2)

:rpi-pico-spi-dfl:`SPI0_SCK`
:rpi-pico-spi:`SPI1_CSN`

SPI0_SCK

SPI1_CSN

Raspberry Pi Pico signal line label special purpose

  • Total number of SPI0_SCK (Serial Clock line on default SPI 0)

  • Total number of SPI1_CSN (Chip Select Negative line on SPI 1)

:rpi-pico-i2c-dfl:`I2C0_SDA`
:rpi-pico-i2c:`I2C1_SCL`

I2C0_SDA

I2C1_SCL

Raspberry Pi Pico signal line label special purpose

  • Total number of I2C0_SDA (Serial Data line on default I2C 0)

  • Total number of I2C1_SCL (Serial Clock line on I2C 1)

:rpi-pico-uart-dfl:`UART0_TX`
:rpi-pico-uart:`UART1_RX`

UART0_TX

UART1_RX

Raspberry Pi Pico signal line label special purpose

  • Total number of UART0_TX (Data Transmit line on default UART 0)

  • Total number of UART1_RX (Data Receive line on UART 1)

Special Replacements

Special technical or domain specific UNICODE characters can be used by replacements without having to know their exact numeric code when entering text. For this purpose, the individually maintained list exists in the file doc/bridle/unicode.txt.

The following table shows just a few examples.

reStructuredText

rendered result

unicode

description

Lorem |nbsp| |nbsp| |nbsp| ipsum

Lorem   ipsum

U+000A0

nob-space / non-breaking space

|curs|

¤

U+000A4

currency sign (the old German “pig”)

|copy|

©

U+000A9

copyright sign

|regs|

®

U+000AE

registered sign

|!!| / |!?|

‼ / ⁉

U+0203C, U+02049

double exclamation and exclamation questionmark

|?| / |!|

❓ / ❗

U+02753, U+02757

red question and exclamation mark

|candle| |star| |open book|

🕯 ⭐ 📖

U+1F56F, U+02B50, U+1F4D6

Emojis: candle, star, open book

|secret| |free of charge| |open for business| |passing grade|

㊙ 🈚 🈺 🈴

U+03299, U+1F21A, U+1F23A, U+1F234

CJK signes: secret, free of charge, open for business, passing grade

|oneq|

¼

U+000BC

vulgar fraction one quarter

|oneq|

¼

U+000BC

vulgar fraction one quarter

|oneh|

½

U+000BD

vulgar fraction one half

|threeq|

¾

U+000BE

vulgar fraction three quarters

|sup2| |sup3| |/| |sub3| |sub2|

²³⁄₃₂

U+0338F

special fraction

X |sup7| |sup(| |sup8| |sup-| |sup9| |sup)|

X⁷⁽⁸⁻⁹⁾

U+02070…U+0207E

superscript formatter

X |sub7| |sub(| |sub8| |sub-| |sub9| |sub)|

X₇₍₈₋₉₎

U+02080…U+0208E

subscript formatter

N = J/m = |kg| |*| m |*| s |sup-| |sup2|

N = J/m = ㎏⋅m⋅s⁻²

U+02044, U+0207B, U+000B2

Newton in Joule per meter and in SI units

8 |nm| = 8 |*| 10 |sup-| |sup3| |um|

8 ㎚ = 8⋅10⁻³㎛

U+0339A, U+0339B

nano, micro meter

|nm|/|um|/|mm|/|cm|/|dm|/|km|

㎚/㎛/㎜/㎝/㍷/㎞

U+0339A…U+0339E

nano, micro, milli, centi, deci, kilo meter

|mm2|/|cm2|/|dm2|/|km2|

㎟/㎠/㍸/㎢

U+0339F…U+033A2

square milli, centi, deci, kilo meter squared

|mm3|/|cm3|/|dm3|/|km3|

㎣/㎤/㍹/㎦

U+033A3…U+033A6

square milli, centi, deci, kilo meter cubed

|ul|/|ml|/|dl|

㎕/㎖/㎗

U+03395…U+03397

micro, milli, deci litre

|ug|/|mg|/|kg|

㎍/㎎/㎏

U+0338D…U+0338F

micro, milli, kilo gramm

|ps|/|ns|/|us|/|ms|

㎰/㎱/㎲/㎳

U+033B0…U+033B3

pico, nano, micro, milli, second

|Hz|/|kHz|/|MHz|/|GHz|/|THz|

㎐/㎑/㎒/㎓/㎔

U+03390…U+03394

kilo, mega, giga, tera, hertz

|pA|/|nA|/|uA|/|mA|/A/|kA|

㎀/㎁/㎂/㎃/A/㎄

U+03380…U+03384

pico, nano, micro, milli, kilo ampere

|pV|/|nV|/|uV|/|mV|/V/|kV|/|MV|

㎴/㎵/㎶/㎷/V/㎸/㎹

U+033B4…U+033B9

pico, nano, micro, milli, kilo, mega volt

|pW|/|nW|/|uW|/|mW|/W/|kW|/|MW|

㎺/㎻/㎼/㎽/W/㎾/㎿

U+033BA…U+033BF

pico, nano, micro, milli, kilo, mega watt

|mO|/|O|/|kO|/|MO|

mΩ/Ω/㏀/㏁

U+003A9, U+033C0, U+033C1

milli, kilo, mega ohm

|mO|/|O|/|kO|/|MO|

mΩ/Ω/㏀/㏁

U+003A9, U+033C0, U+033C1

milli, kilo, mega ohm

|pF|/|nF|/|uF|

㎊/㎋/㎌

U+0338A, U+0338B, U+0338C

pico, nano, micro farad

|uH|/|mH|

µH/mH

U+000B5, simulated

micro, milli henry

L = 500 |uH| = 0.5 |mH|

L = 500 µH = 0.5 mH

U+000B5, simulated

micro, milli henry in equation

|Theta| = 20000 |x| 20 |uA| = 400 |mA|

Θ = 20000×20 ㎂ = 400 ㎃

U+00398, U+000D7, U+03382, U+03383

Greek capital letter theta symbol and micro / milli ampere

|theta| = 20 |°C| = 293.15 |K|

ϑ = 20 ℃ = 293.15 K

U+003D1, U+02103, U+0212A

Greek theta symbol and degree Celsius and Kelvin sign

|kb|/|kB|/|MB|/|GB|

kbit/㎅/㎆/㎇

U+03385, U+03386, U+03387

kilo bit / kilo, mega, giga byte

Doxygen style guide

This style guide covers guidelines for the doxygen-based API documentation.

General documentation guidelines

  1. Always use full sentences, except for descriptions for variables, structs, and enums, where sentence fragments with no verb are accepted, and always end everything with period.

  2. Everything that is documented must belong to a group (see below).

  3. Use capitalization sparingly. When in doubt, use lowercase.

  4. Line breaks: In doxygen, break after 80 characters (following the dev guidelines). In RST, break after each sentence.

  5. @note and @warning should only be used in the details section, and only when really needed for emphasis. Use notes for emphasis and warnings if things will really really go wrong if you ignore the warning.

File headers and groups

  1. @file element is always required at the start of a file.

  2. There is no need to use @brief for @file.

  3. @defgroup or @addgroup usually follows @file. You can divide a file into several groups as well.

  4. @{ must open the group, @} must close it.

  5. @brief must be added for every defgroup.

  6. @details is optional to be used within the defgroup.

File header and group documentation example
/** @file
 *  @defgroup nm_lab_pool Nemo LAB attribute pool API
 *  @{
 *  @brief Nemo LAB attribute pools.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <nemo/lab.h>
#include <nemo/uuid.h>

/** @brief Register a primary service descriptor.
 *
 *  @param _svc LAB service descriptor.
 *  @param _svc_uuid_init Service UUID.
 */
#define NM_LAB_POOL_SVC_GET(_svc, _svc_uuid_init) \
{                                                 \
  struct bt_uuid *_svc_uuid = _svc_uuid_init;     \
  nm_lab_pool_svc_get(_svc, _svc_uuid);           \
}

[...]
/** @brief Return a PI descriptor to the pool.
 *
 *  @param attr Attribute describing the PI descriptor to be returned.
 */
void nm_lab_pool_pi_put(struct nm_lab_attr const *attr);

#if CONFIG_NM_LAB_POOL_STATS != 0
/** @brief Print basic module statistics (containing pool size usage). */
void nm_lab_pool_stats_print(void);
#endif

#ifdef __cplusplus
}
#endif

/**
 * @}
 */

Functions

  1. Do not use @fn. Instead, document each function where it is defined.

  2. @brief is mandatory.

    • Start the brief with the “do sth” form.

Brief documentation examples
/** @brief Request a read operation to be executed from Secure Firmware.

/** @brief Send Boot Keyboard Input Report.
  1. @details is optional. It can be introduced either by using @details or by leaving a blank line after @brief.

  2. @param should be used for every parameter.

    • Always add parameter description. Use a sentence fragment (no verb) with period at the end.

    • Make sure the parameter documentation within the function is consistently using the parameter type: [in], [out], or [in,out].

Parameter documentation example
* @param[out] destination Pointer to destination array where the
*                         content is to be copied.
* @param[in]  addr        Address to be copied from.
* @param[in]  len         Number of bytes to copy.
  1. If you include more than one @sa (“see also”, optional), add them this way.

    See also reference example
    * @sa first_function
    * @sa second_function
    
  2. @return should be used to describe a generic return value without a specific value (for example, “@return The length of …”, “@return The handle”). There is usually only one return value.

    Return documentation example
    * @return  Initializer that sets up the pipe, length, and byte array for
    *          content of the TX data.
    
  3. @retval should be used for specific return values (for example, “@retval true”, “@retval CONN_ERROR”). Describe the condition for each of the return values (for example, “If the function completes successfully”, “If the connection cannot be established”).

    Retval documentation example
    * @retval 0 If the operation was successful.
    *           Otherwise, a (negative) error code is returned.
    * @retval (-ENOTSUP) Special error code used when the UUID
    *           of the service does not match the expected UUID.
    
  4. Do not use @returns. Use @return instead.

Complete function documentation example
/** @brief Request a random number from the Secure Firmware.
 *
 *  This function provides a True Random Number from the on-board random
 *  number generator.
 *
 *  @note Currently, the RNG hardware is run each time this function is
 *        called. This consumes significant time and power.
 *
 *  @param[out] output  The random number. Must be at least @p len long.
 *  @param[in]  len     The length of the output array. Currently, @p len
 *                      must be 144.
 *  @param[out] olen    The length of the random number provided.
 *
 *  @retval 0        If the operation was successful.
 *  @retval -EINVAL  If @p len is invalid. Currently, @p len must be 144.
 */
int nm_request_random_number(u8_t *output, size_t len, size_t *olen);

Enums

The documentation block should precede the documented element. This is in accordance with the Zephyr coding style.

Enum documentation example
/** Nemo LAB service events. */
enum nm_lab_svc_evt {

  /** Boot mode entered. */
  NM_LAB_SVC_EVT_BOOT_MODE_ENTERED,

  /** Report mode entered. */
  NM_LAB_SVC_EVT_REPORT_MODE_ENTERED,
};

Structs

The documentation block should precede the documented element. This is in accordance with the Zephyr coding style. Make sure to add :members: when you include the API documentation in RST; otherwise, the member documentation will not show up.

Struct documentation example
/** @brief Event header structure.
 *
 *  @warning When event structure is defined event header must be placed
 *           as the first field.
 */
struct event_header {

  /** Linked list node used to chain events. */
  sys_dlist_t node;

  /** Pointer to the event type object. */
  const struct event_type *type_id;
};

Note

Always add a name for the struct. Avoid using unnamed structs due to Sphinx parser issue.

References

To link to functions, enums, or structs from within doxygen itself, use the @ref keyword.

Reference documentation example
/** @brief Event header structure.
 *  Use this structure with the function @ref function_name and
 *  this structure is related to another structure, @ref structure_name.
 */

Note

Linking to functions does not currently work due to Breathe issue #438.

Typedefs

The documentation block should precede the documented element. This is in accordance with the Zephyr coding style.

Typedef documentation example
/** @brief Download client asynchronous event handler.
 *
 *  Through this callback, the application receives events, such as
 *  download of a fragment, download completion, or errors.
 *
 *  If the callback returns a non-zero value, the download stops.
 *  To resume the download, use @ref download_client_start().
 *
 *  @param[in] event  The event.
 *
 *  @retval 0 The download continues.
 *  @retval non-zero The download stops.
 */
typedef int (*download_client_callback_t)
            (const struct download_client_evt *event);