[RFC]DMA API Update


Liu, Baohong
 

Hi everyone,

I made minor update, the following is the final format.

Data Structure Definitions
-------

/**
* @brief DMA block configuration structure.
*
* source_address is block starting address at source
* source_gather_interval is the address adjustment at gather boundary
* dest_address is block starting address at destination
* dest_scatter_interval is the address adjustment at scatter boundary
* dest_scatter_count is the continuous transfer count between scatter boundaries
* source_gather_count is the continuous transfer count between gather boundaries
* block_size is the number of bytes to be transferred for this block.
* config is a bit field with the following parts:
* source_gather_en [ 0 ] --0-disable, 1-enable
* dest_scatter_en [ 1 ] --0-disable, 1-enable
* source_addr_adj [ 2 : 3 ] --00-increment, 01-decrement, 10-no change
* dest_addr_adj [ 4 : 5 ] --00-increment, 01-decrement, 10-no change
* source_reload_en [ 6 ] --reload source address at the end of block transfer
* 0-disable, 1-enable
* dest_reload_en [ 7 ] --reload destination address at the end of block transfer
* 0-disable, 1-enable
* fifo_mode_control [ 8 : 11 ] --How full of the fifo before transfer start. HW specific.
* flow_control_mode [ 12 ] --0-source request served upon data availability
* 1-wait until destination request happens
* RESERVED [ 13 : 15 ]
*/
struct dma_block_config {
uint32_t source_address;
uint32_t source_gather_interval;
uint32_t dest_address;
uint32_t dest_scatter_interval;
uint16_t dest_scatter_count;
uint16_t source_gather_count;
uint32_t block_size;
struct dma_block_config *next_block;
uint16_t config;
}

/**
* @brief DMA configuration structure.
*
* config is a bit field with the following parts:
* dma_slot [ 0 : 5 ] --which peripheral and direction(HW specific)
* channel_direction [ 6 : 8 ] --000-memory to memory, 001-memory to peripheral,
* 010-peripheral to memory ...
* complete_callback_en [ 9 ] --0-callback invoked at completion only
* 1-callback invoked at completion of each block
* error_callback_en [ 10 ] --0-err callback enabled
* 1-err callback disabled
* source_handshake [ 11 ] --0-HW, 1-SW
* dest_handshake [ 12 ] --0-HW, 1-SW
* channel_priority [ 13 : 16 ] --DMA channel priority
* source_chaining_en [ 17 ] --enable/disable source block chaining
* 0-disable, 1-enable
* dest_chaining_en [ 18 ] --enable/disable destination block chaining
* 0-disable, 1-enable
* RESERVED [ 19 : 31 ]
* config_size is a bit field with the following parts:
* source_data_size [ 0 : 7 ] --number of bytes
* dest_data_size [ 8 : 15 ] -- number of bytes
* source_burst_length [ 16 : 23 ] -- number of source data units
* dest_burst_length [ 24 : 31 ] -- number of destination data units
* dma_callback is the callback function pointer. If enabled, callback function will be invoked
* at transfer completion or when error happens (non zero error_code).
*/
struct dma_config {
uint32_t config;
uint32_t config_size;
uint32_t block_count;
struct dma_block_config *head_block;
void (*dma_callback)(struct device *dev, uint32_t channel, int error_code); }

API Interfaces
-------

