API Overview

API Overview

In this documentation, you will find the API structure, the description of the libraries used.


The firmware is divided into three applications: bootloader, Application A, and Application B. Each of them is built separately and, in the end, merged into a final image. This means that each of them uses both their own separate source files and shared ones. One good approach is to keep the source code structure the same as in our demonstration application. In this case, the structure is:

├── app_a
│   ├── BUILD
│   ├── build.sh
│   ├── mbed_app.json
│   ├── mbed-os
│   └── mbed-os.lib
├── app_b
│   ├── BUILD
│   ├── build.sh
│   ├── mbed_app.json
│   ├── mbed-os
│   └── mbed-os.lib
├── app_src
│   ├── drivers
│   ├── main.cpp
│   └── sensors
├── app_src_backup
│   ├── drivers
│   ├── main.cpp
│   └── sensors
├── bin
│   ├── app_a.bin
│   ├── app_b.bin
│   └── image.bin
├── build_app.sh
├── build_image.sh
├── clean.sh
├── common
│   └── global_consts.h
├── docker_build_image.sh
├── docker_build_windows.bat
├── docker_flash_image.sh
├── flash_image.sh
├── libs
│   └── vitroio-sdk
├── README.md
└── shard-v2-bootloader-image
    ├── bootloader.bin
    └── README.md

Each subdirectory is organized as follows:

  • app_a
    • Application A files only.
    • To build the app_a binary, there is a build.sh script.


There are no source code files in this particular example, but only those used by Mbed OS to build.

  • app_b
    • Application B files only.
    • To build the app_b binary, there is a build.sh script.


There are no source code files in this particular example, but only those used by Mbed OS to build.

  • app_src
    • Applications A and B common source files.
    • At a minimum, a main.cpp file must be present.
    • Application's sensors source code should be saved on drivers and sensors folders.


In this particular example, applications A and B are the same. As such, their source code is in this directory. Furthermore, drivers and sensors folders have the source code for temperature and humidity DHT22, light LM393, and current meter MCT-0016.

  • app_src_backup

    • If it doesn't exist, the build_app.sh script will create it.
    • When building the firmware, build_app.sh script creates a backup of the app_src directory.
  • bin

    • Contains final binaries only.
    • if it doesn't exist, it is created by build_image.sh script during the build process.
  • shard-v2-bootloader-image

    • Contains the bootloader binary file (git submodule).
  • common

    • Contains source files related to bootloader, and Applications A and B.
    • At least global_consts.h file should be placed in this folder;
  • libs

    • Contains necessary, external libraries packed into vitroio-sdk.


Details can be found in section Libraries of this documentation.


  • build_app.sh: Check for dependencies, backup app-src, and then call docker_build_image.sh.
  • docker_build_image.sh: Creates a docker container with vitrotech/docker-mbed-cli image, then call build_image.sh script.
    • build_image.sh: Create bin folder if it doesn't exist, configure the secure boot, and run the build.sh script on each application directory.
    • build.sh: Install Mbed OS and compile the application on its directory.
  • docker_flash_image.sh: Create a docker container with the required privileges and vitrotech/docker-mbec-sli image. After creating the container, it calls the flash_image.sh script.
  • flash_image.sh: Erases the device's firmware and then writes the new one starting at 0x8000000 memory address.


The 0x8000000 address comes from the memory mapping for the MCU. You can check it here, on Fig. 14.

  • clean.sh: Delete the created build folders, bin folder, and files.


The firmware requires external libraries. For convenience, they are all included in one package - vitroio-sdk. Vitro Shard needs some of them even to run a basic firmware. Others extend the list of features that can be implemented.

  • libvitro-shard-sdk1.5.2.a
    • Library given in already pre-compiled binary form along with dedicated API in header files (git submodule).
    • Core library for every Vitro Shard application. Thus, it must be included in all projects.
    • It handles all low-level operations such as operating system initialization, upgrades process, task management, event handling, communication handling, and reliable measurements.
  • ecc-api
    • Open-source library.
    • It allows to communicate with Vitro Shard's ATECC608A to perform cryptographic operations, such as reading symmetric key, and computing SHA256 or ECDSA.
  • mbed-cryptoauthlib
    • Mbed OS library which allows interaction with cryptographic elements via an I2C interface.
    • It is an intermediate layer between ecc-api and the physical ATECC608A chip.
  • shard-edge-lib
    • Library given in open source form.
    • It allows to configure Vitro Shard Edge by enabling and disabling dedicated peripherals e.g. SPI or UART.
    • It allows to configure ADCs and current loops ranges.
  • tls-api
    • Library given in open source form.
    • It allows performing AES encryption and decryption on given data. Those operations are performed directly by MCU.
    • The symmetric key is kept on the ECC module and read whenever it must be used.


