Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 201 additions & 2 deletions Documentation/components/drivers/character/timers/capture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,58 @@ Supported ``ioctl`` Commands

**Argument:** ``int`` (value to watch for).

.. c:macro:: CAPIOC_REGISTER

Register for capture edge event notifications. This allows applications
to receive asynchronous signal notifications when capture edge events
occur, instead of polling for events.

**Argument:** ``struct cap_notify_s *`` (pointer to notification structure).

The ``struct cap_notify_s`` contains:

* ``event`` - The signal event configuration (``struct sigevent``)
* ``chan`` - Capture channel number
* ``type`` - Edge type (``CAP_TYPE_RISING``, ``CAP_TYPE_FALLING``, or ``CAP_TYPE_BOTH``)
* ``ptr`` - User data pointer

**Returns:**

* ``OK`` on success
* ``-EINVAL`` for invalid channel
* ``-EBUSY`` if channel already registered by another task

.. c:macro:: CAPIOC_UNREGISTER

Unregister capture edge event notifications.

**Argument:** ``int`` (channel number).

**Returns:** ``OK`` on success.

Configuration
-------------

To enable the capture driver, enable the following configuration options:

* ``CONFIG_CAPTURE``
* ``CONFIG_STM32H7_TIM4_CAP`` (for STM32H7 Timer 4)
* ``CONFIG_CAPTURE`` - Enable the capture driver framework
* ``CONFIG_CAPTURE_NOTIFY`` - Enable signal notification support for edge events
* ``CONFIG_FAKE_CAPTURE`` - Enable fake capture driver for testing (generates 10Hz signal with 50% duty cycle)
* ``CONFIG_STM32H7_TIM4_CAP`` (for STM32H7 Timer 4, platform-specific)

The ``CONFIG_CAPTURE`` option enables the lower-half driver and registers
the ``/dev/capture`` device.

The ``CONFIG_CAPTURE_NOTIFY`` option enables the signal notification feature,
allowing applications to receive asynchronous notifications when capture
edge events occur. This requires hardware support for edge interrupts and
depends on ``CONFIG_CAPTURE``.

The ``CONFIG_FAKE_CAPTURE`` option enables a software-based fake capture
driver that simulates a 10Hz square wave with 50% duty cycle. This is
useful for development and testing without requiring actual hardware.
It depends on ``CONFIG_CAPTURE`` and ``CONFIG_CAPTURE_NSIGNALS > 0``.

Without it, capture is still possible manually by including the appropriate
header (e.g., ``arch/arm/src/stm32h7/stm32_capture.h``) and performing a
manual initialization.
Expand Down Expand Up @@ -125,6 +166,129 @@ frequency:
return 0;
}

Signal Notification Example
----------------------------

Here is an example using signal notifications for event-driven capture
(requires ``CONFIG_CAPTURE_NOTIFY``):

.. code-block:: c

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <nuttx/timers/capture.h>

static volatile int edge_count = 0;

static void capture_handler(int signo, siginfo_t *info, void *context)
{
edge_count++;
}

int main(int argc, char *argv[])
{
int fd;
struct cap_notify_s notify;
struct sigaction sa;
uint32_t frequency;
uint8_t duty;

/* Set up signal handler */
sa.sa_sigaction = capture_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);

/* Open capture device */
fd = open("/dev/capture0", O_RDONLY);
if (fd < 0)
{
perror("Failed to open capture device");
return 1;
}

/* Configure notification for both edges on channel 0 */
notify.chan = 0;
notify.type = CAP_TYPE_BOTH;
notify.event.sigev_notify = SIGEV_SIGNAL;
notify.event.sigev_signo = SIGUSR1;
notify.event.sigev_value.sival_ptr = NULL;

if (ioctl(fd, CAPIOC_REGISTER, (unsigned long)&notify) < 0)
{
perror("Failed to register notification");
close(fd);
return 1;
}

printf("Waiting for capture events...\n");

/* Wait for some events */
sleep(2);

/* Get frequency and duty cycle */
ioctl(fd, CAPIOC_FREQUENCE, (unsigned long)&frequency);
ioctl(fd, CAPIOC_DUTYCYCLE, (unsigned long)&duty);

printf("Captured %d edges\n", edge_count);
printf("Frequency: %u Hz, Duty: %u%%\n", frequency, duty);

/* Unregister notification */
ioctl(fd, CAPIOC_UNREGISTER, 0);

close(fd);
return 0;
}

Fake Capture Testing Example
-----------------------------

The fake capture driver can be used for testing without hardware
(requires ``CONFIG_FAKE_CAPTURE``):

