Documentation: migrate the rest of drivers readmes

This commit is contained in:
raiden00pl 2023-10-26 11:31:58 +02:00 committed by Xiang Xiao
parent d98ae9d3e4
commit 443e900188
5 changed files with 836 additions and 0 deletions

View File

@ -44,3 +44,100 @@ Block device drivers have these properties:
Can be used to set up a block of memory or (read-only) FLASH as
a block driver that can be mounted as a file system. See
include/nuttx/drivers/ramdisk.h.
EEPROM
======
EEPROMs are a form of Memory
Technology Device (MTD). EEPROMs are non-volatile memory like FLASH, but
differ in underlying memory technology and differ in usage in many respects:
They may not be organized into blocks (at least from the standpoint of the
user) and it is not necessary to erase the EEPROM memory before re-writing
it. In addition, EEPROMs tend to be much smaller than FLASH parts, usually
only a few kilobytes vs megabytes for FLASH. EEPROM tends to be used to
retain a small amount of device configuration information; FLASH tends
to be used for program or massive data storage. For these reasons, it may
not be convenient to use the more complex MTD interface but instead use
the simple character interface provided by the EEPROM drivers.
EEPROM Device Support
---------------------
drivers/eeprom/spi_xx25xx.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is a driver for SPI EEPROMs that use the same commands as the
25AA160::
Manufacturer Device Bytes PgSize AddrLen
Microchip
25xx010A 128 16 1
25xx020A 256 16 1
25AA02UID 256 16 1
25AA02E48 256 16 1
25AA02E64 256 16 1
25xx040 512 16 1+bit
25xx040A 512 16 1+bit
25xx080 1024 16 1
25xx080A 1024 16 2
25xx080B 1024 32 2
25xx080C 1024 16 x
25xx080D 1024 32 x
25xx160 2048 16 2
25xx160A/C 2048 16 2 TESTED
25xx160B/D 2048 32 2
25xx160C 2048 16 2
25xx160D 2048 32 2
25xx320 4096 32 2
25xx320A 4096 32 2
25xx640 8192 32 2
25xx640A 8192 32 2
25xx128 16384 64 2
25xx256 32768 64 2
25xx512 65536 128 2
25xx1024 131072 256 3
Atmel
AT25010B 128 8 1
AT25020B 256 8 1
AT25040B 512 8 1+bit
AT25080B 1024 32 2
AT25160B 2048 32 2
AT25320B 4096 32 2
AT25640B 8192 32 2
AT25128B 16384 64 2
AT25256B 32768 64 2
AT25512 65536 128 2
AT25M01 131072 256 3
drivers/mtd/at24xx.c
~~~~~~~~~~~~~~~~~~~~
This is a driver for I2C-based at24cxx EEPROM (at24c32, at24c64, at24c128,
at24c256, at24c512). This driver is currently provided as an MTD driver
but could easily be modified to support the character driver interface.
File Systems
------------
Most EEPROM parts are too small to be candidates for use with a file
system. The character driver interface is optimal for these small parts
because you can open and access the EEPROM part as if it were a single,
fixed size file.
It is also possible to use these character drivers with a file system.
The character driver can converted to a block device using the NuttX loop
device. The loop device can be found the file drivers/loop.c. Interface
function prototypes can be found in include/nuttx/fs/fs.h::
int losetup(FAR const char *devname, FAR const char *filename,
uint16_t sectsize, off_t offset, bool readonly);
Given a file or character devices at 'filename', losetup will create the
block device 'devname' using a bogus sector size of sectsize. 'offset' is
normally zero but can be used to provide an offset into the EEPROM where
the block driver data starts; The EEPROM block driver can also be read-
only.
There is a corresponding function that will destroy the loop device::
int loteardown(FAR const char *devname);

View File

@ -35,3 +35,5 @@ following section.
usbdev.rst
rwbuffer.rst
regmap.rst
sensors.rst
video.rst

View File

