Mbed OS directory structure and public headers identification


In Mbed OS 5.14 we introduced a new directory structure convention and we started to clean-up the Mbed OS public headers.


A key feature of modular software is the separation of the interface from the implementation. This allows for more flexible, extensible and portable software. The public API - the interface - is guaranteed to be backwards compatible for minor and patch releases. It is well defined and well documented to make it easier for developers to use the code. In comparison, the internal API hides the implementation details, and can change from one release to the next. Making a clear separation between public and internal APIs allows user applications to depend on the interface - the public API - and not the implementation.

For this reason, we started to work on cleaning up the mbed-os directory structure and identifying public headers in Mbed OS 5.14.

The scope of the work covers the following subdirectories:

  • drivers
  • events
  • platform
  • rtos

Note: We moved the contents of the usb/ directory to appropriate locations and removed the usb/ directory.

We adopted the following convention:

  • module/header.h: module public header.
  • module/internal/internal_header.h: header that implements or is included by the main header.
  • module/source/header.c: source for header.h.
  • module/source/private.c : module internal code.
  • module/source/private.h: header for internal code.

New files and APIs should follow this convention.

We also added Doxygen commands to classify the headers as public or internal. The Doxygen modules hierarchy in 5.14 is:

+-- Public API
    +-- Drivers
        +-- GPIO
        +-- CAN
        +-- I2C
        +-- Ticker
        +-- SPI
        +-- UART
        +-- USB
    +-- Events
    +-- Device key
    +-- Platform
        +-- File
        +-- Power management functions
    +-- RTOS
+-- Internal API
    +-- Drivers
        +-- USB
    +-- Platform
    +-- RTOS

Doxygen provides a mechanism to group documentation with a combination of \defgroup, \addtogroup and \ingroup commands:

  • The opening and closing braces /** @{*/ and /** @}*/ put everything between them in a given group.
  • \defgroup <groupname> (group title) creates a new group.
    • The first argument of the command is a label to uniquely identify the group.
    • The second argument is the name or title of the group as it should appear in the documentation.
  • \addtogroup <groupname> specifies that all valid Doxygen comments and all groups created between the opening and closing braces will go under an existing group.
  • \ingroup <groupname>, in conjunction with \defgroup, specifies to which group you are adding a new group.
  • Only define a group once, in the first file encountered for a given group.

Example using the addtogroup command

Define and add a new group platform_CThunk to the platform-public-api group using the addtogroup command. This results in Public API/Platform/CThunk class in the Doxygen module hierarchy:

platform/CThunk.h
------------------
 
/** \addtogroup platform-public-api */
/** @{*/
 
/**
* \defgroup platform_CThunk CThunk class
* @{
*/
class CThunk{
    ...
}
/** @}*/
/** @}*/

Example using the ingroup command

Define and add a new group drivers_I2CSlave to the drivers-public-api group using the ingroup command. This results in Public API/I2C/I2CSlave class in the Doxygen module hierarchy:

drivers/I2CSlave.h
------------------
 
/**
* \defgroup drivers_I2CSlave I2CSlave class
* \ingroup drivers-public-api-i2c
* @{
*/
class I2CSlave {
    ...
}
/** @}*/

We recognize the importance of clearly separating internal and public APIs. The conventions we have adopted will emphasize this distinction. We shall continue this work in future releases.

You need to log in to post a discussion