Cogeno’s documentation!¶
Welcome to Cogeno’s documentation!¶
This documentation is continuously written. It is edited via text files in the reStructuredText markup language and then compiled into a static website/ offline document using the open source Sphinx and Read the Docs tools.
You can contribute to cogeno’s dcoumentation by opening GitLab issues or sending patches via merge requests on its GitLab repository.
Sections¶
Indices and tables¶
Generated Content Index¶
adc-controller¶
include: adc-controller.yaml
# Copyright (c) 2017, NXP
# SPDX-License-Identifier: Apache-2.0
# Common fields for ADC controllers
include: base.yaml
properties:
label:
required: true
"#io-channel-cells":
type: int
required: true
base¶
include: base.yaml
# Common fields for all devices
properties:
status:
type: string
required: false
description: indicates the operational status of a device
enum:
- "okay"
- "disabled"
- "reserved"
- "fail"
- "fail-sss"
compatible:
type: string-array
required: true
description: compatible strings
reg:
type: array
description: register space
required: false
reg-names:
type: string-array
description: name of each register space
required: false
interrupts:
type: array
required: false
description: interrupts for device
# Does not follow the 'type: phandle-array' scheme, but gets type-checked
# by the code. Declare it here just so that other bindings can make it
# 'required: true' easily if they want to.
interrupts-extended:
type: compound
required: false
description: extended interrupt specifier for device
interrupt-names:
type: string-array
required: false
description: name of each interrupt
interrupt-parent:
type: phandle
required: false
description: phandle to interrupt controller node
label:
type: string
required: false
description: Human readable string describing the device (used by Zephyr for API name)
clocks:
type: phandle-array
required: false
description: Clock gate information
clock-frequency:
type: int
required: false
description: >
Frequency of clock in Hz. Encoded as an arbitrary number
of frequency values.
clock-accuracy:
type: int
required: false
description: >
Accuracy of clock in ppb (parts per billion). Encoded as an
arbitrary number of ppb values.
"#address-cells":
type: int
required: false
description: number of address cells in reg property
"#size-cells":
type: int
required: false
description: number of size cells in reg property
pinctrl-\d+:
type: phandle
required: false
description: pin control for device
pinctrl-names:
type: string-array
required: false
description: name of each pin control
can-controller¶
include: can-controller.yaml
# Common fields for CAN controllers
include: base.yaml
bus: can
properties:
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 0
label:
required: true
bus-speed:
type: int
required: true
description: bus speed in Baud/s
sjw:
type: int
required: true
description: Resynchronization jump width (ISO 11898-1)
prop-seg:
type: int
required: true
description: Time quantums of propagation segment (ISO 11898-1)
phase-seg1:
type: int
required: true
description: Time quantums of phase buffer 1 segment (ISO 11898-1)
phase-seg2:
type: int
required: true
description: Time quantums of phase buffer 2 segment (ISO 11898-1)
can-device¶
include: can-device.yaml
# Copyright (c) 2018 Alexander Wachter
# SPDX-License-Identifier: Apache-2.0
# Common fields for CAN devices
include: base.yaml
on-bus: can
properties:
reg:
required: true
label:
required: true
chosen¶
include: chosen.yaml
# Copyright (c) 2019..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Chosen properties
compatible: "chosen"
properties:
stdout-path:
type: string
required: false
description: >
Device to be used for boot console output
If the character ":" is present in the value, this terminates the path.
The meaning of any characters following the ":" is device-specific, and
must be specified in the relevant binding documentation.
For UART devices, the preferred binding is a string in the form:
path:<baud>{<parity>{<bits>{<flow>}}}
where
path - path of uart device
baud - baud rate in decimal
parity - 'n' (none), 'o', (odd) or 'e' (even)
bits - number of data bits
flow - 'r' (rts)
For example: 115200n8r
zephyr,entropy:
type: path
required: false
description: A device which can be used as a system-wide entropy source.
zephyr,flash:
type: path
required: false
description: >
A node whose reg is sometimes used to set the defaults for CONFIG_FLASH_BASE_ADDRESS
and CONFIG_FLASH_SIZE.
zephyr,sram:
type: path
required: false
description: >
A node whose reg sets the base address and size of SRAM memory available to the Zephyr
image, used during linking.
zephyr,ccm:
type: path
required: false
description: TBD
zephyr,console:
type: path
required: false
description: TBD
zephyr,shell-uart:
type: path
required: false
description: TBD
zephyr,bt-uart:
type: path
required: false
description: TBD
zephyr,uart-pipe:
type: path
required: false
description: TBD
zephyr,bt-mon-uart:
type: path
required: false
description: TBD
zephyr,uart-mcumgr:
type: path
required: false
description: TBD
clock-consumer¶
include: clock-consumer.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
# -- Assigned clock parents and rates --
# Some platforms may require initial configuration of default parent clocks
# and clock frequencies. Such a configuration can be specified in a device tree
# node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
# properties.
description: Clock consumer
include: base.yaml
properties:
clocks:
required: true
description: >
List of phandle and clock specifier pairs, one pair for each clock
input to the device. Note - if the clock provider specifies '0' for
clock-cells, then only the phandle portion of the pair will appear.
clock-names:
required: false
description: >
List of clock input name strings sorted in the same order as the clocks
property.
clock-ranges:
type: boolean
required: false
description: >
Empty property indicating that child nodes can inherit named clocks from
this node. Useful for bus nodes to provide a clock to their children.
assigned-clocks:
type: phandle-array
required: false
description: >
List of phandle and clock specifier pairs, one pair for each assigned
clock input. Note - if the clock provider specifies '0' for
clock-cells, then only the phandle portion of the pair will appear.
assigned-clock-parents:
type: phandle-array
required: false
description: >
List of parent clocks in the form of a phandle and clock
specifier pair. The list shall correspond to the clocks listed in the
assigned-clocks directive.
assigned-clock-rates:
type: array
required: false
description: >
List of frequencies in Hz. The list shall correspond to the clocks
listed in the assigned-clocks directive.
clock-controller¶
include: clock-controller.yaml
# Copyright (c) 2019, Linaro Limited
# Copyright (c) 2019..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
# Common fields for clock controllers
properties:
"#clock-cells":
type: int
required: true
description: Number of items to expect in a Clock specifier
clock-output-names:
type: string-array
required: false
description: >
A list of strings of clock output signal names indexed by the first
cell in the clock specifier.
clock-indices:
type: array
required: false
description: >
The identifying number for the clocks in the node. If it is not linear
from zero, then this allows the mapping of identifiers into the
clock-output-names array.
protected-clocks:
type: phandles
required: false
description: >
Clocks that are not fully exposed, such as in situations where those
clocks are used by drivers running in ARM secure execution levels.
cpu¶
include: cpu.yaml
# Copyright (c) 2019 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
# Common fields for CPUs
include: base.yaml
properties:
clock-frequency:
type: int
required: false
description: Clock frequency in Hz
dma-client¶
include: dma-client.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: DMA client
properties:
dmas:
type: phandle-array
required: true
description: >
List of one or more DMA specifiers, each consisting of
- A phandle pointing to DMA controller node
- A number of integer cells, as determined by the
dma-cells property in the node referenced by phandle
containing DMA controller specific information. This
typically contains a DMA request line number or a
channel number, but can contain any data that is
required for configuring a channel.
dma-names:
type: string-array
required: false
description: >
Contains one identifier string for each DMA specifier in
the dmas property. The specific strings that can be used
are defined in the binding of the DMA client device.
Multiple DMA specifiers can be used to represent
alternatives and in this case the dma-names for those
DMA specifiers must be identical (see examples).
dma-controller¶
include: dma-controller.yaml
# Copyright (c) 2019, Song Qiang <songqiang1304521@gmail.com>
# SPDX-License-Identifier: Apache-2.0
# Common fields for DMA controllers
include: base.yaml
bus: dma
properties:
label:
required: true
"#dma-cells":
type: int
required: true
description: Number of items to expect in a DMA specifier
dma-channel-mask:
type: int
required: false
description: >
Bitmask of available DMA channels in ascending order that are
not reserved by firmware and are available to the
kernel. i.e. first channel corresponds to LSB.
dma-channels:
type: int
required: false
description: Number of DMA channels supported by the controller
dma-requests:
type: int
required: false
description: Number of DMA request signals supported by the controller.
eeprom-base¶
include: eeprom-base.yaml
# Copyright (c) 2019 Vestas Wind Systems A/S
# SPDX-License-Identifier: Apache-2.0
# Common fields for EEPROM devices
include: base.yaml
properties:
size:
type: int
required: false
description: Total EEPROM size in bytes
read-only:
type: boolean
required: false
description: Disable writes to the EEPROM
label:
required: true
eeprom-spi-i2c¶
include: eeprom-spi-i2c.yaml
# Copyright (c) 2019 Vestas Wind Systems A/S
# SPDX-License-Identifier: Apache-2.0
# Common fields for I2C and SPI EEPROM devices
include: eeprom-base.yaml
properties:
size:
required: true
pagesize:
type: int
required: true
description: EEPROM page size in bytes
address-width:
type: int
required: true
description: EEPROM address width in bits
timeout:
type: int
required: true
description: EEPROM write cycle timeout in milliseconds
wp-gpios:
type: phandle-array
required: false
description: GPIO to which the write-protect pin of the chip is connected
espi-controller¶
include: espi-controller.yaml
# Copyright (c) 2019 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
# Common fields for ESPI devices
include: base.yaml
bus: espi
properties:
label:
required: true
ethernet¶
include: ethernet.yaml
# Copyright (c) 2018, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
# Common fields for Ethernet devices
include: base.yaml
properties:
local-mac-address:
type: uint8-array
required: false
description: mac address
label:
required: true
fixed-clock¶
include: fixed-clock.yaml
#
# Copyright (c) 2017..2019 b0661n0e17e@gmail.com
#
# SPDX-License-Identifier: Apache-2.0
#
title: Simple fixed-rate clock sources.
description: >
Binding for simple fixed-rate clock sources.
inherits:
!include clock-provider.yaml
properties:
compatible:
constraint: "fixed-clock"
"#clock-cells":
constraint: 0
clock-frequency:
type: int
category: required
description: Frequency of clock in Hz. Should be a single cell.
clock-accuracy:
type: int
category: optional
description: Accuracy of clock in ppb (parts per billion). Should be a single cell.
oscillator:
type: int
category: optional
description: clock is an oszillator (a quartz)
fixed-partition¶
include: fixed-partition.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Fixed partition (one of the partions of a 'fixed-partitions' node).
compatible: "fixed-partition"
properties:
label:
type: string
required: false
description: The label / name for this partition. If omitted, the label is taken
from the node name (excluding the unit address).
read-only:
type: boolean
required: false
description: This parameter, if present, is a hint that this
partition should/ can only be used read-only.
reg:
type: array
required: false
description: partition offset (address) and size within flash
flash¶
include: flash.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Flash Base Structure
include: base.yaml
properties:
label:
required: true
reg:
required: true
"#address-cells":
type: int
required: true
description: >
<1>: for flash devices that require a single 32-bit cell to represent their
address (aka the value is below 4 GiB)
<2>: for flash devices that require two 32-bit cells to represent their
address (aka the value is 4 GiB or greater).
"#size-cells":
type: int
required: true
description: >
<1>: for flash devices that require a single 32-bit cell to represent their
size (aka the value is below 4 GiB)
<2>: for flash devices that require two 32-bit cells to represent their
size (aka the value is 4 GiB or greater).
write-block-size:
type: int
required: false
description: Size of flash blocks for write operations
erase-block-size:
type: int
required: false
description: Size of flash blocks for erase operations
flash-controller¶
include: flash-controller.yaml
# Common fields for flash controllers
include: base.yaml
properties:
label:
required: true
reg:
required: true
gpio-controller¶
include: gpio-controller.yaml
# Copyright (c) 2019, Linaro Limited
# Copyright (c) 2019..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
# Common fields for GPIO controllers
include: base.yaml
properties:
"gpio-controller":
type: boolean
required: true
description: Convey's this node is a GPIO controller
"#gpio-cells":
type: int
required: true
description: Number of items to expect in a GPIO specifier
ngpios:
type: int
required: false
description: Number of gpios supported
gpio-ranges:
type: phandle-array
required: false
description: gpio range in pin controller
gpio-ranges-group-names:
type: string-array
required: false
description: gpio range names
gpio-cells:
- pin
- flags
gpio-keys¶
include: gpio-keys.yaml
# Copyright (c) 2018, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
description: GPIO KEYS parent node
compatible: "gpio-keys"
child-binding:
description: GPIO KEYS child node
properties:
gpios:
type: phandle-array
required: true
label:
required: true
type: string
description: Human readable string describing the device (used by Zephyr for API name)
gpio-led¶
include: gpio-led.yaml
# Copyright (c) 2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: GPIO LED
compatible: "gpio-led"
properties:
label:
type: string
required: false
description: Human readable string describing the device (used by Zephyr for API name)
gpios:
type: phandle-array
required: true
function:
required: false
type: int
description: Numerical LED functon identifier.
color:
required: false
type: int
description: Numerical LED color identifier
default-state:
required: false
type: int
default: 0
description: >
The initial state of the LED. Valid values are LED_STATE_OFF (0),
LED_STATE_ON (1), and LED_STATE_KEEP (2). If the LED is already on or
off and the default-state property is set the to same value, then no
glitch should be produced where the LED momentarily turns off (or on).
The LED_STATE_KEEP setting will keep the LED at whatever its current
state is, without producing a glitch. The default is LED_STATE_OFF (0)
if this property is not present.
led-pattern:
required: false
type: array
description: Array of integers with default pattern for certain triggers.
retain-state-suspended:
required: false
type: boolean
description: Retain the state of the LED in suspend state.
retain-state-shutdown:
required: false
type: boolean
description: Retain the state of the LED on shutdown.
panic-indicator:
required: false
type: boolean
description: The LED should be used as a panic indicator.
gpio-leds¶
include: gpio-leds.yaml
# Copyright (c) 2018, Linaro Limited
# Copyright (c) 2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: GPIO LEDs controller
compatible: "gpio-leds"
include: base.yaml
properties:
label:
default: "GPIO_LEDS"
gpio-nexus¶
include: gpio-nexus.yaml
# Copyright (c) 2019, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
# Common fields for GPIO nexus nodes
properties:
gpio-map:
type: compound
required: true
gpio-map-mask:
type: compound
required: false
gpio-map-pass-thru:
type: compound
required: false
"#gpio-cells":
type: int
required: true
description: Number of items to expect in a GPIO specifier
i2c-controller¶
include: i2c-controller.yaml
# Copyright (c) 2017 I-SENSE group of ICCS
# SPDX-License-Identifier: Apache-2.0
# Common fields for I2C controllers
include: base.yaml
bus: i2c
properties:
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 0
clock-frequency :
type: int
required: false
description: Initial clock frequency in Hz
label:
required: true
i2c-device¶
include: i2c-device.yaml
# Copyright (c) 2017, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
# Common fields for I2C devices
include: base.yaml
on-bus: i2c
properties:
reg:
required: true
label:
required: true
i2s-controller¶
include: i2s-controller.yaml
# Copyright (c) 2018, STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
# Common fields for I2S controllers
include: base.yaml
bus: i2s
properties:
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 0
label:
required: true
i2s-device¶
include: i2s-device.yaml
# Copyright (c) 2018, STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
# Common fields for I2S devices
include: base.yaml
on-bus: i2s
properties:
reg:
required: true
label:
required: true
interrupt-controller¶
include: interrupt-controller.yaml
# Copyright (c) 2019, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
# Common fields for interrupt controllers
properties:
"interrupt-controller":
type: boolean
required: true
description: Convey's this node is an interrupt controller
"#interrupt-cells":
type: int
required: true
description: Number of items to expect in an interrupt specifier
kscan¶
include: kscan.yaml
# Copyright (c) 2019, Intel Corporation
# SPDX-License-Identifier: Apache-2.0
# Common properties for keyboard matrix devices
include: base.yaml
bus: kscan
properties:
"#address-cells":
required: true
const: 1
"#size-cells":
type: int
const: 0
label:
required: true
memory¶
include: memory.yaml
# Copyright (c) 2020 Bobby Noeltw
# SPDX-License-Identifier: Apache-2.0
# Common fields for memory
description: Memory properties
compatible: "memory"
include: base.yaml
properties:
reg:
required: true
memory-region¶
include: memory-region.yaml
# Copyright (c) 2020 Bobby Noeltw
# SPDX-License-Identifier: Apache-2.0
# Common fields for memory regions
description: Memory region properties
compatible: "memory-region"
include: base.yaml
properties:
reg:
required: true
label:
required: false
mmc¶
include: mmc.yaml
# Copyright (c) 2019, NXP
# SPDX-License-Identifier: Apache-2.0
# Specifies the MMC/SDHC module
include: base.yaml
mmc-spi-slot¶
include: mmc-spi-slot.yaml
# Copyright (c) 2018 Google LLC.
# SPDX-License-Identifier: Apache-2.0
description: MMC/SD/SDIO slot connected via SPI
compatible: "zephyr,mmc-spi-slot"
include: spi-device.yaml
mmio-sram¶
include: mmio-sram.yaml
# Copyright (c) 2018, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
description: Generic on-chip SRAM description
compatible: "mmio-sram"
include: base.yaml
properties:
reg:
required: true
label:
required: false
partition¶
include: partition.yaml
# Copyright (c) 2018,2019 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Flash partition definition for fixed partitions
compatible: "fixed-partitions"
properties:
"#address-cells":
type: int
required: true
description: >
<1>: for partitions that require a single 32-bit cell to represent their
size/address (aka the value is below 4 GiB)
<2>: for partitions that require two 32-bit cells to represent their
size/address (aka the value is 4 GiB or greater).
"#size-cells":
type: int
required: false
description: >
<1>: for partitions that require a single 32-bit cell to represent their
size/address (aka the value is below 4 GiB)
<2>: for partitions that require two 32-bit cells to represent their
size/address (aka the value is 4 GiB or greater).
phy-controller¶
include: phy-controller.yaml
# Copyright (c) 2018, Yannis Damigos
# SPDX-License-Identifier: Apache-2.0
# Common fields for PHY providers
include: base.yaml
properties:
"#phy-cells":
type: int
required: true
description: Number of cells in a PHY provider. The meaning those
cells is defined by the binding for the phy node.
pin-controller¶
include: pin-controller.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Pin controller
include: base.yaml
properties:
pin-controller:
type: boolean
required: true
description: device controller identification
"#pinctrl-cells":
type: int
required: false
description: >
Number of pin control cells in addition to the index within the
pin controller device instance
pincfg¶
include: pincfg.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: Pin configuration
compatible: "pincfg"
properties:
groups:
description: >
The list of names of the groups that properties in the node apply to
(either this, "pins", "pinmux" or "pinctrl-pin-array" have to be
specified).
required: false
type: string-array
pins:
description: >
The list of numeric pin ids that properties in the node apply to
(either this, "groups", "pinmux" or "pinctrl-pin-array" have to be
specified).
required: false
type: array
function:
required: false
type: string
pinmux:
description: >
The list of numeric pin ids and their mux settings that properties
in the node apply to (either this, "pins", "groups" or
"pinctrl-pin-array" have to be specified).
required: false
type: array
pinctrl-pin-array:
description: >
The list of pin controller register index and values (either this,
"pins", "pinmux" or "groups" have to be specified). pinctrl-cells
specifies the number of value cells in addition to the index of the
registers. No other properties shall be in the node.
required: false
type: array
bias-disable:
description: Disable any pin bias.
required: false
type: boolean
bias-high-impedance:
required: false
type: boolean
bias-bus-hold:
required: false
type: boolean
bias-pull-up:
description: Pull up strength in Ohm. 0 to disable pull up.
required: false
type: int
bias-pull-down:
description: Pull down strength in Ohm. 0 to disable pull down.
required: false
type: int
bias-pull-pin-default:
required: false
type: int
drive-push-pull:
required: false
type: boolean
drive-open-drain:
required: false
type: boolean
drive-open-source:
required: false
type: boolean
drive-strength:
description: >
Sink or source at most X mA. 0 to disable drive strength control.
required: false
type: int
input-enable:
required: false
type: boolean
input-debounce:
description: Debounce time in usec. 0 to disable debouncing.
required: false
type: int
input-disable:
required: false
type: boolean
input-schmitt-enable:
required: false
type: boolean
input-schmitt-disable:
required: false
type: boolean
low-power-enable:
description: Enable low power mode.
required: false
type: boolean
low-power-disable:
description: Disable low power mode.
required: false
type: boolean
output-disable:
required: false
type: boolean
output-enable:
required: false
type: boolean
output-low:
required: false
type: boolean
output-high:
required: false
type: boolean
power-source:
description: Numerical ID of power source to select.
required: false
type: int
default: 0
slew-rate:
description: Slew rate
required: false
type: int
default: 0
skew-delay:
description: >
Expected clock skew on input pins and the delay before latching
a value to an output pin.
Typically indicated by the number of double-inverters used to
delay the signal.
required: false
type: int
default: 0
pinctrl-state¶
include: pinctrl-state.yaml
# Copyright (c) 2018..2020 Bobby Noelte
# SPDX-License-Identifier: Apache-2.0
description: >
Pinctrl state. A node that bundles a set of pin configuration
nodes that shall be applied in a single pin control operation.
compatible: "pinctrl-state"
ps2¶
include: ps2.yaml
# Copyright (c) 2019, Intel Corporation
# SPDX-License-Identifier: Apache-2.0
# Common properties for PS/2 devices
include: base.yaml
bus: ps2
properties:
"#address-cells":
type: int
required: true
description: should be 1.
"#size-cells":
type: int
required: true
description: should be 0.
label:
required: true
pwm-client¶
include: pwm-client.yaml
#
# Copyright (c) 2018..2020 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#
description: PWM Client
properties:
pwms:
type: phandle-array
required: true
description: >
List of phandle and pwm specifiers, one set for each pwm
input to the device. Note - The number of pwm specifiers is
determined by the dma-cells property in the node referenced by phandle
pwm-names:
type: string-array
required: false
description: >
List of strings to label each of the PWM devices sorted in the same
order as the pwms property.
pwm-controller¶
include: pwm-controller.yaml
# Copyright (c) 2017, NXP
# Copyright (c) 2019 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
# Common fields for PWM controllers
include: base.yaml
properties:
label:
required: true
"#pwm-cells":
type: int
required: true
description: Number of items to expect in a pwm specifier
clocks:
required: false
pwm-leds¶
include: pwm-leds.yaml
# Copyright (c) 2018, Linaro Limited
# SPDX-License-Identifier: Apache-2.0
description: PWM LEDs parent node
compatible: "pwm-leds"
child-binding:
description: PWM LED child node
properties:
pwms:
type: phandle-array
required: true
label:
required: false
type: string
description: Human readable string describing the device (used by Zephyr for API name)
reserved-memory¶
include: reserved-memory.yaml
# Copyright (c) 2020 Bobby Noeltw
# SPDX-License-Identifier: Apache-2.0
# Common fields for reserved memory
description: Reserved memory properties
compatible: "reserved-memory"
include: base.yaml
properties:
ranges:
type: boolean
required: true
description: standard definition
reserved-memory-region¶
include: reserved-memory-region.yaml
# Copyright (c) 2020 Bobby Noeltw
# SPDX-License-Identifier: Apache-2.0
# Common fields for reserved memory regions
description: Reserved memory region properties
compatible: "reserved-memory-region"
include: base.yaml
properties:
reg:
required: false
size:
type: int
required: false
description: >
length based on parent's #size-cells
Size in bytes of memory to reserve.
alignment:
type: int
required: false
description: >
length based on parent's #size-cells
Address boundary for alignment of allocation.
alloc-ranges:
type: array
required: false
description: >
prop-encoded-array (address, length pairs).
Specifies regions of memory that are
acceptable to allocate from.
rtc¶
include: rtc.yaml
# Copyright (c) 2018, blik GmbH
# SPDX-License-Identifier: Apache-2.0
# Common fields for RTC devices
include: base.yaml
properties:
clock-frequency:
type: int
required: false
description: Clock frequency information for RTC operation
label:
required: true
interrupts:
required: true
prescaler:
type: int
required: false
description: RTC frequency equals clock-frequency divided by the prescaler value
soc-nv-flash¶
include: soc-nv-flash.yaml
description: Flash node
compatible: "soc-nv-flash"
include: base.yaml
properties:
label:
required: false
erase-block-size:
type: int
description: address alignment required by flash erase operations
required: false
write-block-size:
type: int
description: address alignment required by flash write operations
required: false
spi-controller¶
include: spi-controller.yaml
# Copyright (c) 2018, I-SENSE group of ICCS
# SPDX-License-Identifier: Apache-2.0
# Common fields for SPI controllers
include: base.yaml
bus: spi
properties:
clock-frequency:
type: int
required: false
description: Clock frequency the SPI peripheral is being driven at
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 0
label:
required: true
cs-gpios:
type: phandle-array
required: false
spi-device¶
include: spi-device.yaml
# Copyright (c) 2018, I-SENSE group of ICCS
# SPDX-License-Identifier: Apache-2.0
# Common fields for SPI devices
include: base.yaml
on-bus: spi
properties:
reg:
required: true
spi-max-frequency:
type: int
required: true
description: Maximum clock frequency of device's SPI interface in Hz
label:
required: true
uart-controller¶
include: uart-controller.yaml
# Common fields for UART controllers
include: base.yaml
bus: uart
properties:
clock-frequency:
type: int
required: false
description: Clock frequency information for UART operation
current-speed:
type: int
required: false
description: Initial baud rate setting for UART
label:
required: true
hw-flow-control:
type: boolean
required: false
description: Set to enable RTS/CTS flow control at boot time
uart-device¶
include: uart-device.yaml
# Copyright (c) 2018, Foundries.io
# SPDX-License-Identifier: Apache-2.0
# Common fields for UART devices
include: base.yaml
on-bus: uart
properties:
label:
required: true
usb-controller¶
include: usb-controller.yaml
# Copyright (c) 2018, I-SENSE group of ICCS
# SPDX-License-Identifier: Apache-2.0
# Common fields for USB controllers
include: base.yaml
properties:
maximum-speed:
type: string
required: false
description: Configures USB controllers to work up to a specific
speed. Valid arguments are "super-speed", "high-speed",
"full-speed" and "low-speed". If this is not passed
via DT, USB controllers should use their maximum
hardware capability.
enum:
- "low-speed"
- "full-speed"
- "high-speed"
- "super-speed"
label:
required: true
usb-ep¶
include: usb-ep.yaml
# Copyright (c) 2018, I-SENSE group of ICCS
# SPDX-License-Identifier: Apache-2.0
# Common fields that give the number of endpoints supported by the USB hardware
include: usb-controller.yaml
properties:
num-bidir-endpoints:
type: int
required: true
description: Number of bi-directional endpoints supported by hardware
(including EP0)
num-in-endpoints:
type: int
required: false
description: Number of IN endpoints supported by hardware
(including EP0 IN)
num-out-endpoints:
type: int
required: false
description: Number of OUT endpoints supported by hardware
(including EP0 OUT)
EDTS Bindings Index¶
About Cogeno¶
For some repetitive or parameterized coding tasks, it’s convenient to use a code generating tool to build code fragments, instead of writing (or editing) that source code by hand.
Cogeno, the inline code generation tool, processes Python 3 or Jinja2 script “snippets” inlined in your source files. It can also access CMake build parameters and device tree information to generate source code automatically tailored and tuned to a specific project configuration.
Cogeno can be used, for example, to generate source code that creates and fills data structures, adapts programming logic, creates configuration-specific code fragments, and more.
About Cogeno scripts¶
Script snippets that are inlined in a source file are used as code generators. The tool to scan the source file for the script snippets and process them is Cogeno. Cogeno and part of this documentation is based on Cog from Ned Batchelder.
The inlined script snippets can contain any Python 3 or Jinja2 code, they are regular scripts.
All Python snippets in a source file and all Python snippets of included template files are treated as a python script with a common set of global Python variables. Global data created in one snippet can be used in another snippet that is processed later on. This feature could be used, for example, to customize included template files.
Jinja2 snippets provide a - compared to Python - simplified script language.
An inlined script snippet can always access the cogeno module. The cogeno module encapsulates and provides all the functions to retrieve information (options, devicetree properties, CMake variables, config properties) and to output the generated code.
Cogeno transforms files in a very simple way: it finds snippets of script code embedded in them, executes the script code, and places its output combined with the original file into the generated file. The original file can contain whatever text you like around the script code. It will usually be source code.
For example, if you run this file through cogeno:
/* This is my C file. */
...
/**
* @code{.cogeno.py}
* fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing']
* for fn in fnames:
* cogeno.outl(f'void {fn}();')
* @endcode{.cogeno.py}
*/
/** @code{.cogeno.ins}@endcode */
...
it will come out like this:
/* This is my C file. */
...
/**
* @code{.cogeno.py}
* fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing']
* for fn in fnames:
* cogeno.outl(f'void {fn}();')
* @endcode{.cogeno.py}
*/
void DoSomething();
void DoAnotherThing();
void DoLastThing();
/** @code{.cogeno.ins}@endcode */
...
Lines with @code{.cogeno.py}
or @code{.cogeno.ins}@endcode
are marker lines.
The lines between @code{.cogeno.py}
and @endcode{.cogeno.py}
are the
generator Python code. The lines between @endcode{.cogeno.py}
and
@code{.cogeno.ins}@endcode
are the output from the generator.
When Cogeno runs, it discards the last generated Python output, executes the generator Python code, and writes its generated output into the file. All text lines outside of the special markers are passed through unchanged.
The Cogeno marker lines can contain any text in addition to the marker tokens. This makes it possible to hide the generator Python code from the source file.
In the sample above, the entire chunk of Python code is a C comment, so the Python code can be left in place while the file is treated as C code.
About Cogeno extensions¶
On invocation Cogeno scans a list of given directories for extension modules and imports the modules. An extension module may add additional options to the Cogeno invocation or may provide other information specific to the extension directory. The Cogeno extensions are available to the script snippets.
About Cogeno modules¶
Cogeno includes several Cogeno modules to support specific code generation tasks.
Getting started with Cogeno¶
Set up an environment for Cogeno¶
To start off, be sure that you have installed a fairly recent Python 3 and the Python package manager pip3. Git is needed in case you want to get the source.
Get Cogeno¶
Get the source¶
Cogeno’s latest version is available from https://gitlab.com/b0661/cogeno:
git clone https://gitlab.com/b0661/cogeno.git
Run Cogeno¶
To run from source one time assure all dependencies are installed:
pip3 install -r <cogeno repo clone>/requirements.txt
Then call:
python3 <cogeno repo clone>/cogeno/cogeno.py <any option>
To run the installed variant you only have to call:
cogeno <any option>
For all the possible options see Invoking Cogeno.
Integrate Cogeno into your project´s build system¶
Cogeno usually is invoked during the build process by your favourite build system.
Cogeno provides example solutions for some of them (see Build with Cogeno), especially for the CMake build system generator.
Get Cogeno´s documentation¶
Cogeno´s documentation is available online at Read the Docs.
The source of the documentation is in the docs
folder.
To build it first assure all dependencies are fulfilled:
pip3 install -r <cogeno repo clone>/cogeno/docs/requirements.txt
You can then create it by:
cd <cogeno repo clone>/cogeno/docs
make html
Invoking Cogeno¶
Synopsis¶
cogeno [OPTIONS]
Description¶
Cogeno transforms files in a very simple way: it finds chunks of script code embedded in them, executes the script code, and places its output combined with the original file content into the generated file. It supports Python and Jinja2 scripts.
Options¶
The following options are understood:
-h, --help
show this help message and exit
-x, --delete-code
Delete the generator code from the output file.
-w, --warn-empty
Warn if a file has no generator code in it.
-n ENCODING, --encoding ENCODING
Use ENCODING when reading and writing files.
-U, --unix-newlines
Write the output with Unix newlines (only LF line-endings).
-D DEFINE, --define DEFINE
Define a global string available to your generator code.
-m DIR [DIR ...], --modules DIR [DIR ...]
Use modules from modules DIR. We allow multiple
-t DIR [DIR ...], --templates DIR [DIR ...]
Use templates from templates DIR. We allow multiple
-e DIR [DIR ...], --extensions DIR [DIR ...]
Import extensions from extensions DIR. We allow multiple
-i FILE, --input FILE
Get the input from FILE.
-o FILE, --output FILE
Write the output to FILE. “-” indicates stdout.
--output-sanitize-suffix
Sanitize the suffix of the output file. Remove typical template suffixes.
-l FILE, --log FILE
Log to FILE.
-k FILE, --lock FILE
Use lock FILE for concurrent runs of cogeno.
--base
Return the base directory of cogeno. Other options are ignored.
Additional options are related to Cogeno modules.
--cmake:cache FILE
Use CMake variables from CMake cache FILE.
--cmake:define [defxxx=valyyy ...]
Define CMake variables to your generator code.
--config:db FILE
Write or read config database to/ from FILE.
--config:file FILE
Read configuration variables from this FILE.
--config:kconfig-file FILE
Top-level Kconfig FILE (default: Kconfig).
--config:kconfig-srctree DIR
Kconfig files are looked up relative to the srctree DIR (unless absolute paths are used), and .config files are looked up relative to the srctree DIR if they are not found in the current directory.
--config:kconfig-defines DEFINE [DEFINE ...]
Define variable to Kconfig. We allow multiple.
--config:inputs FILE [FILE ...]
Read configuration file fragment from FILE. We allow multiple.
--edts:bindings-dirs DIR [DIR ...]
Use bindings from bindings DIR for device tree extraction. We allow multiple.
--edts:bindings-exclude [DIR ...] [FILE ...]
Exclude bindings DIR or FILE from usage for device tree extraction. We allow multiple.
--edts:bindings-no-default
Do not add EDTS database’s generic bindings to bindings by default.
--edts:db FILE
Write or read EDTS database to/ from FILE.
--edts:dts FILE
Write (see dts-pp-sources) or read device tree specification to/ from this FILE.
--edts:dts-pp-sources FILE [FILE ...]
Generate the DTS file by pre-processing the DTS source FILE(s).
--edts:dts-pp-include-dirs DIR [DIR ...]
Define include DIR(s) to pre-processor.
--edts:dts-pp-defines DEFINE [DEFINE ...]
DEFINE variable to pre-processor.
--protobuf:db-dir DIR
Write or read protocol buffer code databases to/ from DIR.
--protobuf:sources FILE [FILE ...]
The *.proto source FILE(s) to generate the protocol buffer code for.
--protobuf:include-dirs DIR [DIR ...]
Search for *.proto import files in the protocol buffer include DIR(s).
Scripting with Cogeno¶
Code generation functions¶
The cogeno
module provides the core functions for inline
code generation. It encapsulates all the functions to retrieve information
(options, device tree properties, CMake variables, config properties) and
to output the generated code.
The cogeno
module is automatically imported by all code snippets. No
explicit import is necessary.
Note
The cogeno
module provides the public functions of the code generator
Mixin
classes as cogeno functions. You can simply write:
cogeno.func(…)
The mixin class function cogeno.xxx.XxxMixin.func(self, …) is not directly available to code snippets.
Output¶
cogeno.out(*args)¶
-
cogeno::output::OutputMixin.out(self, args)
Write text to the output.
The string arguments are concenated. The filters are then applied to the lines of the concenated string. The resulting string is written to the output.
OutputFilterDedent
andOutputFilterTrimBlankLines
make it easier to use multi-line strings, and they are only are useful for multi-line strings:cogeno.out(""" These are lines I want to write into my source file. """, cogeno.OutputFilterDedent(), cogeno.OutputFilterTrimBlankLines())
- Return
output string
- Parameters
*args
: Variable length argument list of strings and output filters.
cogeno.outl(*args)¶
-
cogeno::output::OutputMixin.outl(self, args)
Write text to the output with newline appended.
- See
OutputMixin::out(self, *args)
- Return
output string
- Parameters
*args
: Variable length argument list of strings and output filters.
cogeno.out_insert(insert_file, *args)¶
-
cogeno::output::OutputMixin.out_insert(self, insert_file, args)
Insert the text from the file into the output.
- See
OutputMixin::out(self, *args)
- Return
output string
- Parameters
insert_file
: Path of file, either absolute path or relative to current directory or relative to templates directory.*args
: Variable length argument list of strings and output filters.
Output filters¶
cogeno.OutputFilterTrimBlankLines()¶
-
cogeno.output.OutputMixin.OutputFilterTrimBlankLines : public cogeno.output.OutputMixin.OutputFilter
Remove initial and trailing blank lines from the block of lines.
cogeno.OutputFilterTrimDedent()¶
-
cogeno.output.OutputMixin.OutputFilterDedent : public cogeno.output.OutputMixin.OutputFilter
Remove common initial white space from the lines.
- Parameters
new_indent
: Optional new indentation (after dedent)
cogeno.OutputFilterLineNumbers()¶
-
cogeno.output.OutputMixin.OutputFilterLineNumbers : public cogeno.output.OutputMixin.OutputFilter
Filter lines by line numbers.
Filter lines that are given by line sumber specifications (such as “1,2,4-6”).
- Parameters
args
: list of arguments denoting line number specifications
cogeno.OutputFilterStartAt()¶
-
cogeno.output.OutputMixin.OutputFilterStartAt : public cogeno.output.OutputMixin.OutputFilter
Start output at pattern.
- Parameters
start_at
: Start pattern
cogeno.OutputFilterStopAt()¶
-
cogeno.output.OutputMixin.OutputFilterStopAt : public cogeno.output.OutputMixin.OutputFilter
Stop output at pattern.
- Parameters
stop_at
: Stop pattern
cogeno.OutputFilterReplace()¶
-
cogeno.output.OutputMixin.OutputFilterReplace : public cogeno.output.OutputMixin.OutputFilter
Replace substring.
- Parameters
old
: old substring to replacenew
: new substring which will replace the old substring. if new is None and the resulting line is empty it is deleted.count
: (optional) the number of times to replace the old substring with the new substring
cogeno.OutputFilterReSub()¶
-
cogeno.output.OutputMixin.OutputFilterReSub : public cogeno.output.OutputMixin.OutputFilter
Substitude regular expression pattern.
Replace the leftmost non-overlapping occurrences of pattern in each line by the replacement repl.
- Parameters
pattern
: Pattern for replacement. Pattern is a string that will be compiled to a pattern object.repl
: Replacement. Repl can be a string or a function. If repl is a function, it is called for every non-overlapping occurrence of pattern.count
: (optional) maximum number of pattern occurrences to be replaced
cogeno.OutputFilterTemplateSubstitude()¶
-
cogeno.output.OutputMixin.OutputFilterTemplateSubstitude : public cogeno.output.OutputMixin.OutputFilter
Substitude template placeholders.
Template placeholder substitution supports $-based substitutions, using the following rules:
$$ is an escape; it is replaced with a single $.
$identifier names a substitution placeholder matching a mapping key of “identifier”. By default, “identifier” is restricted to any case-insensitive ASCII alphanumeric string (including underscores) that starts with an underscore or ASCII letter. The first non-identifier character after the $ character terminates this placeholder specification.
${identifier} is equivalent to $identifier. It is required when valid identifier characters follow the placeholder but are not part of the placeholder, such as “${noun}ification”.
At least up to 4 nesting levels of placeholders are substituded, e.g.:
${placeholder_level1} : mapping = ‘placeholder_level1’ : ‘holder’
${place${placeholder_level1}_level2} : mapping = ‘placeholder_level2’ : ‘placeholder’
${${placeholder_level2}_level3} : mapping = ‘placeholder_level3’ : ‘placeholder_level’
${${placeholder_level3}4} : mapping = ‘placeholder_level4’ : ‘success’
If more than one placeholder patterns are provided the substitution is done for each pattern sequencing through the patterns list.
- Parameters
mapping
: Mapping is any dictionary-like object with keys that match the template placeholders.patterns
: (optional) Patterns is a list of regular expressions describing the pattern for non-braced placeholders.
The cogeno module also provides a set of convenience functions:
Code generator¶
cogeno.cogeno_state()¶
-
cogeno::generator::CodeGenerator.cogeno_state(self)
numeric cogeno state id
Code generation module import¶
cogeno.import_module(name)¶
-
cogeno::importmodule::ImportMixin.import_module(self, name)
Import a Cogeno module.
Import a module.
Module file is searched in current directory or modules directories.
- Parameters
name
: Module to import. Specified without any path.
See Cogeno modules for the available modules.
Template file inclusion¶
cogeno.out_include(include_file)¶
-
cogeno::include::IncludeMixin.out_include(self, include_file)
Write the text from include_file to the output.
The
include_file
is processed by cogeno. Inline code generation ininclude_file
can access the globals defined in theincluding source file
before inclusion. Theincluding source file
can access the globals defined in theinclude_file
(after inclusion).- Parameters
include_file
: Path of include file, either absolute path or relative to current directory or relative to templates directory (e.g. ‘templates/drivers/simple_tmpl.c’)
cogeno.guard_include()¶
-
cogeno::include::IncludeMixin.guard_include(self)
Prevent the current file to be included by
cogeno.out_include()
when called the next time.
Error handling¶
cogeno.error(msg [, frame_index=0] [, snippet_lineno=0])¶
-
cogeno::error::ErrorMixin.error(self, msg='Error raised by cogeno generator.', frame_index=0, lineno=0)
Raise Error exception.
Extra information is added that maps the python snippet line seen by the Python interpreter to the line of the file that inlines the python snippet.
- Parameters
msg
: [optional] exception messageframe_index
: [optional] Call frame index. The call frame offset of the function calling error(). Zero if directly called in a snippet. Add one for every level of function call.lineno
: [optional] line number within template
Log output¶
cogeno.log(message, message_type=None, end=”n”, logonly=True)¶
-
cogeno::log::LogMixin.log(self, message, message_type=None, end="\, logonly=True)
Print message and write to log file.
- Parameters
message
: Messagemessage_type
: If given will be prepended to the messageend
: Character to put at the end of the message. ‘\n’ by default.logonly
: Only write to logfile. True by default.
cogeno.msg(message)¶
-
cogeno::log::LogMixin.msg(self, message)
Print message to stdout and log with a “message: ” prefix.
- See
- Parameters
message
: Message
cogeno.warning(message)¶
-
cogeno::log::LogMixin.warning(self, message)
Print message to stdout and log with a “warning: ” prefix.
- See
- Parameters
message
: Message
cogeno.prout(message, end=”n”)¶
-
cogeno::log::LogMixin.prout(self, message, end="\)
Print message to stdout and log.
- See
- Parameters
message
: Messageend
: Character to put at the end of the message. ‘\n’ by default.
cogeno.prerr(message, end=”n”)¶
-
cogeno::log::LogMixin.prerr(self, message, end="\)
Print message to stderr and log with a “error: ” prefix.
- See
- Parameters
message
: Messageend
: Character to put at the end of the message. ‘\n’ by default.
See Invoking Cogeno for how to provide the path to the file used for logging.
Lock access¶
cogeno.lock()¶
-
cogeno::lock::LockMixin.lock(self)
Get the global cogeno lock.
try: with cogeno.lock().acquire(timeout = 10): ... except cogeno.lock_timeout(): cogeno.error(...) except: raise
- Return
Lock object
cogeno.lock_timeout()¶
-
cogeno::lock::LockMixin.lock_timeout(self)
Lock timeout.
- Return
Lock timeout object
See Invoking Cogeno for how to provide the path to the file used for locking.
Lock object¶
-
cogeno::filelock::BaseFileLock.acquire(self, timeout=None, poll_intervall=0.05)
Acquires the file lock or fails with a :exc:`Timeout` error. .. code-block:: python # You can use this method in the context manager (recommended) with lock.acquire(): pass # Or use an equivalent try-finally construct: lock.acquire() try: pass finally: lock.release() :arg float timeout: The maximum time waited for the file lock. If ``timeout <= 0``, there is no timeout and this method will block until the lock could be acquired. If ``timeout`` is None, the default :attr:`~timeout` is used. :arg float poll_intervall: We check once in *poll_intervall* seconds if we can acquire the file lock. :raises Timeout: if the lock could not be acquired in *timeout* seconds. .. versionchanged:: 2.0.0 This method returns now a *proxy* object instead of *self*, so that it can be used in a with statement without side effects.
-
cogeno::filelock::BaseFileLock.release(self, force=False)
Releases the file lock. Please note, that the lock is only completely released, if the lock counter is 0. Also note, that the lock file itself is not automatically deleted. :arg bool force: If true, the lock counter is ignored and the lock is released in every case.
-
cogeno::filelock::BaseFileLock.is_locked(self)
True, if the object holds the file lock. .. versionchanged:: 2.0.0 This was previously a method and is now a property.
Options¶
cogeno.option()¶
-
cogeno::options::OptionsMixin.option(self, name)
Get option of actual context.
- Return
option value
- Parameters
name
: Name of option
cogeno.options_add_argument(*args, **kwargs)¶
-
cogeno::options::OptionsMixin.options_add_argument(self, args, kwargs)
Add option arguments to option parser of actual context.
Cogeno modules may add arguments to the cogeno option parser. The argument variables given to cogeno are rescanned after new option arguments are provided.
def mymodule(cogeno): if not hasattr(cogeno, '_mymodule'): cogeno._mymodule = None cogeno.options_add_argument('-m', '--mymodule', metavar='FILE', dest='mymodule_file', action='store', type=lambda x: cogeno.option_is_valid_file(x), help='Load mymodule data from FILE.') if getattr(cogeno, '_mymodule') is not None: return cogeno._mymodule if cogeno.option('mymodule_file'): mymodule_file = cogeno.option('mymodule_file') else: cogeno.error(..., 2) ... cogeno._mymodule = ...
Path functions¶
cogeno.path_walk(top, topdown = False, followlinks = False)¶
-
cogeno::paths::PathsMixin.path_walk(top, topdown=False, followlinks=False)
Walk directory tree.
For each directory in the tree rooted at directory top (including top itself), it yields a 3-tuple (dirpath, dirnames, filenames):
dirpath: the path to the directory.
dirnames: list of the paths of the subdirectories in dirpath
filenames: list of the paths of the non-directory files in dirpath
See Python docs for os.walk, exact same behavior but it yields Path() instances instead. From: http://ominian.com/2016/03/29/os-walk-for-pathlib-path/
- Return
yields a 3-tuple (dirpath, dirpathes, filepathes)
- Parameters
top
: root of directory treetopdown
: if topdown is True, the triple for a directory is generated before the triples for any of its subdirectories (directories are generated top-down). If topdown is False, the triple for a directory is generated after the triples for all of its subdirectories (directories are generated bottom-up).followlinks
:
cogeno.rmtree(top)¶
-
cogeno::paths::PathsMixin.rmtree(top)
Delete an entire directory tree.
- Parameters
top
: root of directory tree
cogeno.find_template_files(top, marker, suffix=’.c’)¶
-
cogeno::paths::PathsMixin.find_template_files(top, marker, suffix='.c')
Find template files.
- Return
List of template file pathes
- Parameters
marker
: Marker as b’my-marker’suffix
:
Standard streams¶
cogeno.set_standard_streams(self, stdout=None, stderr=None)¶
-
cogeno::redirectable::RedirectableMixin.set_standard_streams(self, stdout=None, stderr=None)
Redirect status and error reporting.
Assign new files for standard out and/or standard error.
- Parameters
stdout
:stderr
:
Standard Modules - CMake¶
cogeno.cmake_variable(variable_name [, default=”<unset>”])¶
-
cogeno::stdmodules::StdModulesMixin.cmake_variable(self, variable_name, default="<unset>")
Get the value of a CMake variable.
If variable_name is not provided to cogeno by CMake the default value is returned.
A typical set of CMake variables that are not available in the
CMakeCache.txt
file and have to be provided as defines to cogeno if needed:“PROJECT_NAME”
”PROJECT_SOURCE_DIR”
”PROJECT_BINARY_DIR”
”CMAKE_SOURCE_DIR”
”CMAKE_BINARY_DIR”
”CMAKE_CURRENT_SOURCE_DIR”
”CMAKE_CURRENT_BINARY_DIR”
”CMAKE_CURRENT_LIST_DIR”
”CMAKE_FILES_DIRECTORY”
”CMAKE_PROJECT_NAME”
”CMAKE_SYSTEM”
”CMAKE_SYSTEM_NAME”
”CMAKE_SYSTEM_VERSION”
”CMAKE_SYSTEM_PROCESSOR”
”CMAKE_C_COMPILER”
”CMAKE_CXX_COMPILER”
”CMAKE_COMPILER_IS_GNUCC”
”CMAKE_COMPILER_IS_GNUCXX”
- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
cogeno.cmake_cache_variable(variable_name [, default=”<unset>”])¶
-
cogeno::stdmodules::StdModulesMixin.cmake_cache_variable(self, variable_name, default="<unset>")
Get the value of a CMake variable from CMakeCache.txt.
If variable_name is not given in
CMakeCache.txt
the default value is returned.- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
See Invoking Cogeno and Build with Cogeno for how to provide CMake variables to cogeno.
Standard Modules - config¶
cogeno.config_properties()¶
-
cogeno::stdmodules::StdModulesMixin.config_properties(self)
Get all config properties.
The property names are the ones config file.
- Return
A dictionary of config properties.
cogeno.config_property(property_name [, default=”<unset>”])¶
-
cogeno::stdmodules::StdModulesMixin.config_property(self, property_name, default="<unset>")
Get the value of a configuration property fromthe config file.
If property_name is not given in .config the default value is returned.
- Return
property value
- Parameters
property_name
: Name of the propertydefault
: Property value to return per default.
See Invoking Cogeno and Build with Cogeno for how to provide config variables to cogeno.
Standard Modules - Extended Device Tree Database¶
cogeno.edts()¶
-
cogeno::stdmodules::StdModulesMixin.edts(self, force_extract=False)
Get the extended device tree database.
- Return
Extended device tree database.
See Invoking Cogeno and Build with Cogeno for how to provide all files to enable cogeno to build the extended device tree database.
Cogeno modules¶
Cogeno modules provide supporting functions for code generation.
Some modules have to be imported to gain access to the module’s functions and variables. The standard modules are accessible by convenience functions.
/* This file uses modules. */ ... /** * @code{.cogeno.py} * cogeno.import_module('my_special_module') * my_special_module.do_everything(): * @endcode{.cogeno.py} */ /** @code{.cogeno.ins}@endcode */ ...
C code generation (ccode)¶
Description¶
The ccode module supports code generation for the C language.
To use the module in inline code generation import it by:
cogeno.import_module('ccode')
In case you want to use the ccode module in another Python project import it by:
import cogeno.modules.ccode
Cogeno invocation options¶
There are NO Cogeno invocation options.
Code generation functions¶
-
cogeno.modules.ccode.
outl_config_guard
(property_name)¶ Write #if guard for config property to output.
If there is a configuration property of the given name the property value is used as guard value, otherwise it is set to 0.
- Parameters
property_name
: Property name
-
cogeno.modules.ccode.
outl_config_unguard
(property_name)¶ Write #endif guard for config property to output.
This is the closing command for outl_guard_config().
- Parameters
property_name
: Property name
-
cogeno.modules.ccode.
out_comment
(s, blank_before=True)¶ Write ‘s’ as a comment.
- Parameters
s
: string, is allowed to have multiple lines.blank_before
: True adds a blank line before the comment.
-
cogeno.modules.ccode.
out_edts_defines
(prefix='EDT_')¶ Write EDTS database properties as C defines.
- Parameters
prefix
: Define label prefix. Default is ‘EDT_’.
CMake support (cmake)¶
Description¶
The CMake module provides access to CMake variables and the CMake cache.
You may get access to the database by cogeno.cmake()
.
Cogeno invocation options¶
--cmake:cache FILE
Use CMake variables from CMake cache FILE.
--cmake:define [defxxx=valyyy ...]
Define CMake variables to your generator code.
Code generation functions¶
There are convenience functions to access the CMake variables:
-
cogeno::stdmodules::StdModulesMixin.cmake(self)
Get the cmake variables database.
- Return
CMake variables database.
-
cogeno::stdmodules::StdModulesMixin.cmake_variable(self, variable_name, default="<unset>")
Get the value of a CMake variable.
If variable_name is not provided to cogeno by CMake the default value is returned.
A typical set of CMake variables that are not available in the
CMakeCache.txt
file and have to be provided as defines to cogeno if needed:“PROJECT_NAME”
”PROJECT_SOURCE_DIR”
”PROJECT_BINARY_DIR”
”CMAKE_SOURCE_DIR”
”CMAKE_BINARY_DIR”
”CMAKE_CURRENT_SOURCE_DIR”
”CMAKE_CURRENT_BINARY_DIR”
”CMAKE_CURRENT_LIST_DIR”
”CMAKE_FILES_DIRECTORY”
”CMAKE_PROJECT_NAME”
”CMAKE_SYSTEM”
”CMAKE_SYSTEM_NAME”
”CMAKE_SYSTEM_VERSION”
”CMAKE_SYSTEM_PROCESSOR”
”CMAKE_C_COMPILER”
”CMAKE_CXX_COMPILER”
”CMAKE_COMPILER_IS_GNUCC”
”CMAKE_COMPILER_IS_GNUCXX”
- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
-
cogeno::stdmodules::StdModulesMixin.cmake_cache_variable(self, variable_name, default="<unset>")
Get the value of a CMake variable from CMakeCache.txt.
If variable_name is not given in
CMakeCache.txt
the default value is returned.- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
The CMake database may be used directly to get access to the CMake variables:
-
cogeno.modules.cmake.CMakeDB : public object
Config/ Kconfig support (config)¶
Description¶
The config module provides access to config properties and the config database.
You may get access to the database by cogeno.configs()
.
Cogeno invocation options¶
--config:db FILE
Write or read config database to/ from FILE.
--config:file FILE
Read configuration variables from this FILE.
--config:kconfig-file FILE
Top-level Kconfig FILE (default: Kconfig).
--config:kconfig-srctree DIR
Kconfig files are looked up relative to the srctree DIR (unless absolute paths are used), and .config files are looked up relative to the srctree DIR if they are not found in the current directory.
--config:kconfig-defines DEFINE [DEFINE ...]
Define variable to Kconfig. We allow multiple.
--config:inputs FILE [FILE ...]
Read configuration file fragment from FILE. We allow multiple.
Code generation functions¶
There are convenience functions to access the config properties:
-
cogeno::stdmodules::StdModulesMixin.configs(self, force_extract=False)
Get the configuration variables database.
- Return
Configuration variables database.
-
cogeno::stdmodules::StdModulesMixin.config_properties(self)
Get all config properties.
The property names are the ones config file.
- Return
A dictionary of config properties.
-
cogeno::stdmodules::StdModulesMixin.config_property(self, property_name, default="<unset>")
Get the value of a configuration property fromthe config file.
If property_name is not given in .config the default value is returned.
- Return
property value
- Parameters
property_name
: Name of the propertydefault
: Property value to return per default.
The config database itself provides a more rich set of methods for configuration access:
-
cogeno.modules.config.ConfigDB : public object
Public Functions
-
generate
(self, config_kconfig_file, config_kconfig_srctree, config_kconfig_defines=None, config_inputs=None, config_file=None)¶ Generate config database.
- Parameters
config_kconfig_file
: path of top-level Kconfig fileconfig_kconfig_srctree
: path for relative lookup of filesconfig_kconfig_defines
: optional, dictionary of variables to be defined to Kconfigconfig_inputs
: optional, list of configuration fragment file pathesconfig_file
: optional, config file path
-
load
(self, file_path)¶ Load config database from JSON database file.
- Parameters
file_path
: Path of JSON file
-
save
(self, file_path)¶ Save config database to JSON database file.
- Parameters
file_path
: Path of JSON file
-
extract
(self, config_file)¶ Extract config database from config file.
The config file does not provide symbol information. symbols(), symbol_info() and kconfig_files() will not work on a database that was extracted from a config file.
- Parameters
config_file
: Path of config file
-
property
(self, property_name, default='<unset>')¶ Get the value of a configuration property from .config.
If property_name is not given in the database the default value is returned.
- Return
property value
- Parameters
property_name
: Name of the property (aka. symbol)default
: Property value to return per default.
-
properties
(self)¶ Get all config properties.
The property names are the ones that are in the database.
- Return
A dictionary of config properties.
-
symbols
(self)¶ Get all config symbols.
- Return
A dictionary of config symbols.
-
symbol_info
(self, symbol_name, default='<unknown>')¶ Get the info of a configuration symbol.
If symbol_name is not available or Kconfig was not processed the default value is returned.
- Return
symbol info
- Parameters
symbol_name
: Name of the configuration symboldefault
: Symbol info to return per default.
-
kconfig_files
(self)¶ Get all Kconfig files.
Get all Kconfig files used to generate() the database.
- Return
A list of kconfig file pathes.
-
Generate code with config¶
Kconfig Guide¶
This is a high-level guide to Kconfig and how to use it with Cogeno. See config code generation functions for an API reference.
Projects can be configured by Kconfig at build time to adapt them for specific application and platform needs. The goal is to support configuration without having to change any source code. Kconfig is the configuration system used by the Linux kernel and several other projects.
Configuration options (often called symbols) are defined in Kconfig files, which also specify dependencies between symbols that determine what configurations are valid. Symbols can be grouped into menus and sub-menus to keep the interactive configuration interfaces organized.
The usual output from Kconfig is a header file autoconf.h
with macros that can be tested at
build time. Kconfig itself keeps the values of the configuration symbols in a config file usually
named .config
. Kconfig can either read the config file and produce output or generate or change
the config file using one of several interactive configuration interfaces.
The values of the configuration symbols can also be changed by hand editing a Kconfig file and let Kconfig update the config file and the output.
Cogeno includes a complete Kconfig system (provided by Kconfiglib) but no interactive configuration interfaces.
The Cogeno config module creates it´s own database of configuration symbol values. It may either
extract the symbol names and values from a config file provided to Cogeno as an option or
run the whole process of symbol and value generation based on Kconfig files, and config file and/ or config fragment files also provided to Cogeno as options.
In the first case only the name and value of the symbols are known to the config module, whereas in the second case additional symbol information is available from the Kconfig files.
Use cogeno.config_property(<symbol>)()
to get the value of a single symbol.
Use cogeno.config_properties()
to get a dictionary of symbols with their
associated values.
Extended device tree support (edts)¶
Description¶
The EDTS database module extracts device tree information from the device tree specification. See the Devicetree Guide for more information on device tree.
The EDTS database is a key value store. The keys are pathes to the device tree information. The EDTS database may be loaded from a json file, stored to a json file or extracted from the DTS files and the bindings yaml files of the project. The EDTS database is automatically available to Cogeno scripts. It can also be used as a standalone tool.
You may get access to the database by cogeno.edts()
.
In case you want to use the extended device tree database in another Python project import it by:
import cogeno.modules.edts
Cogeno invocation options¶
--edts:bindings-dirs DIR [DIR ...]
Use bindings from bindings DIR for device tree extraction. We allow multiple.
--edts:bindings-exclude [DIR ...] [FILE ...]
Exclude bindings DIR or FILE from usage for device tree extraction. We allow multiple.
--edts:bindings-no-default
Do not add EDTS database’s generic bindings to bindings by default.
--edts:db FILE
Write or read EDTS database to/ from FILE.
--edts:dts FILE
Write (see dts-pp-sources) or read device tree specification to/ from this FILE.
--edts:dts-pp-sources FILE [FILE ...]
Generate the DTS file by pre-processing the DTS source FILE(s).
--edts:dts-pp-include-dirs DIR [DIR ...]
Define include DIR(s) to pre-processor.
--edts:dts-pp-defines DEFINE [DEFINE ...]
DEFINE variable to pre-processor.
Code generation functions¶
There is a convenience function to access the EDTS database:
-
cogeno::stdmodules::StdModulesMixin.edts(self, force_extract=False)
Get the extended device tree database.
- Return
Extended device tree database.
The EDTS database itself provides a more rich set of methods for database access:
edtsdb API¶
edtsdb is a Python module with the primary class: EDTSDb
.
The basis for the edtsb module is the edtlib
library.
EDTSDb
¶-
cogeno::modules::edtsdb::consumer::EDTSConsumerMixin.device_id_by_name(self, name)
Get device id of activated device with given name.
- Return
device id
- Parameters
name
:
-
cogeno.modules.edtsdb.database.EDTSDb : public cogeno.modules.edtsdb.consumer.EDTSConsumerMixin , public cogeno.modules.edtsdb.provider.EDTSProviderMixin , public cogeno.modules.edtsdb.extractor.EDTSExtractorMixin , public Mapping
Extended DTS database.
Database schema:
_edts dict( 'aliases': dict(alias) : sorted list(device-id)), 'chosen': dict(chosen), 'devices': dict(device-id : device-struct), 'compatibles': dict(compatible : sorted list(device-id)), ... ) device-struct dict( 'device-id' : device-id, 'compatible' : list(compatible) or compatible, 'label' : label, '<property-name>' : property-value ) property-value for "boolean", "string", "int" -> string for 'array', "string-array", "uint8-array" -> dict(index : string) for "phandle-array" -> dict(index : device-id)
Database types:
device-id: opaque id for a device (do not use for other purposes),
compatible: any of [‘st,stm32-spi-fifo’, …] - ‘compatibe’ from <binding>.yaml
label: any of [‘UART_0’, ‘SPI_11’, …] - label directive from DTS
Subclassed by cogeno.modules.edts.EDTSDatabase
The EDTSDb
class includes (sub-classes) several mixin classes:
-
cogeno.modules.edtsdb.consumer.EDTSConsumerMixin : public object
ETDS Database consumer.
Methods for ETDS database usage.
Subclassed by cogeno.modules.edtsdb.database.EDTSDb
Public Functions
-
info
(self)¶ Get info.
- Return
edts ‘info’ dict
- Parameters
None
:
-
compatibles
(self)¶ Get compatibles.
- Return
edts ‘compatibles’ dict
- Parameters
None
:
-
aliases
(self)¶ Get aliases.
- Return
edts ‘aliases’ dict
- Parameters
None
:
-
chosen
(self)¶ Get chosen.
- Return
edts ‘chosen’ dict
- Parameters
None
:
-
device_ids_by_compatible
(self, compatibles)¶ Get device ids of all activated compatible devices.
- Return
list of device ids of activated devices that are compatible
- Parameters
compatibles
: compatible(s)
-
device_ids_by_dependency_order
(self)¶ Get device ids of activated devices sorted by dependency ordinal.
Device ids of devices that are not activated but have an ordinal associated are set to None.
- Return
list of device ids of activated devices sorted by dependency ordinal
- Parameters
None
:
-
device_id_by_name
(self, name)¶ Get device id of activated device with given name.
- Return
device id
- Parameters
name
:
-
device_id_by_alias
(self, alias)¶ Get device id of activated device for given alias.
- Return
device id or None
- Parameters
alias
:
-
device_id_by_chosen
(self, chosen)¶ Get device id of activated device for given chosen.
- Return
device id or None
- Parameters
chosen
:
-
device_name_by_id
(self, device_id)¶ Get label/ name of a device by device id.
If the label is omitted, the name is taken from the node name (including unit address).
- Return
name
- Parameters
device_id
:
-
device_property
(self, device_id, property_path, default='<unset>')¶ Get device tree property value of a device.
- Return
property value
- Parameters
device_id
:property_path
: Path of the property to access (e.g. ‘reg/0/address’, ‘interrupts/prio’, ‘device_id’, …)default
: Default value provided if device or property not available
-
device_properties
(self, device_id)¶ Get all device tree properties of a device.
- Return
Dictionary of properties
- Parameters
device_id
:
-
device_properties_flattened
(self, device_id, path_prefix='')¶ Device properties flattened to property path : value.
- Return
dictionary of property_path and property_value
- Parameters
device_id
:path_prefix
:
-
device_template_substitute
(self, device_id, template, presets={}, aliases={})¶ Substitude device property value placeholders in template.
Local placeholders may be defined with direct and indirect path resolution:
${<property_path>}
${path/${<property_path>}}
${path/${<device-id>:<property_path>}}
Global placeholders may also be defined with direct and indirect path resolution:
${<device-id>:<property_path>}
${${<property_path>}:<property_path>}
${${path/${<property_path>}}:<property_path>}
${${path/${<device-id>:<property_path>}}:<property_path>}
${${<device-id>:<property_path>}:<property_path>}
${${<device-id>:path/${<property_path>}}:<property_path>}
${${<device-id>:path/${<device-id>:<property_path>}}:<property_path>}
- Parameters
device_id
:template
:presets
: dict of preset property-path : property value items either of the local form “<property_path>” : value or the global form “<device-id>:<property_path>” : valuealiases
: dict of property path alias : property path items.
-
load
(self, file_path)¶ Load extended device tree database from JSON file.
- Parameters
file_path
: Path of JSON file
-
_DeviceGlobalTemplate : public Template
Public Static Attributes
-
idpattern
= r'/[_a-z0-9\-/,@:]*'¶
-
-
_DeviceLocalTemplate : public Template
Public Static Attributes
-
idpattern
= r'[_a-z][_a-z0-9\-/,]*'¶
-
-
-
cogeno.modules.edtsdb.extractor.EDTSExtractorMixin : public object
ETDS Database extractor.
Methods for ETDS database extraction from DTS.
Subclassed by cogeno.modules.edtsdb.database.EDTSDb
Public Functions
-
extract
(self, dts_path, bindings_dirs, bindings_exclude, bindings_no_default)¶ Extract DTS info to database.
- Parameters
dts_path
: DTS filebindings_dirs
: YAML file directories, we allow multiplebindings_exclude
: YAML file directories and YAML files, we allow multiplebindings_no_default
: Do not use default bindings
-
dts_path
(self)¶ Device tree file path.
- Return
Device tree file path
-
bindings_dirs
(self)¶ Bindings directories paths.
- Return
List of binding directories
-
dts_source
(self)¶ DTS source code.
DTS source code of the loaded devicetree after merging nodes and processing /delete-node/ and /delete-property/.
- Return
DTS source code as string
-
-
cogeno.modules.edtsdb.provider.EDTSProviderMixin : public object
ETDS Database provider.
Methods for ETDS database creation.
Subclassed by cogeno.modules.edtsdb.database.EDTSDb
Public Functions
-
insert_alias
(self, alias_path, alias_value)¶ Insert an alias.
- Parameters
alias_path
: Aliasalias_value
: The value the alias aliases.
-
insert_chosen
(self, chosen_path, chosen_value)¶
-
insert_child_property
(self, device_id, child_name, property_path, property_value)¶ Insert property value for the child of a device id.
- Parameters
device_id
:child_name
:property_path
: Path of the property to access (e.g. ‘reg/0’, ‘interrupts/prio’, ‘label’, …)property_value
: value
-
insert_device_property
(self, device_id, property_path, property_value)¶ Insert property value for the device of the given device id.
- Parameters
device_id
:property_path
: Path of the property to access (e.g. ‘reg/0’, ‘interrupts/prio’, ‘label’, …)property_value
: value
-
save
(self, file_path)¶ Write json file.
- Parameters
file_path
: Path of the file to write
-
edtlib
¶-
class
cogeno.modules.edtsdb.libraries.edtlib.
EDT
¶ Represents a devicetree augmented with information from bindings. These attributes are available on EDT objects: nodes: A list of Node objects for the nodes that appear in the devicetree compat2nodes: A collections.defaultdict that maps each 'compatible' string that appears on some Node to a list of Nodes with that compatible. compat2okay: Like compat2nodes, but just for nodes with status 'okay'. For example, edt.compat2okay["bar"] would include the 'foo' and 'bar' nodes below. foo { compatible = "bar"; status = "okay"; ... }; bar { compatible = "foo", "bar", "baz"; status = "okay"; ... } label2node: A collections.OrderedDict that maps a node label to the node with that label. chosen_nodes: A collections.OrderedDict that maps the properties defined on the devicetree's /chosen node to their values. 'chosen' is indexed by property name (a string), and values are converted to Node objects. Note that properties of the /chosen node which can't be converted to a Node are not included in the value. dts_path: The .dts path passed to __init__() dts_source: The final DTS source code of the loaded devicetree after merging nodes and processing /delete-node/ and /delete-property/, as a string bindings_dirs: The bindings directory paths passed to __init__()
Public Functions
-
__init__
(self, dts, bindings_dirs, warn_file=None, warn_reg_unit_address_mismatch=True, bindings_exclude=[])¶ EDT constructor. This is the top-level entry point to the library. dts: Path to devicetree .dts file bindings_dirs: List of paths to directories containing bindings, in YAML format. These directories are recursively searched for .yaml files. warn_file (default: None): 'file' object to write warnings to. If None, sys.stderr is used. warn_reg_unit_address_mismatch (default: True): If True, a warning is printed if a node has a 'reg' property where the address of the first entry does not match the unit address of the node bindings_exclude: List of paths to bindings directories and/ or files that shall be excluded from usage.
-
get_node
(self, path)¶ Returns the Node at the DT path or alias 'path'. Raises EDTError if the path or alias doesn't exist.
-
chosen_nodes
(self)¶
-
chosen_node
(self, name)¶ Returns the Node pointed at by the property named 'name' in /chosen, or None if the property is missing
-
dts_source
(self)¶
-
__repr__
(self)¶
-
scc_order
(self)¶ Returns a list of lists of Nodes where all elements of each list depend on each other, and the Nodes in any list do not depend on any Node in a subsequent list. Each list defines a Strongly Connected Component (SCC) of the graph. For an acyclic graph each list will be a singleton. Cycles will be represented by lists with multiple nodes. Cycles are not expected to be present in devicetree graphs.
-
-
class
cogeno.modules.edtsdb.libraries.edtlib.
Node
¶ Represents a devicetree node, augmented with information from bindings, and with some interpretation of devicetree properties. There's a one-to-one correspondence between devicetree nodes and Nodes. These attributes are available on Node objects: edt: The EDT instance this node is from name: The name of the node unit_addr: An integer with the ...@<unit-address> portion of the node name, translated through any 'ranges' properties on parent nodes, or None if the node name has no unit-address portion description: The description string from the binding for the node, or None if the node has no binding. Leading and trailing whitespace (including newlines) is removed. path: The devicetree path of the node label: The text from the 'label' property on the node, or None if the node has no 'label' labels: A list of all of the devicetree labels for the node, in the same order as the labels appear, but with duplicates removed. This corresponds to the actual devicetree source labels, unlike the "label" attribute, which is the value of a devicetree property named "label". parent: The Node instance for the devicetree parent of the Node, or None if the node is the root node children: A dictionary with the Node instances for the devicetree children of the node, indexed by name dep_ordinal: A non-negative integer value such that the value for a Node is less than the value for all Nodes that depend on it. The ordinal is defined for all Nodes including those that are not 'enabled', and is unique among nodes in its EDT 'nodes' list. required_by: A list with the nodes that directly depend on the node depends_on: A list with the nodes that the node directly depends on status: The node's status property value, as a string, or "okay" if the node has no status property set. If the node's status property is "ok", it is converted to "okay" for consistency. read_only: True if the node has a 'read-only' property, and False otherwise matching_compat: The 'compatible' string for the binding that matched the node, or None if the node has no binding binding_path: The path to the binding file for the node, or None if the node has no binding compats: A list of 'compatible' strings for the node, in the same order that they're listed in the .dts file regs: A list of Register objects for the node's registers props: A collections.OrderedDict that maps property names to Property objects. Property objects are created for all devicetree properties on the node that are mentioned in 'properties:' in the binding. aliases: A list of aliases for the node. This is fetched from the /aliases node. clocks: A list of ControllerAndData objects for the clock inputs on the node, sorted by index. The list is empty if the node does not have a clocks property. clock_outputs: A list of ControllerAndData objects for the clock outputs on the node, sorted by index. The list is empty if the node does not have a #clock-cells property. gpio_leds: A list of ControllerAndData objects of the leds a gpio leds controller controls. The list is empty if the node is not a gpio leds controller or it does not have and gpio led children. interrupts: A list of ControllerAndData objects for the interrupts generated by the node. The list is empty if the node does not generate interrupts. pinctrls: A list of PinCtrl objects for the pinctrl-<index> properties on the node, sorted by index. The list is empty if the node does not have any pinctrl-<index> properties. pinctrl_states: A list with the Node instances for the 'pinctrl-state' children of a pin controller node. The list is empty if the node does not have any pinctrl state children. pinctrl_gpio_ranges: A list of ControllerAndData objects of the gpio ranges a pin controller controls. The list is empty if the node is not a pin controller or no 'gpio-ranges' are defined by the gpio nodes. pincfgs: A list of PinCfg objects for the 'pinctrl-state' node. The list is empty if the node is not a 'pinctrl-state' node. pin_controller: The pin controller for the node. Only meaningful for nodes representing pinctrl states. bus: If the node is a bus node (has a 'bus:' key in its binding), then this attribute holds the bus type, e.g. "i2c" or "spi". If the node is not a bus node, then this attribute is None. on_bus: The bus the node appears on, e.g. "i2c" or "spi". The bus is determined by searching upwards for a parent node whose binding has a 'bus:' key, returning the value of the first 'bus:' key found. If none of the node's parents has a 'bus:' key, this attribute is None. bus_node: Like on_bus, but contains the Node for the bus controller, or None if the node is not on a bus. flash_controller: The flash controller for the node. Only meaningful for nodes representing flash partitions. partitions: A list of Partition objects of the partitions of the 'partitions' node of a flash. Only meaningful for nodes representing a flash - otherwise an empty list. spi_cs_gpio: The device's SPI GPIO chip select as a ControllerAndData instance, if it exists, and None otherwise. See Documentation/devicetree/bindings/spi/spi-controller.yaml in the Linux kernel.
Public Functions
-
name
(self)¶
-
unit_addr
(self)¶
-
description
(self)¶
-
path
(self)¶
-
label
(self)¶
-
labels
(self)¶
-
parent
(self)¶
-
children
(self)¶
-
required_by
(self)¶
-
depends_on
(self)¶
-
status
(self)¶
-
read_only
(self)¶
-
aliases
(self)¶
-
bus
(self)¶
-
clocks
(self)¶
-
on_bus
(self)¶
-
flash_controller
(self)¶
-
spi_cs_gpio
(self)¶
-
__repr__
(self)¶
-
-
class
cogeno.modules.edtsdb.libraries.edtlib.
Register
¶ Represents a register on a node. These attributes are available on Register objects: node: The Node instance this register is from name: The name of the register as given in the 'reg-names' property, or None if there is no 'reg-names' property addr: The starting address of the register, in the parent address space, or None if #address-cells is zero. Any 'ranges' properties are taken into account. size: The length of the register in bytes
Public Functions
-
__repr__
(self)¶
-
-
class
cogeno.modules.edtsdb.libraries.edtlib.
ControllerAndData
¶ Represents an entry in an 'interrupts' or 'type: phandle-array' property value, e.g. <&ctrl-1 4 0> in cs-gpios = <&ctrl-1 4 0 &ctrl-2 3 4>; These attributes are available on ControllerAndData objects: node: The Node instance the property appears on controller: The Node instance for the controller (e.g. the controller the interrupt gets sent to for interrupts) data: A dictionary that maps names from the *-cells key in the binding for the controller to data values, e.g. {"pin": 4, "flags": 0} for the example above. 'interrupts = <1 2>' might give {"irq": 1, "level": 2}. name: The name of the entry as given in 'interrupt-names'/'gpio-names'/'pwm-names'/etc., or None if there is no *-names property
Public Functions
-
__repr__
(self)¶
-
Generate code with edts¶
Devicetree Guide¶
This is a high-level guide to devicetree and how to use it with Cogeno. See edtsdb API for an API reference.
The guide is a partial copy of the Zephyr devicetree guide adapted to the specific devicetree capabilities of the Cogeno EDTS database module.
Tip
This is a conceptual overview of devicetree and how the Cogeno EDTS database module provides the devicetree information.
A devicetree is a hierarchical data structure that describes hardware. The Devicetree specification defines its source and binary representations. Devicetree may be used to describe the hardware available on a board, as well as that hardware’s initial configuration.
There are two types of devicetree input files: devicetree sources and devicetree bindings. The sources contain the devicetree itself. The bindings describe its contents, including data types. The EDTS database module uses devicetree sources and bindings to produce a key-value database, which you can use to get information from your devicetree. The keys are pathes to the device tree information.
Here is a view of the process executed by the EDTS database module:

EDTS database build flow¶
All Cogeno script snippets can access the EDTS database.
/* This is my C file. */
...
/**
* @code{.cogeno.py}
* edtsdb = cogeno.edts()
* ...
* @endcode{.cogeno.py}
*/
/** @code{.cogeno.ins}@endcode */
...
As the name indicates, a devicetree is a tree. The human-readable text format for this tree is called DTS (for devicetree source), and is defined in the Devicetree specification.
Here is an example DTS file:
/dts-v1/;
/ {
a-node {
subnode_label: a-sub-node {
foo = <3>;
};
};
};
The /dts-v1/;
line means the file’s contents are in version 1 of the DTS
syntax, which has replaced a now-obsolete “version 0”.
The tree has three nodes:
A root node:
/
A node named
a-node
, which is a child of the root nodeA node named
a-sub-node
, which is a child ofa-node
Nodes can be given labels, which are unique shorthands that can be used to
refer to the labeled node elsewhere in the devicetree. Above, a-sub-node
has label subnode_label
. A node can have zero, one, or multiple node
labels.
Devicetree nodes have paths identifying their locations in the tree. Like
Unix file system paths, devicetree paths are strings separated by slashes
(/
), and the root node’s path is a single slash: /
. Otherwise, each
node’s path is formed by concatenating the node’s ancestors’ names with the
node’s own name, separated by slashes. For example, the full path to
a-sub-node
is /a-node/a-sub-node
.
Devicetree nodes can also have properties. Properties are name/value pairs. Property values can be any sequence of bytes. In some cases, the values are an array of what are called cells. A cell is just a 32-bit unsigned integer.
Node a-sub-node
has a property named foo
, whose value is a cell with
value 3. The size and type of foo
’s value are implied by the enclosing
angle brackets (<
and >
) in the DTS. See
Writing property values below for more example property values.
In practice, devicetree nodes usually correspond to some hardware, and the node hierarchy reflects the hardware’s physical layout. For example, let’s consider a board with three I2C peripherals connected to an I2C bus controller on an SoC, like this:

Nodes corresponding to the I2C bus controller and each I2C peripheral would be present in the devicetree. Reflecting the hardware layout, the I2C peripheral nodes would be children of the bus controller node. Similar conventions exist for representing other types of hardware.
The DTS would look something like this:
/dts-v1/;
/ {
soc {
i2c-bus-controller {
i2c-peripheral-1 {
};
i2c-peripheral-2 {
};
i2c-peripheral-3 {
};
};
};
};
Properties are used in practice to describe or configure the hardware the node represents. For example, an I2C peripheral’s node has a property whose value is the peripheral’s address on the bus.
Here’s a tree representing the same example, but with real-world node names and properties you might see when working with I2C devices.

I2C devicetree example with real-world names and properties. Node names are at the top of each node with a gray background. Properties are shown as “name=value” lines.¶
This is the corresponding DTS:
/dts-v1/;
/ {
soc {
i2c@40003000 {
compatible = "nordic,nrf-twim";
label = "I2C_0";
reg = <0x40003000 0x1000>;
apds9960@39 {
compatible = "avago,apds9960";
label = "APDS9960";
reg = <0x39>;
};
ti_hdc@43 {
compatible = "ti,hdc", "ti,hdc1010";
label = "HDC1010";
reg = <0x43>;
};
mma8652fc@1d {
compatible = "nxp,fxos8700", "nxp,mma8652fc";
label = "MMA8652FC";
reg = <0x1d>;
};
};
};
};
In addition to showing more realistic names and properties, the above example
introduces a new devicetree concept: unit addresses. Unit addresses are the
parts of node names after an “at” sign (@
), like 40003000
in
i2c@40003000
, or 39
in apds9960@39
. Unit addresses are optional:
the soc
node does not have one.
Some more details about unit addresses and important properties follow.
In devicetree, unit addresses give a node’s address in the address space of its parent node. Here are some example unit addresses for different types of hardware.
- Memory-mapped peripherals
The peripheral’s register map base address. For example, the node named
i2c@40003000
represents an I2C controller whose register map base address is 0x40003000.- I2C peripherals
The peripheral’s address on the I2C bus. For example, the child node
apds9960@39
of the I2C controller in the previous section has I2C address 0x39.- SPI peripherals
An index representing the peripheral’s chip select line number. (If there is no chip select line, 0 is used.)
- Memory
The physical start address. For example, a node named
memory@2000000
represents RAM starting at physical address 0x2000000.- Memory-mapped flash
Like RAM, the physical start address. For example, a node named
flash@8000000
represents a flash device whose physical start address is 0x8000000.- Fixed flash partitions
This applies when the devicetree is used to store a flash partition table. The unit address is the partition’s start offset within the flash memory. For example, take this flash device and its partitions:
flash@8000000 { /* ... */ partitions { partition@0 { /* ... */ }; partition@20000 { /* ... */ }; /* ... */ }; };
The node named
partition@0
has offset 0 from the start of its flash device, so its base address is 0x8000000. Similarly, the base address of the node namedpartition@20000
is 0x8020000.
Some important properties are:
- compatible
The name of the hardware device the node represents.
The recommended format is
"vendor,device"
, like"avago,apds9960"
, or a sequence of these, like"ti,hdc", "ti,hdc1010"
. Thevendor
part is an abbreviated name of the vendor. The file :zephyr_file:`dts/bindings/vendor-prefixes.txt` contains a list of commonly acceptedvendor
names. Thedevice
part is usually taken from the datasheet.It is also sometimes a value like
gpio-keys
,mmio-sram
, orfixed-clock
when the hardware’s behavior is generic.The build system uses the compatible property to find the right bindings for the node. Device drivers use
devicetree.h
to find nodes with relevant compatibles, in order to determine the available hardware to manage.The
compatible
property can have multiple values. Additional values are useful when the device is a specific instance of a more general family, to allow the system to match from most- to least-specific device drivers.Within Zephyr’s bindings syntax, this property has type
string-array
.- label
The device’s name according to Zephyr’s device_model_api. The value can be passed to
device_get_binding()
to retrieve the corresponding driver-level struct device*. This pointer can then be passed to the correct driver API by application code to interact with the device. For example, callingdevice_get_binding("I2C_0")
would return a pointer to a device structure which could be passed to I2C API functions likei2c_transfer()
. The generated C header will also contain a macro which expands to this string.- reg
Information used to address the device. The value is specific to the device (i.e. is different depending on the compatible property).
The
reg
property is a sequence of(address, length)
pairs. Each pair is called a “register block”. Here are some common patterns:Devices accessed via memory-mapped I/O registers (like
i2c@40003000
):address
is usually the base address of the I/O register space, andlength
is the number of bytes occupied by the registers.I2C devices (like
apds9960@39
and its siblings):address
is a slave address on the I2C bus. There is nolength
value.SPI devices:
address
is a chip select line number; there is nolength
.
You may notice some similarities between the
reg
property and common unit addresses described above. This is not a coincidence. Thereg
property can be seen as a more detailed view of the addressable resources within a device than its unit address.- status
A string which describes whether the node is enabled.
The devicetree specification allows this property to have values
"okay"
,"disabled"
,"reserved"
,"fail"
, and"fail-sss"
. Only the values"okay"
and"disabled"
are currently relevant to Zephyr; use of other values currently results in undefined behavior.A node is considered enabled if its status property is either
"okay"
or not defined (i.e. does not exist in the devicetree source). Nodes with status"disabled"
are explicitly disabled. (For backwards compatibility, the value"ok"
is treated the same as"okay"
, but this usage is deprecated.) Devicetree nodes which correspond to physical devices must be enabled for the correspondingstruct device
in the Zephyr driver model to be allocated and initialized.- interrupts
Information about interrupts generated by the device, encoded as an array of one or more interrupt specifiers. Each interrupt specifier has some number of cells. See section 2.4, Interrupts and Interrupt Mapping, in the Devicetree Specification release v0.3 for more details.
Zephyr’s devicetree bindings language lets you give a name to each cell in an interrupt specifier.
There are two additional ways beyond node labels to refer to a particular node without specifying its entire path: by alias, or by chosen node.
Here is an example devicetree which uses both:
/dts-v1/;
/ {
chosen {
zephyr,console = &uart0;
};
aliases {
my-uart = &uart0;
};
soc {
uart0: serial@12340000 {
...
};
};
};
The /aliases
and /chosen
nodes do not refer to an actual hardware
device. Their purpose is to specify other nodes in the devicetree.
Above, my-uart
is an alias for the node with path /soc/serial@12340000
.
Using its node label uart0
, the same node is set as the value of the chosen
zephyr,console
node.
Zephyr sample applications sometimes use aliases to allow overriding the
particular hardware device used by the application in a generic way. For
example, blinky-sample uses this to abstract the LED to blink via the
led0
alias.
The /chosen
node’s properties are used to configure system- or
subsystem-wide values. See devicetree-chosen-nodes for more information.
This section describes the input and output files shown in the figure at the top of this introduction in more detail.
There are three basic types of devicetree input files:
sources (
.dts
)includes (
.dtsi
)bindings (
.yaml
)
As the devicetree files are preprocessed by the C/C++ style preprocessor any includes may de done.
includes (
.h
, …)
Usually every board has a <board>.dts
file describing its hardware.
<board>.dts
includes one or more .dtsi
files. These .dtsi
files
describe the CPU or system-on-chip the board is made of, perhaps by including other
.dtsi
files. They can also describe other common hardware features shared by
multiple boards. In addition to these includes, <board>.dts
also describes
the board’s specific hardware.
The C/C++ style preprocessor is run on all
devicetree files to expand macro references, and includes should generally be done
with #include <filename>
directives, even though DTS has a
/include/ "<filename>"
syntax.
Some project build systems may support to extend and/ or modify the <board>.dts
by using overlays. Overlays are also DTS files; The build system concatenates the
overlay files to the <board>.dts
, with the overlays put last. This relies
on DTS syntax which allows merging overlapping definitions of nodes in the devicetree.
Devicetree bindings (which are YAML files) are essentially glue. They describe the contents of devicetree sources, includes, and overlays in a way that allows to extract the EDTS database usable by Cogeno scripts. The EDTS database module provides a set of generic bindings.
edts.dts
The final merged devicetree. This file is output by the EDTS database module as a debugging aid, and is unused otherwise.
edts.json
The EDTS database as a .json export. This file, if available, is read in by the EDTS database module to avoid multiple evaluation of the devicetree. Dependency changes are regarded and lead to a full re-evaluation.
Here are some example ways to write property values in DTS format. Some specifics are skipped in the interest of keeping things simple; if you’re curious about details, see the devicetree specification.
Arrays of 32-bit unsigned integers, or cells, can be written between angle
brackets (<
and >
) and separated by spaces:
foo = <0xdeadbeef 1234 0>;
The foo
property value is three cells with values 0xdeadbeef, 1234, and 0,
in that order. Note that hexadecimal and decimal numbers are allowed and can be
intermixed. Since Zephyr transforms DTS to C sources, it is not necessary to
specify the endianness of an individual cell here.
64-bit integers are written as two 32-bit cells in big-endian order. The value
0xaaaa0000bbbb1111 would be written <0xaaaa0000 0xbbbb1111>
.
Parentheses, arithmetic operators, and bitwise operators are allowed. The
bar
property contains a single cell with value 64:
bar = <2 * (1 << 5)>;
Strings are double quoted:
a-string = "hello, world!";
String arrays are separated by commas:
a-string-array = "string one", "string two", "string three";
Arrays of bytes are written in hexadecimal without leading 0x
between
square brackets ([
and ]
). Property a-byte-array
is the three bytes
0x00, 0x01, 0xab, in that order:
a-byte-array = [00 01 ab];
Properties can refer to other nodes in the devicetree by their phandles. You
can write a phandle using &label
, like in this devicetree fragment:
baz: device@0 {
/* ... */
};
device@1 {
sibling = <&baz 1 2>;
/* ... */
};
The sibling
property of node device@1
contains three cells:
The
device@0
node’s phandle. Each phandle occupies an entire cell. Thebaz
label is used to write the phandle&baz
inside thesibling
property value.The values 1 and 2, each in its own cell, in that order.
A devicetree on its own is only half the story for describing hardware. The devicetree format itself is relatively unstructured, and doesn’t tell the Cogeno EDTS module which pieces of information in a particular devicetree are useful to be integrated into the EDTS database.
Devicetree bindings provide the other half of this information. Cogeno EDTS devicetree bindings are YAML files in a custom format (Cogeno uses the Zephyr bindings and extends them in some rare cases. It does not use the dt-schema tools used by the Linux kernel). Cogeno uses bindings when generating the EDTS database.
During the EDTS database build flow, the EDTS database module tries to map each node in the devicetree to a binding file. The EDTS database module only generates database entries for devicetree nodes which have matching bindings. Nodes are mapped to bindings by their compatible properties. Take the following node as an example:
bar-device {
compatible = "foo-company,bar-device";
/* ... */
};
The EDTS database module will try to map
the bar-device
node to a YAML binding with this compatible:
line:
compatible: "foo-company,bar-device"
Built-in generic bindings are provided by the
EDTS database module. Binding file
names usually match their compatible:
lines, so the above binding would be
named foo-company,bar-device.yaml
.
If a node has more than one string in its compatible
property, the
EDTS database module looks for compatible bindings
in the listed order and uses the first match. Take this node as an example:
baz-device {
compatible = "foo-company,baz-device", "generic-baz-device";
};
The baz-device
node would get mapped to the binding for compatible
"generic-baz-device"
if the build system can’t find a binding for
"foo-company,baz-device"
.
Nodes without compatible properties can be mapped to bindings associated with
their parent nodes. For an example, see the pwmleds
node in the bindings
file format described below.
If a node describes hardware on a bus, like I2C or SPI, then the bus type is
also taken into account when mapping nodes to bindings. See the comments near
on-bus:
in the bindings syntax for details.
Below is a template (binding-template.yaml
) that shows the bindings
file syntax. It is taken from Zephyr.
description: |
Free-form description of the device/node. Can have multiple
lines/paragraphs.
See https://yaml-multiline.info/ for formatting help.
# Used to map nodes to bindings
compatible: "manufacturer,device"
# The 'compatible' above would match this node:
#
# device {
# compatible = "manufacturer,device";
# ...
# };
#
# Assuming no binding has 'compatible: "manufacturer,device-v2"', it would also
# match this node:
#
# device {
# compatible = "manufacturer,device-v2", "manufacturer,device";
# ...
# };
#
# Strings in 'compatible' properties on nodes are tried from left to right, and
# the first binding found is used.
#
# If more than one binding for a compatible is found, an error is raised.
# Bindings can include other files, which can be used to share common
# definitions between bindings.
#
# Included files are merged into bindings with a simple recursive dictionary
# merge. It is up to the binding author to make sure that the final merged
# binding is well-formed, though it is checked by the code as well.
#
# It is an error if a key appears with a different value in a binding and in a
# file it includes, with one exception: A binding can have 'required: true' for
# some property for which the included file has 'required: false' (see the
# description of 'properties' below). The 'required: true' from the binding
# takes precedence, allowing bindings to strengthen requirements from included
# files.
#
# Note that weakening requirements by having 'required: false' where the
# included file has 'required: true' is an error. This is meant to keep the
# organization clean.
#
# The file base.yaml contains definitions for many common properties. When
# writing a new binding, it is a good idea to check if base.yaml already
# defines some of the needed properties, and including it in that case. Note
# that you can make a property defined in base.yaml obligatory like this
# (taking 'reg' as an example):
#
# reg:
# required: true
#
# This relies on the dictionary merge to fill in the other keys for 'reg', like
# 'type'.
#
# When including multiple files, any overlapping 'required' keys on properties
# in the included files are ORed together. This makes sure that a
# 'required: true' is always respected.
include: other.yaml # or [other1.yaml, other2.yaml]
# If the node describes a bus, then the bus type should be given, like below
bus: <string describing bus type, e.g. "i2c">
# If the node appears on a bus, then the bus type should be given, like below.
#
# When looking for a binding for a node, the code checks if the binding for the
# parent node contains 'bus: <bus type>'. If it does, then only bindings with a
# matching 'on-bus: <bus type>' are considered. This allows the same type of
# device to have different bindings depending on what bus it appears on.
on-bus: <string describing bus type, e.g. "i2c">
# 'properties' describes properties on the node, e.g.
#
# reg = <1 2>;
# current-speed = <115200>;
# label = "foo";
#
# This is used to check that required properties appear, and to
# control the format of output generated for them. Except for some
# special-cased properties like 'reg', only properties listed here will
# generate output.
#
# A typical property entry looks like this:
#
# <property name>:
# required: <true | false>
# type: <string | int | boolean | array | uint8-array | string-array |
# phandle | phandles | phandle-array | path | compound>
# description: <description of the property>
# enum:
# - <item1>
# - <item2>
# ...
# - <itemN>
# const: <string | int>
# default: <default>
#
# These types are available:
#
# - 'type: string' is for properties that are assigned a single string, like
#
# ident = "foo";
#
# - 'type: int' is for properties that are assigned a single 32-bit value,
# like
#
# frequency = <100>;
#
# - 'type: boolean' is for properties used as flags that don't take a value,
# like
#
# hw-flow-control;
#
# The macro generated for the property gets set to 1 if the property exists
# on the node, and to 0 otherwise. When combined with 'required: true',
# this type just forces the flag to appear on the node. The output will
# always be 1 in that case.
#
# Warning: Since a macro is always generated for 'type: boolean'
# properties, don't use #ifdef in tests. Do this instead:
#
# #if DT_SOME_BOOLEAN_PROP == 1
#
# - 'type: array' is for properties that are assigned zero or more 32-bit
# values, like
#
# pin-config = <1 2 3>;
#
# - 'type: uint8-array' is for properties that are assigned zero or more
# bytes with the [] syntax, like
#
# lookup-table = [89 AB CD EF];
#
# Each byte is given in hex.
#
# This type is called 'bytestring' in the Devicetree specification.
#
# - 'type: string-array' if for properties that are assigned zero or more
# strings, like
#
# idents = "foo", "bar", "baz";
#
# - 'type: phandle' is for properties that are assigned a single phandle,
# like
#
# foo = <&label>;
#
# - 'type: phandles' is for properties that are assigned zero or more
# phandles, like
#
# foo = <&label1 &label2 ...>;
#
# - 'type: phandle-array' is for properties that take a list of phandles and
# (possibly) 32-bit numbers, like
#
# pwms = <&ctrl-1 1 2 &ctrl-2 3 4>;
#
# This type requires that the property works in the standard way that
# devicetree properties like pwms, clocks, *-gpios, and io-channels work.
# Taking 'pwms' as an example, the final -s is stripped from the property
# name, and #pwm-cells is looked up in the node for the controller
# (&ctrl-1/&ctrl-2) to determine the number of data values after the
# phandle. The binding for each controller must also have a *-cells key
# (e.g. pwm-cells), giving names to data values. See below for an
# explanation of *-cells.
#
# A *-names (e.g. pwm-names) property can appear on the node as well,
# giving a name to each entry (the 'pwms' example above has two entries,
# <&ctrl-1 1 2> and <&ctrl-2 3 4>).
#
# Because other property names are derived from the name of the property by
# removing the final -s, the property name must end in -s. An error is
# raised if it doesn't.
#
# *-gpios properties are special-cased so that e.g. foo-gpios resolves to
# #gpio-cells rather than #foo-gpio-cells.
#
# All phandle-array properties support mapping through *-map properties,
# e.g. gpio-map. See the devicetree spec.
#
# - 'type: path' is for properties that are assigned a path. Usually, this
# would be done with a path reference:
#
# foo = &label;
#
# Plain strings are accepted too, and are verified to be a path to an
# existing node:
#
# foo = "/path/to/some/node";
#
# - 'type: compound' is a catch-all for more complex types, e.g.
#
# foo = <&label>, [01 02];
#
# 'type: array' and the other array types also allow splitting the value into
# several <> blocks, e.g. like this:
#
# foo = <1 2>, <3 4>; // Okay for 'type: array'
# foo = <&label1 &label2>, <&label3 &label4>; // Okay for 'type: phandles'
# foo = <&label1 1 2>, <&label2 3 4>; // Okay for 'type: phandle-array'
# etc.
#
# The optional 'default:' setting gives a value that will be used if the
# property is missing from the device tree node. If 'default: <default>' is
# given for a property <prop> and <prop> is missing, then the output will be as
# if '<prop> = <default>' had appeared (except YAML data types are used for the
# default value).
#
# Note that it only makes sense to combine 'default:' with 'required: false'.
# Combining it with 'required: true' will raise an error.
#
# See below for examples of 'default:'. Putting 'default:' on any property type
# besides those used in the examples will raise an error.
properties:
# Describes a property like 'current-speed = <115200>;'. We pretend that
# it's obligatory for the example node and set 'required: true'.
current-speed:
type: int
required: true
description: Initial baud rate for bar-device
# Describes an optional property like 'keys = "foo", "bar";'
keys:
type: string-array
required: false
description: Keys for bar-device
# Describes an optional property like 'maximum-speed = "full-speed";
# the enum specifies known values that the string property may take
maximum-speed:
type: string
required: false
description: Configures USB controllers to work up to a specific speed.
enum:
- "low-speed"
- "full-speed"
- "high-speed"
- "super-speed"
# Describes a required property '#address-cells = <1>'; the const
# specifies that the value for the property is expected to be the value 1
"#address-cells":
type: int
required: true
const: 1
int-with-default:
type: int
required: false
default: 123
array-with-default:
type: array
required: false
default: [1, 2, 3] # Same as 'array-with-default = <1 2 3>'
string-with-default:
type: string
required: false
default: "foo"
string-array-with-default:
type: string-array
required: false
default: ["foo", "bar"] # Same as 'string-array-with-default = "foo", "bar"'
uint8-array-with-default:
type: uint8-array
required: false
default: [0x12, 0x34] # Same as 'uint8-array-with-default = [12 34]'
# 'child-binding' can be used when a node has children that all share the same
# properties. Each child gets the contents of 'child-binding' as its binding
# (though an explicit 'compatible = ...' on the child node takes precedence, if
# a binding is found for it).
#
# The example below is for a binding for PWM LEDs, where the child nodes are
# required to have a 'pwms' property. It corresponds to this .dts structure
# (assuming the binding has 'compatible: "pwm-leds"'):
#
# pwmleds {
# compatible = "pwm-leds";
#
# red_pwm_led {
# pwms = <&pwm3 4 15625000>;
# };
# green_pwm_led {
# pwms = <&pwm3 0 15625000>;
# };
# ...
# };
child-binding:
description: LED that uses PWM
properties:
pwms:
type: phandle-array
required: true
# 'child-binding' also works recursively. For example, the binding below would
# provide a binding for the 'grandchild' node in this .dts (assuming
# 'compatible: "foo"'):
#
# parent {
# compatible = "foo";
# child {
# grandchild {
# prop = <123>;
# };
# };
# }
child-binding:
description: ...
...
child-binding:
description: ...
properties:
prop:
type: int
required: true
# If the binding describes an interrupt controller, GPIO controller, pinmux
# device, or any other node referenced by other nodes via 'phandle-array'
# properties, then *-cells should be given.
#
# To understand the purpose of *-cells, assume that some node has
#
# pwms = <&pwm-ctrl 1 2>;
#
# , where &pwm-ctrl refers to a node whose binding is this file.
#
# The <1 2> part of the property value is called a *specifier* (this
# terminology is from the devicetree specification), and contains additional
# data associated with the GPIO. Here, the specifier has two cells, and the
# node pointed at by &gpio-ctrl is expected to have '#pwm-cells = <2>'.
#
# *-cells gives a name to each cell in the specifier. These names are used when
# generating identifiers.
#
# In this example, assume that 1 refers to a pin and that 2 is a flag value.
# This gives a *-cells assignment like below.
pwm-cells:
- channel # name of first cell
- period # name of second cell
# If the specifier is empty (e.g. '#clock-cells = <0>'), then *-cells can
# either be omitted (recommended) or set to an empty array. Note that an empty
# array is specified as e.g. 'clock-cells: []' in YAML.
# As a special case, all *-gpio properties map to the key 'gpio-cells',
# regardless of prefix
gpio-cells:
- pin
- flags
Devicetree access from Cogeno¶
This guide describes Cogeno’s edtsdb API for reading the devicetree information from the EDTS database. It assumes you’re familiar with the concepts in Introduction to devicetree and Devicetree bindings. See edtsdb API for API reference documentation.
To get information about a particular devicetree device node, you need a device identifier for it. This is just a key that refers to the device node.
These are the main ways to get a device identifier:
- By path
Use the the device node’s
full path in the devicetree
, starting from the root node as device identifier (e.g./soc/i2c@40002000
). This is mostly useful if you happen to know the exact node you’re looking for.- By node name
Use
cogeno.edts().device_id_by_name(<node name>)
to get a device identifier from a device node name (e.g.i2c@40002000
).- By node label
Use
cogeno.edts().device_id_by_name(<node label name>)
to get a device identifier from the node label of a device node. The function first searches for a matching node name before looking into the node labels of a device node. node labels are often provided by SoC.dtsi
to give nodes names that match the SoC datasheet, likei2c1
,spi2
, etc.- By label property
Use
cogeno.edts().device_id_by_name(<node label property name>)
to get a device identifier from the label property of a device node. The function first searches for a matching node name before looking into the node label and finally checks the label property. label properties are often provided by board.dtsi
to give device nodes names that match the board interface, likeI2C_1
,SPI_2
, etc.- By alias
Use
cogeno.edts().device_id_by_alias(<alias name>)
to get a device node identifier for a property of the special /aliases node (e.g.sensor-controller
).- By instance number
Use
cogeno.edts().device_ids_by_compatible(<compatible>)[<instance number>]
to get the device identifier of an individual device node based on a matching compatible, but be careful doing so. See below.- By chosen node
Use
cogeno.edts().device_id_by_chosen(<chosen property>)
to get a device identifier for a /chosen node property (e.g.zephyr,console
).- By parent
Use
cogeno.edts().device_property(<device id>, 'parent')
to get a device identifier for a parent device node, starting from a device identifier you already have.
Two device identifiers which refer to the same device node are identical and can be used interchangeably.
Here’s a DTS fragment for some imaginary hardware we’ll return to throughout this file for examples:
/dts-v1/;
/ {
aliases {
sensor-controller = &i2c1;
};
soc {
i2c1: i2c@40002000 {
compatible = "vnd,soc-i2c";
label = "I2C_1";
reg = <0x40002000 0x1000>;
status = "okay";
clock-frequency = < 100000 >;
};
};
};
Here are a few ways to get the device identifier for the i2c@40002000
node:
'/soc/i2c@40002000'
cogeno.edts().device_id_by_name('i2c@40002000')
cogeno.edts().device_id_by_name('i2c1')
cogeno.edts().device_id_by_name('I2C_1')
cogeno.edts().device_id_by_alias('sensor-controller')
cogeno.edts().device_ids_by_compatible('vnd,soc_i2c')[x]
for some unknown numberx
.
The right API to use to read property values depends on the format the property values shall be provided.
You can use cogeno.edts().device_property(<device id>, <property path>, None)
to check
if a device node has a property <property path>. None
will be returned if the property
does not exist.
Use cogeno.edts().device_property(<device id>, <property path>, <default value>)
to
read a single property.
Multiple properties at the same time can be read in several ways.
Use cogeno.edts().device_properties(<device_id>)
to get a dictionary of dictionaries
representing the properties of a device node.
Use cogeno.edts().device_properties_flattened(<device_id>. <path prefix>)
to
get the properties flattened to one key-value dictionary where the keys
represent the property path.
Use cogeno.edts().device_template_substitute(<device_id>, <template>, <presets>, <aliases>)
to get the property values requested by the placeholders in the template.
EDTS bindings¶
The EDTS database module uses devicetree bindings (a kind of data schema) to know what data to extract and to know the kind of data. A set of generic devicetree bindings in conjunction with project specific bindings control the extraction process.
The generic bindings are part of the EDTS database module.
Protocol buffer code generation (protobuf)¶
Description¶
The protobuf module supports code generation for protocol buffers.
To use the module in inline code generation import it by:
cogeno.import_module('protobuf')
In case you want to use the protobuf module in another Python project import it by:
import cogeno.modules.protobuf
Code generation functions¶
-
cogeno.modules.protobuf.
proto_gen
(generator='nanopb', force_generate=False)¶ Get protocol buffer code prepared for cogeno use.
- Return
Protocol buffer code database
- Parameters
generator
: The protocol buffer generator to use to generate the protocol buffer code. One of ‘nanopb’, ‘pbtools’, ‘protobluff’, ‘cpp’, ‘python’. Default is ‘nanopb’.force_generate
: Force generation of the protocol buffer code, even if already generated. Default is False.
Generate code with protobuf¶
Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data. There exist several implementations for a lot of programming languages.
The protobuf module supports the following code generators:
Language |
Generator |
---|---|
C |
|
C |
|
C |
|
C++ |
|
Python |
The protocol buffer code that is generated by a generator is added to the protocol buffer code database.
-
cogeno.modules.protobuf.ProtoCodeDb : public MutableMapping
Protocol buffers code database.
All generated code is cached in dictionary.
Usage:
cogeno.module_import('protobuf') db = protobuf.protodb("nanopb") db2 = protobuf.protodb("py") cogeno.out(db['my_message.pb.h']) cogeno.out(db('pb_encode.c'])
Public Functions
-
__init__
(self, generator=None, sources=None, include_dirs=None, dst_dir=None)¶ Initialize protocol buffer code database.
- Parameters
generator
: Any of ‘nonopb’, …sources
: *.proto sourcesinclude_dirs
: Directories to search for *.proto importdst_dir
: Destination directory for generated code
-
__getitem__
(self, key)¶
-
__setitem__
(self, key, value)¶
-
__delitem__
(self, key)¶
-
__iter__
(self)¶
-
__len__
(self)¶
-
add_sources
(self, sources)¶ Add sources to the list of sources for generation.
- Return
True in case new sources were added, False otherwise.
- Parameters
sources
: List of source file pathes
-
add_include_dirs
(self, include_dirs)¶ Add include directories to the list for generation.
- Return
True in case new include dirs were added, False otherwise.
- Parameters
include_dirs
: List of include dir pathes
-
load
(self)¶ Load generated code into database.
-
generate
(self)¶ Generate protocol buffer code.
- Note
This routine will use grpcio-provided protoc if it exists, and is using the system-installed protoc as a fallback.
- Return
protoc invocation return value
-
Generate protobuf code using protobluff¶
There is no uptodate PyPI package available for protobluff. The protobluff plugin for protoc has to be build and installed from source as described in the protobluff documentation. The source code is available on GitHub.
On Ubuntu you might use this script (setup_protobluff.sh
):
#! /usr/bin/env sh
# Install protobluff to user local
# Ubuntu
sudo apt install git gcc automake libtool protobuf-compiler libprotoc-dev libprotobuf-dev check
# get the sources
git clone https://github.com/squidfunk/protobluff protobluff.git
cd protobluff.git
# configure
./autogen.sh
./configure --prefix ${HOME}/.local
# build & test & install to user dir
make
make test
make install
# remove the git repository
cd ..
rm -rf protobluff.git
The protobuf module searches the pathes defined in the environment for protoc-gen-protobluff.
ReST/ RST code generation (rstcode)¶
Description¶
The rstcode module supports code generation for the reST (RST) markup language.
To use the module in inline code generation import it by:
cogeno.import_module('rstcode')
In case you want to use the rstcode module in another Python project import it by:
import cogeno.modules.rstcode
Cogeno invocation options¶
There are NO Cogeno invocation options.
Code generation functions¶
-
cogeno.modules.rstcode.
sanitize_target
(target)¶ Sanitize target string.
Replace weired characters in the target string. Prevent
_
at start and end of target string.- Return
Sanitized target string.
-
cogeno.modules.rstcode.
link_reference
(target)¶ Get target reference.
Get the target reference for target string. The target string is sanitized by sanitize_target() before.
- Return
Target reference.
-
cogeno.modules.rstcode.Node : public object
A node of a RST document.
Subclassed by cogeno.modules.rstcode.BulletList, cogeno.modules.rstcode.CodeBlock, cogeno.modules.rstcode.Comment, cogeno.modules.rstcode.Document, cogeno.modules.rstcode.LinkTarget, cogeno.modules.rstcode.OrderedList, cogeno.modules.rstcode.Paragraph, cogeno.modules.rstcode.Section, cogeno.modules.rstcode.Table, cogeno.modules.rstcode.Text
Public Functions
-
text_begin
(self)¶ Get the text to be issued at beginning of node output.
Maybe overloaded by child classes to dynamically adapt the output text at out() processing.
- Return
text
-
text_end
(self)¶ Get the text to be issued at end of node output.
Maybe overloaded by child classes to dynamically adapt the output text at out() processing.
- Return
text
-
add_child
(self, node)¶ Add a
Node
object to the current node.- Return
True
in case of success.- Parameters
node
: Node to add as a child of this node.
-
out
(self, out_redirect=None)¶ Output node content.
- Parameters
output_redirect
: Optional - redirect output, default is cogeno.out.
-
-
cogeno.modules.rstcode.Text : public cogeno.modules.rstcode.Node
A pure text node.
Public Functions
-
__init__
(self, text)¶ Initialise the text node.
- Parameters
text
: Multiline text
-
-
cogeno.modules.rstcode.Comment : public cogeno.modules.rstcode.Node
A comment node.
Public Functions
-
__init__
(self, text)¶ Initialise the comment node.
- Parameters
text
: Multiline text
-
-
cogeno.modules.rstcode.CodeBlock : public cogeno.modules.rstcode.Node
A code block node.
Public Functions
-
__init__
(self, code, code_type='none')¶ Initialise the code block node.
- Parameters
code
: Multiline codecode_type
: The type of code as understood by the code-block directive
-
-
cogeno.modules.rstcode.Paragraph : public cogeno.modules.rstcode.Node
A paragraph node.
Public Functions
-
__init__
(self, text)¶ Initialise the paragraph node.
- Parameters
text
: Multiline text
-
-
cogeno.modules.rstcode.Section : public cogeno.modules.rstcode.Node
A section node.
Public Functions
-
__init__
(self, title, depth=1)¶ Initialise the section node.
- Parameters
title
: Title of the sectiondepth
: Either depth of the section, default is 1, or section mark character (e.g. ‘#’).
-
-
cogeno.modules.rstcode.BulletList : public cogeno.modules.rstcode.Node
A bullet list node.
-
cogeno.modules.rstcode.OrderedList : public cogeno.modules.rstcode.Node
A ordered list node.
-
cogeno.modules.rstcode.Table : public cogeno.modules.rstcode.Node
A table node.
Output will be done in csv-table style.
Public Functions
-
__init__
(self, title='', headers=[], widths=[])¶ Initialise the paragraph node.
- Parameters
title
: the table titleheaders
: list of header items in the tablewidths
: list of column widths in the table
-
add_row
(self, row)¶ Add new row to the table.
- Parameters
row
: List of column items in the row.
-
-
cogeno.modules.rstcode.LinkTarget : public cogeno.modules.rstcode.Node
A link target node.
Public Functions
-
__init__
(self, target)¶ Initialise the link target node.
The target string will be santized using sanitize_target().
- Parameters
target
: Target
-
-
cogeno.modules.rstcode.Document : public cogeno.modules.rstcode.Node
A document node.
Public Functions
-
__init__
(self, file_path=None)¶ Initialise the document node.
- Parameters
file_path
: Optional, file to write the document to
-
out
(self, out_redirect=None)¶ Output document content.
If no out_redirect is provided the content is written to the file_path specified on initialisation. If also the file_path is not specified the output is re-directed to cogeno.out().
- Parameters
output_redirect
: Optional - redirect output, default is file_path.
-
Zephyr support (zephyr)¶
Description¶
The Zephyr module supports code generation for the Zephyr RTOS.
To use the module in inline code generation import it by:
cogeno.import_module('zephyr')
In case you want to use the Zephyr module in another Python project import it by:
import cogeno.modules.zephyr
Cogeno invocation options¶
There are NO Cogeno invocation options.
Code generation functions¶
-
cogeno.modules.zephyr.
str2ident
(s)¶ Converts ‘s’ to a form suitable for (part of) an identifier.
- Return
identifier
- Parameters
s
: string
-
cogeno.modules.zephyr.
device_name_by_id
(device_id)¶ Get device name from device id.
- Return
device name
- Parameters
device_id
: device id
-
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_defaults
is a dictionary of property path : property value (e.g. { ‘label’ : ‘My default label’ }).
-
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_defaults
is a dictionary of property path : property value.
Generate code with zephyr¶
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).
The device declaration functions work on templates that feature placeholder substitution.
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. |
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”’.
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}.
Placeholder |
Substitution |
Remark |
---|---|---|
${CONFIG_[configuration parameter]} |
KConfig configuration parameter value |
|
‘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),
};
"""
-
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_defaults
is a dictionary of property path : property value (e.g. { ‘label’ : ‘My default label’ }).
-
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_defaults
is 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 */
Code Generation Templates¶
Code generation templates provide sophisticated code generation functions.
Templates are simply text files. They may be hierarchical organized. There is always one top level template. All the other templates have to be included to gain access to the template’s functions and variables.
A template file usually contains normal text and templating commands intermixed. A bound sequence of templating commands is called a script snippet. As a special case a template file may be a script snippet as a whole.
Cogeno supports two flavours of script snippets: Python and Jinja2. A script snippet has to be written in one of the two scripting languages. Within a template file snippets of different language can coexist.
Template Snippets¶
/* This file uses templates. */ ... /** * @code{.cogeno.py} * template_in_var = 1 * cogeno.out_include('templates/template_tmpl.c') * if template_out_var not None: * cogeno.outl("int x = %s;" % template_out_var) * @endcode{.cogeno.py} */ /** @code{.cogeno.ins}@endcode */ ...
Cogeno extensions¶
Search for Cogeno extensions¶
On invocation Cogeno searches the list of directories given in the --extensions DIR [DIR...]
option for Cogeno extensions.
If a cogeno/<extension_name>.py
Python module is found in an extension directory
the module is imported by Cogeno. All Python commands within the <extension_name> module
are executed. Scripts and script snippets can import the module by it’s name <extension_name>.
There may be several modules within the cogeno
directory. All of them will be imported.
Script Cogeno extension modules¶
The cogeno/<extension_name>.py
file is a regular Python module. All of Python can be used.
Add options to the Cogeno invocation¶
A typical use case is to add further options to the Cogeno invocation:
from pathlib import Path
import cogeno
component_path = Path(__file__).parent.parent
cogeno.options_argv_append('--edts:dts-pp-defines', 'MY_EXTENSION=1')
cogeno.options_argv_append('--edts:dts-pp-include-dirs', str(component_path.joinpath('include')))
cogeno.options_argv_append('--edts:bindings-dirs', str(component_path.joinpath('edts/bindings')))
cogeno.options_argv_append('--protobuf:sources', str(component_path.joinpath('proto/myproto.proto')))
Manage extensions hirarchy with Kconfig variables¶
Another use case is to have a hirarchy of extensions possibly controlled by Kconfig variables.
Toplevel <extension directory>/cogeno/<toplevel_name>.py
file:
from pathlib import Path
import cogeno
component_path = Path(__file__).parent.parent
if cogeno.config_property('CONFIG_MY_SUB_EXTENSION', None):
cogeno.import_extensions(component_path.joinpath('whatever/sub-extension'))
...
Sublevel <extension directory/whatever/sub-extension>/cogeno/<sub_extension_name>.py
file:
from pathlib import Path
import cogeno
component_path = Path(__file__).parent.parent
cogeno.options_argv_append('--edts:dts-pp-defines', 'MY_SUB_EXTENSION=1')
...
Build with Cogeno¶
Code generation has to be invoked as part of the build process of a project.
Build with CMake and Cogeno¶
Projects that use CMake to manage building the project
can add the cogeno.cmake script (cogeno.cmake
).
By this a file that contains inline code generation can be added to the project
using the cogeno_sources
command in the respective CMakeList.txt
file.
cogeno_sources(target [EXTERN] [DELETE_SOURCE] [source_file..]
[INCLUDES include_file...] [TXTFILES text_file...]
[SOURCE_DIR dir] [INCLUDE_DIR dir] [TXTFILE_DIR dir]
[COGENO_DEFINES defines..] [DEPENDS target.. file.. dir..])
- EXTERN
EXTERN
has to be given in case the target was not created in the sameCMakeList.txt
file as thecogeno_sources
command is issued.
- DELETE_SOURCE
If
DELETE_SOURCE
is given the generator code is removed from the output file.
- SOURCE_DIR
SOURCE_DIR
specifies the directory to write the generated source file(s) to. A relative path is relative to${CMAKE_CURRENT_BINARY_DIR})
. It defaults to${CMAKE_CURRENT_BINARY_DIR}
or to the CogenoSOURCE_DIR
property if given. Do not setSOURCE_DIR
in case the generated file is a compilable source file (eg. *.c, *.cpp), this will trigger CMake issue #14633.
- INCLUDE_DIR
INCLUDE_DIR
specifies the directory to write the generated include file(s) to. A relative path is relative to${CMAKE_CURRENT_BINARY_DIR})
. It defaults to${CMAKE_CURRENT_BINARY_DIR}
or to the CogenoINCLUDE_DIR
property if given.
- TXTFILE_DIR
TXTFILE_DIR
specifies the directory to write the generated text file(s) to. A relative path is relative to${CMAKE_CURRENT_BINARY_DIR})
. It defaults to${CMAKE_CURRENT_BINARY_DIR}
or to the CogenoTXTFILE_DIR
property if given.
- INCLUDES
INCLUDES
marks files to be handled as include files (vs. source files).
- TXTFILES
TXTFILES
marks files to be handled as text files (vs. source files). Text files are added as a dependency to the target.
- COGENO_DEFINES
The arguments given by the
COGENO_DEFINES
keyword have to be of the formdefine_name=define_value
. The arguments become globals in the python snippets and can be accessed bydefine_name
.
- DEPENDS
Dependencies given by the
DEPENDS
keyword are added to the dependencies of the generated file. Adding a dependency to a directory adds all files in that directory as a dependency.
Use Cogeno modules with CMake¶
The options provided to the modules are set by Cogeno CMake properties.
Module |
Property |
Usage |
---|---|---|
ccode |
– |
– |
cmake |
CMAKE_CACHE |
Path to CMake cache file |
CMAKE_DEFINES |
CMake variable defines |
|
config |
:ref:`CONFIG_DB ` |
Path to config database file |
CONFIG_FILE |
Path to config file |
|
CONFIG_KCONFIG_FILE |
Path to Kconfig file |
|
edts |
EDTS_ARCH |
|
EDTS_ARCH_FLAVOUR |
||
EDTS_DTS |
||
EDTS_DTS_ROOT |
||
EDTS_DTS_PP_DEFINES |
||
EDTS_DTS_PP_INCLUDE_DIRS |
||
EDTS_DTS_PP_SOURCES |
||
EDTS_BINDINGS_DIRS |
||
EDTS_BINDINGS_EXCLUDE |
||
EDTS_BINDINGS_NO_DEFAULT |
||
EDTS_DB |
||
protobuf |
PROTOBUF_DB_DIR |
|
PROTOBUF_SOURCES |
||
PROTOBUF_INCLUDE_DIRS |
||
zephyr |
– |
– |
Use the Cogeno EDTS module with CMake¶
The cogeno.cmake script searches the list of directories in the EXTENSION_DIRS
property and the edts
or dts
sub-directories within for device tree root pathes.
If the directories exist they are added to the EDTS_DTS_ROOT property.
EXTENSION_DIRS sub-directory |
Property/ usage |
---|---|
|
EDTS_DTS_ROOT |
|
EDTS_DTS_ROOT |
|
EDTS_DTS_ROOT |
The EDTS_DTS_ROOT pathes are searched for a set of standard sub-directories. If available these sub-directories are added to the respective Cogeno EDTS properties.
EDTS_DTS_ROOT sub-directory |
Property/ usage |
---|---|
|
EDTS_DTS_PP_INCLUDE_DIRS |
|
EDTS_DTS_PP_INCLUDE_DIRS |
|
EDTS_DTS_PP_INCLUDE_DIRS |
EDTS_ARCH |
EDTS_DTS_PP_INCLUDE_DIRS |
EDTS_ARCH/EDTS_ARCH_FLAVOUR |
EDTS_DTS_PP_INCLUDE_DIRS |
|
EDTS_BINDINGS_DIRS |
Use the Cogeno protobuf module with CMake¶
The cogeno.cmake script searches the list of directories in the EXTENSION_DIRS
property for a proto
sub-directory.
If the directory exists it is added to the PROTOBUF_INCLUDE_DIRS property.
The protobuf sources (*.proto) shall be added to the dependencies of the source file that is
using the protobuf code database. The protobuf sources may either be given with absolute
path or with a path relative to the CMakeList.txt
directory.
The include directories that contain protobuf files to be imported by the protobuf sources, and that are not listed in the PROTOBUF_INCLUDE_DIRS property, shall also be added to the dependencies. The enclosing directories of the protobuf sources are automatically added.
CMakeList.txt
cogeno_sources('proto_user.c' DEPENDS proto/myproto.proto ../../general/proto)
Cogeno CMake properties¶
DEFINES
MODULES
TEMPLATES
EXTENSION_DIRS
CMAKE_CACHE
CMAKE_DEFINES
CONFIG_FILE
EDTS_ARCH
EDTS_ARCH_FLAVOUR
EDTS_DTS
EDTS_DTS_ROOT
EDTS_DTS_PP_DEFINES
EDTS_DTS_PP_INCLUDE_DIRS
EDTS_DTS_PP_SOURCES
EDTS_BINDINGS_DIRS
EDTS_BINDINGS_EXCLUDE
EDTS_BINDINGS_NO_DEFAULT
EDTS_DB
PROTOBUF_DB_DIR
PROTOBUF_SOURCES
PROTOBUF_INCLUDE_DIRS
Build with Zephyr and Cogeno¶
Zephyr uses the CMake build system with custom extensions. Build with CMake and Cogeno also applies to Zephyr builds.
To use Cogeno you have to include cogeno.cmake in your project’s CMakeList.txt
file.
The easiest way to get cogeno.cmake and all of Cogeno with Zephyr is to install Cogeno as a Zephyr module.
west.yml
manifest:
remotes:
- name: gitlab_b0661
url-base: https://gitlab.com/b0661
projects:
- name: cogeno
remote: gitlab_b0661
revision: master
path: cogeno
Assure that on build the Cogeno module is processed before the modules that use it. If the sequence created by west –list does not suite your needs explicitly set ZEPHYR_MODULES in your project.
CMakeList.txt
set(ZEPHYR_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/../cogeno
...
)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
In Zephyr the processing of source files is controlled by the CMake
extension functions zephyr.._sources_cogeno..(..)
or zephyr_..includes_cogeno..(..)
.
During build the source files are processed by Cogeno and the generated source files are written
to the CMake binary directory. The generated source files are added to the Zephyr sources.
A file that contains inline code generation has to be added to the project
by one of the following commands in a CMakeList.txt
file:
-
zephyr_sources_cogeno
(file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_sources_cogeno_ifdef
(ifguard file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_sources_cogeno
(file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_sources_cogeno_ifdef
(ifguard file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_includes_cogeno
(file.. [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_includes_cogeno_ifdef
(ifguard file.. [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
Use Cogeno modules with Zephyr¶
Use the Cogeno EDTS module with Zephyr¶
The project device tree file is processed twice by gen_defines.py of Zephyr and cogeno.edts() of Cogeno.
Usually the both should work on the same properties - but in some rare cases gen_defines.py of Zephyr may not understand certain properties because
the property is not foreseen for extraction
or the include directory for an include file for device tree preprocessing provided to the EDTS module is not provided to gen_defines.py (
edts
vs.dts
)or a binding file provided to the EDTS module is different from the one provided to gen_defines.py
In these cases you can use defines to exclude parts of the device tree file from processing
by gen_defines.py. COGENO_EDTS
is only defined if device tree preprocessing
is done on behalf of Cogeno. If you need a more fine grained control you should add a define in the
cogeno/<extension>.py
Cogeno extension module of your project or Zephyr module
(see Search for Cogeno extensions and Script Cogeno extension modules):
import cogeno
cogeno.option_argv_append('--edts:dts-pp-defines', "MY_DTS_DEFINE=1")
In the project device tree file you can control the DTS preprocessing in the usual way:
#if defined(MY_DTS_DEFINE)
#include <dt-bindings/my_special_driver/my_special_driver.h>
#endif
&my_special_driver {
#if defined(MY_DTS_DEFINE)
clock-output-names = MY_SPECIAL_DRIVER_CLOCK_1 MY_SPECIAL_DRIVER_CLOCK_2
#endif
};
Build with ESP-IDF/ MDF and Cogeno¶
Cogeno can be integrated as a component into ESP32 projects using the ESP-IDF or ESP-MDF framework and the CMake build system. Build with CMake and Cogeno also applies to ESP-IDF/ ESP-MDF builds.
To create the Cogeno component make Cogeno a git submodule within the project’s components directory.
cd <project>/components
git submodule add https://gitlab.com/b0661/cogeno
Source files of components may use inline code generation. To generate the inline code the
component sources have to be marked using the cogeno_sources()
command in the respective
CMakeList.txt
file.
cogeno_sources()
adds the generated source files to COGENO_COMPONENT_SRCS
. It also adds
include directories to COGENO_COMPONENT_INCLUDE_DIRS
. The COGENO_COMPONENT_SRCS
and the
COGENO_COMPONENT_INCLUDE_DIRS
have to be registered for the component.
Components should have the Cogeno component given in their PRIV_REQUIRES
property.
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
cogeno_sources(${COMPONENT_NAME} inline_code_filea.c inline_code_fileb.c ...)
endif()
idf_component_register(
SRCS ${COGENO_COMPONENT_SRCS} ...
PRIV_REQUIRES cogeno ...
INCLUDE_DIRS ${COGENO_COMPONENT_INCLUDE_DIRS} ...)
Use Cogeno modules with ESP-IDF and ESP-MDF¶
Use the Cogeno EDTS module with ESP-IDF and ESP-MDF¶
To use the Cogeno Extended Device Tree Specification (EDTS) module your project has to
provide the top level device tree specification edts/project.dts
. The project.dts
file should include device tree source files from the main component
and other components provided in their respective edts
directory.
edts/project.dts
#include <boards/esp32/esp32.dts>
A special component holds most of the generic device tree source files for inclusion:
edts (see examples/esp_idf/edts)
cogeno.cmake¶
# Cogeno CMake example for build system integration.
# See examples/cmake/cogeno.cmake
#
# Cogeno properties - leave untouched for default:
# - DELETE_CODE
# - DEFINES
# - MODULES
# - TEMPLATES
# - EXTENSION_DIRS
# - CMAKE_CACHE
# - CMAKE_DEFINES
# - CONFIG_DB
# - CONFIG_FILE
# - CONFIG_INPUTS
# - CONFIG_KCONFIG_FILE
# - CONFIG_KCONFIG_SRCTREE
# - CONFIG_KCONFIG_DEFINES
# - EDTS_ARCH
# - EDTS_ARCH_FLAVOUR
# - EDTS_BINDINGS_DIRS
# - EDTS_BINDINGS_EXCLUDE
# - EDTS_BINDINGS_NO_DEFAULT
# - EDTS_DB
# - EDTS_DTS
# - EDTS_DTS_ROOT
# - EDTS_DTS_PP_DEFINES
# - EDTS_DTS_PP_INCLUDE_DIRS
# - EDTS_DTS_PP_SOURCES
# - PROTOBUF_DB_DIR
# - PROTOBUF_INCLUDE_DIRS
# - PROTOBUF_SOURCES
# protect against multiple inclusions
include_guard(GLOBAL)
# utilities
function(cogeno_unique_target_name_from_filename filename target_name)
get_filename_component(basename ${filename} NAME)
string(REPLACE "." "_" x ${basename})
string(REPLACE "@" "_" x ${x})
string(MD5 unique_chars ${filename})
set(${target_name} cogeno_${x}_${unique_chars} PARENT_SCOPE)
endfunction()
##
# @brief Retrieve cogeno property of a project.
#
# @param var
# @param property
function(cogeno_get_property var property)
get_property(is_set GLOBAL PROPERTY "COGENO_${property}" SET)
if(${is_set})
get_property(val GLOBAL PROPERTY "COGENO_${property}")
set(${var} "${val}" PARENT_SCOPE)
endif()
endfunction()
##
# @brief Set cogeno property on a project.
#
# @param property
# @param val
# @param APPEND
# @param UNIQUE
function(cogeno_set_property property val)
set(options APPEND UNIQUE)
cmake_parse_arguments(_ "${options}" "" "" ${ARGN})
# Allow for relative path type properties
cogeno_get_property(path_properties PATH_PROPERTIES)
if(NOT path_properties)
# Init standard cogeno path type properties
list(APPEND path_properties
MODULES TEMPLATES EXTENSION_DIRS CMAKE_CACHE
CONFIG_DB CONFIG_FILE CONFIG_INPUTS
CONFIG_KCONFIG_FILE CONFIG_KCONFIG_SRCTREE
EDTS_DTS EDTS_DTS_PP_INCLUDE_DIRS EDTS_DTS_PP_SOURCES
EDTS_BINDINGS_DIRS EDTS_DB PROTOBUF_DB_DIR PROTOBUF_INCLUDE_DIRS
PROTOBUF_SOURCES)
set_property(GLOBAL PROPERTY "COGENO_PATH_PROPERTIES" "${path_properties}")
endif()
if(${property} IN_LIST path_properties)
if(NOT IS_ABSOLUTE ${val})
set(val "${CMAKE_CURRENT_LIST_DIR}/${val}")
endif()
get_filename_component(val ${val} REALPATH)
endif()
if(__APPEND AND __UNIQUE)
cogeno_get_property(property_val ${property})
if(${val} IN_LIST property_val)
return()
endif()
endif()
if(__APPEND)
set_property(GLOBAL APPEND PROPERTY "COGENO_${property}" "${val}")
else()
set_property(GLOBAL PROPERTY "COGENO_${property}" "${val}")
endif()
# Keep track of set cogeno properties
cogeno_get_property(properties PROPERTIES)
if(NOT property IN_LIST properties)
cogeno_set_property(PROPERTIES ${property} APPEND)
endif()
endfunction()
# Find Cogeno
#
# In case cogeno is installed at a custom location the cogeno INSTALL_PATH property
# may be set before calling FindCogeno().
# ``cogeno_set_property(INSTALL_PATH /install/path)``
#
# Result variables:
# ``Cogeno_FOUND``
# ``Cogeno_EXECUTABLE``
# ``Cogeno_EXECUTABLE_ARGS``
# ``Cogeno_BASE``
function(FindCogeno)
cogeno_get_property(found FOUND)
if(NOT DEFINED found)
# Search for cogeno
set(found FALSE)
# We do the simple check - the example file was included - first.
# If this is not the case we search for cogeno.py later on.
#
# If this file
# - is named cogeno.cmake
# - and is in examples/cmake/
# - and there exists a cogeno.py in ../../cogeno
# we know about the cogeno file.
get_filename_component(cogeno_cmake_example ${CMAKE_CURRENT_LIST_FILE} ABSOLUTE)
if(cogeno_cmake_example MATCHES ".*/examples/cmake/cogeno\.cmake")
set(found TRUE)
get_filename_component(base "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE)
set(cogeno_py "${base}/cogeno/cogeno.py")
endif()
# Looking for Zephyr specific installation
if(NOT ${found} AND DEFINED ZEPHYR_BASE AND EXISTS "${ZEPHYR_BASE}")
# Preferred solution is cogeno as a west managed module
if(ZEPHYR_MODULES)
foreach(module ${ZEPHYR_MODULES})
set(full_path ${module}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${module}")
set(cogeno_py ${full_path})
break()
endif()
endforeach()
endif()
endif()
# Looking for ESP-IDF/MDF specific installation
if(NOT ${found} AND DEFINED ESP_PLATFORM AND ESP_PLATFORM)
# Preferred solution is cogeno as a component.
# Git submodule of cogeno is in {component}/cogeno
foreach(component_dir ${COMPONENT_DIRS})
FILE(GLOB components LIST_DIRECTORIES true "${component_dir}")
foreach(component ${components})
set(full_path ${component}/cogeno/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${component}/cogeno" CACHE INTERNAL "cogeno base directory")
set(cogeno_py ${full_path})
break()
endif()
endforeach()
if(${found})
break()
endif()
endforeach()
endif()
# Looking for custom installation provided by cogeno property
cogeno_get_property(install_path INSTALL_PATH)
if(NOT ${found} AND DEFINED install_path)
# take install path as top level cogeno directory
set(full_path ${install_path}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${install_path}")
set(cogeno_py ${full_path})
# search sub directories of install path
else()
FILE(GLOB modules LIST_DIRECTORIES true "${install_path}/*")
foreach(module ${modules})
set(full_path ${module}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${module}")
set(cogeno_py ${full_path})
break()
endif()
endforeach()
endif()
endif()
# Do some further heuristics in case we have not found cogeno
# Priorities:
# - 1st priority: cogeno installed side by side to the project that hosts this file
# - 2nd priority: cogeno installed on host
# - 3rd priority: get cogeno from the git repository
# cogeno installed side by side to the project that hosts this file
# We do not know the nesting - just go up two or one level and search
if(NOT ${found})
# - 2 levels
FILE(GLOB modules LIST_DIRECTORIES true "${CMAKE_SOURCE_DIR}/../../*")
foreach(module ${modules})
set(full_path ${module}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${module}")
set(cogeno_py ${full_path})
break()
endif()
endforeach()
endif()
if(NOT ${found})
# - 1 level
FILE(GLOB modules LIST_DIRECTORIES true "${CMAKE_SOURCE_DIR}/../*")
foreach(module ${modules})
set(full_path ${module}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${module}")
set(cogeno_py ${full_path})
break()
endif()
endforeach()
endif()
# cogeno installed on host
if(NOT ${found})
find_program(executable_found cogeno)
if(EXISTS "${executable_found}")
# Ask cogeno itself for base
execute_process(${executable_found} "--base"
OUTPUT_VARIABLE base RESULT_VARIABLE ret)
if(NOT ${ret} EQUAL 0)
message(FATAL_ERROR ${ret})
endif()
set(executable "${executable_found}")
set(found TRUE)
endif()
endif()
# Get cogeno from the git repository
# Only install if a install path is given as a cogeno property.
if(NOT ${found} AND DEFINED install_path)
find_package(Git)
if(NOT GIT_FOUND)
message(FATAL_ERROR "git not found!")
endif()
if(NOT EXISTS "${install_path}")
message(FATAL_ERROR "install path '${install_path}' does not exist!")
endif()
execute_process(
COMMAND ${GIT_EXECUTABLE} clone https://gitlab.com/b0661/cogeno.git --recursive
WORKING_DIRECTORY "${install_path}"
OUTPUT_VARIABLE git_output)
message(STATUS "${git_output}")
set(module "${install_path}/cogeno")
if (EXISTS ${module})
execute_process(
COMMAND ${GIT_EXECUTABLE} checkout master
WORKING_DIRECTORY "${module}"
OUTPUT_VARIABLE git_output)
message(STATUS "${git_output}")
set(full_path ${module}/cogeno/cogeno.py)
if(EXISTS ${full_path})
set(found TRUE)
set(base "${module}")
set(cogeno_py ${full_path})
endif()
endif()
endif()
cogeno_set_property(FOUND ${found})
if(${found})
# We may need a Python interpreter for cogeno
if(DEFINED executable)
# We do not need the Python 3 interpreter
set(executable_args)
else()
if(${CMAKE_VERSION} VERSION_LESS "3.12")
set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5)
find_package(PythonInterp)
set(Python3_Interpreter_FOUND ${PYTHONINTERP_FOUND})
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
set(Python3_VERSION ${PYTHON_VERSION_STRING})
else()
# CMake >= 3.12
find_package(Python3 COMPONENTS Interpreter)
endif()
if(NOT ${Python3_Interpreter_FOUND})
message(FATAL_ERROR "Python 3 not found")
endif()
set(executable "${Python3_EXECUTABLE}")
set(executable_args "${cogeno_py}")
endif()
cogeno_set_property(EXECUTABLE ${executable})
cogeno_set_property(EXECUTABLE_ARGS ${executable_args})
cogeno_set_property(BASE ${base})
endif()
endif()
set(Cogeno_FOUND ${found} CACHE INTERNAL "cogeno found" PARENT_SCOPE)
if(${found})
cogeno_get_property(executable EXECUTABLE)
set(Cogeno_EXECUTABLE ${executable}
CACHE INTERNAL "cogeno executable" PARENT_SCOPE)
cogeno_get_property(executable_args EXECUTABLE_ARGS)
set(Cogeno_EXECUTABLE_ARGS ${executable_args}
CACHE INTERNAL "cogeno executable arguments" PARENT_SCOPE)
cogeno_get_property(base BASE)
set(Cogeno_BASE ${base}
CACHE INTERNAL "cogeno base directory" PARENT_SCOPE)
endif()
endfunction()
function(cogeno_init_properties_zephyr)
# Set directories to be searched for cogeno extensions
foreach(extension_dir ${DTS_ROOT} ${ZEPHYR_MODULES})
get_filename_component(extension_dir "${extension_dir}" REALPATH)
cogeno_set_property(EXTENSION_DIRS ${extension_dir} APPEND UNIQUE)
endforeach()
if(EXISTS "${APPLICATION_SOURCE_DIR}/templates")
cogeno_set_property(TEMPLATES "${APPLICATION_SOURCE_DIR}/templates" APPEND UNIQUE)
cogeno_set_property(MODULES "${APPLICATION_SOURCE_DIR}/templates" APPEND UNIQUE)
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/templates")
cogeno_set_property(TEMPLATES "${PROJECT_SOURCE_DIR}/templates" APPEND UNIQUE)
cogeno_set_property(MODULES "${PROJECT_SOURCE_DIR}/templates" APPEND UNIQUE)
endif()
# DOTCONFIG and merge_config_files is created by Zephyr - use it to get the config fragements
set(config_file "${DOTCONFIG}")
cogeno_set_property(CONFIG_FILE "${config_file}")
foreach(config_fragment ${merge_config_files})
if(${config_fragment} STREQUAL ${config_file})
continue()
endif()
cogeno_set_property(CONFIG_INPUTS "${config_fragment}" APPEND UNIQUE)
endforeach()
cogeno_set_property(CONFIG_KCONFIG_FILE "${KCONFIG_ROOT}")
cogeno_set_property(CONFIG_KCONFIG_SRCTREE "${ZEPHYR_BASE}")
cogeno_set_property(CONFIG_KCONFIG_DEFINES "ZEPHYR_BASE=${ZEPHYR_BASE}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "KERNELVERSION=${KERNELVERSION}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "KCONFIG_CONFIG=${config_file}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "ARCH=${ARCH}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "BOARD_DIR=${BOARD_DIR}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "SHIELD_AS_LIST=${SHIELD_AS_LIST}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "KCONFIG_BINARY_DIR=${KCONFIG_BINARY_DIR}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "ARCH_DIR=${ARCH_DIR}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR}" APPEND UNIQUE)
cogeno_set_property(CONFIG_KCONFIG_DEFINES "EDT_PICKLE=${EDT_PICKLE}" APPEND UNIQUE)
cogeno_set_property(CMAKE_DEFINES "APPLICATION_SOURCE_DIR" APPEND UNIQUE)
cogeno_set_property(CMAKE_DEFINES "APPLICATION_BINARY_DIR" APPEND UNIQUE)
cogeno_set_property(EDTS_ARCH ${ARCH})
# Set EDTS_DTS_PP_SOURCES property
if(NOT DEFINED DTS_SOURCE)
message(STATUS "Cogeno can't create EDTS - Zephyr 'DTS_SOURCE' not provided")
elseif(NOT EXISTS ${DTS_SOURCE})
message(STATUS "Cogeno can't create EDTS - '${DTS_SOURCE}' not found")
else()
cogeno_set_property(EDTS_DTS_PP_SOURCES "${DTS_SOURCE}")
if(DTC_OVERLAY_FILE)
# DTC_OVERLAY_FILE is a space-separated list
foreach(overlay_file ${DTC_OVERLAY_FILE})
if(EXISTS ${overlay_file})
cogeno_set_property(EDTS_DTS_PP_SOURCES "${overlay_file}" APPEND UNIQUE)
else()
message(STATUS "Cogeno can't create EDTS - '${overlay_file}' not found")
endif()
endforeach()
endif()
endif()
# Set EDTS_DTS_PP_DEFINES
cogeno_set_property(EDTS_DTS_PP_DEFINES "__DTC__" APPEND UNIQUE)
# Set EDTS_DTS_ROOT property
if(NOT DEFINED DTS_ROOT)
message(STATUS "Cogeno may not create EDTS - Zephyr 'DTS_ROOT' not provided")
endif()
# Set EDTS_BINDINGS_DIRS property
if(NOT DEFINED DTS_ROOT_BINDINGS)
message(STATUS "Cogeno may not create EDTS - Zephyr 'DTS_ROOT_BINDINGS' not provided")
else()
string(REPLACE "?" ";" root_bindings "${DTS_ROOT_BINDINGS}")
list(APPEND edts_bindings_dirs ${root_bindings})
list(REMOVE_DUPLICATES edts_bindings_dirs)
foreach(binding_dir ${edts_bindings_dirs})
if(EXISTS ${binding_dir})
cogeno_set_property(EDTS_BINDINGS_DIRS ${binding_dir} APPEND UNIQUE)
endif()
endforeach()
endif()
# Set EDTS_BINDINGS_EXCLUDE property
# Exclude generic bindings that are provided by cogeno
foreach(binding_exclude
"${ZEPHYR_BASE}/dts/bindings/iio/adc/adc-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/base/base.yaml"
"${ZEPHYR_BASE}/dts/bindings/can/can-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/can/can-device.yaml"
"${ZEPHYR_BASE}/dts/bindings/clock/clock-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/clock/fixed-clock.yaml"
"${ZEPHYR_BASE}/dts/bindings/cpu/cpu.yaml"
"${ZEPHYR_BASE}/dts/bindings/dma/dma-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/espi/espi-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/ethernet/ethernet.yaml"
"${ZEPHYR_BASE}/dts/bindings/flash_controller/flash-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/gpio/gpio-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/gpio/gpio-keys.yaml"
"${ZEPHYR_BASE}/dts/bindings/gpio/gpio-leds.yaml"
"${ZEPHYR_BASE}/dts/bindings/gpio/gpio-nexus.yaml"
"${ZEPHYR_BASE}/dts/bindings/i2c/i2c-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/i2c/i2c-device.yaml"
"${ZEPHYR_BASE}/dts/bindings/i2s/i2s-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/i2s/i2s-device.yaml"
"${ZEPHYR_BASE}/dts/bindings/interrupt-controller/interrupt-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/interrupt-controller/shared-irq.yaml"
"${ZEPHYR_BASE}/dts/bindings/kscan/kscan.yaml"
"${ZEPHYR_BASE}/dts/bindings/led/pwm-leds.yaml"
"${ZEPHYR_BASE}/dts/bindings/mmc/mmc-spi-slot.yaml"
"${ZEPHYR_BASE}/dts/bindings/mmc/mmc.yaml"
"${ZEPHYR_BASE}/dts/bindings/mtd/eeprom-base.yaml"
"${ZEPHYR_BASE}/dts/bindings/mtd/eeprom-spi-i2c.yaml"
"${ZEPHYR_BASE}/dts/bindings/mtd/partition.yaml"
"${ZEPHYR_BASE}/dts/bindings/mtd/soc-nv-flash.yaml"
"${ZEPHYR_BASE}/dts/bindings/phy/phy-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/ps2/ps2.yaml"
"${ZEPHYR_BASE}/dts/bindings/pwm/pwm-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/rtc/rtc.yaml"
"${ZEPHYR_BASE}/dts/bindings/serial/uart-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/serial/uart-device.yaml"
"${ZEPHYR_BASE}/dts/bindings/spi/spi-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/spi/spi-device.yaml"
"${ZEPHYR_BASE}/dts/bindings/sram/mmio-sram.yaml"
"${ZEPHYR_BASE}/dts/bindings/usb/usb-controller.yaml"
"${ZEPHYR_BASE}/dts/bindings/usb/usb-ep.yaml")
cogeno_set_property(EDTS_BINDINGS_EXCLUDE ${binding_exclude} APPEND UNIQUE)
endforeach()
endfunction()
function(cogeno_postprocess_properties_zephyr)
# Make the bindings include dirs publically available
cogeno_get_property(edts_dts_pp_include_dirs EDTS_DTS_PP_INCLUDE_DIRS)
zephyr_include_directories(${edts_dts_pp_include_dirs})
endfunction()
function(cogeno_init_properties_esp_platform)
# Search for components
# - extension dirs
# - cogeno component
# - main component
# - edts component ???
#
# Take always the last component directory found.
#
# Explanation from IDF documentation:
# This allows, for example, overriding ESP-IDF components with
# a modified version by copying that component from the ESP-IDF
# components directory to the project components directory and
# then modifying it there. If used in this way, the ESP-IDF
# directory itself can remain untouched.
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
foreach(component_target ${build_component_targets})
__component_get_property(component_dir ${component_target} COMPONENT_DIR)
__component_get_property(component_name ${component_target} COMPONENT_NAME)
# Set directories to be searched for cogeno extensions
cogeno_set_property(EXTENSION_DIRS ${component_dir} APPEND UNIQUE)
# cogeno component
set(full_path ${component_dir}/cogeno/cogeno/cogeno.py)
if(EXISTS ${full_path})
cogeno_set_property(COMPONENT_COGENO "${component}")
endif()
endforeach()
# main component
if(EXISTS "${PROJECT_SOURCE_DIR}/main")
cogeno_set_property(COMPONENT_MAIN "${PROJECT_SOURCE_DIR}/main")
endif()
cogeno_set_property(CONFIG_FILE "${SDKCONFIG}")
cogeno_set_property(CMAKE_DEFINES "SDKCONFIG" APPEND)
cogeno_set_property(CMAKE_DEFINES "SDKCONFIG_DEFAULTS" APPEND)
cogeno_set_property(CMAKE_DEFINES "BUILD_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENTS" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENT_ALIAS" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENT_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENT_LIB" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENT_NAME" APPEND)
cogeno_set_property(CMAKE_DEFINES "COMPONENT_TYPE" APPEND)
cogeno_set_property(CMAKE_DEFINES "EMBED_FILES" APPEND)
cogeno_set_property(CMAKE_DEFINES "EMBED_TXTFILES" APPEND)
cogeno_set_property(CMAKE_DEFINES "INCLUDE_DIRS" APPEND)
cogeno_set_property(CMAKE_DEFINES "KCONFIG" APPEND)
cogeno_set_property(CMAKE_DEFINES "KCONFIG_PROJBUILD" APPEND)
cogeno_set_property(CMAKE_DEFINES "LDFRAGMENTS" APPEND)
cogeno_set_property(CMAKE_DEFINES "PRIV_INCLUDE_DIRS" APPEND)
cogeno_set_property(CMAKE_DEFINES "PRIV_REQUIRES" APPEND)
cogeno_set_property(CMAKE_DEFINES "REQUIRED_IDF_TARGETS" APPEND)
cogeno_set_property(CMAKE_DEFINES "REQUIRES" APPEND)
cogeno_set_property(CMAKE_DEFINES "SRCS" APPEND)
# Set EDTS system architecture
cogeno_set_property(EDTS_ARCH "xtensa")
cogeno_set_property(EDTS_ARCH_FLAVOUR "espressif")
# Set EDTS_DTS_PP_SOURCES property
set(full_path "${PROJECT_SOURCE_DIR}/edts/project.dts")
if(NOT EXISTS ${full_path})
message(STATUS "Cogeno can't create EDTS - '${full_path}' not found")
else()
cogeno_set_property(EDTS_DTS_PP_SOURCES "${full_path}")
endif()
endfunction()
function(cogeno_postprocess_properties_esp_platform)
endfunction()
function(cogeno_init_properties_unknown_platform)
endfunction()
function(cogeno_postprocess_properties_unknown_platform)
endfunction()
function(cogeno_init_properties)
# Generic properties provided by FindCogeno are:
# - FOUND
# - EXECUTABLE
# - EXECUTABLE_ARGS
# - BASE
# Properties that are set to default values before platform init:
# - DELETE_CODE
# - EXTENSION_DIRS
# - CONFIG_DB
# - CMAKE_DEFINES
# - EDTS_DB
# - EDTS_DTS
# - PLATFORM
# - PROTOBUF_DB_DIR
# Generic properties provided by platform init:
# - CONFIG_FILE
# - CONFIG_INPUTS
# - CONFIG_KCONFIG_FILE
# - CONFIG_KCONFIG_SRCTREE
# - CONFIG_KCONFIG_DEFINES
# - CMAKE_CACHE
# - EDTS_ARCH
# - EDTS_ARCH_FLAVOUR
# - EDTS_DTS_PP_SOURCES
# - EDTS_DTS_PP_DEFINES
# Properties that are set to default values after platform init:
# - MODULES
# - TEMPLATES
# - EDTS_BINDINGS_DIRS
# - EDTS_DTS_PP_INCLUDE_DIRS
# - EDTS_DTS_ROOT
# - PROTOBUF_INCLUDE_DIRS
# Assure cogeno is available
# --------------------------
cogeno_get_property(Cogeno_FOUND FOUND)
if(NOT DEFINED Cogeno_FOUND)
FindCogeno()
endif()
if(NOT Cogeno_FOUND)
message(FATAL "Cogeno not found")
endif()
# directories to be searched for extended device tree sources, bindings, includes
set(edts_dirs "edts" "dts")
# Set pre platform init default properties
# ----------------------------------------
cogeno_set_property(DELETE_CODE FALSE)
cogeno_set_property(EXTENSION_DIRS "${PROJECT_SOURCE_DIR}" APPEND)
cogeno_set_property(LOG "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cogeno.log")
cogeno_set_property(LOCK "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cogeno.lock")
cogeno_set_property(CMAKE_CACHE "${CMAKE_BINARY_DIR}/CMakeCache.txt")
cogeno_set_property(CMAKE_DEFINES "PROJECT_NAME" APPEND)
cogeno_set_property(CMAKE_DEFINES "PROJECT_SOURCE_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "PROJECT_BINARY_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_SOURCE_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_BINARY_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_CURRENT_SOURCE_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_CURRENT_BINARY_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_CURRENT_LIST_DIR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_FILES_DIRECTORY" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_PROJECT_NAME" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_SYSTEM" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_SYSTEM_NAME" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_SYSTEM_VERSION" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_SYSTEM_PROCESSOR" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_C_COMPILER" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_CXX_COMPILER" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_COMPILER_IS_GNUCC" APPEND)
cogeno_set_property(CMAKE_DEFINES "CMAKE_COMPILER_IS_GNUCXX" APPEND)
cogeno_set_property(CONFIG_DB "${CMAKE_BINARY_DIR}/config.json")
cogeno_set_property(EDTS_DB "${CMAKE_BINARY_DIR}/edts.json")
cogeno_set_property(EDTS_DTS "${CMAKE_BINARY_DIR}/edts.dts")
cogeno_set_property(EDTS_DTS_PP_DEFINES "COGENO_EDTS=1")
cogeno_set_property(PROTOBUF_DB_DIR "${CMAKE_BINARY_DIR}/protobuf")
# Set platform init properties
# ----------------------------
if(DEFINED ZEPHYR_BASE AND EXISTS "${ZEPHYR_BASE}")
cogeno_set_property(PLATFORM "zephyr")
cogeno_init_properties_zephyr()
elseif(DEFINED ESP_PLATFORM AND ESP_PLATFORM)
cogeno_set_property(PLATFORM "esp")
cogeno_init_properties_esp_platform()
else()
cogeno_set_property(PLATFORM "generic")
cogeno_init_properties_unknown_platform()
endif()
# Set post platform init default properties
# -----------------------------------------
# Update EXTENSION_DIRS for cogeno extensions
cogeno_get_property(extension_dirs EXTENSION_DIRS)
# Report EXTENSION_DIRS
foreach(extension_dir ${extension_dirs})
message(VERBOSE "Cogeno found extension dir '${extension_dir}'")
endforeach()
# Set MODULES and TEMPLATES
foreach(extension_dir ${extension_dirs})
set(full_path "${extension_dir}/cogeno/modules")
if(EXISTS ${full_path})
cogeno_set_property(MODULES "${full_path}" APPEND UNIQUE)
endif()
set(full_path "${extension_dir}/cogeno/templates")
if(EXISTS ${full_path})
cogeno_set_property(TEMPLATES "${full_path}" APPEND UNIQUE)
endif()
endforeach()
cogeno_get_property(modules MODULES)
cogeno_get_property(templates TEMPLATES)
# Report MODULES
foreach(module ${modules})
message(VERBOSE "Cogeno found module dir '${module}'")
endforeach()
# Report TEMPLATES
foreach(template ${templates})
message(VERBOSE "Cogeno found template dir '${template}'")
endforeach()
# Set EDTS_DTS_ROOT property
foreach(extension_dir ${extension_dirs})
# Use <dir>/include/dt-bindings as DTS root dir
set(full_path "${extension_dir}/include/dt-bindings")
if(EXISTS ${full_path})
cogeno_set_property(EDTS_DTS_ROOT "${extension_dir}" APPEND UNIQUE)
endif()
# Search for <dir>/edts and/or <dir>/dts
foreach(edts_dir ${edts_dirs})
set(full_path "${extension_dir}/${edts_dir}")
if(EXISTS ${full_path})
cogeno_set_property(EDTS_DTS_ROOT "${full_path}" APPEND UNIQUE)
endif()
endforeach()
endforeach()
cogeno_get_property(edts_dts_root EDTS_DTS_ROOT)
# Report EDTS_DTS_ROOT
foreach(dts_root ${edts_dts_root})
message(VERBOSE "Cogeno found EDT specification root '${dts_root}'")
endforeach()
# Set EDTS_BINDINGS_DIRS property
foreach(dts_root ${edts_dts_root})
# Bindings given in dts root
set(full_path "${dts_root}/bindings")
if(EXISTS ${full_path})
cogeno_set_property(EDTS_BINDINGS_DIRS "${full_path}" APPEND UNIQUE)
endif()
# This is the device tree component - use skeleton.dtsi to detect
set(full_path "${dts_root}/common/skeleton.dtsi")
if(EXISTS ${full_path})
cogeno_set_property(COMPONENT_EDTS "${dts_root}" APPEND UNIQUE)
endif()
endforeach()
cogeno_get_property(edts_bindings_dirs EDTS_BINDINGS_DIRS)
cogeno_get_property(component_edts COMPONENT_EDTS)
# Report EDTS_BINDINGS_DIRS
foreach(edts_bindings_dir ${edts_bindings_dirs})
message(VERBOSE "Cogeno found EDT bindings dir '${edts_bindings_dir}'")
endforeach()
# Report COMPONENT_EDTS
foreach(component ${component_edts})
message(VERBOSE "Cogeno found EDT specification component '${component}'")
endforeach()
# Get system architecture and create sub dts root architecture standard pathes
cogeno_get_property(edts_arch EDTS_ARCH)
if(DEFINED edts_arch)
set(edts_arch_path "${edts_arch}")
cogeno_get_property(edts_arch_flavour EDTS_ARCH_FLAVOUR)
if(DEFINED edts_arch_flavour)
set(edts_arch_flavour_path "${edts_arch_path}/${edts_arch_flavour}")
endif()
endif()
# Set EDTS_DTS_PP_INCLUDE_DIRS property
foreach(dts_root ${edts_dts_root})
cogeno_set_property(EDTS_DTS_PP_INCLUDE_DIRS "${dts_root}" APPEND UNIQUE)
set(full_path "${dts_root}/include/dt-bindings")
if(EXISTS ${full_path})
cogeno_set_property(EDTS_DTS_PP_INCLUDE_DIRS "${dts_root}/include" APPEND UNIQUE)
endif()
foreach(dts_root_standard_path include common ${edts_arch_path} ${edts_arch_flavour_path})
set(full_path ${dts_root}/${dts_root_standard_path})
if(EXISTS ${full_path})
cogeno_set_property(EDTS_DTS_PP_INCLUDE_DIRS "${full_path}" APPEND UNIQUE)
endif()
endforeach()
endforeach()
cogeno_get_property(edts_dts_pp_include_dirs EDTS_DTS_PP_INCLUDE_DIRS)
# Report EDTS_DTS_PP_INCLUDE_DIRS
foreach(edts_bindings_include_dir ${edts_dts_pp_include_dirs})
message(VERBOSE "Cogeno found EDT bindings include dir '${edts_bindings_include_dir}'")
endforeach()
# Set EDTS_DTS_PP_SOURCES property - already set by platform code
cogeno_get_property(edts_dts_pp_sources EDTS_DTS_PP_SOURCES)
# Report EDTS_DTS_PP_SOURCES
foreach(edts_dts_pp_source ${edts_dts_pp_sources})
message(VERBOSE "Cogeno found DTS source '${edts_dts_pp_source}'")
endforeach()
# Set EDTS_DTS_PP_DEFINES
# - add platform defines
cogeno_get_property(platform PLATFORM)
if(DEFINED platform)
string(TOUPPER "${platform}" platform_uc)
cogeno_set_property(EDTS_DTS_PP_DEFINES "COGENO_${platform_uc}=1" APPEND UNIQUE)
endif()
# - add architecture defines
cogeno_get_property(edts_arch EDTS_ARCH)
if(DEFINED edts_arch)
string(TOUPPER "${edts_arch}" edts_arch_uc)
cogeno_set_property(EDTS_DTS_PP_DEFINES "COGENO_EDTS_ARCH_${edts_arch_uc}=1" APPEND UNIQUE)
cogeno_get_property(edts_arch_flavour EDTS_ARCH_FLAVOUR)
if(DEFINED edts_arch_flavour)
string(TOUPPER "${edts_arch_flavour}" edts_arch_flavour_uc)
cogeno_set_property(EDTS_DTS_PP_DEFINES "COGENO_EDTS_ARCH_${edts_arch_uc}_${edts_arch_flavour_uc}=1" APPEND UNIQUE)
endif()
endif()
cogeno_get_property(edts_dts_pp_defines EDTS_DTS_PP_DEFINES)
# Report EDTS_DTS_PP_DEFINES
foreach(edts_dts_pp_define ${edts_dts_pp_defines})
message(VERBOSE "Cogeno found DTS preprocessor define '${edts_dts_pp_define}'")
endforeach()
# Set PROTOBUF_INCLUDE_DIRS property
foreach(extension_dir ${extension_dirs})
# Use <dir>/proto as include dir
set(full_path "${extension_dir}/proto")
if(EXISTS ${full_path})
cogeno_set_property(PROTOBUF_INCLUDE_DIRS "${extension_dir}" APPEND UNIQUE)
endif()
endforeach()
cogeno_get_property(protobuf_include_dirs PROTOBUF_INCLUDE_DIRS)
# Report PROTOBUF_INCLUDE_DIRS
foreach(protobuf_include_dir ${protobuf_include_dirs})
message(VERBOSE "Cogeno found protobuf include directory '${protobuf_include_dir}'")
endforeach()
# Set platform post init properties
# ---------------------------------
if(DEFINED ZEPHYR_BASE AND EXISTS "${ZEPHYR_BASE}")
cogeno_postprocess_properties_zephyr()
elseif(DEFINED ESP_PLATFORM AND ESP_PLATFORM)
cogeno_postprocess_properties_esp_platform()
else()
cogeno_postprocess_properties_unknown_platform()
endif()
cogeno_set_property(PROPERTIES_INITIALIZED TRUE)
endfunction()
function(cogeno_set_options
args_source_dir
args_include_dir
args_txtfile_dir
args_delete_code
args_cogeno_defines
args_depends)
cogeno_get_property(properties_initialized PROPERTIES_INITIALIZED)
if(NOT DEFINED properties_initialized)
# Global cogeno properties not initialized - init now
cogeno_init_properties()
endif()
# cogeno executable
cogeno_get_property(executable EXECUTABLE)
set(cogeno_opt_executable ${executable} PARENT_SCOPE)
cogeno_get_property(executable_args EXECUTABLE_ARGS)
set(cogeno_opt_executable_args ${executable_args} PARENT_SCOPE)
cogeno_get_property(base BASE)
set(cogeno_opt_base ${base} PARENT_SCOPE)
# directory to put the sources in
cogeno_get_property(source_dir SOURCE_DIR)
if(NOT "${args_source_dir}" STREQUAL "")
set(cogeno_opt_source_dir "${args_source_dir}")
elseif(DEFINED source_dir AND source_dir)
set(cogeno_opt_source_dir "${source_dir}")
else()
set(cogeno_opt_source_dir "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT IS_ABSOLUTE ${cogeno_opt_source_dir})
# relative path - use whole relative path
set(cogeno_opt_source_dir ${CMAKE_CURRENT_BINARY_DIR}/${cogeno_opt_source_dir})
endif()
set(cogeno_opt_source_dir ${cogeno_opt_source_dir} PARENT_SCOPE)
# directory to put the includes in
cogeno_get_property(include_dir INCLUDE_DIR)
if(NOT "${args_include_dir}" STREQUAL "")
set(cogeno_opt_include_dir "${args_include_dir}")
elseif(DEFINED include_dir AND include_dir)
set(cogeno_opt_include_dir "${include_dir}")
else()
set(cogeno_opt_include_dir "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT IS_ABSOLUTE ${cogeno_opt_include_dir})
# relative path - use whole relative path
set(cogeno_opt_include_dir ${CMAKE_CURRENT_BINARY_DIR}/${cogeno_opt_include_dir})
endif()
set(cogeno_opt_include_dir ${cogeno_opt_include_dir} PARENT_SCOPE)
# directory to put the text files in
cogeno_get_property(txtfile_dir TXTFILE_DIR)
if(NOT "${args_txtfile_dir}" STREQUAL "")
set(cogeno_opt_txtfile_dir "${args_txtfile_dir}")
elseif(DEFINED txtfile_dir AND txtfile_dir)
set(cogeno_opt_txtfile_dir "${txtfile_dir}")
else()
set(cogeno_opt_txtfile_dir "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT IS_ABSOLUTE ${cogeno_opt_txtfile_dir})
# relative path - use whole relative path
set(cogeno_opt_txtfile_dir ${CMAKE_CURRENT_BINARY_DIR}/${cogeno_opt_txtfile_dir})
endif()
set(cogeno_opt_txtfile_dir ${cogeno_opt_txtfile_dir} PARENT_SCOPE)
# generated files dependencies
set(cogeno_opt_depends)
foreach(depend ${args_depends})
if(TARGET ${depend})
list(APPEND cogeno_opt_depends ${depend})
endif()
# Find path of dependency
if(NOT IS_ABSOLUTE ${depend})
# relative path - use whole relative path
set(depend ${CMAKE_CURRENT_SOURCE_DIR}/${depend})
endif()
if(IS_DIRECTORY "${depend}")
FILE(GLOB depends LIST_DIRECTORIES false "${depend}/*")
if(depends)
list(APPEND cogeno_opt_depends ${depends})
endif()
else()
list(APPEND cogeno_opt_depends ${depend})
endif()
endforeach()
set(cogeno_opt_depends ${cogeno_opt_depends} PARENT_SCOPE)
# --lock
cogeno_get_property(lock LOCK)
if(DEFINED lock AND lock)
set(cogeno_opt_lock "--lock" ${lock})
else()
set(cogeno_opt_lock)
endif()
set(cogeno_opt_lock ${cogeno_opt_lock} PARENT_SCOPE)
# --lock
cogeno_get_property(log LOG)
if(DEFINED log AND log)
set(cogeno_opt_log "--log" ${log})
else()
set(cogeno_opt_log)
endif()
set(cogeno_opt_log ${cogeno_opt_log} PARENT_SCOPE)
# -x
cogeno_get_property(delete_code DELETE_CODE)
if((DEFINED delete_code AND delete_code) OR args_delete_code)
set(cogeno_opt_delete_code '-x')
else()
set(cogeno_opt_delete_code)
endif()
set(cogeno_opt_delete_code ${cogeno_opt_delete_code} PARENT_SCOPE)
# -D
cogeno_get_property(defines DEFINES)
if((DEFINED defines AND defines) OR args_cogeno_defines)
string(REGEX REPLACE "([^;]+)" "-D;\\1"
cogeno_opt_defines "${defines};${args_cogeno_defines}")
else()
set(cogeno_opt_defines)
endif()
set(cogeno_opt_defines ${cogeno_opt_defines} PARENT_SCOPE)
# --extensions
cogeno_get_property(extensions EXTENSION_DIRS)
if(DEFINED extensions AND extensions)
set(cogeno_opt_extensions "--extensions" ${extensions})
else()
set(cogeno_opt_extensions)
endif()
set(cogeno_opt_extensions ${cogeno_opt_extensions} PARENT_SCOPE)
# --modules
cogeno_get_property(modules MODULES)
if(DEFINED modules AND modules)
set(cogeno_opt_modules "--modules" ${modules})
else()
set(cogeno_opt_modules)
endif()
set(cogeno_opt_modules ${cogeno_opt_modules} PARENT_SCOPE)
# --templates
cogeno_get_property(templates TEMPLATES)
if(DEFINED templates AND templates)
set(cogeno_opt_templates "--templates" ${templates})
else()
set(cogeno_opt_templates)
endif()
set(cogeno_opt_templates ${cogeno_opt_templates} PARENT_SCOPE)
# --cmake:define
cogeno_get_property(cmake_defines CMAKE_DEFINES)
list(REMOVE_DUPLICATES cmake_defines)
# Add current values
foreach(cmake_define ${cmake_defines})
if(DEFINED ${cmake_define})
list(APPEND cogeno_opt_cmake_defines
--cmake:define "\"${cmake_define}=${${cmake_define}}\"")
endif()
endforeach()
set(cogeno_opt_cmake_defines ${cogeno_opt_cmake_defines} PARENT_SCOPE)
# --cmake:cache
cogeno_get_property(cmake_cache CMAKE_CACHE)
if(DEFINED cmake_cache)
set(cogeno_opt_cmake_cache "--cmake:cache" "${cmake_cache}")
else()
set(cogeno_opt_cmake_cache)
endif()
set(cogeno_opt_cmake_cache ${cogeno_opt_cmake_cache} PARENT_SCOPE)
# --config:db
cogeno_get_property(config_db CONFIG_DB)
if(DEFINED config_db)
set(cogeno_opt_config_db "--config:db" "${config_db}")
else()
set(cogeno_opt_config_db)
endif()
set(cogeno_opt_config_db ${cogeno_opt_config_db} PARENT_SCOPE)
# --config:file
cogeno_get_property(config_file CONFIG_FILE)
if(DEFINED config_file)
set(cogeno_opt_config_file "--config:file" "${config_file}")
else()
set(cogeno_opt_config_file)
endif()
set(cogeno_opt_config_file ${cogeno_opt_config_file} PARENT_SCOPE)
# --config:inputs
cogeno_get_property(config_inputs CONFIG_INPUTS)
if(DEFINED config_inputs)
set(cogeno_opt_config_inputs "--config:inputs" ${config_inputs})
else()
set(cogeno_opt_config_inputs)
endif()
set(cogeno_opt_config_inputs ${cogeno_opt_config_inputs} PARENT_SCOPE)
# --config:kconfig-file
cogeno_get_property(config_kconfig_file CONFIG_KCONFIG_FILE)
if(DEFINED config_kconfig_file)
set(cogeno_opt_config_kconfig_file "--config:kconfig-file" "${config_kconfig_file}")
else()
set(cogeno_opt_config_kconfig_file)
endif()
set(cogeno_opt_config_kconfig_file ${cogeno_opt_config_kconfig_file} PARENT_SCOPE)
# --config:kconfig-srctree
cogeno_get_property(config_kconfig_srctree CONFIG_KCONFIG_SRCTREE)
if(DEFINED config_kconfig_srctree)
set(cogeno_opt_config_kconfig_srctree "--config:kconfig-srctree" "${config_kconfig_srctree}")
else()
set(cogeno_opt_config_kconfig_srctree)
endif()
set(cogeno_opt_config_kconfig_srctree ${cogeno_opt_config_kconfig_srctree} PARENT_SCOPE)
# --config:kconfig-defines
cogeno_get_property(config_kconfig_defines CONFIG_KCONFIG_DEFINES)
if(DEFINED config_kconfig_defines)
set(cogeno_opt_config_kconfig_defines "--config:kconfig-defines")
# Add current values
foreach(config_kconfig_define ${config_kconfig_defines})
list(APPEND cogeno_opt_config_kconfig_defines "\"${config_kconfig_define}\"")
endforeach()
else()
set(cogeno_opt_config_kconfig_defines)
endif()
set(cogeno_opt_config_kconfig_defines ${cogeno_opt_config_kconfig_defines} PARENT_SCOPE)
# --edts:dts
cogeno_get_property(edts_dts EDTS_DTS)
if(DEFINED edts_dts)
set(cogeno_opt_edts_dts "--edts:dts" "${edts_dts}")
else()
set(cogeno_opt_edts_dts)
endif()
set(cogeno_opt_edts_dts ${cogeno_opt_edts_dts} PARENT_SCOPE)
# --edts:dts-pp-sources
cogeno_get_property(edts_dts_pp_sources EDTS_DTS_PP_SOURCES)
if(DEFINED edts_dts_pp_sources)
set(cogeno_opt_edts_dts_pp_sources "--edts:dts-pp-sources" ${edts_dts_pp_sources})
else()
set(cogeno_opt_edts_dts_pp_sources)
endif()
set(cogeno_opt_edts_dts_pp_sources ${cogeno_opt_edts_dts_pp_sources} PARENT_SCOPE)
# --edts:dts-pp-defines
cogeno_get_property(edts_dts_pp_defines EDTS_DTS_PP_DEFINES)
if(DEFINED edts_dts_pp_defines)
set(cogeno_opt_edts_dts_pp_defines "--edts:dts-pp-defines")
# Add current values
foreach(edts_dts_pp_define ${edts_dts_pp_defines})
list(APPEND cogeno_opt_edts_dts_pp_defines "\"${edts_dts_pp_define}\"")
endforeach()
else()
set(cogeno_opt_edts_dts_pp_defines)
endif()
set(cogeno_opt_edts_dts_pp_defines ${cogeno_opt_edts_dts_pp_defines} PARENT_SCOPE)
# --edts:dts-pp-include-dirs
cogeno_get_property(edts_dts_pp_include_dirs EDTS_DTS_PP_INCLUDE_DIRS)
if(DEFINED edts_dts_pp_include_dirs)
set(cogeno_opt_edts_dts_pp_include_dirs "--edts:dts-pp-include-dirs" ${edts_dts_pp_include_dirs})
else()
set(cogeno_opt_edts_dts_pp_include_dirs)
endif()
set(cogeno_opt_edts_dts_pp_include_dirs ${cogeno_opt_edts_dts_pp_include_dirs} PARENT_SCOPE)
# --edts:bindings-dirs
cogeno_get_property(edts_bindings_dirs EDTS_BINDINGS_DIRS)
if(DEFINED edts_bindings_dirs)
set(cogeno_opt_edts_bindings_dirs "--edts:bindings-dirs" ${edts_bindings_dirs})
else()
set(cogeno_opt_edts_bindings_dirs)
endif()
set(cogeno_opt_edts_bindings_dirs ${cogeno_opt_edts_bindings_dirs} PARENT_SCOPE)
# --edts:bindings-exclude
cogeno_get_property(edts_bindings_exclude EDTS_BINDINGS_EXCLUDE)
if(DEFINED edts_bindings_exclude)
set(cogeno_opt_edts_bindings_exclude "--edts:bindings-exclude" ${edts_bindings_exclude})
else()
set(cogeno_opt_edts_bindings_exclude)
endif()
set(cogeno_opt_edts_bindings_exclude ${cogeno_opt_edts_bindings_exclude} PARENT_SCOPE)
# --edts:bindings-no-default
cogeno_get_property(edts_bindings_no_default EDTS_BINDINGS_NO_DEFAULT)
if(DEFINED edts_bindings_no_default)
set(cogeno_opt_edts_bindings_no_default "--edts:bindings-no-default" ${edts_bindings_no_default})
else()
set(cogeno_opt_edts_bindings_no_default)
endif()
set(cogeno_opt_edts_bindings_no_default ${cogeno_opt_edts_bindings_no_default} PARENT_SCOPE)
# --edts:db
cogeno_get_property(edts_db EDTS_DB)
if(DEFINED edts_db)
set(cogeno_opt_edts_db "--edts:db" "${edts_db}")
else()
set(cogeno_opt_edts_db)
endif()
set(cogeno_opt_edts_db ${cogeno_opt_edts_db} PARENT_SCOPE)
# --protobuf:db-dir
cogeno_get_property(protobuf_db_dir PROTOBUF_DB_DIR)
if(DEFINED protobuf_db_dir)
set(cogeno_opt_protobuf_db_dir "--protobuf:db-dir" "${protobuf_db_dir}")
else()
set(cogeno_opt_protobuf_db_dir)
endif()
set(cogeno_opt_protobuf_db_dir ${cogeno_opt_protobuf_db_dir} PARENT_SCOPE)
# Search for protobuf dependencies
set(args_protobuf_sources)
set(args_protobuf_include_dirs)
foreach(depend ${args_depends})
if(TARGET ${depend})
continue()
endif()
# Find path of dependency
if(NOT IS_ABSOLUTE ${depend})
# relative path - use whole relative path
set(depend ${CMAKE_CURRENT_SOURCE_DIR}/${depend})
endif()
if(IS_DIRECTORY "${depend}")
FILE(GLOB protos LIST_DIRECTORIES false "${depend}/*.proto")
if(protos)
list(APPEND args_protobuf_include_dirs ${depend})
endif()
else()
get_filename_component(depend_ext ${depend} EXT)
if("${depend_ext}" STREQUAL ".proto")
list(APPEND args_protobuf_sources ${depend})
get_filename_component(depend_dir ${depend} DIRECTORY)
list(APPEND args_protobuf_include_dirs ${depend_dir})
endif()
endif()
endforeach()
# --protobuf:include-dirs
cogeno_get_property(protobuf_include_dirs PROTOBUF_INCLUDE_DIRS)
if(NOT DEFINED protobuf_include_dirs)
set(protobuf_include_dirs ${args_protobuf_include_dirs})
else()
set(protobuf_include_dirs ${protobuf_include_dirs} ${args_protobuf_include_dirs})
endif()
if(protobuf_include_dirs)
set(cogeno_opt_protobuf_include_dirs "--protobuf:include-dirs" ${protobuf_include_dirs})
else()
set(cogeno_opt_protobuf_include_dirs)
endif()
set(cogeno_opt_protobuf_include_dirs ${cogeno_opt_protobuf_include_dirs} PARENT_SCOPE)
# --protobuf:sources
cogeno_get_property(protobuf_sources PROTOBUF_SOURCES)
if(NOT DEFINED protobuf_sources)
set(protobuf_sources ${args_protobuf_sources})
else()
set(protobuf_sources ${protobuf_sources} ${args_protobuf_sources})
endif()
if(protobuf_sources)
set(cogeno_opt_protobuf_sources "--protobuf:sources" ${protobuf_sources})
else()
set(cogeno_opt_protobuf_sources)
endif()
set(cogeno_opt_protobuf_sources ${cogeno_opt_protobuf_sources} PARENT_SCOPE)
endfunction()
# Get all the files that make up cogeno for dependency reasons.
#file(GLOB_RECURSE cogeno_sources LIST_DIRECTORIES false
# ${COGENO_BASE}/cogeno/*.py
# ${COGENO_BASE}/cogeno/*.yaml
# ${COGENO_BASE}/cogeno/*.c
# ${COGENO_BASE}/cogeno/*.jinja2)
function(cogeno_sources
target # The CMake target that depends on the generated file
)
# Prepare arguments
set(options EXTERN DELETE_CODE)
set(oneValueArgs SOURCE_DIR INCLUDE_DIR TXTFILE_DIR)
set(multiValueArgs INCLUDES TXTFILES COGENO_DEFINES DEPENDS)
cmake_parse_arguments(SOURCES "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
# Prepare all options
cogeno_set_options("${SOURCES_SOURCE_DIR}" "${SOURCES_INCLUDE_DIR}" "${SOURCES_TXTFILE_DIR}"
"${SOURCES_DELETE_CODE}" "${SOURCES_COGENO_DEFINES}" "${SOURCES_DEPENDS}")
message(STATUS "Cogeno will generate for target ${target}")
set(include_file FALSE)
set(text_file FALSE)
foreach(arg ${SOURCES_UNPARSED_ARGUMENTS} "!includes!" ${SOURCES_INCLUDES} "!txtfiles!" ${SOURCES_TXTFILES})
if("${arg}" STREQUAL "!includes!")
# We are now processing include files
set(text_file FALSE)
set(include_file TRUE)
continue()
endif()
if("${arg}" STREQUAL "!txtfiles!")
# We are now processing text files
set(text_file TRUE)
set(include_file FALSE)
continue()
endif()
get_filename_component(generated_file_name ${arg} NAME)
# Find path for generated file
if(${include_file})
# This is an include file - we got an output directory for include files
# -> put into include directory
set(generated_file ${cogeno_opt_include_dir}/${generated_file_name})
set(generated_dir ${cogeno_opt_include_dir})
elseif(${text_file})
# This is a text file - we got an output directory for text files
# -> put into txtfiles directory
set(generated_file ${cogeno_opt_txtfile_dir}/${generated_file_name})
set(generated_dir ${cogeno_opt_txtfile_dir})
else()
# This is a source file - we got an output directory for source files
# -> put into source directory but take care that
# compilable source files must be generated to the current binary directory.
# Otherwise this would trigger CMake issue #14633:
# https://gitlab.kitware.com/cmake/cmake/issues/14633
get_filename_component(generated_ext ${generated_file_name} EXT)
if(("${generated_ext}" STREQUAL ".c"
OR "${generated_ext}" STREQUAL ".cpp")
AND NOT "${cogeno_opt_source_dir}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
message(WARNING "Compilable source ${arg} generated to non CMAKE_CURRENT_BINARY_DIR (${cogeno_opt_source_dir})")
endif()
set(generated_file ${cogeno_opt_source_dir}/${generated_file_name})
set(generated_dir ${cogeno_opt_source_dir})
endif()
# Find path of template file
if(IS_ABSOLUTE ${arg})
set(template_file ${arg})
else()
# relative path - use whole relative path
set(template_file ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
endif()
get_filename_component(template_dir ${template_file} DIRECTORY)
if(IS_DIRECTORY ${template_file})
message(FATAL_ERROR "cogeno_sources() was called on a directory")
endif()
# Remove common template extensions from generated file name
get_filename_component(generated_ext ${generated_file} EXT)
get_filename_component(generated_name_we ${generated_file} NAME_WE)
foreach(gen_ext ".in" ".cogeno" ".py" ".jinja")
foreach(ext ".h" ".hpp" ".c" ".cpp" ".html" ".txt" ".rst" ".md")
if("${generated_ext}" STREQUAL "${gen_ext}${ext}")
set(generated_file "${generated_dir}/${generated_name_we}${ext}")
set(generated_ext ${ext})
break()
endif()
endforeach()
endforeach()
# Generate file from template
message(STATUS " from '${template_file}'")
message(STATUS " to '${generated_file}'")
add_custom_command(
COMMENT "cogeno ${generated_file}"
OUTPUT ${generated_file}
MAIN_DEPENDENCY ${template_file}
DEPENDS
"${cogeno_opt_base}/cogeno/cogeno.py"
${cogeno_opt_depends}
COMMAND
${cogeno_opt_executable}
${cogeno_opt_executable_args}
${cogeno_opt_defines}
${cogeno_opt_delete_code}
${cogeno_opt_extensions}
${cogeno_opt_cmake_defines}
${cogeno_opt_cmake_cache}
${cogeno_opt_config_db}
${cogeno_opt_config_file}
${cogeno_opt_config_inputs}
${cogeno_opt_config_kconfig_file}
${cogeno_opt_config_kconfig_srctree}
${cogeno_opt_config_kconfig_defines}
${cogeno_opt_edts_bindings_dirs}
${cogeno_opt_edts_bindings_exclude}
${cogeno_opt_edts_bindings_no_default}
${cogeno_opt_edts_db}
${cogeno_opt_edts_dts}
${cogeno_opt_edts_dts_pp_defines}
${cogeno_opt_edts_dts_pp_sources}
${cogeno_opt_edts_dts_pp_include_dirs}
${cogeno_opt_protobuf_db_dir}
${cogeno_opt_protobuf_include_dirs}
${cogeno_opt_protobuf_sources}
${cogeno_opt_modules}
${cogeno_opt_templates}
${cogeno_opt_log}
${cogeno_opt_lock}
--input "${template_file}"
--output "${generated_file}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set_source_files_properties(${generated_file} PROPERTIES GENERATED 1)
# 1) Add generated files to target component.
# 2) Add template directory to include path to allow includes with
# relative path in generated file to work
# 3) Add directory of generated file to include path to allow includes
# of generated header file with relative path.
#
# Standard way to add to target is using CMake target_sources() and
# target_include_directories().
#
# Some platforms need a different strategy to achieve the above 1,2,3.
if(DEFINED ESP_PLATFORM AND ESP_PLATFORM AND "${target}" STREQUAL "${COMPONENT_NAME}")
# ESP platforms use idf_component_register
cogeno_get_property(component_name COMPONENT_NAME)
if(NOT "${component_name}" STREQUAL "${COMPONENT_NAME}")
# We are working on a new component - assure everything is prepared
cogeno_set_property(COMPONENT_SRCS "")
cogeno_set_property(COMPONENT_INCLUDE_DIRS "")
cogeno_set_property(COMPONENT_NAME "${COMPONENT_NAME}")
endif()
if(${include_file})
cogeno_set_property(COMPONENT_INCLUDE_DIRS ${generated_dir} APPEND)
# We add include file to SRCS to get a dependency
cogeno_set_property(COMPONENT_SRCS ${generated_file} APPEND)
else()
cogeno_set_property(COMPONENT_SRCS ${generated_file} APPEND)
endif()
cogeno_set_property(COMPONENT_INCLUDE_DIRS ${template_dir} APPEND)
# Return the values to be used by idf_component_register
cogeno_get_property(component_srcs COMPONENT_SRCS)
set(COGENO_COMPONENT_SRCS ${component_srcs} PARENT_SCOPE)
cogeno_get_property(component_include_dirs COMPONENT_INCLUDE_DIRS)
list(REMOVE_DUPLICATES component_include_dirs)
set(COGENO_COMPONENT_INCLUDE_DIRS ${component_include_dirs} PARENT_SCOPE)
else()
if(${SOURCES_EXTERN} OR ${text_file})
# EXTERN:
# We are adding to a target that was not created in the same CMakelLists.txt file.
# - The generated property is not visible to the target in this case.
# - The generated file has to be generated first because of that. target_sources
# expects a file in this case.
# - A dependency has to be added to assure the generated file is build
# before the target
# TXTFILE:
# Usually text files are added to custom targets.
# - A dependency has to be added to assure the generated file is build
# before the (custom) target
cogeno_unique_target_name_from_filename(${generated_file} generated_target_name)
add_custom_target(${generated_target_name} ALL DEPENDS ${generated_file})
add_dependencies(${target} ${generated_target_name})
if(NOT ${include_file} AND NOT ${text_file})
# We are adding a source file
# Assure the ouput directory exists
file(MAKE_DIRECTORY ${generated_dir})
# Generate the file - add_custom_target will always force (re-)generation
file(TOUCH ${generated_file})
endif()
endif()
if(${include_file})
# Add output directory for generated file to include path to allow includes
# of generated header file with relative path.
target_include_directories(${target} SYSTEM BEFORE INTERFACE ${generated_dir})
elseif(${text_file})
# Nothing to do
else()
target_sources(${target} PRIVATE ${generated_file})
endif()
# Add template directory to include path to allow includes with
# relative path in generated file to work
if(${include_file})
# target maybe interface only target
target_include_directories(${target} PRIVATE INTERFACE ${template_dir})
elseif(${text_file})
# Nothing to do
else()
target_include_directories(${target} PRIVATE ${template_dir})
endif()
endif()
endforeach()
endfunction()
# Assure cogeno is available
# --------------------------
FindCogeno()
if(NOT Cogeno_FOUND)
message(FATAL "Cogeno not found")
endif()
# This is a Zephyr project.
# -------------------------
if(DEFINED ZEPHYR_BASE AND EXISTS "${ZEPHYR_BASE}")
message(STATUS "Cogeno added to Zephyr")
function(zephyr_sources_cogeno)
cogeno_sources(zephyr EXTERN ${ARGN})
endfunction()
function(zephyr_sources_cogeno_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_sources_cogeno(${ARGN})
endif()
endfunction()
function(zephyr_library_sources_cogeno)
cogeno_sources(${ZEPHYR_CURRENT_LIBRARY} EXTERN ${ARGN})
endfunction()
function(zephyr_library_sources_cogeno_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_library_sources_cogeno(${ARGN})
endif()
endfunction()
function(zephyr_library_includes_cogeno)
cogeno_sources(zephyr_interface EXTERN INCLUDES ${ARGN}
INCLUDE_DIR "${CMAKE_BINARY_DIR}/zephyr/include/generated")
endfunction()
function(zephyr_library_includes_cogeno_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_library_includes_cogeno(${ARGN})
endif()
endfunction()
# Add include directory to the directories scanned for syscall include files
# - workaround
macro(zephyr_syscall_include_dirs)
foreach(dir ${ARGN})
get_filename_component(dir "${dir}" REALPATH)
if(${dir} IN_LIST SYSCALL_INCLUDE_DIRS)
continue()
endif()
list(APPEND SYSCALL_INCLUDE_DIRS ${dir})
endforeach()
SET(SYSCALL_INCLUDE_DIRS "${SYSCALL_INCLUDE_DIRS}" CACHE INTERNAL "SYSCALL_INCLUDE_DIRS")
endmacro()
# This is an ESP IDF project
# --------------------------
elseif(DEFINED ESP_PLATFORM AND ESP_PLATFORM)
message(STATUS "Cogeno added to ESP platform")
# Could not identify the type of project
# --------------------------------------
else()
message(STATUS "Cogeno added to unknown platform")
endif()
Development¶
Code generation principle¶
How code generation works with cogeno.
Cogeno API¶
cogeno is a Python module that provides access to the public functions
of the class: CodeGenerator
and the sub-classes of it. See
Code generation functions for a description of all cogeno
module’s functions.
The interfaces listed hereafter are the internal interfaces of Cogeno.
The Cogeno CodeGenerator
is made of a set of Mixin
classes that
bundle specific generator functionality. The CodeGenerator
stores it´s
states in Context
class objects.
CodeGenerator
¶
-
cogeno.generator.CodeGenerator : public cogeno.context.ContextMixin , public cogeno.options.OptionsMixin , public cogeno.lock.LockMixin , public cogeno.inlinegen.InlineGenMixin , public cogeno.pygen.PyGenMixin , public cogeno.jinja2gen.Jinja2GenMixin , public cogeno.paths.PathsMixin , public cogeno.stdmodules.StdModulesMixin , public cogeno.include.IncludeMixin , public cogeno.log.LogMixin , public cogeno.error.ErrorMixin , public cogeno.output.OutputMixin , public cogeno.importmodule.ImportMixin , public cogeno.redirectable.RedirectableMixin
The CodeGenerator
class includes (sub-classes) several mixin
classes:
ContextMixin
¶
-
cogeno.context.ContextMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
context
(self)¶ Get actual code generation context.
- Return
context
-
context_enter
(self, context)¶ Switch to new code generation context.
- Parameters
The
: new context
-
context_exit
(self)¶ Switch back from code generation context.
Write to output file in case we are leaving the top level context.
- Return
the outstring of the context just left
-
context_out
(self, text)¶ Output text to current context.
- Parameters
text
: Text string
-
ErrorMixin
¶
-
cogeno.error.ErrorMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
error
(self, msg='Error raised by cogeno generator.', frame_index=0, lineno=0)¶ Raise Error exception.
Extra information is added that maps the python snippet line seen by the Python interpreter to the line of the file that inlines the python snippet.
- Parameters
msg
: [optional] exception messageframe_index
: [optional] Call frame index. The call frame offset of the function calling error(). Zero if directly called in a snippet. Add one for every level of function call.lineno
: [optional] line number within template
-
ImportMixin
¶
-
cogeno.importmodule.ImportMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
import_module
(self, name)¶ Import a Cogeno module.
Import a module.
Module file is searched in current directory or modules directories.
- Parameters
name
: Module to import. Specified without any path.
-
import_extensions
(self, extensions_paths, update=False)¶ Import extension modules.
Extension paths are searched for extension modules.
- Parameters
extensions_paths
: Directory paths for extensionsupdate
: Optional, on true the modules are reloaded if already loaded
-
import_extensions_from_option
(self, update=False)¶ Import extension modules given in extension:paths option.
Extension paths are searched for extension modules. Thes modules are imported. As modules may update the option in itself the import is done recursively.
- Parameters
update
: Optional, on true the modules are reloaded if already loaded
-
IncludeMixin
¶
-
cogeno.include.IncludeMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
out_include
(self, include_file)¶ Write the text from include_file to the output.
The
include_file
is processed by cogeno. Inline code generation ininclude_file
can access the globals defined in theincluding source file
before inclusion. Theincluding source file
can access the globals defined in theinclude_file
(after inclusion).- Parameters
include_file
: Path of include file, either absolute path or relative to current directory or relative to templates directory (e.g. ‘templates/drivers/simple_tmpl.c’)
-
guard_include
(self)¶ Prevent the current file to be included by
cogeno.out_include()
when called the next time.
-
InlineGenMixin
¶
-
cogeno.inlinegen.InlineGenMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Jinja2GenMixin
¶
-
cogeno.jinja2gen.Jinja2GenMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
render
(self, template_spec, data=None)¶ Render a Ninja2 template.
- Parameters
template_spec
:data
:
-
LockMixin
¶
-
cogeno.lock.LockMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
lock_file
(self)¶ Lock file used for the current context.
- Return
lock file name
-
lock
(self)¶ Get the global cogeno lock.
try: with cogeno.lock().acquire(timeout = 10): ... except cogeno.lock_timeout(): cogeno.error(...) except: raise
- Return
Lock object
-
lock_timeout
(self)¶ Lock timeout.
- Return
Lock timeout object
-
LogMixin
¶
-
cogeno.log.LogMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
log
(self, message, message_type=None, end="\, logonly=True)¶ Print message and write to log file.
- Parameters
message
: Messagemessage_type
: If given will be prepended to the messageend
: Character to put at the end of the message. ‘\n’ by default.logonly
: Only write to logfile. True by default.
-
msg
(self, message)¶ Print message to stdout and log with a “message: ” prefix.
- See
- Parameters
message
: Message
-
warning
(self, message)¶ Print message to stdout and log with a “warning: ” prefix.
- See
- Parameters
message
: Message
-
prout
(self, message, end="\)¶ Print message to stdout and log.
- See
- Parameters
message
: Messageend
: Character to put at the end of the message. ‘\n’ by default.
-
prerr
(self, message, end="\)¶ Print message to stderr and log with a “error: ” prefix.
- See
- Parameters
message
: Messageend
: Character to put at the end of the message. ‘\n’ by default.
-
OptionsMixin
¶
-
cogeno.options.OptionsMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
option
(self, name)¶ Get option of actual context.
- Return
option value
- Parameters
name
: Name of option
-
options_add_argument
(self, args, kwargs)¶ Add option arguments to option parser of actual context.
Cogeno modules may add arguments to the cogeno option parser. The argument variables given to cogeno are rescanned after new option arguments are provided.
def mymodule(cogeno): if not hasattr(cogeno, '_mymodule'): cogeno._mymodule = None cogeno.options_add_argument('-m', '--mymodule', metavar='FILE', dest='mymodule_file', action='store', type=lambda x: cogeno.option_is_valid_file(x), help='Load mymodule data from FILE.') if getattr(cogeno, '_mymodule') is not None: return cogeno._mymodule if cogeno.option('mymodule_file'): mymodule_file = cogeno.option('mymodule_file') else: cogeno.error(..., 2) ... cogeno._mymodule = ...
-
option_is_valid_file
(self, filepath)¶
-
option_is_valid_directory
(self, directorypath)¶
-
options_argv_append
(self, args)¶
-
OutputMixin
¶
-
cogeno.output.OutputMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
out
(self, args)¶ Write text to the output.
The string arguments are concenated. The filters are then applied to the lines of the concenated string. The resulting string is written to the output.
OutputFilterDedent
andOutputFilterTrimBlankLines
make it easier to use multi-line strings, and they are only are useful for multi-line strings:cogeno.out(""" These are lines I want to write into my source file. """, cogeno.OutputFilterDedent(), cogeno.OutputFilterTrimBlankLines())
- Return
output string
- Parameters
*args
: Variable length argument list of strings and output filters.
-
outl
(self, args)¶ Write text to the output with newline appended.
- See
OutputMixin::out(self, *args)
- Return
output string
- Parameters
*args
: Variable length argument list of strings and output filters.
-
out_insert
(self, insert_file, args)¶ Insert the text from the file into the output.
- See
OutputMixin::out(self, *args)
- Return
output string
- Parameters
insert_file
: Path of file, either absolute path or relative to current directory or relative to templates directory.*args
: Variable length argument list of strings and output filters.
-
class
cogeno.
OutputFilter
¶ Subclassed by cogeno.output.OutputMixin.OutputFilterDedent, cogeno.output.OutputMixin.OutputFilterLineNumbers, cogeno.output.OutputMixin.OutputFilterReplace, cogeno.output.OutputMixin.OutputFilterReSub, cogeno.output.OutputMixin.OutputFilterStartAt, cogeno.output.OutputMixin.OutputFilterStopAt, cogeno.output.OutputMixin.OutputFilterTemplateSubstitude, cogeno.output.OutputMixin.OutputFilterTrimBlankLines
Public Functions
-
__call__
(self, line, lineno=None, lines=None)¶ Apply filter.
- Return
line with filter applied. Maybe None in case the line is deleted
- Parameters
line
: line to apply filter tolineno
: line number - starts at 1lines
: all lines
-
parselinenos
(self, spec, total)¶ Parse a line number spec.
- Return
A list of wanted line numbers (line numbers start at 1).
- Parameters
spec
: Line number spec (such as “1,2,4-6”)total
: Total number of lines
-
-
OutputFilterDedent : public cogeno.output.OutputMixin.OutputFilter
Remove common initial white space from the lines.
- Parameters
new_indent
: Optional new indentation (after dedent)
-
OutputFilterLineNumbers : public cogeno.output.OutputMixin.OutputFilter
Filter lines by line numbers.
Filter lines that are given by line sumber specifications (such as “1,2,4-6”).
- Parameters
args
: list of arguments denoting line number specifications
-
OutputFilterReplace : public cogeno.output.OutputMixin.OutputFilter
Replace substring.
- Parameters
old
: old substring to replacenew
: new substring which will replace the old substring. if new is None and the resulting line is empty it is deleted.count
: (optional) the number of times to replace the old substring with the new substring
-
OutputFilterReSub : public cogeno.output.OutputMixin.OutputFilter
Substitude regular expression pattern.
Replace the leftmost non-overlapping occurrences of pattern in each line by the replacement repl.
- Parameters
pattern
: Pattern for replacement. Pattern is a string that will be compiled to a pattern object.repl
: Replacement. Repl can be a string or a function. If repl is a function, it is called for every non-overlapping occurrence of pattern.count
: (optional) maximum number of pattern occurrences to be replaced
-
OutputFilterStartAt : public cogeno.output.OutputMixin.OutputFilter
Start output at pattern.
- Parameters
start_at
: Start pattern
-
OutputFilterStopAt : public cogeno.output.OutputMixin.OutputFilter
Stop output at pattern.
- Parameters
stop_at
: Stop pattern
-
OutputFilterTemplateSubstitude : public cogeno.output.OutputMixin.OutputFilter
Substitude template placeholders.
Template placeholder substitution supports $-based substitutions, using the following rules:
$$ is an escape; it is replaced with a single $.
$identifier names a substitution placeholder matching a mapping key of “identifier”. By default, “identifier” is restricted to any case-insensitive ASCII alphanumeric string (including underscores) that starts with an underscore or ASCII letter. The first non-identifier character after the $ character terminates this placeholder specification.
${identifier} is equivalent to $identifier. It is required when valid identifier characters follow the placeholder but are not part of the placeholder, such as “${noun}ification”.
At least up to 4 nesting levels of placeholders are substituded, e.g.:
${placeholder_level1} : mapping = ‘placeholder_level1’ : ‘holder’
${place${placeholder_level1}_level2} : mapping = ‘placeholder_level2’ : ‘placeholder’
${${placeholder_level2}_level3} : mapping = ‘placeholder_level3’ : ‘placeholder_level’
${${placeholder_level3}4} : mapping = ‘placeholder_level4’ : ‘success’
If more than one placeholder patterns are provided the substitution is done for each pattern sequencing through the patterns list.
- Parameters
mapping
: Mapping is any dictionary-like object with keys that match the template placeholders.patterns
: (optional) Patterns is a list of regular expressions describing the pattern for non-braced placeholders.
Public Functions
-
__init__
(self, mapping, patterns=['[_a-zA-Z][_a-zA-Z0-9] *'])¶
-
__call__
(self, line, lineno=None, lines=None)¶
Public Static Attributes
-
templates_classes
= {}¶
-
OutputFilterTrimBlankLines : public cogeno.output.OutputMixin.OutputFilter
Remove initial and trailing blank lines from the block of lines.
-
PathsMixin
¶
-
cogeno.paths.PathsMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
modules_paths_append
(self, path)¶
-
modules_paths
(self)¶
-
templates_paths_append
(self, path)¶
-
templates_paths
(self)¶
-
template_path
(self)¶
Public Static Functions
-
path_walk
(top, topdown=False, followlinks=False)¶ Walk directory tree.
For each directory in the tree rooted at directory top (including top itself), it yields a 3-tuple (dirpath, dirnames, filenames):
dirpath: the path to the directory.
dirnames: list of the paths of the subdirectories in dirpath
filenames: list of the paths of the non-directory files in dirpath
See Python docs for os.walk, exact same behavior but it yields Path() instances instead. From: http://ominian.com/2016/03/29/os-walk-for-pathlib-path/
- Return
yields a 3-tuple (dirpath, dirpathes, filepathes)
- Parameters
top
: root of directory treetopdown
: if topdown is True, the triple for a directory is generated before the triples for any of its subdirectories (directories are generated top-down). If topdown is False, the triple for a directory is generated after the triples for all of its subdirectories (directories are generated bottom-up).followlinks
:
-
rmtree
(top)¶ Delete an entire directory tree.
- Parameters
top
: root of directory tree
-
find_template_files
(top, marker, suffix='.c')¶ Find template files.
- Return
List of template file pathes
- Parameters
marker
: Marker as b’my-marker’suffix
:
-
cogeno_path
()¶
-
find_file_path
(file_name, paths)¶
-
PyGenMixin
¶
-
cogeno.pygen.PyGenMixin : public object
Subclassed by cogeno.generator.CodeGenerator
RedirectableMixin
¶
-
cogeno.redirectable.RedirectableMixin : public object
Subclassed by cogeno.generator.CodeGenerator, cogeno.redirectable.Redirectable
Public Functions
-
set_standard_streams
(self, stdout=None, stderr=None)¶ Redirect status and error reporting.
Assign new files for standard out and/or standard error.
- Parameters
stdout
:stderr
:
-
StdModulesMixin
¶
-
cogeno.stdmodules.StdModulesMixin : public object
Subclassed by cogeno.generator.CodeGenerator
Public Functions
-
edts
(self, force_extract=False)¶ Get the extended device tree database.
- Return
Extended device tree database.
-
cmake
(self)¶ Get the cmake variables database.
- Return
CMake variables database.
-
cmake_variable
(self, variable_name, default='<unset>')¶ Get the value of a CMake variable.
If variable_name is not provided to cogeno by CMake the default value is returned.
A typical set of CMake variables that are not available in the
CMakeCache.txt
file and have to be provided as defines to cogeno if needed:“PROJECT_NAME”
”PROJECT_SOURCE_DIR”
”PROJECT_BINARY_DIR”
”CMAKE_SOURCE_DIR”
”CMAKE_BINARY_DIR”
”CMAKE_CURRENT_SOURCE_DIR”
”CMAKE_CURRENT_BINARY_DIR”
”CMAKE_CURRENT_LIST_DIR”
”CMAKE_FILES_DIRECTORY”
”CMAKE_PROJECT_NAME”
”CMAKE_SYSTEM”
”CMAKE_SYSTEM_NAME”
”CMAKE_SYSTEM_VERSION”
”CMAKE_SYSTEM_PROCESSOR”
”CMAKE_C_COMPILER”
”CMAKE_CXX_COMPILER”
”CMAKE_COMPILER_IS_GNUCC”
”CMAKE_COMPILER_IS_GNUCXX”
- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
-
cmake_cache_variable
(self, variable_name, default='<unset>')¶ Get the value of a CMake variable from CMakeCache.txt.
If variable_name is not given in
CMakeCache.txt
the default value is returned.- Return
value
- Parameters
variable_name
: Name of the CMake variabledefault
: Default value
-
configs
(self, force_extract=False)¶ Get the configuration variables database.
- Return
Configuration variables database.
-
config_properties
(self)¶ Get all config properties.
The property names are the ones config file.
- Return
A dictionary of config properties.
-
config_property
(self, property_name, default='<unset>')¶ Get the value of a configuration property fromthe config file.
If property_name is not given in .config the default value is returned.
- Return
property value
- Parameters
property_name
: Name of the propertydefault
: Property value to return per default.
-
Context
¶
-
cogeno.context.Context : public object
Context for code generation.
Public Functions
-
__init__
(self, generator, parent_context=None, generation_globals=None, options=None, eval_begin=None, eval_end=None, eval_adjust=None, delete_code=None, template_file=None, template=None, template_source_type=None, script_type=None, template_tabsize=None, templates_paths=None, modules_paths=None, jinja2_environment=None, output_file=None, log_file=None, lock_file=None)¶ Initialise context object.
-
__str__
(self)¶
-
__repr__
(self)¶
-
parent
(self)¶
-
generation_globals
(self)¶
-
script_is_inline
(self)¶
-
script_is_python
(self)¶
-
script_is_jinja2
(self)¶
-
script_type
(self)¶
-
template_is_snippet
(self)¶ Template is a snippet.
Snippets are parts of the template of the parent context.
- Return
True in case the template is a snippet, False otherwise.
-
template_is_file
(self)¶
-
template_is_string
(self)¶
-
options
(self)¶ Options.
-
out
(self, line)¶ Add line.
-
outl
(self, line)¶ Add line with newline.
-
Frequently asked questions¶
TBD