@ -1,3 +1,5 @@
.. note:: See also the usage of the LCD driver in the graphics/ directory.
=====================
LCD Character Drivers
=====================
@ -52,6 +54,96 @@ details on how an LCD screen is bound to an LCD character driver.
* ``include/nuttx/lcd/lcd.h`` provides structures and APIs needed to work
with LCD screens, whether using the framebuffer adapter or the :doc:`lcd`;
Supported devices
=================
Re-usable LCD drivers reside in the drivers/lcd directory:
LCDs
----
- ``mio283qt2.c``
This is a driver for the MI0283QT-2 LCD from Multi-Inno
Technology Co., Ltd. This LCD is based on the Himax HX8347-D LCD
controller.
- ``mio283qt9a.c``
This is a driver for the MI0283QT-9A LCD from Multi-Inno
Technology Co., Ltd. This LCD is based on the Ilitek ILI9341 LCD
controller.
- ``ssd12989.c``
Generic LCD driver for LCDs based on the Solomon Systech
SSD1289 LCD controller. Think of this as a template for an LCD driver
that you will probably have to customize for any particular LCD
hardware. (See also boards/arm/stm32/hymini-stm32v/src/ssd1289.c below).
- ``st7567.c``
LCD Display Module, ST7567, Univision Technology Inc.
Used with the LPCXpresso and Embedded Artists base board.
- ``memlcd.c``
Sharp Memory LCD Suite, LS013B7DH01, LS013B7DH03, etc.
There are some more different models, they are basically controlled
by similar logics, thus this driver can be extended.
- ``ra8875.c``
RAiO Technologies RA8875 LCD controller. Contributed by Marten Svanfeldt.
OLEDs
-----
- ``p14201.c``
Driver for RiT P14201 series display with SD1329 IC controller.
Based on the SD1329 controller. This OLED is used with
older versions of the TI/Luminary LM3S8962 Evaluation Kit. Example
usage::
boards/arm/tiva/lm3s6965-ek/src
boards/arm/tiva/lm3s8962-ek/src
- ``ug-2864ambag01.c``
OLED Display Module, UUG-2864AMBAG01, Univision Technology Inc.
Based on the SH1101A controller. Example usage::
boards/arm/stm32/stm32f4discovery
boards/arm/lpc214x/zp214xpa
- ``ug-9664hswag01.c``
OLED Display Module, UG-9664HSWAG01, Univision Technology Inc.
Based on the SSD1305 controller. Used with the
LPC Xpresso and Embedded Artists base board. Example usage::
boards/arm/lpc71xx_40xx/lpcxpresso-lpc1768
- ``ssd1306.c``
OLED Display Modules based on the SSD1306 controllers.
This includes the UG-2864HSWEG01 and UG2832HSWEG04, both from Univision
Technology Inc. The latter is used with the OLED1 module that comes
with the Atmel SAM4l Xplained Pro board. This driver also supports
Densitron Technologies DD-12864WO-4A which is based on SSD1309 LCD
controller. Example usage::
boards/arm/stm32/stm32f4discovery
boards/arm/sam34/sam4l-xplained
Segment LCDS (SLCDs)
--------------------
- ``pcf8574_lcd_backpack.c``
See pcf8574_lcd_backpack_readme.txt.
Examples
========
@ -132,3 +224,82 @@ built with the LCD character interface.
* The LVGL demo application (``lvgldemo``) makes use of the ``ioctl`` system
call to trigger an ``LCDDEVIO_PUTAREA`` request to the higher-level device
driver to refresh the LCD screen with data as usual;
LCD Header files
================
``include/nuttx/lcd/lcd.h``
Structures and APIs needed to work with LCD drivers are provided in
this header file. This header file also depends on some of the same
definitions used for the frame buffer driver as provided in
include/nuttx/video/fb.h.
``struct lcd_dev_s``
Each LCD device driver must implement an instance of struct lcd_dev_s.
That structure defines a call table with the following methods:
- Get information about the LCD video controller configuration and the
configuration of each LCD color plane.
.. code-block:: C
int (*getvideoinfo)(FAR struct lcd_dev_s *dev,
FAR struct fb_videoinfo_s *vinfo);
int (*getplaneinfo)(FAR struct lcd_dev_s *dev, unsigned int planeno,
FAR struct lcd_planeinfo_s *pinfo);
- The following are provided only if the video hardware supports RGB
color mapping:
.. code-block:: C
int (*getcmap)(FAR struct lcd_dev_s *dev,
FAR struct fb_cmap_s *cmap);
int (*putcmap)(FAR struct lcd_dev_s *dev,
FAR const struct fb_cmap_s *cmap);
- The following are provided only if the video hardware supports a
hardware cursor:
.. code-block:: C
int (*getcursor)(FAR struct lcd_dev_s *dev,
FAR struct fb_cursorattrib_s *attrib);
int (*setcursor)(FAR struct lcd_dev_s *dev,
FAR struct fb_setcursor_s *settings);
- Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER:
full on). On backlit LCDs, this setting may correspond to the
backlight setting:
.. code-block:: C
int (*getpower)(struct lcd_dev_s *dev);
- Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER:
full on). On backlit LCDs, this setting may correspond to the
backlight setting:
.. code-block:: C
int (*setpower)(struct lcd_dev_s *dev, int power);
- Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST):
.. code-block:: C
int (*getcontrast)(struct lcd_dev_s *dev);
- Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST):
.. code-block:: C
int (*setcontrast)(struct lcd_dev_s *dev, unsigned int contrast);

