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:¶
Placeholder |
Substitution |
Remark |
|---|---|---|
${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 config structure name |
Name is generated by the declaration function. |
${device-config-irq} |
device instance interrupt configuration funtion name |
Name is generated by the declaration function. |
Device instance device tree property placeholders:¶
Placeholder |
Substitution |
Remark |
|---|---|---|
${[path to DTS property]} |
device instance device |
see below (*) |
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:¶
Placeholder |
Substitution |
Remark |
|---|---|---|
${[device id]:[path to DTS property]} |
device node property value |
see below (*) |
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:¶
Placeholder |
Substitution |
Remark |
|---|---|---|
${CONFIG_[configuration parameter]} |
KConfig configuration parameter value |
|
Driver info template 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¶
-
cogeno.modules.zephyr.device_declare_single(device_config_symbol, driver_name, device_init, device_pm_control, device_level, device_prio, device_api, device_info, device_defaults={})¶ Declare a single device instance.
Generate device instances code for a device instance that:
match the driver names that
is activated (‘status’ = ‘ok’) in the board device tree file and that is
configured by Kconfig.
The device name is derived from the device tree label property or - if not avalable - the node name.
- Return
True if device is declared, False otherwise
- Parameters
device_config_symbol: A configuration symbol for device instantiation. (e.g. ‘CONFIG_SPI_0’)driver_name: The name this instance of the driver can be looked up from user mode with device_get_binding().device_init: Address to the init function of the driver.device_pm_control: The device power management functiondevice_level: The initialization level at which configuration occurs. Must be one of the following symbols, which are listed in the order they are performed by the kernel:PRE_KERNEL_1: Used for devices that have no dependencies, such as those that rely solely on hardware present in the processor/SOC. These devices cannot use any kernel services during configuration, since they are not yet available.
PRE_KERNEL_2: Used for devices that rely on the initialization of devices initialized as part of the PRE_KERNEL_1 level. These devices cannot use any kernel services during configuration, since they are not yet available.
POST_KERNEL: Used for devices that require kernel services during configuration.
POST_KERNEL_SMP: Used for initialization objects that require kernel services during configuration after SMP initialization
APPLICATION: Used for application components (i.e. non-kernel components) that need automatic configuration. These devices can use all services provided by the kernel during configuration.
device_prio: The initialization priority of the device, relative to other devices of the same initialization level. Specified as an integer value in the range 0 to 99; lower values indicate earlier initialization. Must be a decimal integer literal without leading zeroes or sign (e.g. 32), or an equivalent symbolic name (e.g. #define MY_INIT_PRIO 32 or e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).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: Device default property values.device_defaultsis a dictionary of property path : property value (e.g. { ‘label’ : ‘My default label’ }).
Declaration of multiple device instances¶
-
cogeno.modules.zephyr.device_declare_multi(device_config_symbols, driver_names, device_inits, device_pm_controls, device_levels, device_prios, device_api, device_info, device_defaults={})¶ Declare multiple device instances.
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_config_symbols: A list of configuration symbols 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 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_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’)device_levels: A list of driver initialisation levels or one 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 one 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: Device default property values.device_defaultsis a dictionary of property path : property value.
Example:
/**
* @code{.cogeno.py}
* 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.py}
*/
/** @code{.codeins}@endcode */