blob: acaf3cb5f7cd5467904152ac6d4a6ce95c37856c [file] [log] [blame]
/***************************************************************************//**
* \file cy_dma.c
* \version 2.10
*
* \brief
* The source code file for the DMA driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
#include "cy_dma.h"
#ifdef CY_IP_M4CPUSS_DMA
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* Function Name: Cy_DMA_Crc_Init
****************************************************************************//**
*
* Initializes the DMA CRC functionality.
*
* \param base The pointer to the hardware DMA block.
*
* \param crcConfig The pointer to the CRC configuration structure
* \ref cy_stc_dma_crc_config_t.
*
* \return The status /ref cy_en_dma_status_t.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Crc_Init
*
*******************************************************************************/
cy_en_dma_status_t Cy_DMA_Crc_Init(DW_Type * base, cy_stc_dma_crc_config_t const * crcConfig)
{
cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
if((NULL != base) && (NULL != crcConfig) && CY_DW_CRC)
{
DW_CRC_CTL(base) = _BOOL2FLD(DW_V2_CRC_CTL_DATA_REVERSE, crcConfig->dataReverse) |
_BOOL2FLD(DW_V2_CRC_CTL_REM_REVERSE, crcConfig->reminderReverse);
DW_CRC_DATA_CTL(base) = _VAL2FLD(DW_V2_CRC_DATA_CTL_DATA_XOR, crcConfig->dataXor);
DW_CRC_REM_CTL(base) = _VAL2FLD(DW_V2_CRC_REM_CTL_REM_XOR, crcConfig->reminderXor);
DW_CRC_POL_CTL(base) = _VAL2FLD(DW_V2_CRC_POL_CTL_POLYNOMIAL, crcConfig->polynomial);
ret = CY_DMA_SUCCESS;
}
return ret;
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_Init
****************************************************************************//**
*
* Initializes the descriptor structure in SRAM from a pre-initialized
* configuration structure.
* This function initializes only the descriptor and not the channel.
*
* \param descriptor
* The descriptor structure instance declared by the user/component.
*
* \param config
* This is a configuration structure that has all initialization information for
* the descriptor.
*
* \return
* The status /ref cy_en_dma_status_t.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Enable
*
*******************************************************************************/
cy_en_dma_status_t Cy_DMA_Descriptor_Init(cy_stc_dma_descriptor_t * descriptor, const cy_stc_dma_descriptor_config_t * config)
{
cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
if ((NULL != descriptor) && (NULL != config))
{
CY_ASSERT_L3(CY_DMA_IS_RETRIG_VALID(config->retrigger));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->interruptType));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerOutType));
CY_ASSERT_L3(CY_DMA_IS_TRIG_TYPE_VALID(config->triggerInType));
CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->srcTransferSize));
CY_ASSERT_L3(CY_DMA_IS_XFER_SIZE_VALID(config->dstTransferSize));
CY_ASSERT_L3(CY_DMA_IS_CHANNEL_STATE_VALID(config->channelState));
CY_ASSERT_L3(CY_DMA_IS_DATA_SIZE_VALID(config->dataSize));
CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(config->descriptorType));
descriptor->ctl =
_VAL2FLD(CY_DMA_CTL_RETRIG, config->retrigger) |
_VAL2FLD(CY_DMA_CTL_INTR_TYPE, config->interruptType) |
_VAL2FLD(CY_DMA_CTL_TR_OUT_TYPE, config->triggerOutType) |
_VAL2FLD(CY_DMA_CTL_TR_IN_TYPE, config->triggerInType) |
_VAL2FLD(CY_DMA_CTL_SRC_SIZE, config->srcTransferSize) |
_VAL2FLD(CY_DMA_CTL_DST_SIZE, config->dstTransferSize) |
_VAL2FLD(CY_DMA_CTL_CH_DISABLE, config->channelState) |
_VAL2FLD(CY_DMA_CTL_DATA_SIZE, config->dataSize) |
_VAL2FLD(CY_DMA_CTL_TYPE, config->descriptorType);
descriptor->src = (uint32_t)config->srcAddress;
descriptor->dst = (uint32_t)config->dstAddress;
switch(config->descriptorType)
{
case CY_DMA_SINGLE_TRANSFER:
descriptor->xCtl = (uint32_t)config->nextDescriptor;
ret = CY_DMA_SUCCESS;
break;
case CY_DMA_1D_TRANSFER:
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
descriptor->xCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
/* Convert the data count from the user's range (1-256) into the machine range (0-255). */
_VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
descriptor->yCtl = (uint32_t)config->nextDescriptor;
ret = CY_DMA_SUCCESS;
break;
case CY_DMA_2D_TRANSFER:
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstXincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcYincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->dstYincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->yCount));
descriptor->xCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstXincrement) |
/* Convert the data count from the user's range (1-256) into the machine range (0-255). */
_VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
descriptor->yCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcYincrement) |
_VAL2FLD(CY_DMA_CTL_DST_INCR, config->dstYincrement) |
/* Convert the data count from the user's range (1-256) into the machine range (0-255). */
_VAL2FLD(CY_DMA_CTL_COUNT, config->yCount - 1UL);
descriptor->nextPtr = (uint32_t)config->nextDescriptor;
ret = CY_DMA_SUCCESS;
break;
case CY_DMA_CRC_TRANSFER:
if (CY_DW_CRC)
{
CY_ASSERT_L2(0L == config->dstXincrement);
CY_ASSERT_L2(CY_DMA_IS_LOOP_INCR_VALID(config->srcXincrement));
CY_ASSERT_L2(CY_DMA_IS_LOOP_COUNT_VALID(config->xCount));
descriptor->xCtl =
_VAL2FLD(CY_DMA_CTL_SRC_INCR, config->srcXincrement) |
/* Convert the data count from the user's range (1-256) into the machine range (0-255). */
_VAL2FLD(CY_DMA_CTL_COUNT, config->xCount - 1UL);
descriptor->yCtl = (uint32_t)config->nextDescriptor;
ret = CY_DMA_SUCCESS;
}
break;
default: /* An unsupported type of a descriptor */
break;
}
}
return ret;
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_DeInit
****************************************************************************//**
*
* Clears the content of the specified descriptor.
*
* \param descriptor
* The descriptor structure instance declared by the user/component.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Descriptor_Deinit
*
*******************************************************************************/
void Cy_DMA_Descriptor_DeInit(cy_stc_dma_descriptor_t * descriptor)
{
descriptor->ctl = 0UL;
descriptor->src = 0UL;
descriptor->dst = 0UL;
descriptor->xCtl = 0UL;
descriptor->yCtl = 0UL;
descriptor->nextPtr = 0UL;
}
/*******************************************************************************
* Function Name: Cy_DMA_Channel_Init
****************************************************************************//**
*
* Initializes the DMA channel with a descriptor and other parameters.
*
* \param base
* The pointer to the hardware DMA block.
*
* \param channel
* A channel number.
*
* \param channelConfig
* The structure that has the initialization information for the
* channel.
*
* \return
* The status /ref cy_en_dma_status_t.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Enable
*
*******************************************************************************/
cy_en_dma_status_t Cy_DMA_Channel_Init(DW_Type * base, uint32_t channel, cy_stc_dma_channel_config_t const * channelConfig)
{
cy_en_dma_status_t ret = CY_DMA_BAD_PARAM;
if ((NULL != base) &&
(NULL != channelConfig) &&
(NULL != channelConfig->descriptor) &&
(CY_DMA_IS_CH_NR_VALID(channel)))
{
CY_ASSERT_L2(CY_DMA_IS_PRIORITY_VALID(channelConfig->priority));
/* Set the current descriptor */
DW_CH_CURR_PTR(base, channel) = (uint32_t)channelConfig->descriptor;
/* Set the channel configuration */
DW_CH_CTL(base, channel) =
_BOOL2FLD(DW_CH_STRUCT_CH_CTL_PREEMPTABLE, channelConfig->preemptable) |
_VAL2FLD(DW_CH_STRUCT_CH_CTL_PRIO, channelConfig->priority) |
_BOOL2FLD(DW_CH_STRUCT_CH_CTL_ENABLED, channelConfig->enable) |
_BOOL2FLD(DW_CH_STRUCT_CH_CTL_B, channelConfig->bufferable);
ret = CY_DMA_SUCCESS;
}
return (ret);
}
/*******************************************************************************
* Function Name: Cy_DMA_Channel_DeInit
****************************************************************************//**
*
* Clears the content of registers corresponding to the channel.
*
* \param base
* The pointer to the hardware DMA block.
*
* \param channel
* A channel number.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Disable
*
*******************************************************************************/
void Cy_DMA_Channel_DeInit(DW_Type * base, uint32_t channel)
{
CY_ASSERT_L1(CY_DMA_IS_CH_NR_VALID(channel));
DW_CH_CTL(base, channel) = 0UL;
DW_CH_IDX(base, channel) = 0UL;
DW_CH_CURR_PTR(base, channel) = 0UL;
DW_CH_INTR_MASK(base, channel) = 0UL;
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_SetNextDescriptor
****************************************************************************//**
*
* Sets a Next Descriptor parameter for the specified descriptor.
*
* Based on the descriptor type, the offset of the address for the next descriptor may
* vary. For the single-transfer descriptor type, this register is at offset 0x0c.
* For the 1D-transfer descriptor type, this register is at offset 0x10.
* For the 2D-transfer descriptor type, this register is at offset 0x14.
*
* \param descriptor
* The descriptor structure instance declared by the user/component.
*
* \param nextDescriptor
* The pointer to the next descriptor.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Descriptor_SetNextDescriptor
*
*******************************************************************************/
void Cy_DMA_Descriptor_SetNextDescriptor(cy_stc_dma_descriptor_t * descriptor, cy_stc_dma_descriptor_t const * nextDescriptor)
{
CY_ASSERT_L1(NULL != descriptor);
switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl))
{
case CY_DMA_SINGLE_TRANSFER:
descriptor->xCtl = (uint32_t)nextDescriptor;
break;
case CY_DMA_CRC_TRANSFER:
case CY_DMA_1D_TRANSFER:
descriptor->yCtl = (uint32_t)nextDescriptor;
break;
case CY_DMA_2D_TRANSFER:
descriptor->nextPtr = (uint32_t)nextDescriptor;
break;
default:
/* Unsupported type of descriptor */
break;
}
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_GetNextDescriptor
****************************************************************************//**
*
* Returns a next descriptor address of the specified descriptor.
*
* Based on the descriptor type, the offset of the address for the next descriptor may
* vary. For a single-transfer descriptor type, this register is at offset 0x0c.
* For the 1D-transfer descriptor type, this register is at offset 0x10.
* For the 2D-transfer descriptor type, this register is at offset 0x14.
*
* \param descriptor
* The descriptor structure instance declared by the user/component.
*
* \return
* The pointer to the next descriptor.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Descriptor_GetNextDescriptor
*
*******************************************************************************/
cy_stc_dma_descriptor_t * Cy_DMA_Descriptor_GetNextDescriptor(cy_stc_dma_descriptor_t const * descriptor)
{
cy_stc_dma_descriptor_t * retVal = NULL;
CY_ASSERT_L1(NULL != descriptor);
switch((cy_en_dma_descriptor_type_t) _FLD2VAL(CY_DMA_CTL_TYPE, descriptor->ctl))
{
case CY_DMA_SINGLE_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->xCtl;
break;
case CY_DMA_CRC_TRANSFER:
case CY_DMA_1D_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->yCtl;
break;
case CY_DMA_2D_TRANSFER:
retVal = (cy_stc_dma_descriptor_t*) descriptor->nextPtr;
break;
default:
/* An unsupported type of the descriptor */
break;
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_DMA_Descriptor_SetDescriptorType
****************************************************************************//**
*
* Sets the descriptor's type for the specified descriptor.
* Moves the next descriptor register value into the proper place in accordance
* to the actual descriptor type.
* During the descriptor's type changing, the Xloop and Yloop settings, such as
* data count and source/destination increment (i.e. the content of the
* xCtl and yCtl descriptor registers) might be lost (overriden by the
* next descriptor value) because of the different descriptor registers structures
* for different descriptor types. Set up carefully the Xloop
* (and Yloop, if used) data count and source/destination increment if the
* descriptor type is changed from a simpler to a more complicated type
* ("single transfer" -> "1D", "1D" -> "2D", etc.).
*
* \param descriptor
* The descriptor structure instance declared by the user/component.
*
* \param descriptorType
* The descriptor type \ref cy_en_dma_descriptor_type_t.
*
* \funcusage
* \snippet dma\2.10\snippet\main.c snippet_Cy_DMA_Descriptor_SetNextDescriptor
*
*******************************************************************************/
void Cy_DMA_Descriptor_SetDescriptorType(cy_stc_dma_descriptor_t * descriptor, cy_en_dma_descriptor_type_t descriptorType)
{
CY_ASSERT_L1(NULL != descriptor);
CY_ASSERT_L3(CY_DMA_IS_TYPE_VALID(descriptorType));
if ((CY_DMA_CRC_TRANSFER != descriptorType) || CY_DW_CRC)
{
if (descriptorType != Cy_DMA_Descriptor_GetDescriptorType(descriptor)) /* Don't perform if the type is not changed */
{
/* Store the current nextDescriptor pointer. */
cy_stc_dma_descriptor_t * locNextDescriptor = Cy_DMA_Descriptor_GetNextDescriptor(descriptor);
/* Change the descriptor type. */
CY_REG32_CLR_SET(descriptor->ctl, CY_DMA_CTL_TYPE, descriptorType);
/* Restore the nextDescriptor pointer into the proper place. */
Cy_DMA_Descriptor_SetNextDescriptor(descriptor, locNextDescriptor);
}
}
}
#if defined(__cplusplus)
}
#endif
#endif /* CY_IP_M4CPUSS_DMA */
/* [] END OF FILE */