Skip to content

MikroElektronika/click_id

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ClickID - the self introducing add-on board

mikroID

What is it?

ClickID is a unique way for embedded board personalization by dedicating a device ID to each of them. Simplified communication through the 1-Wire protocol applicable to any board type using a secure authenticator device.

What will you get?

Building blocks for the self-identifying and configurable embedded system, capable of knowing its peripherals like the PC systems.

The GOAL

To make the configuration of the tools faster using a hot-plug system like in the PC world and to add traceability and authenticity to the embedded devices.

The story behind - identifying a problem

One of the long-time problems in embedded Linux and all similar OS is the non-existing standard for hot plugging add-on boards. Adding add-on boards into an embedded Linux system typically involves the following steps:

  1. Identify the type of add-on board you have and the interface it uses to connect to the embedded Linux system. Common interfaces include SPI, I2C, UART, USB, and Ethernet.
  2. Ensure that the kernel module for the add-on board is installed and loaded on the embedded Linux system. If the module is not installed, you may need to cross-compile it from the source code and install it manually.
  3. Configure the interface used by the add-on board, such as SPI or I2C, on the embedded Linux system. This involves specifying the bus and device addresses that the add-on board uses.
  4. Test the add-on board by writing a simple application that interacts with the board using the appropriate interface.
  5. If necessary, modify the device tree for the embedded Linux system to ensure the add-on board is correctly recognized and configured at boot time.

As you can see, adding add-on boards to an embedded Linux system can be a complex process that requires careful attention to detail and a good understanding of the hardware and software involved. Multiplying 1,000 boards by the number of 1000 host boards by the number of sockets supported on each of those boards ends up being a LOT of device tree overlay fragments. Further, applying those fragments is error-prone and can even prevent a system from booting.

Click Boards™ in Embedded Linux

ClickID is a hardware & software solution based on a secure authenticator device that enables the hot-plugging of Click Boards™ or any other mikroBUS™ compatible add-ons to embedded Linux. ClickID communicates with the operating system kernel via the 1-Wire protocol, authorizing any sensor on the add-on board to be automatically recognized. ClickID will deliver the manifest file to the operating system, and the proper driver loads to use the following interfaces (SPI, I2C, UART, PWM, ADC, reset, interrupt) for communication with the target device located on the add-on board.

How does it work?

Click board™ with ID functionality can operate in two modes:

  • REGULAR MODE
    • Works as a Click Board™ without ID functionality. This is a default mode.
  • ID MODE
    • It works as a unique device capable of introducing itself to the Linux kernel to load the driver automatically.

    • To switch a Click Board™ in the ID MODE, the host board must hold the reset line to the '0' logic state. This way, the CS line is connected to EEPROM memory on the Click Board™ through a multiplexer. To handle the mikroBUS™ socket and read the corresponding ID, we use the CS line, because only one host line must be unique for each mikroBUS™. This way, the host can uniquely identify each mikroBUS™ socket on the host board and read the ID from the corresponding Click Board™.

clickIDDiagram Fig 1. - The block diagram of ClickID functionality

ClickID Memory Organization

Each Click Board™ is described and identified by the information stored in the EEPROM memory of the Click Board™. The DS28E36 is used as ID MCU for storing the manifest file and unique identifier of the Click Board™. In the table below, you can see EEPROM memory organization:

The EEPROM memory is divided into two slices:

  • permanent data - it is written to a zero page at production time, and this page is locked for changes.
  • configurable data - it's starting for the first sector, and it is rewritable. This part of EEPROM is reserved for configurable information (Default: Here will be a Click Board™ manifest used by Embedded Linux OS)

Information in first sector
Fig 2. The Click Board™ permanent information is stored in the zero sector, and the manifest is stored in the rest of the EEPROM.

Permanent data description

Permanent information such as name, version, and serial number will be stored in the first 32 bytes of the EEPROM zero sector.

First sector format

Fig 3. The permanent information

Version - Mikroelektronika's hardware board version
Product ID - Product identification number

  • Custom - 1 bit
    • 0 - Standard Mikroelektronika's board
    • 1 - Customized board for customer
  • Type - 10 bits (big-endian). Product type (Click Board™, display, MCU card, etc.)
  • Reserved - 5 bits reserved in case that should be needed to increase the length of fields custom or serial
  • Serial - 16 bits (little-endian) reserved for current Mikroelektronika's EPR PID number of hardware board