View File

@ -0,0 +1,496 @@
.. warning:: this list is incomplete. See drivers/sensors for ar full list of
supported sensors
==============
Sensor Drivers
==============
ADXL345
=======
Contributed by Alan Carvalho de Assis
The ADXL345 accelerometer can operate in I2C or SPI mode. To operate in I2C
mode just connect the CS pin to Vddi/o.
In order to operate in SPI mode CS need to use connected to microcontroller,
it cannot leave unconnected.
In SPI mode it works with clock polarity (CPOL) = 1 and clock phase (CPHA)
= 1.
ADXL372
=======
Contributed by Bob Feretich
The ADXL372 is a 200g tri-axis accelerometer that is capable of detecting
and recording shock impact impact events. Recording trigger
characteristics are programmed into the sensor via multiple threshold and
duration registers. The ADXL372 is a SPI only device that can transfer
data at 10 MHz. The data transfer performance of this part permits the
sensor to be sampled "on demand" rather than periodically sampled by a
worker task.
See the description of the "Common Sensor Register Interface" below for more
details. It also implements the "Sensor Cluster Driver Interface".
LSM330_SPI
==========
Contributed by Bob Feretich
The LSM330 consists of a multi-range tri-axis accelerometer and a
multi-range tri-axis gyroscope. The tri-axis accelerometer features two
state machines that can be firmware programmed for event detection. The
tri-axis gyroscope features threshold and duration registers for event
detection.
This driver supports the LSM330 in SPI mode. In this mode, the LSM330
that can transfer data at 10 MHz. The data transfer performance of
this part permits the sensor to be sampled "on demand" rather than
periodically sampled by a worker task. See the description of the "Common
Sensor Register Interface" below for more details. It also implements the
"Sensor Cluster Driver Interface".
MPL115A
=======
Contributed by Alan Carvalho de Assis
This driver has support only for MPL115A1 (SPI), but support to MPL115A2
(I2C) can be added easily.
Common Sensor Register Interface
================================
Contributed by Bob Feretich
Background and problem statement:
The capabilities and performance of modern sensors have grown tremendously.
Most sensors are now capable of some degree of autonomous behavior and
several permit the user to load firmware into them and perform as
nanocontrollers. Other sensors have very sophisticated built-in digital
filters that can be programmed with hundreds of parameters.
Currently most sensor drivers in the NuttX drivers/sensors
directory implement file_ops open(), close(), and read() functions.
The open() function initializes the sensor and places it in a mode where
it can transfer live data in a default configuration. The close() function
places the sensor in a low power shutdown mode. The read() function
returns the most recent data sample from the sensor's most used data
output registers. The write() function is rarely implemented and when it
is there is no consistency in its use. The lseek() and poll() functions
seem to be completely ignored. This results in the sensors being operated
in only their most primitive modes using a fixed "default configuration".
To work around this problem sensor drivers have implemented ioctl()
functions to perform configuration, program the sensor, and manage
autonomous activity. Ioctls provide a method where user programs can
tunnel through a high level driver to access and control device specific
features. The problem with using ioctls is that before the ioctl interface
can be used, the sensor driver must be opened; and the open() function
causes the driver to start performing these primitive actions, so before
ioctls can manage the drivers as desired, ioctls must first be used to
undo the generic actions caused by the open() function. Another major
issue is that there is no consistency from sensor to sensor on ioctl
definitions, not even for the most common sensor actions like writing a
sensor control register or reading a sensor status register.
Purpose:
The purpose of the "Common Sensor Register Interface" is to implement a
consistent and more useful definition of file_ops interface and to make the
file_ops open() function more flexible in establishing the initial
operational state of the sensor. Compatibility for user applications that
implement the current open(), close(), read() interface will be
maintained; and the much greater capabilities of modern sensors will
become accessible through this interface.
Scope:
Applicable to I2C and SPI attached sensors, and some serial port attached
sensors.
The file_ops interface definition:
open(): This function performs the below actions...
1) Reads the sensors ID register. If the sensor responds with an
unexpected value, then...
a) The driver's write() function is disabled.
b) The open function initializes the driver instance, so
that read() and lseek() operations may be performed to enable
problem diagnoses, but the sensor hardware is not initialized.
(No write operations are performed to the sensor.)
c) The errno global variable is set to positive ENODEV
("No such device").
d) The open() function returns successfully with a file_handle.
Note that the calling routine should clear errno before
calling open(). (The file_ops rules prevent drivers from
setting errno to zero.)
2) The other file_ops functions are enabled.
3) The driver's "current reg address" state variable is set to the
sensor's first sensor data output register. (This will make
calls to read() return live sensor data and maintain compatibility
with existing user programs.)
4) If the driver supports a default worker task and an interrupt
handler is specified by in the sensor configuration structure, then
the default worker task is bound to the default worker task.
5) The sensor configuration structure (that was provided to the driver
registration function) is examined to determine whether a custom
sensor configuration is specified. (The custom configuration is
basically an array of (device_reg_address, value) pairs that are
written to the sensor via "single register write" operations.
If a custom sensor configuration was specified, then that
configuration is written to the sensor, otherwise the "default
sensor configuration" is written to the sensor.
(A side effect of writing this data may result in interrupts
occurring and data being transferred to/from the worker task.)
6) The open() function returns successfully with a file_handle.
``close()``: This function stops sensor activity and places it in a low
power mode. The file_ops interface functions are disabled for this
instance of the sensor driver. (Except for open())
``read()``: The action of this function is dependent on whether a "default
worker task" is running and the value of the driver's "current reg
address" state variable.
If a "default worker task" is running,
AND the driver's "current reg address" is equal to the value of
the first sensor data output register,
AND the number of bytes to be read is less than or equal to the
number of bytes in a "default worker task" sample,
Then data is copied from the "default worker task's" sample memory to
the caller's provided buffer.
Otherwise, this function transfers data from sensor registers to the
data buffer provided by the caller. The first byte read is from the
sensor register address specified by the sensor's "current reg
address". The addresses of subsequent bytes to be read are context
sensitive. If more than bus transfer is needed to complete the read,
then a "multi-byte" (sometimes called "burst mode") data transfer
will be used to fill the buffer.
See the sensor's datasheet to determine the auto-increment
behavior of a "multi-byte" data transfers.
Note: That most sensors collect only a few bytes of data per sample.
Small data transfers occurring over a high speed bus (like SPI and some
high speed i2c and serial interfaces) are much more efficient when
collected directly from the sensor hardware than by using a worker task
as an intermediary.
``write()``: This function transfers data from the data buffer provided by
the caller to sensor registers. The first byte written is to the
sensor register address specified by the sensor's "current reg
address". The addresses of subsequent bytes to be read are context
sensitive. If more than bus transfer is needed to complete the write,
then a "multi-byte" (sometimes called "burst mode") data
transfer will be used to transfer data from the buffer.
See the sensor's datasheet to determine the auto-increment
behavior of a "multi-byte" data transfers.
Note: If write() function was disabled, then no writes will be performed
and the function will return 0 (characters transferred) and errno
is set to -EROFS ("read-only file system").
``lseek()``: This function sets the value of the sensor's "current reg address"
(seek_address). The open() function initializes the "current reg address"
to the first sensor data output register, so unless the user needs
to change the sensor configuration, lseek() does not need to be
called. Neither read() nor write() change the sensor's "current reg
address".
The definition of lseek is...::
off_t lseek(int fd, off_t offset, int whence);
For whence == SEEK_SET, the sensor's "current reg address" will be set
to offset.
For whence == SEEK_CUR, offset will be added to the sensor's "current
reg address".
For whence == SEEK_END, offset is ignored and the sensor's "current
reg address" is set to the first sensor data output register.
lseek() will return an error if the resulting "current reg address"
is invalid for the sensor.
``ioctl()``: Ioctls() may still be used and this interface make no attempt to
regulate them. But, it is expected that far fewer ioctls will be needed.
The above interface can be used to fully configure a sensor to the needs
of an application, including the ability to load firmware into sensor
state machines
Sensor Cluster Driver Interface
===============================
Contributed by Bob Feretich
Background and problem statement:
Most microcontrollers can support SPI bus transfers at 8 MHz or greater.
Most SPI attached sensors can support a 10 MHz SPI bus. Most tri-axis
accelerometers, tri-axis gyroscopes, or tri-axis magnetometers use only 6
bytes per sample. Many sensors use less than 6 bytes per sample. On an 8
MHz SPI bus it takes about 8 microseconds to transfer a 6 byte sample.
(This time includes a command byte, 6 data bytes, and chip select select
setup and hold.) So, for the below discussion keep in mind that the sensor
sample collection work we want to perform should ideally take 8 microseconds
per sample.
The drivers in the drivers/sensors directory support only the user space
file_ops interface (accessing drivers through the POSIX open/read/close
functions using a file descriptor). Also these drivers typically start
their own worker task to perform sensor data collection, even when their
sensors only transfer a few bytes of data per sample and those transfers
are being made over a high performance bus.
Using the current implementation...
1) A sensor "data ready" or timer interrupt occurs.
2) Context is saved and and the driver's interrupt handler is scheduled
to run.
3) The NuttX scheduler dispatches the driver's interrupt handler task.
4) The driver's interrupt handler task posts to a semaphore that the
driver's worker task is waiting on.
5) NuttX restores the context for the driver's worker task and starts it
running.
6) The driver's worker task starts the i/o to collect the sample.) (This is
where the 8 microseconds of real work gets performed.) And waits on a
SPI data transfer complete semaphore.
7) The NuttX saves the context of the driver's worker task, and the
scheduler dispatches some other task to run while we are waiting.
Note that this is a good thing. This task is probably performing some
other real work. We want this to happen during the data transfer.
8) The completion of the data transfer causes an interrupt. NuttX saves the
current context and restores the driver's worker task's context.
9) The driver's worker task goes to sleep waiting on the semaphore for the
next sensor "data ready" or timer interrupt.
10) The NuttX saves the context of the driver's worker task, and the
scheduler dispatches some other task to run while we are waiting.
Independently with the above...
a) The sensor application program performs a file_ops read() to collect a
sample.
b) The NuttX high level driver receives control, performs a thin layer of
housekeeping and calls the sensor driver's read function.
c) The sensor driver's read function copies the most recent sample from the
worker task's data area to the application's buffer and returns.
d) The NuttX high level driver receives control, performs a thin layer of
housekeeping and returns.
e) The application processes the sample.
Using a 216 MHz STM32F7 with no other activity occurring, we have timed the
above the elapsed time for the above to be on average 45 microseconds.
Most sensor applications process data from multiple sensors. (An 9-DoF IMU
is typically represented as three sensors (accelerometer, gyroscope, and
magnetometer). In this case there are three copies of 1-10 occurring in
parallel.
In applications where live data is being used, the context switch
thrashing and cache pollution of this approach cripples system
performance. In applications where sensor FIFO data is being used and
therefore a large amount of data is collected per iteration, the non "zero
copy" nature of the data collection becomes a performance issue.
Purpose:
The "Sensor Cluster Driver Interface" provides a standard mechanism for
an application to collect data from multiple sensor drivers in a much more
efficient manner. It significantly reduces the number of running tasks and
the context thrashing and cache pollution caused by them. It also permits
"zero copy" collection of sensor data.
The Sensor Cluster Driver Interface uses a single "worker task" to be shared
by an arbitrary number of drivers. This shared worker task is a kernel
task that is registered like a driver, supports a driver interface to
application programs, and collects data from multiple sensors (a cluster of
sensors), we refer to it a "Sensor Cluster Driver".
Its goal is to change the sequence of events detailed above to...
1) A sensor "data ready" or timer interrupt occurs.
2) Context is saved and and the cluster driver's interrupt handler is
scheduled to run.
3) The NuttX scheduler dispatches the cluster driver's interrupt handler
task.
4) The cluster driver's interrupt handler task posts to a semaphore that
the cluster driver's worker task is waiting on.
5) NuttX restores the context for the driver's worker task and starts it
running.
6) The cluster driver's worker task starts the i/o to collect the sample.
There are two choices here. Programmed I/O (PIO) or DMA. If PIO is
fastest for a small sample size, but it will lock up the processor for
the full duration of the transfer; it can only transfer from one
sensor at a time; and the worker task should manually yield control
occasionally to permit other tasks to run. DMA has higher start and
completion overhead, but it is much faster for long transfers, can
perform simultaneous transfers from sensors on different buses, and
automatically releases the processor while the transfer is occurring.
For this reason our drivers allows the worker task to choose between
PIO (driver_read()) and DMA (driver_exchange()), a common extension to
the sensor_cluster_operations_s structure. So either way after one or
more transfers we yield control and move to the next step. Note that
the data is being transferred directly into the buffer provided by the
application program; so no copy needs to be performed.
7) The NuttX saves the context of the cluster driver's worker task, and the
scheduler dispatches some other task to run while we are waiting.
Again note that this is a good thing. This task is probably performing
some other real work. We want this to happen during the data transfer.
8) The completion of the last of the previous data transfers causes an
interrupt. NuttX saves the current context and restores the cluster
driver's worker task's context. If there is more sensor data to
collect, then goto Step 6. Otherwise it posts to a semaphore that
will wake the application.
9) The driver's worker task goes to sleep waiting on the semaphore for the
next sensor "data ready" or timer interrupt.
10) The NuttX saves the context of the driver's worker task, and the
scheduler dispatches some other task to run while we are waiting.
Independently with the above...
a) The sensor application program performs a file_ops read() to collect a
sample.
b) The NuttX high level driver receives control, performs a thin layer of
housekeeping and calls the sensor driver's read function.
c) The sensor driver's read function copies the most recent sample from the
worker task's data area to the application's buffer and returns.
d) The NuttX high level driver receives control, performs a thin layer of
housekeeping and returns.
e) The application processes the sample.
So when collecting data from three sensors, this mechanism saved...
* the handling of 2 sensor "data ready" or timer interrupts (Steps 1 - 4).
* 2 occurrences of waking and scheduling of a worker task (Step 5).
* 2 context switches to other tasks (Step 9 & 10)
* if the three sensors were on separate buses, then 2 occurrences of
Steps 6 - 8 could have also been saved.
* An extra copy operation of the collected sensor data.
* The cache pollution caused by 2 competing worker tasks.
Definitions:
"Leaf Driver" - a kernel driver that implements the "Sensor Cluster Driver
Interface" so that it can be called by Cluster drivers.
"Cluster Driver" - a kernel driver that uses the "Sensor Cluster Driver
Interface" to call leaf drivers.
"Entry-Point Vector" - an array of function addresses to which a leaf driver
will permit calls by a Cluster Driver.
"Leaf Driver Instance Handle" - a pointer to an opaque Leaf Driver structure
that identifies an instance of the leaf driver. Leaf Drivers store this
handle in its configuration structure during registration.
Sensor Cluster Interface description:
* The definition of an entry-point vector. This is similar to the
entry-point vector that is provided to the file-ops high level driver.
This entry-point vector must include the sensor_cluster_operations_s
structure as its first member.
* The the definition of an driver entry-point vector member in the leaf
driver's configuration structure. The leaf driver registration function
must store the address of its entry-point vector in this field.
* The the definition of an instance handle member in the leaf drivers
configuration structure. The leaf driver registration function must store
a handle (opaque pointer) to the instance of the leaf driver being
registered in this field. Note that this should be the same handle that
the leaf driver supplies to NuttX to register itself. The cluster driver
will include this handle as a parameter in calls made to the leaf driver.
.. code-block:: C
struct sensor_cluster_operations_s
{
CODE int (*driver_open)(FAR void *instance_handle, int32_t arg);
CODE int (*driver_close)(FAR void *instance_handle, int32_t arg);
CODE ssize_t (*driver_read)(FAR void *instance_handle, FAR char *buffer,
size_t buflen);
CODE ssize_t (*driver_write)(FAR void *instance_handle,
FAR const char *buffer, size_t buflen);
CODE off_t (*driver_seek)(FAR void *instance_handle, off_t offset,
int whence);
CODE int (*driver_ioctl)(FAR void *instance_handle, int cmd,
unsigned long arg);
CODE int (*driver_suspend)(FAR void *instance_handle, int32_t arg);
CODE int (*driver_resume)(FAR void *instance_handle, int32_t arg);
};
Note that the sensor_cluster_operations_s strongly resembles the NuttX fs.h
file_operations structures. This permits the current file_operations
functions to become thin wrappers around these functions.
``driver_open()`` Same as the fs.h open() except that arg can be specify
permitting more flexibility in sensor configuration and initial operation.
when arg = 0 the function of driver_open() must be identical to open().
``driver_close()`` Same as the fs.h close() except that arg can be specify
permitting more flexibility in selecting a sensor low power state.
when arg = 0 the function of driver_close() must be identical to close().
``driver_read()`` Same as the fs.h read().
``driver_write()`` Same as the fs.h write(). Optional. Set to NULL if not
supported.
``driver_seek()`` Same as the fs.h seek(). Optional. Set to NULL if not
supported.
``driver_ioctl()`` Same as the fs.h ioctl(). Optional. Set to NULL if not
supported.
``driver_suspend()`` and ``driver_resume()`` Optional. Set to NULL if not
supported. It is common for sensor applications to conserve power and
send their microcontroller into a low power sleep state. It seems
appropriate to reserve these spots for future use. These driver entry
points exist in Linux and Windows. Since microcontrollers and sensors
get more capable every year, there should soon be a requirement for
these entry points. Discussion on how to standardize their use and
implementation should
be taken up independently from this driver document.
Note that all drivers are encouraged to extend their entry-point vectors
beyond this common segment. For example it may be beneficial for the
worker task to select between programmed i/o and DMA data transfer
routines. Unregulated extensions to the Entry-Point Vector should be
encouraged to maximize the benefits of a sensor's features.
Operation:
Board logic (configs directory) will register the cluster driver. The
cluster driver will register the leaf drivers that it will call.
This means that the cluster driver has access to the leaf driver's
configuration structures and can pass the Leaf Driver Instance Handle to
the leaf driver as a parameter in calls made via the Entry-Point Vector.
Either board logic or an application program may open() the cluster
driver. The cluster driver open() calls the open() function of the leaf
drivers. The cluster driver open() or read() function can launch the
shared worker task that collects the data.
The cluster driver close() function calls the close functions of the leaf
drivers.
ADT7320
=======
Contributed by Augusto Fraga Giachero
The ADT7320 is a SPI temperature sensor with a temperature range of
40°C to +150°C.

