mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-17 10:33:49 +01:00
Merge pull request #14050 from akshaim/Documentation_Update
doc/driver-guide.md : Update for compile-time configuration
This commit is contained in:
commit
045874abe6
@ -25,27 +25,26 @@ However, please avoid the use of `float` or `double`. Instead, multiply to the
|
|||||||
next SI (or appropriate) unit. E.g. if an ADC would return values like `1.23 V`,
|
next SI (or appropriate) unit. E.g. if an ADC would return values like `1.23 V`,
|
||||||
chose to return `1230 mV` instead.
|
chose to return `1230 mV` instead.
|
||||||
|
|
||||||
Additionally towards ease of use, all device drivers in RIOT should provide a
|
Additionally, towards ease of use, all device drivers in RIOT should provide a
|
||||||
similar 'look and feel'. They should behave similar concerning things like their
|
similar 'look and feel'. They should behave similarly in terms of their state
|
||||||
state after initialization, like their used data representation and so on.
|
after initialization, like their used data representation and so on.
|
||||||
|
|
||||||
Secondly, all device drivers should be optimized for minimal RAM/ROM usage, as
|
Secondly, all device drivers should be optimized for minimal RAM/ROM usage, as
|
||||||
RIOT targets (very) constrained devices. This implies, that instead of exposing
|
RIOT targets (very) constrained devices. This implies that instead of exposing
|
||||||
all thinkable functionality, the drivers should focus on exporting and
|
all thinkable functionality, the drivers should focus on exporting and
|
||||||
implementing a device's core functionality, thus covering ~95% of the use cases.
|
implementing a device's core functionality, thus covering ~95% of the use cases.
|
||||||
Furthermore great care should be put into ...(?)
|
|
||||||
|
|
||||||
Third, it should always be possible, to handle more than a single device of one
|
Third, it should always be possible to handle more than a single device of the
|
||||||
kind. Drivers and their interfaces are thus designed to keep their state
|
same kind. Drivers and their interfaces are thus designed to keep their state
|
||||||
information in a parameterized location instead of driver defined global
|
information in a parameterized location instead of driver defined global
|
||||||
variables.
|
variables.
|
||||||
|
|
||||||
Fourth, RIOT defines high-level interfaces for certain groups of devices (i.e.
|
Fourth, RIOT defines high-level interfaces for certain groups of devices (i.e.
|
||||||
netdev for network devices, SAUL for sensors and actuators), which enable users
|
netdev for network devices, SAUL for sensors and actuators), which enable users
|
||||||
to work with a wide variety of devices without having to know anything about the
|
to work with a wide variety of devices without having to know much about the
|
||||||
actual device that is mapped.
|
actual device that is mapped.
|
||||||
|
|
||||||
Fifth, during initialization we make sure that we can communicate with a device.
|
Fifth, during initialization, we make sure that we can communicate with a device.
|
||||||
Other functions should check the dev pointer is not void, and should also handle
|
Other functions should check the dev pointer is not void, and should also handle
|
||||||
error return values from the lower layer peripheral driver implementations,
|
error return values from the lower layer peripheral driver implementations,
|
||||||
where there are some.
|
where there are some.
|
||||||
@ -59,8 +58,8 @@ platform independent interfaces as the peripheral drivers, xtimer, etc.
|
|||||||
## Documentation {#driver-guide-doc}
|
## Documentation {#driver-guide-doc}
|
||||||
|
|
||||||
Document what your driver does! Most devices come with a very large number of
|
Document what your driver does! Most devices come with a very large number of
|
||||||
features, while the corresponding device driver only supports a sub-set of them.
|
features, while the corresponding device driver only supports a subset of them.
|
||||||
This should be clearly stated in the device driver's documentation, so that
|
This should be clearly stated in the device driver's documentation so that
|
||||||
anyone wanting to use the driver can find out the supported features without
|
anyone wanting to use the driver can find out the supported features without
|
||||||
having to scan through the code.
|
having to scan through the code.
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ configuration, using the naming scheme of `DEVNAME_t` (e.g. `dht_t`, or
|
|||||||
descriptor.
|
descriptor.
|
||||||
|
|
||||||
This device descriptor MUST contain all the state data of a device. By this, we
|
This device descriptor MUST contain all the state data of a device. By this, we
|
||||||
are not limited on the number of instances of the driver we can run
|
are not limited to the number of instances of the driver we can run
|
||||||
concurrently. The descriptor is hereby used for identifying the device we want
|
concurrently. The descriptor is hereby used for identifying the device we want
|
||||||
to interact with, and SHOULD always be the first parameter for all device driver
|
to interact with, and SHOULD always be the first parameter for all device driver
|
||||||
related functions.
|
related functions.
|
||||||
@ -87,7 +86,7 @@ is `DEVNAME_params_t`. In contrary to the device descriptor, this data structure
|
|||||||
should only contain static information, that is needed for the device
|
should only contain static information, that is needed for the device
|
||||||
initialization as it is preferably allocated in ROM.
|
initialization as it is preferably allocated in ROM.
|
||||||
|
|
||||||
A simple I2C temperature sensors's device descriptor could look like this:
|
A simple I2C temperature sensors' device descriptor could look like this:
|
||||||
|
|
||||||
@code{.c}
|
@code{.c}
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -103,8 +102,8 @@ typedef struct {
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
**NOTE:** In many cases it makes sense, to copy the `xxx_params` data into the
|
**NOTE:** In many cases it makes sense, to copy the `xxx_params` data into the
|
||||||
device descriptor during initialization. In some cases, it is however better to
|
device descriptor during initialization. In some cases, it is, however, better
|
||||||
just link the `params` data via pointer and only copy selected data. This way,
|
to just link the `params` data via pointer and only copy selected data. This way,
|
||||||
configuration data that is only used once can be read directly from ROM, while
|
configuration data that is only used once can be read directly from ROM, while
|
||||||
often used fields (e.g. used peripherals) are stored directly in the device
|
often used fields (e.g. used peripherals) are stored directly in the device
|
||||||
descriptor and one saves hereby one de-referencing step when accessing them.
|
descriptor and one saves hereby one de-referencing step when accessing them.
|
||||||
@ -113,7 +112,7 @@ descriptor and one saves hereby one de-referencing step when accessing them.
|
|||||||
|
|
||||||
Each device driver in RIOT MUST supply a default configuration file, named
|
Each device driver in RIOT MUST supply a default configuration file, named
|
||||||
`DEVNAME_params.h`. This file should be located in the `RIOT/drivers/...`. The
|
`DEVNAME_params.h`. This file should be located in the `RIOT/drivers/...`. The
|
||||||
idea is, that this file can be overridden by an application or a board, by
|
idea is that this file can be overridden by an application or a board, by
|
||||||
simply putting a file with the same name in the application's or the board's
|
simply putting a file with the same name in the application's or the board's
|
||||||
include folders, while RIOT's build system takes care of preferring those files
|
include folders, while RIOT's build system takes care of preferring those files
|
||||||
instead of the default params file.
|
instead of the default params file.
|
||||||
@ -166,7 +165,7 @@ CFLAGS="-DTMPABC_PARAM_ADDR=0x23" make all
|
|||||||
Second, we can override selected parameters from the board configuration
|
Second, we can override selected parameters from the board configuration
|
||||||
(`board.h`):
|
(`board.h`):
|
||||||
|
|
||||||
@code.{c}
|
@code
|
||||||
/* ... */
|
/* ... */
|
||||||
/**
|
/**
|
||||||
* @brief TMPABC sensor configuration
|
* @brief TMPABC sensor configuration
|
||||||
@ -202,21 +201,50 @@ Third, we can define more than a single device in the board configuration
|
|||||||
And finally, we can simply override the `tmpabc_params.h` file as described
|
And finally, we can simply override the `tmpabc_params.h` file as described
|
||||||
above.
|
above.
|
||||||
|
|
||||||
|
## Compile-time configuration documentation {#driver-guide-doxygen}
|
||||||
|
|
||||||
|
The macros that configure the driver during compilation is added to the listing
|
||||||
|
for [Compile time configurations](@ref config). Refer to the following example
|
||||||
|
that exposes
|
||||||
|
[TMP00x sensor](https://github.com/RIOT-OS/RIOT/blob/master/drivers/include/tmp00x.h#L96-L157)
|
||||||
|
to [sensors group](@ref config_drivers_sensors).
|
||||||
|
|
||||||
|
@code
|
||||||
|
/**
|
||||||
|
* @defgroup drivers_tmp00x_config TMP006/TMP007 Infrared Thermopile
|
||||||
|
* Sensor driver compile configuration
|
||||||
|
* @ingroup config_drivers_sensors
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief Default Address
|
||||||
|
* ....
|
||||||
|
*/
|
||||||
|
#ifndef TMP00X_I2C_ADDRESS
|
||||||
|
#define TMP00X_I2C_ADDRESS (0x40)
|
||||||
|
#endif
|
||||||
|
....
|
||||||
|
/** @} */
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Sub-groups defined for different types of drivers can be found in
|
||||||
|
[drivers/doc.txt](https://github.com/RIOT-OS/RIOT/blob/master/drivers/doc.txt)
|
||||||
|
|
||||||
## Initialization {#driver-guide-initialization}
|
## Initialization {#driver-guide-initialization}
|
||||||
|
|
||||||
In general, the initialization functions should to the following:
|
In general, the initialization functions should do the following:
|
||||||
|
|
||||||
- initialize the device descriptor
|
- initialize the device descriptor
|
||||||
- initialize non-shared peripherals they use, e.g. GPIO pins
|
- initialize non-shared peripherals they use, e.g. GPIO pins
|
||||||
- test for device connectivity, e.g. does a SPI/I2C slave react
|
- test for device connectivity, e.g. does an SPI/I2C slave react
|
||||||
- reset the device to a well defined state, e.g. use external reset lines or do
|
- reset the device to a well-defined state, e.g. use external reset lines or do
|
||||||
a software rest
|
a software rest
|
||||||
- do the actual device initialization
|
- do the actual device initialization
|
||||||
|
|
||||||
For testing a device's connectivity, it is recommended to read certain
|
For testing a device's connectivity, it is recommended to read certain
|
||||||
configuration data with a defined value from the device. Some devices offer
|
configuration data with a defined value from the device. Some devices offer
|
||||||
`WHO_AM_I` or `DEVICE_ID` registers for this purpose. Writing and reading back
|
`WHO_AM_I` or `DEVICE_ID` registers for this purpose. Writing and reading back
|
||||||
some data to the device is another valid option for testing it's responsiveness.
|
some data to the device is another valid option for testing its responsiveness.
|
||||||
|
|
||||||
For more detailed information on how the signature of the init functions should
|
For more detailed information on how the signature of the init functions should
|
||||||
look like, please refer below to the specific requirements for network devices
|
look like, please refer below to the specific requirements for network devices
|
||||||
@ -224,10 +252,10 @@ and sensors.
|
|||||||
|
|
||||||
## Return values {#driver-guide-return-values}
|
## Return values {#driver-guide-return-values}
|
||||||
|
|
||||||
As stated above, we check communication of a device during initialization, and
|
As stated above, we check communication of a device during initialization and
|
||||||
handle error return values from the lower layers, where they exist. To prevent
|
handle error return values from the lower layers, where they exist. To prevent
|
||||||
subsequent misuse by passing NULL pointers and similar to the subsequent
|
subsequent misuse by passing NULL pointers and similar to the subsequent
|
||||||
functions, the recommended way is to check parameter using `assert`, e.g.:
|
functions, the recommended way is to check the parameter using `assert`, e.g.:
|
||||||
|
|
||||||
@code{.c}
|
@code{.c}
|
||||||
int16_t tmpabc_read(const tmpabc_t *dev)
|
int16_t tmpabc_read(const tmpabc_t *dev)
|
||||||
@ -238,7 +266,7 @@ int16_t tmpabc_read(const tmpabc_t *dev)
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Whenever status/error return values are implemented by you in your driver, they
|
Whenever you implement status/error return values in your driver, they
|
||||||
should be named, meaning that the driver MUST define an enum assigning names to
|
should be named, meaning that the driver MUST define an enum assigning names to
|
||||||
the actual used value, e.g.
|
the actual used value, e.g.
|
||||||
|
|
||||||
@ -282,7 +310,7 @@ Then answer a few questions about the driver:
|
|||||||
- Driver name: enter a name for your driver. It will be used as both the name
|
- Driver name: enter a name for your driver. It will be used as both the name
|
||||||
of the driver directory where the source files are created and the build
|
of the driver directory where the source files are created and the build
|
||||||
system module.
|
system module.
|
||||||
- Driver doxygen group name: Enter the name of driver, as displayed in the
|
- Driver doxygen group name: Enter the name of the driver, as displayed in the
|
||||||
Doxygen documentation.
|
Doxygen documentation.
|
||||||
- Brief doxygen description: Describe in one line what is this driver about.
|
- Brief doxygen description: Describe in one line what is this driver about.
|
||||||
- Parent driver Doxygen group: Enter the Doxygen group the driver belongs to.
|
- Parent driver Doxygen group: Enter the Doxygen group the driver belongs to.
|
||||||
@ -350,7 +378,7 @@ preferred type where applicable.
|
|||||||
In many situations, the physical values cannot be mapped directly to integer
|
In many situations, the physical values cannot be mapped directly to integer
|
||||||
values. For example, we do not want to map temperature values to integers
|
values. For example, we do not want to map temperature values to integers
|
||||||
directly while using their fraction. The recommended way to solve this is by
|
directly while using their fraction. The recommended way to solve this is by
|
||||||
scaling the result value using decimal fixed point arithmetic, in other words
|
scaling the result value using decimal fixed point arithmetic, in other words,
|
||||||
just return centi-degree instead of degree (e.g. 2372c°C instead of 23.72°C).
|
just return centi-degree instead of degree (e.g. 2372c°C instead of 23.72°C).
|
||||||
|
|
||||||
## Additional Sensor Driver Checklist {#driver-guide-sensor-checklist}
|
## Additional Sensor Driver Checklist {#driver-guide-sensor-checklist}
|
||||||
@ -375,7 +403,7 @@ just return centi-degree instead of degree (e.g. 2372c°C instead of 23.72°C).
|
|||||||
|
|
||||||
## Initialization {#driver-guide-netdev-init}
|
## Initialization {#driver-guide-netdev-init}
|
||||||
|
|
||||||
The initialization process MUST be split into 2 steps: first initialize the
|
The initialization process MUST be split into 2 steps: first, initialize the
|
||||||
device descriptor and if applicable the used peripherals, and secondly do the
|
device descriptor and if applicable the used peripherals, and secondly do the
|
||||||
actual device initialization. The reason for this is, that before a device is
|
actual device initialization. The reason for this is, that before a device is
|
||||||
actually activated and can start to process data, the network stack for the
|
actually activated and can start to process data, the network stack for the
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user