Name - HW board name without a word for the product type. Ex. for "OLED C click" in this field should be written only OLED C.
Reserved - 6 bytes reserved for future use

Variable data

This is a part of the ID chip memory, where we store user-configurable information. By default, that is a ClickID manifest binary file that contains the necessary information for a specific Linux driver for the Click Board™.

Embedded Linux and ClickID

For the purpose of identifying Click Board™ in the Embedded Linux enviroment, mikroBUS™ kernel driver has been developed in collaboration with the BeagleBoard Foundation. To take full advantage of the clickID hot-plug functionality, it is necessary to have a Linux image kernel with the mikroBUS driver enabled.

Currently available images with the driver enabled are:

If you use one of the mentioned images, it is enough to simply plug the Click Board™ into the mikroBUS socket, and Linux will automatically connect your Click Board™ with the appropriate driver and expose the interface for working with it.

Information about the loaded driver can be found at the location /sys/bus/mikrobus/devices/mikrobus-0. Additionally, some basic information can be seen through dmesg (dmesg | grep mikrobus).

Depending on the type of mikroBUS™ Add-On board, the Linux driver could be of various different types. Identify how the driver exposes the data: IIO, net, etc. For sensors, the most common is the IIO driver and you could use all driver functionalities.

NOTE: To be sure that your Click Board™ is supported look for the “ID” logo on the back side of the Click Board™ and check the currently supported Click Board™.

NOTE: Even though the dynamic system allows for Plug-and-Play, Click Boards™ are not hot-swappable! When switching between Click Boards™, be sure to remove power from the device first in order to prevent damage to the Click Board™ or the platform they are connected to.

If you do not have one of the mentioned images, things are slightly more complex:

  • Rebuild the mikroBUS driver for your version of the kernel. You can do this by building the driver as a built-in driver or as a module for dynamic loading.

    NOTE: If you build the driver as a module, it is necessary to include both the mikroBUS module and the mikroBUS_id module.

  • Modify the Linux device tree so the mikroBUS™ compatible socket can be supported.

  • After you have applied the mikroBUS™ kernel driver onto the embedded Linux platform, perform the following:

    • Verify the mikroBUS™ kernel driver is enabled by utilizing the following command in the Terminal: ls /sys/bus/mikrobus/devices/.
    • What you will eventually get is something like this: mikrobus-0 (and/or mikrobus-1, mikrobus-2, mikrobus-3 - depending on how many mikroBUS™ sockets Your embedded Linux Platform supports).

Now you can use the driver the same as with the driver included in the prebuilt image.

ClickID for Linux driver developers

Currently, database of the Click Boards™ is much larger than the number of drivers in Linux, so it is sometimes necessary to add support for a Click Board™ in Linux.

Support for a Click Board™ in Linux consists of several steps:

  • Check if the embedded Linux has the mikroBUS driver installed. If this is not the case, refer to the previous section on how to do this.

  • Checking if the module on the Click Board™ already has a driver in the Linux kernel. If this is not the case, it is necessary to develop a Linux driver for the respective module.

  • Create a ClickID manifest for theClick Board™, which is necessary for the host to correctly configure the Click Board™ during loading. ClickID manifest file contains the necessary information for a specific Linux driver for the Click Board™. For reference, you can analyze the example manifest for the OLEDC Click.

  • Create the manifest binary file (mnfb file) from ClickID manifest using a Python tool

  • Write the manifest file to the Click Board™.
    'dd if=/lib/firmware/mikrobus/your_manifest.mnfb of=/sys/bus/w1/devices/w1_bus_master1-<unique ID>/mikrobus_manifest'

NOTE: Make a pull request to this repository if you want to add your ClickID manifest to our database.

ClickID manifest

This section will describe the Click Board™ manifest file format required for the ClickID driver in the Linux kernel. Click Board™ manifest is derived from the Greybus manifest. Below are briefly described only fields of interest for the Click Board™ manifest.

