Skip to content
Permalink
Browse files

api: dma: add api to retrieve runtime status

Some applications using DMA, such as UART RX, could
need to complete the current DMA transaction earlier than
predefined, based on other termination conditions,
like UART's IDLE interrupts.

In that case, the client needs to know how many data are
still left in DMA transfer buffer so that it can figure
out how many data has been transfered. However, the current
DMA API doesn't provide any information for the client
to learn the transfer buffer information.

And some other information, like whether DMA transfer is busy
or not, transfer direction, etc, could interest a client.

So, added a dma API function to retrieve the current DMA
runtime status.

And implemented the API for STM32F4's DMA while keeping
others unimplemented.

Signed-off-by: Jun Li <jun.r.li@intel.com>
  • Loading branch information...
jli157 authored and nashif committed Mar 26, 2019
1 parent 9f21b09 commit 74e320d85943dedcf22256d3e09c109cadf94580
Showing with 63 additions and 0 deletions.
  1. +17 −0 drivers/dma/dma_stm32f4x.c
  2. +46 −0 include/dma.h
@@ -523,6 +523,22 @@ static int dma_stm32_stop(struct device *dev, u32_t id)
return 0;
}

static int dma_stm32_get_status(struct device *dev, u32_t id,
struct dma_status *stat)
{
struct dma_stm32_device *ddata = dev->driver_data;

if (id >= DMA_STM32_MAX_STREAMS || stat == NULL) {
return -EINVAL;
}

stat->dir = ddata->stream[id].direction;
stat->busy = ddata->stream[id].busy;
stat->pending_length = dma_stm32_read(ddata, DMA_STM32_SNDTR(id));

return 0;
}

static int dma_stm32_init(struct device *dev)
{
struct dma_stm32_device *ddata = dev->driver_data;
@@ -556,6 +572,7 @@ static const struct dma_driver_api dma_funcs = {
.config = dma_stm32_config,
.start = dma_stm32_start,
.stop = dma_stm32_stop,
.get_status = dma_stm32_get_status,
};

const struct dma_stm32_config dma_stm32_1_cdata = {
@@ -154,6 +154,21 @@ struct dma_config {
int error_code);
};

/**
* DMA runtime status structure
*
* busy - is current DMA transfer busy or idle
* dir - DMA transfer direction
* pending_length - data length pending to be transferred in bytes
* or platform dependent.
*
*/
struct dma_status {
bool busy;
enum dma_channel_direction dir;
u32_t pending_length;
};

/**
* @cond INTERNAL_HIDDEN
*
@@ -171,11 +186,15 @@ typedef int (*dma_api_start)(struct device *dev, u32_t channel);

typedef int (*dma_api_stop)(struct device *dev, u32_t channel);

typedef int (*dma_api_get_status)(struct device *dev, u32_t channel,
struct dma_status *status);

struct dma_driver_api {
dma_api_config config;
dma_api_reload reload;
dma_api_start start;
dma_api_stop stop;
dma_api_get_status get_status;
};
/**
* @endcond
@@ -274,6 +293,33 @@ static inline int z_impl_dma_stop(struct device *dev, u32_t channel)
return api->stop(dev, channel);
}

/**
* @brief get current runtime status of DMA transfer
*
* Implementations must check the validity of the channel ID passed in and
* return -EINVAL if it is invalid or -ENOSYS if not supported.
*
* @param dev Pointer to the device structure for the driver instance.
* @param channel Numeric identification of the channel where the transfer was
* being processed
* @param stat a non-NULL dma_status object for storing DMA status
*
* @retval non-negative if successful.
* @retval Negative errno code if failure.
*/
static inline int dma_get_status(struct device *dev, u32_t channel,
struct dma_status *stat)
{
const struct dma_driver_api *api =
(const struct dma_driver_api *)dev->driver_api;

if (api->get_status) {
return api->get_status(dev, channel, stat);
}

return -ENOSYS;
}

/**
* @brief Look-up generic width index to be used in registers
*

0 comments on commit 74e320d

Please sign in to comment.
You can’t perform that action at this time.