.. code-block:: c

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <nuttx/timers/capture.h>

int main(int argc, char *argv[])
{
int fd;
uint32_t frequency;
uint8_t duty;

/* Open fake capture device */
fd = open("/dev/fake_capture0", O_RDONLY);
if (fd < 0)
{
perror("Failed to open fake capture device");
return 1;
}

/* Start capture */
ioctl(fd, CAPIOC_START, 0);

/* Wait for capture to stabilize */
sleep(1);

/* Read values (should be 10Hz, 50% duty) */
ioctl(fd, CAPIOC_FREQUENCE, (unsigned long)&frequency);
ioctl(fd, CAPIOC_DUTYCYCLE, (unsigned long)&duty);

printf("Fake Capture - Frequency: %u Hz, Duty: %u%%\n",
frequency, duty);

/* Stop capture */
ioctl(fd, CAPIOC_STOP, 0);

close(fd);
return 0;
}

Notes
-----

Expand All @@ -136,3 +300,38 @@ Notes
* **Important:** In debug builds of NuttX, calling an unsupported
``ioctl`` command will trigger a ``DEBUGASSERT`` in the driver,
which will halt or crash the system.

Signal Notification Features
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When ``CONFIG_CAPTURE_NOTIFY`` is enabled:

* Applications can register for asynchronous edge event notifications
* Supports per-channel registration with independent configurations
* Edge types supported: rising edge (``CAP_TYPE_RISING``), falling edge
(``CAP_TYPE_FALLING``), or both (``CAP_TYPE_BOTH``)
* Only one task can register per channel at a time
* Signal notifications use standard POSIX ``sigevent`` mechanism
* Lower-half drivers must implement ``bind()`` and ``unbind()`` operations
* Ideal for event-driven applications like tachometers, encoders, and
frequency counters

Fake Capture Driver
~~~~~~~~~~~~~~~~~~~

The fake capture driver (``CONFIG_FAKE_CAPTURE``) provides:

* Software simulation of capture events using watchdog timers
* Fixed 10Hz frequency with 50% duty cycle
* Edge toggles every 50ms (rising and falling)
* Supports all standard capture operations including notifications
* Available at ``/dev/fake_capture0``, ``/dev/fake_capture1``, etc.
* Useful for development, testing, and CI/CD without hardware
* Platform-independent implementation
* Automatically initialized at boot (2 channels by default)

Limitations:

* Fixed timing parameters (not configurable at runtime)
* Software timing accuracy (not hardware-precise)
* Suitable for functional testing, not timing precision validation
5 changes: 5 additions & 0 deletions drivers/drivers_initialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <nuttx/syslog/syslog_console.h>
#include <nuttx/thermal.h>
#include <nuttx/timers/ptp_clock_dummy.h>
#include <nuttx/timers/capture.h>
#include <nuttx/trace.h>
#include <nuttx/usrsock/usrsock_rpmsg.h>
#include <nuttx/vhost/vhost.h>
Expand Down Expand Up @@ -298,5 +299,9 @@ void drivers_initialize(void)
ptp_clock_dummy_initialize(0);
#endif

#ifdef CONFIG_FAKE_CAPTURE
fake_capture_initialize(2);
#endif

drivers_trace_end();
}
4 changes: 4 additions & 0 deletions drivers/timers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ endif()

if(CONFIG_CAPTURE)
list(APPEND SRCS capture.c)

if(CONFIG_FAKE_CAPTURE)
list(APPEND SRCS fake_capture.c)
endif()
endif()

if(CONFIG_GOLDFISH_TIMER)
Expand Down
19 changes: 19 additions & 0 deletions drivers/timers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@ config CAPTURE
This selection enables building of the "upper-half" Capture driver.
See include/nuttx/timers/capture.h for further Capture driver information.

if CAPTURE

config CAPTURE_NOTIFY
bool "Capture Notification Support"
default n
---help---
Some hardware will support notification when a capture event
occurs. If the hardware will support notification, then this
configuration should be set to enable the capability.

config FAKE_CAPTURE
bool "Fake Capture Driver"
default n
depends on CAPTURE_NSIGNALS > 0
---help---
Enables a fake capture driver for testing purposes.

endif # CAPTURE

config TIMER
bool "Timer Support"
default n
Expand Down
5 changes: 5 additions & 0 deletions drivers/timers/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ endif

ifeq ($(CONFIG_CAPTURE),y)
CSRCS += capture.c

ifeq ($(CONFIG_FAKE_CAPTURE),y)
CSRCS += fake_capture.c
endif

TMRDEPPATH = --dep-path timers
TMRVPATH = :timers
endif
Expand Down
Loading
Loading