/**
* @brief Configure individual channel for DMA transfer.
*
* @param dev Pointer to the device structure for the driver instance.
* @param channel Numeric identification of the channel to configure
* @param config Data structure containing the intended configuration for the
* selected channel
*
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
static inline int dma_config(struct device *dev, uint32_t channel,
struct dma_config *config)
{
}

/**
* @brief Enables DMA channel and starts the transfer, the channel must be
* configured beforehand.
*
* @param dev Pointer to the device structure for the driver instance.
* @param channel Numeric identification of the channel where the transfer will
* be processed
*
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
static inline int dma_start(struct device *dev, uint32_t channel)
{
}

/**
* @brief Stops the DMA transfer and disables the channel.
*
* @param dev Pointer to the device structure for the driver instance.
* @param channel Numeric identification of the channel where the transfer was
* being processed
*
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
static inline int dma_stop(struct device *dev, uint32_t channel)
{
}

All existing data structure definitions and APIs will be deprecated.

-----Original Message-----
From: Liu, Baohong [mailto:baohong.liu(a)intel.com]
Sent: Wednesday, January 11, 2017 11:50 AM
To: devel(a)lists.zephyrproject.org
Subject: [devel] [RFC]DMA API Update


Hi everyone,

I would like to propose the update for DMA API.
(https://jira.zephyrproject.org/browse/ZEP-873).

Known Problems
--------

Struct dma_channel_config consists of quite a few variables of enum types,
two callback function pointers, and one callback user data pointer.

- The enums can be collapsed into a bit field.
This will reduce the size of the data structure.

- The two callback function pointers (for normal and error cases) can be
combined.
A parameter of error code can be used to differentiate the two cases. So,
the
current callback parameter of user data pointer will be replaced by two new
parameters. One for error code and the other one for channel id.

- Callback data pointer can be removed.
Currently, this field holds user data. It can be moved to driver data structure.
The callback function can dig out the information from dev pointer and
channel id passed to it.

Proposed Solution
--------

-- The following are the enums we have now.

handshake_interface /* which peripheral and direction*/
hankshake_polarity /* high or low*/
channel_direction /* memory to memory, memory to peripheral ... */
Source_transfer_width /* source data size */
Destination_transfer_width /* destination data size */
Source_burst_length /* source burst length */
Destination_burst_length /* destination burst length */

All these will be collapsed into a bit field. Some of them will have new names.

Besides the above, three new items will be added.
source_handshake /* HW or SW */
dest_handshake /* HW or SW */
channel_priority /* DMA channel priority */

-- For the callback function, there will be three parameters. They are device
pointer,
channel_id, and error code. As said above, the error callback will be
removed.

-- The callback_data pointer will be removed.

Final API Format
--------

/**
* @brief DMA configuration structure.
*
* config is a bit field with the following parts:
* dma_slot [ 0 : 5 ] --which peripheral and
direction(HW specific)
* hankshake_polarity [ 6 ] --high or low
* channel_direction [ 7 : 9 ] --0-memory to memory, 1-
memory to peripheral,
* 2-peripheral to memory
* source_data_size [ 10 : 12 ] --source data size(8,16,32,64,128
and 256 bits)
* dest_data_size [ 13 : 15 ] --destination data
size(8,16,32,64,128 and 256 bits)
* source_burst_length [ 16 : 18 ] --number of source data
unit(1,4,8,16,32,64,128 and 256)
* dest_burst_length [ 19 : 21 ] -- number of dest data
unit(1,4,8,16,32,64,128 and 256)
* source_handshake [ 22 ] --HW or SW
* dest_handshake [ 23 ] --HW or SW
* channel_priority [ 24 : 27 ] --DMA channel priority
* RESERVED [ 28 : 31 ]
* dma_callback is the callback function pointer
*/
struct dma_channel_config {
uint32_t config;
void (*dma_callback)(struct device *dev, uint32_t channel, int
error_code); }

The remaining parts will stay the same.
No change to the structure dma_transfer_config.
No change to the API function prototypes:
dma_channel_config(...)
dma_transfer_config(...)
dma_transfer_start(...)
dma_transfer_stop(...)

(Note: for xx_data_size and xx_burst_length in the above bit field, the value
will only serve as an index. For example, for source_data_size, bit field values
of 0, 1, 2, 3, 4 and 5 will correspond to sizes of 8,16,32,64,128 and 256 bits.)

Suggestions and comments are welcome.

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