The manifest contains a header and an array of descriptors. All descriptors are 32-bit aligned, and the size of each descriptor is a multiple of 4 bytes.

struct manifest {
    struct manifest_header header;
    struct descriptor descriptors[0];
} __packed;

Header

The manifest header contains information about the manifest binary size and manifest version.

  • size (2 bytes)
  • version (2 bytes)
// Manifest Header 
struct manifest_header {
    uint16_t size;
    uint8_t version_major;
    uint8_t version_minor;
} __packed;

Descriptors

  • Descriptors are formed by descriptor header (4 bytes) and descriptor data. Descriptor's header contains information about the type of descriptor and descriptor length.

  • size (2 bytes)

  • type (1 byte)

  • reserved (1 byte)

// Descriptor's Header
struct descriptor_header {
    uint16_t size;
    uint8_t type; /* descriptor_type */
    uint8_t pad; /* used for alignment */
} __packed;

The descriptor header is followed by descriptor data which can vary by type and size. There are several types of descriptor's types:

  • String,
  • Interface,
  • Mikrobus,
  • Property,
  • Device.

Look at the struct for a descriptor type:

enum descriptor_type {
    MIKROBUS_TYPE_INVALID = 0x00,
    MIKROBUS_TYPE_INTERFACE = 0x01,
    MIKROBUS_TYPE_STRING = 0x02,
    MIKROBUS_TYPE_MIKROBUS = 0x05,
    MIKROBUS_TYPE_PROPERTY = 0x06,
    MIKROBUS_TYPE_DEVICE = 0x07
};

All the types are described briefly below.


Descriptor data types:


1. String descriptor


The string descriptor allows us to describe all kinds of variable-length strings in the manifest. The size of the descriptor will be rounded up to a multiple of 4 bytes by padding the string with 0x00 bytes if necessary. This descriptor is useless as a standalone, so it must be referenced by the ID field in another descriptor. ( For example, look at interface descriptor). This type of descriptor is used for describing information such are: product name, driver name, property name, and GPIO names.
struct descriptor_string {
    uint8_t length;
    uint8_t id;
    uint8_t string[];
} __packed;

2. Interface descriptor


It describes specific values set by the vendor which created the manifest. The manifest must have exactly one interface descriptor.

  • vendor_string_id (1 byte)
  • product_string_id (1 byte)
  • reserved (2 bytes)

The vendor and product string ID are a reference to specific string descriptors that describe the vendor who created the product and the name of the product. If no string represents this information, the reference should be set to 0.

struct descriptor_interface {
    uint8_t vendor_id;
    uint8_t product_id;
    uint8_t reserved[2];
} __packed;

3. mikroBUS descriptor


The mikroBUS descriptor is a fixed-length descriptor (12 bytes), and the manifest shall have precisely one mikroBUS descriptor. Each byte describes a configuration of the corresponding pin on the Click Board™ in a clockwise direction starting from the PWM pin omitting power (VCC and ground) pins as same as the default state of the pin.

There are Click Boards™ that use some dedicated SPI, UART, PWM, and I2C pins as GPIO pins, so it is necessary to redefine the default pin configuration of that pins on the host system. Also, sometimes it is required the pull-up on the host pin for correct functionality. This descriptor provides that information to the host system.

Values that describe the initial configuration pin state:

