Re: RFC: Counter driver API


Tseng, Kuo-Lang <kuo-lang.tseng@...>
 

-----Original Message-----
From: Guedes, Andre
Sent: Wednesday, March 02, 2016 11:05 AM
To: Tseng, Kuo-Lang <kuo-lang.tseng(a)intel.com>; devel(a)lists.zephyrproject.org
Subject: Re: [devel] RFC: Counter driver API

Hi guys,

Quoting Tseng, Kuo-Lang (2016-02-26 17:29:17)
Background
--------------

On Quark (SE and D2000), there are Always On Counter (free running) and Always
ON Periodic Timer devices. A counter|timer driver is to be added for supporting
these devices. At same time, the goal is to create an API that is generic enough for
not just these two specific devices.

As a generic API we should be able to address counters devices with different
features such as counting up and counting down, free running, periodic and one-
shot for instance.

I was exercising this API and I think it might not handle properly counting up devices
with interrupt support since the matching value (which generates the interrupt)
cannot be set.
Correct. Good point.


I'd like to suggest a few changes based on the original proposal (and the feedback
already provided) that I think will enable us to handle counter device with different
features.

/**
* Start the counter device. If the device is a 'count up' counter the
* counter initial value is set to zero. It it is a 'countdown' counter
* the initial value is set to the maximum value supported by the device.
*
* @brief Start counter device.
* @param dev Pointer to the device structure for the driver instance.
* @retval DEV_OK If successful.
* @retval DEV_* Code otherwise.
*/
int counter_start(struct device *dev);

/**
* @brief Stop counter device.
* @param dev Pointer to the device structure for the driver instance.
*
* @retval DEV_OK If successful.
* @retval DEV_* Code otherwise.
*/
int counter_stop(struct device *dev);

/**
* @brief Read current counter value
* @param dev Pointer to the device structure for the driver instance.
*
* @return 32-bit value
*/
uint32_t counter_read(struct device *dev);

/**
* Set an alarm callback. If the counter was not started yet, this
* function starts and set the alarm.
*
* @brief Set an alarm callback.
* @param dev Pointer to the device structure for the driver instance.
* @param callback Pointer to the callback function.
* @param count Number of counter ticks.
*
* @retval DEV_OK If successful.
* @retval DEV_NO_SUPPORT if the device doesn't support interrupt (e.g.
* free running counters).
*/
int counter_set_alarm(struct device *dev, void (*callback)(void *data), int count);
Makes sense. This will work for both count-up timer and counting-down timer.


Regards,

Andre


Proposal:
-----------

Generic counter driver API:
-------------------------------
We will have 3 routines - start, stop, and read, which takes in the device pointer -
which identifies the timer. The driver header, counter.h, is under /include folder:

/**
* @brief Set up counter configuration and start it.
* @param dev Pointer to the device structure for the driver instance.
* @param config Pointer to counter configuration structure
*
* @retval DEV_OK If successful.
* @retval DEV_* Code otherwise.
*/
int counter_start(struct device *dev, counter_input *config);

/**
* @brief Stop the counter.
* @param dev Pointer to the device structure for the driver instance.
*
* @retval DEV_OK If successful.
* @retval DEV_* Code otherwise.
*/
int counter_stop(struct device *dev);

/**
* @brief Read current counter value
* @param dev Pointer to the device structure for the driver instance.
*
* @return 32-bit value
*/
uint32_t counter_read(struct device *dev)

The counter_input structure can be something like below:

/**
* @brief Counter configuration.
*
* Acceptable setting in the configuration structure is hardware-specific.
*
* initial_value - Initial value to load to the counter or timer.
* callback - Callback function when timer expires.
*/
struct counter_input {
uint32_t initial_value;
void (*callback)(void);
};

Note - Using structure, tomorrow we can add more fields for a counter with more
features.
For the Free Running counter in Quark, these fields would be null as it does not
support interrupt or callback notification.

The hardware-specific driver implementation:
-----------------------------------

This can be implemented in /drivers directory. For example, for Quark SE and
D2000, we can have below file which implements the API functionality using the
AON Counter and AON Periodic Timer:

drivers/quark_aon_counter.c

Comment, feedback welcome.

Join devel@lists.zephyrproject.org to automatically receive all group messages.