Linux C++ drivers

Koheron SDK V1 documentation. The V1 branch is recommended for new instrument development and remains under active development ahead of the major release. Boards currently ship with V0; build and install a V1 OS image to follow this workflow. V1 images do not support legacy V0 instruments.

C++ drivers are compiled into the instrument server. Public member functions become commands callable from Python and TypeScript.

Add a driver to an instrument

List driver files in config.mk:

DRIVERS += $(PROJECT_PATH)/fft.hpp
DRIVERS += $(PROJECT_PATH)/fft.cpp

Board-level drivers can be included from a board make fragment:

include $(SDK_PATH)/boards/alpha250/drivers/drivers.mk

Build only the server while developing C++ code:

make -j CFG=examples/alpha250/fft/config.mk server

Include runtime and memory headers

A driver can include the runtime driver manager and generated memory access headers:

#include "server/runtime/driver_manager.hpp"
#include "server/hardware/memory_manager.hpp"

Board drivers may be included as needed:

#include "boards/alpha250/drivers/clock-generator.hpp"
#include "boards/alpha250/drivers/power-monitor.hpp"

Minimal driver skeleton

#include "server/runtime/driver_manager.hpp"
#include "server/hardware/memory_manager.hpp"

#include <cstdint>

class MyInstrument
{
  public:
    MyInstrument()
    : ctl(hw::get_memory<mem::control>())
    , sts(hw::get_memory<mem::status>())
    {}

    void set_output(uint32_t value) {
        ctl.write<reg::digital_outputs>(value);
    }

    uint32_t get_input() {
        return sts.read<reg::digital_inputs>();
    }

  private:
    hw::Memory<mem::control>& ctl;
    hw::Memory<mem::status>& sts;
};

The exact mem::... and reg::... identifiers come from memory.yml.

Memory access flow

A memory region declared in memory.yml:

memory:
  - name: control
    offset: 0x4000_0000
    range: 4K
    registers:
    - digital_outputs

generates C++ identifiers such as mem::control and reg::digital_outputs.

Reuse another driver

Drivers can access other drivers through the runtime driver manager:

auto& power = rt::get_driver<PowerMonitor>();
auto supplies = power.get_supplies_ui();

Command API design

Public driver methods are exported in generated driver metadata. During the server build, the SDK generates C++ dispatch headers under tmp/<project>/server/, builds a metadata dumper, and writes tmp/<project>/server/drivers.json; the instrument ZIP packages that file as drivers.json.

Clients use this metadata to map class and function names to command IDs.

Examples of exported methods:

void set_input_channel(uint32_t channel);
uint32_t get_fft_size() const;
std::array<int32_t, prm::n_adc> get_adc_raw_data(uint32_t n_avg);
auto get_control_parameters();

Use fixed-width integer types such as uint32_t where possible to avoid ambiguity in the client protocol.

Return types

Clients support common scalar types such as integers, floating-point values and booleans. They also support arrays, vectors, tuples and strings when the C++ return type is exposed in the generated command metadata.

See also

hello@koheron.com