View File

@ -0,0 +1,70 @@
====================
Video Device Drivers
====================
max7456
-------
23 March 2019
Bill Gatliff <bgat@billgatliff.com>
The code in drivers/video/max7456.[ch] is a preliminary device driver for the MAX7456 analog
on-screen-display generator. This SPI slave chip is a popular feature in many
embedded devices due its low cost and power requirements. In particular, you
see it a lot on drone flight-management units.
I use the term "preliminary" because at present, only the most rudimentary
capabilities of the chip are supported:
* chip reset and startup
* read and write low-level chip control registers (DEBUG mode only)
* write CA (Character Address) data to the chip's framebuffer memory
Some key missing features are, in no particular order:
* VSYNC and HSYNC synchronization (prevents flicker)
* ability to update NVM (define custom character sets)
If you have a factory-fresh chip, then the datasheet shows you what the factory
character data set looks like. If you've used the chip in other scenarios,
i.e. with Betaflight or similar, then your chip will almost certainly have had
the factory character data replaced with something application-specific.
Either way, you'll probably want to update your character set before long. I
should probably get that working, unless you want to take a look at it
yoruself...
The max7456_register() function starts things rolling. The omnibusf4 target
device provides an example (there may be others by the time you read this).
In normal use, the driver creates a set of interfaces under /dev, i.e.::
/dev/osd0/fb
/dev/osd0/raw (*)
/dev/osd0/vsync (*)
* - not yet implemented
By writing character data to the "fb" interface, you'll see data appear on the
display. NOTE that the data you write is NOT, for example, ASCII text: it is
the addresses of the characters in the chip's onboard character map.
For example, if entry 42 in your onboard character map is a bitmap that looks
like "H", then when you write the ASCII "*" (decimal 42, hex 2a), you'll see
that "H" appear on your screen.
If you build the code with the DEBUG macro defined, you will see a bunch more interfaces::
/dev/osd0/VM0
/dev/osd0/VM1
/dev/osd/DMM
...
...
These are interfaces to the low-level chip registers, which can be read and/or
written to help you figure out what's going on inside the chip. They're
probably more useful for me than you, but there they are in case I'm wrong
about that.
b.g.