Zephyr device declaration

The Zephyr module provides functions to generate device driver instantiations.

cogeno.import_module('zephyr')

The device delaration functions generate device instances code for all devices activated (‘status’ = ‘ok’) in the board device tree file matching the provided compatibles.

Most of the parameters aim at filling the DEVICE_AND_API_INIT macro. Other parameters are there to help code generation to fit driver specifics.

Instance code will only be generated if the Kconfig variable is set. The variable name is build with the device node label name (e.g: CONFIG_I2C_1).

Driver info templates

The device declaration functions work on templates that feature placeholder substitution.

Device instance property placeholders:

  • ${device-name}: device instance name.

    Name is generated by the declaration function.

  • ${driver-name}: device instance driver name.

    Name is taken from the device tree node property ‘label’.

  • ${device-data}: device instance data structure name.

    Name is generated by the declaration function.

  • ${device-config-info}: device instance configuration structure name.

    Name is generated by the declaration function.

  • ${device-config-irq}: device instance interrupt configuration function name.

    Name is generated by the declaration function.

Device instance device tree property placeholders:

  • ${[path to DTS property]}: device instance device tree node property.

    The property path supports every node property that is documented in the node yaml bindings. It also supports yaml heuristics, like ‘bus-master’ and will use documented ‘”#cells”’.

Device tree property placeholders:

  • ${[device id]:[path to DTS property]}: device node property value.

    The device node property is defined by the property path of the device given by the device id. The device id is usually also taken from a DTS property e.g. ${${clock/0/controller}:device-name}.

KConfig configuration parameter placeholders:

  • ${CONFIG_[configuration parameter]}: KConfig configuration parameter value.

Example:

‘c’ template code between triple quotes (“”” “”“) that should provide the expected code to be generated for the driver structures.

"""
#if CONFIG_SPI_STM32_INTERRUPT
DEVICE_DECLARE(${device-name});
static void ${device-config-irq}(struct device *dev)
{
        IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority}, \\
                    spi_stm32_isr, \\
                    DEVICE_GET(${device-name}), 0);
        irq_enable(${interrupts/0/irq});
}
#endif
static const struct spi_stm32_config ${device-config-info} = {
        .spi = (SPI_TypeDef *)${reg/0/address/0},
        .pclken.bus = ${clocks/0/bus},
        .pclken.enr = ${clocks/0/bits},
#if CONFIG_SPI_STM32_INTERRUPT
        .config_irq = ${device-config-irq},
#endif
};
static struct spi_stm32_data ${device-data} = {
        SPI_CONTEXT_INIT_LOCK(${device-data}, ctx),
        SPI_CONTEXT_INIT_SYNC(${device-data}, ctx),
};
"""

Declaration of a single device instance

zephyr.device_declare_single(device_config, driver_name, device_init, device_pm_control, device_level, device_prio, device_api, device_info)

Generate device instance code for a device instance that:

  • matches the driver name that

  • is activated (‘status’ = ‘ok’) in the board device tree file and that is

  • configured by Kconfig.

Parameters
  • device_config – Configuration variables for device instantiation. (e.g. ‘CONFIG_SPI_0’)

  • driver_name – Driver name for device instantiation. (e.g. ‘SPI_0’)

  • device_init – Device initialisation function. (e.g. ‘spi_stm32_init’)

  • device_level – Driver initialisation level. (e.g. ‘PRE_KERNEL_1’)

  • device_prios – Driver initialisation priority definition. (e.g. 32)

  • device_api – Identifier of the device api. (e.g. ‘spi_stm32_driver_api’)

  • device_info – Device info template for device driver config, data and interrupt initialisation.

  • device_defaults – Default property values. (e.g. { ‘label’ : ‘My default label’ })

Param

device_pm_control: Device power management function. (e.g. ‘device_pm_control_nop’)

Declaration of multiple device instances

zephyr.device_declare_multi(device_configs, driver_names, device_inits, device_levels, device_prios, device_api, device_info)

Generate device instances code for all device instances that:

  • match the driver names that

  • are activated (‘status’ = ‘ok’) in the board device tree file and that are

  • configured by Kconfig.

Parameters
  • device_configs – A list of configuration variables for device instantiation. (e.g. [‘CONFIG_SPI_0’, ‘CONFIG_SPI_1’])

  • driver_names – A list of driver names for device instantiation. The list shall be ordered the same way as the list of device configs. (e.g. [‘SPI_0’, ‘SPI_1’])

  • device_inits – A list of device initialisation functions or a single function. The list shall be ordered as the list of device configs. (e.g. ‘spi_stm32_init’)

  • device_levels – A list of driver initialisation levels or a single level definition. The list shall be ordered as the list of device configs. (e.g. ‘PRE_KERNEL_1’)

  • device_prios – A list of driver initialisation priorities or a single priority definition. The list shall be ordered as the list of device configs. (e.g. 32)

  • device_api – Identifier of the device api. (e.g. ‘spi_stm32_driver_api’)

  • device_info – Device info template for device driver config, data and interrupt initialisation.

  • device_defaults – Default property values. (e.g. { ‘label’ : ‘My default label’ })

Param

device_pm_controls: A list of device power management functions or a single function. The list shall be ordered as the list of device configs. (e.g. ‘device_pm_control_nop’)

Example:

/**
 * @code{.cogeno}
 * cogeno.import_module('zephyr')
 *
 * device_configs = ['CONFIG_SPI_{}'.format(x) for x in range(1, 4)]
 * driver_names = ['SPI_{}'.format(x) for x in range(1, 4)]
 * device_inits = 'spi_stm32_init'
 * device_pm_controls = 'device_pm_control_nop'
 * device_levels = 'POST_KERNEL'
 * device_prios = 'CONFIG_SPI_INIT_PRIORITY'
 * device_api = 'spi_stm32_driver_api'
 * device_info = \
 * """
 * #if CONFIG_SPI_STM32_INTERRUPT
 * DEVICE_DECLARE(${device-name});
 * static void ${device-config-irq}(struct device *dev)
 * {
 *         IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority}, \\
 *                     spi_stm32_isr, \\
 *                     DEVICE_GET(${device-name}), 0);
 *         irq_enable(${interrupts/0/irq});
 * }
 * #endif
 * static const struct spi_stm32_config ${device-config-info} = {
 *         .spi = (SPI_TypeDef *)${reg/0/address/0},
 *         .pclken.bus = ${clocks/0/bus},
 *         .pclken.enr = ${clocks/0/bits},
 * #if CONFIG_SPI_STM32_INTERRUPT
 *         .config_irq = ${device-config-irq},
 * #endif
 * };
 * static struct spi_stm32_data ${device-data} = {
 *         SPI_CONTEXT_INIT_LOCK(${device-data}, ctx),
 *         SPI_CONTEXT_INIT_SYNC(${device-data}, ctx),
 * };
 * """
 *
 * zephyr.device_declare_multi( \
 *     device_configs,
 *     driver_names,
 *     device_inits,
 *     device_pm_controls,
 *     device_levels,
 *     device_prios,
 *     device_api,
 *     device_info)
 * @endcode{.cogeno}
 */
/** @code{.codeins}@endcode */