union mikrobus_pin_configuration {
        uint8_t MIKROBUS_STATE_INPUT = 0x01,
        uint8_t MIKROBUS_STATE_OUTPUT_HIGH = 0x02,
        uint8_t MIKROBUS_STATE_OUTPUT_LOW = 0x03,
        uint8_t MIKROBUS_STATE_PWM = 0x04, /* ( applicable only to PWM pin) */
        uint8_t MIKROBUS_STATE_SPI = 0x05, /* ( applicable only to the group of SPI pins) */
        uint8_t MIKROBUS_STATE_I2C = 0x06, /* (applicable only to the I2C pins) */
        uint8_t MIKROBUS_STATE_UART = 0x07, /* (applicable only to the UART  pins)
    };

mikroBus descriptor:

    struct descriptor_mikrobus {
        uint8_t pin_state[12];
    } __packed;

Detailed mikroBUS standard definition.

4. Property descriptor


The property descriptors are used to pass named properties or named GPIOs to the host. The host system uses this information to properly configure specific Click Board™ drivers by passing the properties and GPIO name. There can be multiple instances of property descriptors per add-on board manifest.

  • length (1 byte)
  • id (1 byte)
  • name_id (1 byte)
  • type (1 byte)
  • value (variable length)

The property name is stored in a separate string descriptor referenced by field name_id. The field value can vary in length and contain different types of information defined by the field type's value.

Possible values for field type:

enum mikrobus_property_type {
    MIKROBUS_PROPERTY_TYPE_MIKROBUS = 0x00, 
    MIKROBUS_PROPERTY_TYPE_PROPERTY = 0x01, /* array of references to children properties */
    MIKROBUS_PROPERTY_TYPE_GPIO = 0x02, /* array of references pio names string descriptor */
    MIKROBUS_PROPERTY_TYPE_U8 = 0x03,
    MIKROBUS_PROPERTY_TYPE_U16 = 0x04,
    MIKROBUS_PROPERTY_TYPE_U32 = 0x05,
    MIKROBUS_PROPERTY_TYPE_U64 = 0x06
};

    struct descriptor_property {
        uint8_t length;
        uint8_t id;
        uint8_t name_id;
        uint8_t type;
        uint8_t value[];
    } __packed;

Similar to the string descriptor, the size of the descriptor will be rounded up to a multiple of 4 bytes by padding the value with 0x00 bytes if necessary.

5. Device descriptor


It describes a device on the mikroBUS port. The device descriptor is a fixed-length descriptor, and there can be multiple instances of device descriptors in an add-on board manifest in cases where the add-on board presents more than one device to the host.

  • id
  • driver_id - id of string descriptor storing the device driver id
  • protocol - a protocol used for communication with the module on the Click Board™
  • reg - i2c device address or alternative CS pin for SPI
  • speed_hz - max SPI speed in HZ
  • irq - relative position for GPIO interrupt if exists
  • irq_type - a type of interrupt
  • mode - SPI mode of operation
  • prop_link - a reference to a property that contains a list of properties
  • gpio_link - a reference to property which contains a list of GPIO pin names
  • reg_link
  • clock_link
  • reserved
//Device descriptor struct
struct descriptor_device {
    uint8_t id;
    uint8_t driver_id;
    uint8_t protocol;
    uint8_t reg;
    uint32_t speed_hz;
    uint8_t irq;
    uint8_t irq_type;
    uint8_t mode;
    uint8_t prop_link;
    uint8_t gpio_link;
    uint8_t reg_link;
    uint8_t clock_link;
    uint8_t pad[1];
} __packed;


enum protocol {
    
    PROTOCOL_GPIO = 0x02,
    PROTOCOL_I2C = 0x03,
    PROTOCOL_UART = 0x04,
    PROTOCOL_PWM = 0x09,
    PROTOCOL_SPI = 0x0b,
    PROTOCOL_RAW = 0xfe,
    PROTOCOL_VENDOR = 0xff,
};

Finaly, here is a sample of the manifest file:

;;
; PRESSURE CLICK
; https://www.mikroe.com/pressure-click
; CONFIG_IIO_ST_PRESS
;
; Copyright 2020 BeagleBoard.org Foundation 
; Copyright 2020 Texas Instruments 
;

[manifest-header]
version-major = 0
version-minor = 1

[interface-descriptor]
vendor-string-id = 1
product-string-id = 2

[string-descriptor 1]
string = MIKROE

[string-descriptor 2]
string = Pressure 

[mikrobus-descriptor]
pwm-state = 4
int-state = 1
rx-state = 7
tx-state = 7
scl-state = 6
sda-state = 6
mosi-state = 5
miso-state = 5
sck-state = 5
cs-state = 5
rst-state = 2
an-state = 1

[device-descriptor 1]
driver-string-id = 3
protocol = 0x3
reg = 0x5d

[string-descriptor 3]
string = lps331ap

Beagleboard has made a simple Python tool for generating a mikroBUS manifest called Manifesto. Detail explanation of using this tool can be found here

About

Click indentification support

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published