Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
340 lines
16 KiB
C
340 lines
16 KiB
C
/***************************************************************************//**
|
|
* \file cyhal_dma.h
|
|
*
|
|
* \brief
|
|
* Provides a high level interface for interacting with the Cypress DMA.
|
|
* This interface abstracts out the chip specific details. If any chip specific
|
|
* functionality is necessary, or performance is critical the low level functions
|
|
* can be used directly.
|
|
*
|
|
********************************************************************************
|
|
* \copyright
|
|
* Copyright 2018-2021 Cypress Semiconductor Corporation
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*******************************************************************************/
|
|
|
|
/**
|
|
* \addtogroup group_hal_dma DMA (Direct Memory Access)
|
|
* \ingroup group_hal
|
|
* \{
|
|
* High level interface for interacting with the direct memory access (DMA).
|
|
* The DMA driver allows for initializing and configuring a DMA channel in
|
|
* order to trigger data transfers to and from memory and peripherals. The
|
|
* transfers occur independently of the CPU and are triggered in software.
|
|
* Multiple channels can be active at the same time each with their own
|
|
* user-selectable priority and transfer characteristics.
|
|
*
|
|
* \section section_dma_features Features
|
|
* * CPU independent memory access
|
|
* * Access to memory and peripherals
|
|
* * Multiple independent channels
|
|
* * Configurable transer sizes and bursts
|
|
* * Configurable priorities
|
|
* * Event completion notification
|
|
*
|
|
* \section section_dma_quickstart Quick Start
|
|
*
|
|
* See \ref subsection_dma_snippet_1 for a code snippet that sets up a DMA
|
|
* transfer to move memory from one location to another.
|
|
*
|
|
* \section section_dma_snippets Code snippets
|
|
* \note Error handling code has been intentionally left out of snippets to highlight API usage.
|
|
*
|
|
* \subsection subsection_dma_snippet_1 Snippet 1: Simple DMA initialization and transfer
|
|
* The following snippet initializes a DMA channel and uses it to transfer a a single block of memory.
|
|
* The DMA channel is reserved by calling \ref cyhal_dma_init. It then needs to be configured with
|
|
* \ref cyhal_dma_configure and then the transfer is started with \ref cyhal_dma_start_transfer.<br>
|
|
* If the DMA channel is not needed anymore, it can be released by calling \ref cyhal_dma_free
|
|
*
|
|
* \snippet hal_dma.c snippet_cyhal_dma_simple_init
|
|
*
|
|
*
|
|
* \subsection subsection_dma_snippet_2 Snippet 2: Configuring the DMA channel based on memory requirements
|
|
* \ref cyhal_dma_configure can be used after DMA initialization to handle a variety of memory layouts.
|
|
*
|
|
* \snippet hal_dma.c snippet_cyhal_dma_configure
|
|
*
|
|
*
|
|
* \subsection subsection_dma_snippet_3 Snippet 3: Interrupts and retriggering DMA transfers
|
|
* DMA events like transfer complete or error events can be used to trigger a callback function. <br>
|
|
* This snippet uses \ref cyhal_dma_configure to break the full transfer into multiple bursts. This
|
|
* allows higher priority items access to the memory bus if necessary while the DMA operation is still
|
|
* in progress. It then uses \ref cyhal_dma_enable_event() to enable the transfer complete event to
|
|
* trigger the callback function registered by \ref cyhal_dma_register_callback().
|
|
*
|
|
* \snippet hal_dma.c snippet_cyhal_dma_events
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include "cy_result.h"
|
|
#include "cyhal_hw_types.h"
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \addtogroup group_hal_results_dma DMA HAL Results
|
|
* DMA specific return codes
|
|
* \ingroup group_hal_results
|
|
* \{ *//**
|
|
*/
|
|
|
|
/** Invalid transfer width parameter error */
|
|
#define CYHAL_DMA_RSLT_ERR_INVALID_TRANSFER_WIDTH \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 0))
|
|
/** Invalid parameter error */
|
|
#define CYHAL_DMA_RSLT_ERR_INVALID_PARAMETER \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 1))
|
|
/** Invalid priority parameter error */
|
|
#define CYHAL_DMA_RSLT_ERR_INVALID_PRIORITY \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 2))
|
|
/** Invalid src or dst addr alignment error */
|
|
#define CYHAL_DMA_RSLT_ERR_INVALID_ALIGNMENT \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 3))
|
|
/** Invalid burst_size paramenter error */
|
|
#define CYHAL_DMA_RSLT_ERR_INVALID_BURST_SIZE \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 4))
|
|
/** Channel busy error */
|
|
#define CYHAL_DMA_RSLT_ERR_CHANNEL_BUSY \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_DMA, 5))
|
|
/** Transfer has already been started warning */
|
|
#define CYHAL_DMA_RSLT_WARN_TRANSFER_ALREADY_STARTED \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_WARNING, CYHAL_RSLT_MODULE_DMA, 6))
|
|
/** Unsupported hardware error */
|
|
#define CYHAL_DMA_RSLT_FATAL_UNSUPPORTED_HARDWARE \
|
|
(CYHAL_RSLT_CREATE(CY_RSLT_TYPE_FATAL, CYHAL_RSLT_MODULE_DMA, 7))
|
|
|
|
/**
|
|
* \}
|
|
*/
|
|
|
|
/** Direction for DMA transfers. */
|
|
typedef enum
|
|
{
|
|
CYHAL_DMA_DIRECTION_MEM2MEM, //!< Memory to memory
|
|
CYHAL_DMA_DIRECTION_MEM2PERIPH, //!< Memory to peripheral
|
|
CYHAL_DMA_DIRECTION_PERIPH2MEM, //!< Peripheral to memory
|
|
CYHAL_DMA_DIRECTION_PERIPH2PERIPH, //!< Peripheral to peripheral
|
|
} cyhal_dma_direction_t;
|
|
|
|
/** Flags enum of DMA events. Multiple events can be enabled. */
|
|
typedef enum
|
|
{
|
|
CYHAL_DMA_NO_INTR = 0, //!< No interrupt
|
|
CYHAL_DMA_TRANSFER_COMPLETE = 1 << 0, //!< Indicates that a burst or full transfer has completed
|
|
CYHAL_DMA_SRC_BUS_ERROR = 1 << 1, //!< Indicates that there is a source bus error
|
|
CYHAL_DMA_DST_BUS_ERROR = 1 << 2, //!< Indicates that there is a destination bus error
|
|
CYHAL_DMA_SRC_MISAL = 1 << 3, //!< Indicates that the source address is not aligned
|
|
CYHAL_DMA_DST_MISAL = 1 << 4, //!< Indicates that the destination address is not aligned
|
|
CYHAL_DMA_CURR_PTR_NULL = 1 << 5, //!< Indicates that the current descriptor pointer is null
|
|
CYHAL_DMA_ACTIVE_CH_DISABLED = 1 << 6, //!< Indicates that the active channel is disabled
|
|
CYHAL_DMA_DESCR_BUS_ERROR = 1 << 7, //!< Indicates that there has been a descriptor bus error
|
|
} cyhal_dma_event_t;
|
|
|
|
/** Specifies the transfer type to trigger when an input signal is received.
|
|
* */
|
|
typedef enum
|
|
{
|
|
CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT, //!< Transfer a single element when an input signal is received
|
|
CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST, //!< Transfer a single burst when an input signal is received
|
|
CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS, //!< Transfer all elements when an input signal is received
|
|
} cyhal_dma_input_t;
|
|
|
|
/** Specifies the transfer completion event that triggers a signal output. */
|
|
typedef enum
|
|
{
|
|
CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT, //!< Trigger an output when a single element is transferred
|
|
CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST, //!< Trigger an output when a single burst is transferred
|
|
CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS, //!< Trigger an output when all elements are transferred
|
|
} cyhal_dma_output_t;
|
|
|
|
/** If burst_size is used, selects whether a single trigger of the channel
|
|
* transfers a single burst of burst_size or a full transfer of size length
|
|
* (that is, every burst is triggered). This will also set the initial transfer
|
|
* type that will trigger an output signal on completion.*/
|
|
typedef enum
|
|
{
|
|
CYHAL_DMA_TRANSFER_BURST, //!< A single burst is triggered and a transfer completion event will occur after the burst
|
|
CYHAL_DMA_TRANSFER_FULL, //!< All bursts are triggered and a single transfer completion event will occur at the end of all of them
|
|
} cyhal_dma_transfer_action_t;
|
|
|
|
/** \brief Configuration of a DMA channel. When configuring address,
|
|
* increments, and transfer width keep in mind your hardware may have more
|
|
* stringent address and data alignment requirements. */
|
|
typedef struct
|
|
{
|
|
uint32_t src_addr; //!< Source address
|
|
int16_t src_increment; //!< Source address auto increment amount in multiples of transfer_width
|
|
uint32_t dst_addr; //!< Destination address
|
|
int16_t dst_increment; //!< Destination address auto increment amount in multiples of transfer_width
|
|
uint8_t transfer_width; //!< Transfer width in bits. Valid values are: 8, 16, or 32
|
|
uint32_t length; //!< Number of elements to be transferred in total
|
|
uint32_t burst_size; //!< Number of elements to be transferred per trigger. If set to 0 every element is transferred, otherwise burst_size must evenly divide length.
|
|
cyhal_dma_transfer_action_t action; //!< Sets the behavior of the channel when triggered (using start_transfer). Ignored if burst_size is not configured.
|
|
} cyhal_dma_cfg_t;
|
|
|
|
/** Event handler for DMA interrupts */
|
|
typedef void (*cyhal_dma_event_callback_t)(void *callback_arg, cyhal_dma_event_t event);
|
|
|
|
/** DMA input connection information to setup while initializing the driver. */
|
|
typedef struct
|
|
{
|
|
cyhal_source_t source; //!< Source of signal to DMA; obtained from another driver's cyhal_<PERIPH>_enable_output
|
|
cyhal_dma_input_t input; //!< DMA input signal to be driven
|
|
} cyhal_dma_src_t;
|
|
|
|
/** DMA output connection information to setup while initializing the driver. */
|
|
typedef struct
|
|
{
|
|
cyhal_dma_output_t output; //!< Output signal of DMA
|
|
cyhal_dest_t dest; //!< Destination of DMA signal
|
|
} cyhal_dma_dest_t;
|
|
|
|
/** Initialize the DMA peripheral.
|
|
*
|
|
* If a source signal is provided for \p src, this will connect the provided signal to the DMA
|
|
* just as would be done by calling \ref cyhal_dma_connect_digital. Similarly, if a destination
|
|
* target is provided for \p dest this will enable the specified output just as would be done
|
|
* by calling \ref cyhal_dma_enable_output.
|
|
* @param[out] obj Pointer to a DMA object. The caller must allocate the memory
|
|
* for this object but the init function will initialize its contents.
|
|
* @param[in] src An optional source signal to connect to the DMA
|
|
* @param[in] dest An optional destination singal to drive from the DMA
|
|
* @param[out] dest_source An optional pointer to user-allocated source signal object which
|
|
* will be initialized by enable_output. If \p dest is non-null, this must also be non-null.
|
|
* \p dest_source should be passed to (dis)connect_digital functions to (dis)connect the
|
|
* associated endpoints.
|
|
* @param[in] priority The priority of this DMA operation relative to others. The number of
|
|
* priority levels which are supported is hardware dependent. All implementations define a
|
|
* #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will
|
|
* also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW.
|
|
* The behavior of any other value is implementation defined. See the implementation-specific DMA
|
|
* documentation for more details.
|
|
* @param[in] direction The direction memory is copied
|
|
* @return The status of the init request
|
|
*/
|
|
cy_rslt_t cyhal_dma_init_adv(cyhal_dma_t *obj, cyhal_dma_src_t *src, cyhal_dma_dest_t *dest, cyhal_source_t *dest_source, uint8_t priority, cyhal_dma_direction_t direction);
|
|
|
|
/** Initialize the DMA peripheral.
|
|
*
|
|
* @param[out] obj Pointer to a DMA object. The caller must allocate the memory
|
|
* for this object but the init function will initialize its contents.
|
|
* @param[in] priority The priority of this DMA operation relative to others. The number of priority levels which are supported is hardware dependent. All implementations define a #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW. The behavior of any other value is implementation defined. See the implementation-specific DMA documentation for more details.
|
|
* @param[in] direction The direction memory is copied
|
|
* @return The status of the init request
|
|
*/
|
|
#define cyhal_dma_init(obj, priority, direction) (cyhal_dma_init_adv(obj, NULL, NULL, NULL, priority, direction))
|
|
|
|
/** Free the DMA object. Freeing a DMA object while a transfer is in
|
|
progress (see @ref cyhal_dma_is_busy) is invalid.
|
|
*
|
|
* @param[in,out] obj The DMA object
|
|
*/
|
|
void cyhal_dma_free(cyhal_dma_t *obj);
|
|
|
|
/** Setup a DMA descriptor for specified resource
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] cfg Configuration parameters for the transfer
|
|
* @return The status of the configure request
|
|
*/
|
|
cy_rslt_t cyhal_dma_configure(cyhal_dma_t *obj, const cyhal_dma_cfg_t *cfg);
|
|
|
|
/** Initiates DMA channel transfer for specified DMA object
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @return The status of the start_transfer request
|
|
*/
|
|
cy_rslt_t cyhal_dma_start_transfer(cyhal_dma_t *obj);
|
|
|
|
/** Checks whether a transfer is pending or running on the DMA channel
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @return True if DMA channel is busy
|
|
*/
|
|
bool cyhal_dma_is_busy(cyhal_dma_t *obj);
|
|
|
|
/** Register a DMA callback handler.
|
|
*
|
|
* This function will be called when one of the events enabled by \ref cyhal_dma_enable_event occurs.
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] callback The callback handler which will be invoked when an event triggers
|
|
* @param[in] callback_arg Generic argument that will be provided to the callback when called
|
|
*/
|
|
void cyhal_dma_register_callback(cyhal_dma_t *obj, cyhal_dma_event_callback_t callback, void *callback_arg);
|
|
|
|
/** Configure DMA event enablement.
|
|
*
|
|
* When an enabled event occurs, the function specified by \ref cyhal_dma_register_callback will be called.
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] event The DMA event type
|
|
* @param[in] intr_priority The priority for NVIC interrupt events. The priority from the most recent call will take precedence, i.e all events will have the same priority.
|
|
* @param[in] enable True to turn on interrupts, False to turn off
|
|
*/
|
|
void cyhal_dma_enable_event(cyhal_dma_t *obj, cyhal_dma_event_t event, uint8_t intr_priority, bool enable);
|
|
|
|
/** Connects a source signal and enables the specified input to the DMA
|
|
* channel
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
|
|
* @param[in] input Which input to enable
|
|
* @return The status of the connection
|
|
* */
|
|
cy_rslt_t cyhal_dma_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
|
|
|
|
/** Enables the specified output signal from a DMA channel that is triggered when a transfer is completed
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] output Which event triggers the output
|
|
* @param[out] source Pointer to user-allocated source signal object which
|
|
* will be initialized by enable_output. \p source should be passed to
|
|
* (dis)connect_digital functions to (dis)connect the associated endpoints.
|
|
* @return The status of the output enable
|
|
* */
|
|
cy_rslt_t cyhal_dma_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source);
|
|
|
|
/** Disconnects a source signal and disables the specified input to the DMA channel
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] source Source signal from cyhal_<PERIPH>_enable_output to disable
|
|
* @param[in] input Which input to disable
|
|
* @return The status of the disconnect
|
|
* */
|
|
cy_rslt_t cyhal_dma_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
|
|
|
|
/** Disables the specified output signal from a DMA channel
|
|
*
|
|
* @param[in] obj The DMA object
|
|
* @param[in] output Which output to disable
|
|
* @return The status of the disablement
|
|
* */
|
|
cy_rslt_t cyhal_dma_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output);
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#ifdef CYHAL_DMA_IMPL_HEADER
|
|
#include CYHAL_DMA_IMPL_HEADER
|
|
#endif /* CYHAL_DMA_IMPL_HEADER */
|
|
|
|
/** \} group_hal_dma */
|