There are two ways to enable Timer Support along with the Timer Example. The first is faster and simpler. Just run the following command to use a ready config file with timer support and example included. You need to check if there's a timer config file for your specific chip. You may check it at the specific board's path: ``/boards/<arch>/<chip>/<variant>/config``.
..code-block:: console
$ ./tools/configure.sh <variant>:timer
And the second way is creating your own config file. To do so, follow the next instructions.
Enabling the Timer Support and Example in ``menuconfing``
Below the option, it is possible to manually configure some parameters as the standard timer device path, the timeout, the sample rate in which the counter will be read, the number of samples to be executed, and other parameters.
The previously selected example will basically consult the timer status, set a timer alarm interval, set a timer signal handler function to be notified at the alarm, which only increments a variable, and then it will start the timer. The application will periodically consult the timer status at the sample rate previously configured through the ``menuconfig`` to follow the time left until the timer expires. After the samples have been read, the application stops de timer.
The `example code <https://github.com/apache/incubator-nuttx-apps/blob/master/examples/timer/timer_main.c#ref-example>`_ may be explored, its path is at ``/examples/timer/timer_main.c`` in the apps' repository.
In NuttX, the timer driver is a character driver and when a chip supports multiple timers, each one is accessible through its respective file in ``/dev`` directory. Each timer is registered using a unique numeric identifier (i.e. ``/dev/timer0``, ``/dev/timer1``, ...).
The first necessary thing to be done in order to use the timer driver in an application is to include the header file for the NuttX timer driver. It contains the Application Level Interface to the timer driver. To do so, include:
..code-block:: c
#include <nuttx/timers/timer.h>
At an application level, the timer functionalities may be accessed through ``ioctl`` systems calls. The available ``ioctl`` commands are:
These ``ioctl`` commands internally call lower-half layer operations and the parameters are forwarded to these ops through the ``ioctl`` system call. The return of a system call is the return of an operation.
These ``struct timer_ops_s`` keeps pointers to the implementation of each operation. Following is the struct.
Since ``ioctl`` system calls expect a file descriptor, before using these commands, it's necessary to open the timer device special file in order to get a file descriptor. The following snippet demonstrates how to do so:
:param status:A writable pointer to a struct ``timer_status_s``. This struct contains 3 fields: ``flags`` (``uint32_t``), ``timeout`` (``uint32_t``) and ``timeleft`` (``uint32_t``). Bit 0 from `flags` indicates the timer's status, 1 indicates that the timer is running, zero it is stopped. Bit 1 from `flags` indicates if there's a callback registered. The `timeout` indicates the time interval that was configured to trigger an alarm, it is in microseconds. The `timeleft` interval indicates how many microseconds it's missing to trigger the alarm. The following snippet demonstrates how to use it and how to access these fields.
The getstatus operation sets a timeout interval to trigger the alarm and then trigger an interrupt. It defines the timer interval in which the handler will be called.
The ``TCIOC_NOTIFICATION`` is used to configure the timer callback to notify the application via a signal when the timer expires. This command calls the ``setcallback`` operation. Which will not be described here, since the application does not set a callback directly. Instead, the user should configure a signal handler to catch notifications, and then, configure a timer notifier to notify and to signal the previously configured signal handler. For a better performance, a separate pthread may be configured to wait on sigwaitinfo() for timer events.
In any case, this command expects a read-only pointer to a struct `timer_notify_s`. This struct contains 2 fields: ``pid`` (``pid_t``), that indicates the ID of the task/thread to receive the signal and ``event`` (``struct sigevent``), which describes the way a task will be notified.