Introduction¶
Zephyr from SWARCO is the ultimate sign and parking management system. Zephyr is a user-friendly web-based management system designed specifically to manage full colour matrix signs, car parking systems and warning systems enabling you to create, upload and schedule text and graphical messages. Zephyr 3 Base Antenna Zephyr 3 Rover Antenna Zephyr 3 Rugged Antenna Zephyr™ Geodetic Antennas 5.2XL Point and CrossLine Laser 500/500C Spectra Precision™ Laser 1000 Spectra Precision™ Laser 1242 Spectra Precision™ Laser 1422 Spectra Precision™ Laser 3300 Total Station Series 3600 Total Station Series 4000 series 4400 4600 4600 LS.
The Zephyr kernel supports a variety of device drivers. Whether adriver is available depends on the board and the driver.
The Zephyr device model provides a consistent device model for configuring thedrivers that are part of a system. The device model is responsiblefor initializing all the drivers configured into the system.
Each type of driver (e.g. UART, SPI, I2C) is supported by a generic type API.
In this model the driver fills in the pointer to the structure containing thefunction pointers to its API functions during driver initialization. Thesestructures are placed into the RAM section in initialization level order.
Standard Drivers¶
Device drivers which are present on all supported board configurationsare listed below.
Interrupt controller: This device driver is used by the kernel’sinterrupt management subsystem.
Timer: This device driver is used by the kernel’s system clock andhardware clock subsystem.
Serial communication: This device driver is used by the kernel’ssystem console subsystem.
Random number generator: This device driver provides a source of randomnumbers.
Important
Certain implementations of the random number generator device driverdo not generate sequences of values that are truly random.
Synchronous Calls¶
Zephyr provides a set of device drivers for multiple boards. Each drivershould support an interrupt-based implementation, rather than polling, unlessthe specific hardware does not provide any interrupt.
High-level calls accessed through device-specific APIs, such asi2c.h
or spi.h
, are usually intended as synchronous. Thus,these calls should be blocking.
Driver APIs¶
The following APIs for device drivers are provided by device.h
. The APIsare intended for use in device drivers only and should not be used inapplications.
DEVICE_INIT()
- create device object and set it up for boot time initialization.
DEVICE_AND_API_INIT()
- Create device object and set it up for boot time initialization.This also takes a pointer to driver API struct for link timepointer assignment.
DEVICE_NAME_GET()
- Expands to the full name of a global device object.
DEVICE_GET()
- Obtain a pointer to a device object by name.
DEVICE_DECLARE()
- Declare a device object.
Driver Data Structures¶
The device initialization macros populate some data structures at build timewhich aresplit into read-only and runtime-mutable parts. At a high level we have:
The config
member is for read-only configuration data set at build time. Forexample, base memory mapped IO addresses, IRQ line numbers, or other fixedphysical characteristics of the device. This is the config_info
structurepassed to the DEVICE_*INIT()
macros.
The driver_data
struct is kept in RAM, and is used by the driver forper-instance runtime housekeeping. For example, it may contain reference counts,semaphores, scratch buffers, etc.
The driver_api
struct maps generic subsystem APIs to the device-specificimplementations in the driver. It is typically read-only and populated atbuild time. The next section describes this in more detail.
Subsystems and API Structures¶
Most drivers will be implementing a device-independent subsystem API.Applications can simply program to that generic API, and applicationcode is not specific to any particular driver implementation.
A subsystem API definition typically looks like this:
A driver implementing a particular subsystem will define the real implementationof these APIs, and populate an instance of subsystem_api structure:
The driver would then pass my_driver_api_funcs
as the api
argument toDEVICE_AND_API_INIT()
, or manually assign it to device->driver_api
in the driver init function.
Note
Since pointers to the API functions are referenced in the driver_api
struct, they will always be included in the binary even if unused;gc-sections
linker option will always see at least one reference tothem. Providing for link-time size optimizations with driver APIs inmost cases requires that the optional feature be controlled by aKconfig option.
Device-Specific API Extensions¶
Zephyr Driver
Some devices can be cast as an instance of a driver subsystem such as GPIO,but provide additional functionality that cannot be exposed through thestandard API. These devices combine subsystem operations withdevice-specific APIs, described in a device-specific header.
A device-specific API definition typically looks like this:
A driver implementing extensions to the subsystem will define the realimplementation of both the subsystem API and the specific APIs:
Applications use the device through both the subsystem and specificAPIs. The subsystem APIs will directly access the subsystem part of thespecific API structure.
Single Driver, Multiple Instances¶
Some drivers may be instantiated multiple times in a given system. For examplethere can be multiple GPIO banks, or multiple UARTS. Each instance of the driverwill have a different config_info
struct and driver_data
struct.
Configuring interrupts for multiple drivers instances is a special case. If eachinstance needs to configure a different interrupt line, this can be accomplishedthrough the use of per-instance configuration functions, since the parametersto IRQ_CONNECT()
need to be resolvable at build time.
For example, let’s say we need to configure two instances of my_driver
, eachwith a different interrupt line. In drivers/subsystem/subsystem_my_driver.h
:
In the implementation of the common init function:
Then when the particular instance is declared:
Note the use of DEVICE_DECLARE()
to avoid a circular dependency on providingthe IRQ handler argument and the definition of the device itself.
Initialization Levels¶
Drivers may depend on other drivers being initialized first, orrequire the use of kernel services. The DEVICE_INIT() APIs allow the user tospecify at what time during the boot sequence the init function will beexecuted. Any driver will specify one of four initialization levels:
PRE_KERNEL_1
- Used for devices that have no dependencies, such as those that relysolely on hardware present in the processor/SOC. These devices cannotuse any kernel services during configuration, since the kernel services arenot yet available. The interrupt subsystem will be configured howeverso it’s OK to set up interrupts. Init functions at this level run on theinterrupt stack.
PRE_KERNEL_2
- Used for devices that rely on the initialization of devices initializedas part of the
PRE_KERNEL_1
level. These devices cannot use any kernelservices during configuration, since the kernel services are not yetavailable. Init functions at this level run on the interrupt stack. POST_KERNEL
- Used for devices that require kernel services during configuration.Init functions at this level run in context of the kernel main task.
APPLICATION
- Used for application components (i.e. non-kernel components) that needautomatic configuration. These devices can use all services provided bythe kernel during configuration. Init functions at this level run onthe kernel main task.
Within each initialization level you may specify a priority level, relative toother devices in the same initialization level. The priority level is specifiedas an integer value in the range 0 to 99; lower values indicate earlierinitialization. The priority level must be a decimal integer literal withoutleading zeroes or sign (e.g. 32), or an equivalent symbolic name (e.g.#defineMY_INIT_PRIO32
); symbolic expressions are not permitted (e.g.CONFIG_KERNEL_INIT_PRIORITY_DEFAULT+5
).
System Drivers¶
In some cases you may just need to run a function at boot. Special SYS_*
macros exist that map to DEVICE_*INIT()
calls.For SYS_INIT()
there are no config or runtime data structures and thereisn’t a wayto later get a device pointer by name. The same policies for initializationlevel and priority apply.
For SYS_DEVICE_DEFINE()
you can obtain pointers by name, seepower management section.
SYS_INIT()
SYS_DEVICE_DEFINE()
Error handling¶
In general, it’s best to use __ASSERT()
macros instead ofpropagating return values unless the failure is expected to occurduring the normal course of operation (such as a storage devicefull). Bad parameters, programming errors, consistency checks,pathological/unrecoverable failures, etc., should be handled byassertions.
When it is appropriate to return error conditions for the caller tocheck, 0 should be returned on success and a POSIX errno.h
codereturned on failure. Seehttps://github.com/zephyrproject-rtos/zephyr/wiki/Naming-Conventions#return-codesfor details about this.
API Reference¶
device_model
Device Model APIs.
Defines
DEVICE_INIT
(dev_name, drv_name, init_fn, data, cfg_info, level, prio)¶Create device object and set it up for boot time initialization.
This macro defines a device object that is automatically configured by the kernel during system initialization. Note that devices set up with this macro will not be accessible from user mode since the API is not specified; whenever possible, use DEVICE_AND_API_INIT instead.
dev_name
: Device name. This must be less than Z_DEVICE_MAX_NAME_LEN characters in order to be looked up from user mode with device_get_binding().drv_name
: The name this instance of the driver exposes to the system.init_fn
: Address to the init function of the driver.data
: Pointer to the device’s configuration data.cfg_info
: The address to the structure containing the configuration information for this instance of the driver.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.
- 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.
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); symbolic expressions are not permitted (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).
DEVICE_AND_API_INIT
(dev_name, drv_name, init_fn, data, cfg_info, level, prio, api)¶Create device object and set it up for boot time initialization, with the option to set driver_api.
This macro defines a device object that is automatically configured by the kernel during system initialization. Note that devices set up with this macro will not be accessible from user mode since the API is not specified; whenever possible, use DEVICE_AND_API_INIT instead.
The driver api is also set here, eliminating the need to do that during initialization.
dev_name
: Device name. This must be less than Z_DEVICE_MAX_NAME_LEN characters in order to be looked up from user mode with device_get_binding().drv_name
: The name this instance of the driver exposes to the system.init_fn
: Address to the init function of the driver.data
: Pointer to the device’s configuration data.cfg_info
: The address to the structure containing the configuration information for this instance of the driver.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.
- 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.
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); symbolic expressions are not permitted (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).api
: Provides an initial pointer to the API function struct used by the driver. Can be NULL.
DEVICE_DEFINE
(dev_name, drv_name, init_fn, pm_control_fn, data, cfg_info, level, prio, api)¶Create device object and set it up for boot time initialization, with the option to device_pm_control. In case of Device Idle Power Management is enabled, make sure the device is in suspended state after initialization.
This macro defines a device object that is automatically configured by the kernel during system initialization. Note that devices set up with this macro will not be accessible from user mode since the API is not specified; whenever possible, use DEVICE_AND_API_INIT instead.
The driver api is also set here, eliminating the need to do that during initialization.
dev_name
: Device name. This must be less than Z_DEVICE_MAX_NAME_LEN characters in order to be looked up from user mode with device_get_binding().drv_name
: The name this instance of the driver exposes to the system.init_fn
: Address to the init function of the driver.data
: Pointer to the device’s configuration data.cfg_info
: The address to the structure containing the configuration information for this instance of the driver.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.
- 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.
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); symbolic expressions are not permitted (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).api
: Provides an initial pointer to the API function struct used by the driver. Can be NULL.
pm_control_fn
: Pointer to device_pm_control function. Can be empty function (device_pm_control_nop) if not implemented.
DEVICE_NAME_GET
(name)¶Expands to the full name of a global device object.
Return the full name of a device object symbol created by DEVICE_INIT(), using the dev_name provided to DEVICE_INIT().
It is meant to be used for declaring extern symbols pointing on device objects before using the DEVICE_GET macro to get the device object.
Zephyr Driver Download Windows 10
name
: The same as dev_name provided to DEVICE_INIT()
DEVICE_GET
(name)¶Obtain a pointer to a device object by name.
Return the address of a device object created by DEVICE_INIT(), using the dev_name provided to DEVICE_INIT().
name
: The same as dev_name provided to DEVICE_INIT()
DEVICE_DECLARE
(name)¶Declare a static device object.
This macro can be used at the top-level to declare a device, such that DEVICE_GET() may be used before the full declaration in DEVICE_INIT().
This is often useful when configuring interrupts statically in a device’s init or per-instance config function, as the init function itself is required by DEVICE_INIT() and use of DEVICE_GET() inside it creates a circular dependency.
name
: Device name
Typedefs
- typedef void (*
device_pm_cb
)(structdevice *dev, int status, void *context, void *arg)¶
Functions
device_get_binding
(const char *name)¶Retrieve the device structure for a driver by name.
Device objects are created via the DEVICE_INIT() macro and placed in memory by the linker. If a driver needs to bind to another driver it can use this function to retrieve the device structure of the lower level driver by the name the driver exposes to the system.
name
: device name to search for.
device_pm
¶Device PM info.
dev
: pointer to device structurelock
: lock to synchronize the get/put operationsenable
: device pm enable flagusage
: device usage countfsm_state
: device idle internal power stateevent
: event object to listen to the sync request eventssignal
: signal to notify the Async API callers
device_config
¶Static device information (In ROM) Per driver instance.
name
: name of the deviceinit
: init function for the driverconfig_info
: address of driver instance config information
device
¶Runtime device structure (In memory) Per driver instance.
Zephyr Driver Download Pc
Zephyr Driver Download Torrent
device_config
: Build time config informationdriver_api
: pointer to structure containing the API functions for the device type. This pointer is filled in by the driver at init time.driver_data
: driver instance data. For driver use only