For more documentation, you can check the Mbed documentation and an example.

By using all the libraries mentioned, Vitro Shard can create IoT Blocks for any custom data measurement application. One benefit of using those libraries is many are open-source. This means that they can be modified, extended, and checked for vulnerabilities by anyone.

API Headers


Located in vitroio-sdk/vitroio-sdk.

  • const.h: Defines required flash memory size in bytes for storing environment variables and Vitro Shard pinout.
  • debug.h: Defines debug macros. There are four debug levels (from highest to lowest): HINFO, INFO, WARNING, ERROR. When some level is defined, the defined one and all of the lower levels are enabled.
  • errors.h: Defines error codes. The errors are:
Error CodeDescription
VITROIO_ERR_MEMORY_ALLOCMemory allocation error
VITROIO_ERR_INVALID_PARAMSInvalid parameter error
  • types.h: Defines the variable types used to identify the firmware, version, and flash space parameters.


Located in vitroio-sdk/vitroio-sdk/watchdog.

  • watchdog.h: Defines the watchdog class.


Located in vitroio-sdk/vitroio-sdk/shard-edge-lib.

  • shard_edge.h: Provides an interface for Vitro Shard Edge.


Located in vitroio-sdk/vitroio-sdk/measurement-api.

  • abstract_sensor_driver.h: Virtual class that provides an interface for basic communication with the sensor and optionally performs sensor-specific operations.
  • abstract_sensor_interface.h: Defines sensor parameters and an uniform reading measurement interface for all sensors.
  • measurement_api.h: Uses event queue to cycle through each sensor and reads its measurements.


Located in vitroio-sdk/vitroio-sdk/iot-block-api.

  • iot-block.h: Defines the parameters and interface to create and send IoT Blocks. The parameters define the size of the ciphertext, initialization vector, parameter ID (defined in abstract_sensor_interface.h), node ID, timestamp, digest, and signature.


Located in vitroio-sdk/vitroio-sdk/control.

  • node_controller.h: Defines the Vitro Shard's main component. It handles standard operations, like firmware updates and initialization of communication with the gateway. This is all done through the use of event queues.


Located in vitroio-sdk/vitroio-sdk/communication.

  • canbus_frame.h: A wrapper for Mbed CANMessage. The modifications are done to allow the interface to support frames used by our API.
  • canbus.h: Defines the default CAN communication frequency, and it is a wrapper for Mbed CAN, thus providing an interface for canbus_frame.h.
  • transport_layer.h: Defines a basic communication interface to send IoT Blocks with other devices.
  • can_layer.h: Defines an implementation of the transport_layer.h for the CAN interface.

Vitro Shard Upgrade

This section is explained in the Starter Guide documentation.

The IoT Block

An IoT Block is a special data structure created by Nodes when meaningful information needs to be sent to the Vitro Cloud (sensor's data, device HeartBeat, etc.).

Each IoT Block is created as a result of performing strictly defined steps in a strictly defined sequence. It consists of the Initialize Vector, encrypted data (usually the sensor's measurement), parameter ID (the sensor's ID defined in sensor_parameter.h), Node ID, timestamp, digest, and signature. The digest is a result of SHA-256 hash function on the Initialize Vector + encrypted data + parameter ID + node ID + timestamp. Then, the digest is signed using ECDSA. Thus, creating the signature.

You can read more about it in the SDK documentation.

At the end of the creation process, CAN overhead is added at the end of the IoT Block. This IoT Block + CAN overhead is called Binary Large Object (BLOB). Both the IoT Block and BLOB must comply with the layout and sizes as follows:


IoT and BLOB size calculator table:

SizeSMLXLAbsolute maximum
Actual IoT BlockPayload size [bytes]3214452810401638
Actual IoT BlockNode ID99999
Actual IoT BlockTimestamp44444
Actual IoT BlockIV and encrypted data4816054410561664
Actual IoT BlockSHA2563232323232
Actual IoT BlockECDSA6464646464
Actual IoT BlockActual size15726965311651773
CAN relatedPadding44545
CAN relatedSize with padding16127365811691778
CAN relatedCAN frames count244095168255

What’s Next