Introduction

What is ekfsm?

The ekfsm python package provides access to system management functions on Linux based modular hardware systems, such as CompactPCI-Serial systems.

Features

  • System configuration definition via YAML configuration file

  • Obtain inventory information of the system and its components

  • Obtain sensor information, such as temperature, humidity, voltage, current, accelerometer, gyroscope, etc.

  • Access to system level functions, such as system LEDs, system fan, system power supply, etc.

  • Supports simulation mode for development and testing

Core Concepts

The ekfsm package is built around the following core concepts:

Passive

The ekfsm package is designed to be passive. It will not perform any actions on the system, unless called by the user.

System Configuration

The system configuration is defined in a System Configuration File. The configuration file defines the modular components of the system, i.e. you define which board types (called :class:`~HwModule`s in ekfsm) are expected in which slots of the chassis.

The system configuration file is then passed to the System constructor to create a system object. During instantiation, the system object will create the necessary HwModule objects and all the supported functions for the devices.

It will also check if the actual hardware configuration matches the expected configuration. The result of this check in then available in the corresponding Slot object.

Relation between objects

The objects and subobjects model the hardware topology of the system.

An System object is the root object of the ekfsm package. The system object contains Slot objects, which represent the slots of the chassis. Each slot object contains zero or one HwModule objects, which represents the hardware module in the slot.

_images/ekfsm_system.drawio.png

The hardware modules contain subfunctions, implemented by Device objects and the device objects provide methods to access the hardware functions.

_images/devices.drawio.png

Accessing Device functions

Suppose you have the following configuration system.yaml:

system_config:
  name: "Simple System"
  slots:
    - name: SYSTEM_SLOT
      slot_type: CPCI_S0_SYS
      desired_hwmodule_type: EKF SC9-Toccata
      desired_hwmodule_name: CPU
      attributes:
        is_master: true
    - name: SLOT1
      slot_type: CPCI_S0_PER
      desired_hwmodule_type: EKF SRF-SUR
      desired_hwmodule_name: SER
      attributes:
        slot_coding: 0x1

If you want to access the LEDs on the EKF SUR-UART, you can do the following:

import ekfsm

system = ekfsm.System("system.yaml")

# alternative ways to get the SUR HwModule
sur = system["SER"]    # by using the hwmodule name as key
sur = system.ser       # by using the hwmodule name as attribute
sur = system.slots["SLOT1"].hwmodule  # by using the slot name as key
sur = system.slots.slot1.hwmodule  # by using the slot name as attribute

# accessing the LED device
sur.led_a.set(0,"purple")  # set the color of the LED to purple

For a list of each board’s supported functions, see the Supported Boards section.

Querying slots

To check if the actual system configuration matches the one defined in the configuration file, you can use the info() method, which gives you the desired and actual configuration of the slot.

import ekfsm

system = ekfsm.System("system.yaml")

for slot in system.slots:
    print(f"Slot {slot.info()}")

You can also use the is_populated() method to check if a slot is populated and the is_correctly_populated() method to check if the slot contains the correct hardware module.

Warning

The detection mechanism has limitations. If a board is installed which is unknown to the ekfsm library, the slot will not be marked as populated.

Usage

System Preparation

Many ekfsm devices rely on sysfs to access the hardware. Before ekfsm can be used, the system must be configured so that all necessary sysfs entries are available.

For example, for an X86 CompactPCI Serial system, most of the devices supported by ekfsm are I2C devices, but linux cannot detect them without further configuration.

Therefore, the I2C device tree is typically provided as ACPI SSDT (Secondary System Descriptor Table) to the UEFI BIOS via a UEFI variable, and GRUB is configured to provide the device tree (from that variable) to the kernel.

Consult your hardware provider for guidance.

Root Privileges

The ekfsm package requires root privileges to access the sysfs, dev and proc entries, so your application must be run as root or with sudo.

Logging

The ekfsm package uses the Python logging module for logging. and follows common practices for library logging. By default, if the application does not configure logging, the logging module will log only messages with level WARNING or above and is using the default formatting, i.e. only the message is printed.

To get a more verbose output, the application should call, for example

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

Usage from multiple processes

It is possible to use ekfsm from multiple processes at the same time. The linux kernel ensures that the relevant linux sysfs entries and devices are protected from concurrent access.

However, there are some exceptions due to the nature of some devices. For example, the EKF CCU has some methods that cannot be simultaneously accessed by multiple processes.

This is why the ekfsm package provides a locking mechanism for these devices. The locking mechanism is implemented using a file lock. Application can choose to use the locking mechanism or not. By default, the locking mechanism is enabled and uses the default lockfile directory /var/lock/ekfsm. The locking_configure() method can be used to enable or disable the locking mechanism and to configure the lockfile directory.

To ensure that file locks are properly released, the application should call the locking_cleanup() whenever the program exits. This can be done using the atexit module.

Usage from within a container

The ekfsm package can be used from within a container, but the container must have access to the /sys, /dev # and - if locking is enabled - /var/lock directories of the host system.

This can be achieved by mounting the host’s /sys and /dev directories into the container, e.g.

docker run -v /sys:/sys -v /dev:/dev my_container