S32 Design Studio PE工具配置DMA

工具配置

DMA位置跟设备不一样,在Referenced_components里面。

Configurations里面就默认配置就行

channels是比较重要的,一条信号传输用到一个通道。可以选择UART、ADC、CAN之类的,这里用在了SPI通讯里面。

生成代码

在 Generated_Code\dmaController1.c里面,对应刚才配置的信息。

edma_state_t dmaController1_State;

edma_chn_state_t dmaController1Chn0_State;

edma_chn_state_t dmaController1Chn1_State;

edma_chn_state_t * const edmaChnStateArray[] = {
    &dmaController1Chn0_State,
    &dmaController1Chn1_State
};

edma_channel_config_t dmaController1Chn0_Config = {//通道0配置
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN0_NUMBER,
    .source = EDMA_REQ_LPSPI0_RX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
edma_channel_config_t dmaController1Chn1_Config = {//通道1配置
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN1_NUMBER,
    .source = EDMA_REQ_LPSPI0_TX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
const edma_channel_config_t * const edmaChnConfigArray[] = {//通道数组
    &dmaController1Chn0_Config,
    &dmaController1Chn1_Config
};

const edma_user_config_t dmaController1_InitConfig0 = {//控制器配置
    .chnArbitration = EDMA_ARBITRATION_FIXED_PRIORITY,
    .haltOnError = false
};

接口使用

EDMA_DRV_Init

初始化接口,基本上调用这个就能把DMA用起来,里面的参数都是自动生成的。

EDMA_DRV_Init(&dmaController1_State,&dmaController1_InitConfig0,edmaChnStateArray, edmaChnConfigArray,EDMA_CONFIGURED_CHANNELS_COUNT);

函数原型

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_Init
 * Description   : Initializes the eDMA module.
 *
 * Implements    : EDMA_DRV_Init_Activity
 *END**************************************************************************/
status_t EDMA_DRV_Init(edma_state_t *edmaState,
                       const edma_user_config_t *userConfig,
                       edma_chn_state_t * const chnStateArray[],
                       const edma_channel_config_t * const chnConfigArray[],
                       uint32_t chnCount)
{
    uint32_t index = 0U;
    DMA_Type *edmaRegBase = NULL;
    IRQn_Type irqNumber = NotAvail_IRQn;
    status_t edmaStatus = STATUS_SUCCESS;
    status_t chnInitStatus = STATUS_SUCCESS;
#if defined (CUSTOM_DEVASSERT) || defined (DEV_ERROR_DETECT)
    uint32_t freq = 0U;
    status_t clockManagerStatus = STATUS_SUCCESS;
#endif

    /* Check the state and configuration structure pointers are valid */
    DEV_ASSERT((edmaState != NULL) && (userConfig != NULL));

    /* Check the module has not already been initialized */
    DEV_ASSERT(s_virtEdmaState == NULL);

#if defined (CUSTOM_DEVASSERT) || defined (DEV_ERROR_DETECT)
    /* Check that eDMA and DMAMUX modules are clock gated on */
    for (index = 0U; index < (uint32_t)DMA_INSTANCE_COUNT; index++)
    {
        clockManagerStatus = CLOCK_SYS_GetFreq(s_edmaClockNames[index], &freq);
        DEV_ASSERT(clockManagerStatus == STATUS_SUCCESS);
    }
#ifdef FEATURE_DMAMUX_AVAILABLE
    for (index = 0U; index < (uint32_t)DMAMUX_INSTANCE_COUNT; index++)
    {
        clockManagerStatus = CLOCK_SYS_GetFreq(s_dmamuxClockNames[index], &freq);
        DEV_ASSERT(clockManagerStatus == STATUS_SUCCESS);
    }
#endif /* FEATURE_DMAMUX_AVAILABLE */
#endif /* (CUSTOM_DEVASSERT) || defined (DEV_ERROR_DETECT) */

    /* Save the runtime state structure for the driver */
    s_virtEdmaState = edmaState;

    /* Clear the state structure. */
    EDMA_DRV_ClearStructure((uint8_t *)s_virtEdmaState, sizeof(edma_state_t));

    /* Init all DMA instances */
    for(index = 0U; index < (uint32_t)DMA_INSTANCE_COUNT; index++)
    {
        edmaRegBase = s_edmaBase[index];

        /* Init eDMA module on hardware level. */
        EDMA_Init(edmaRegBase);

#ifdef FEATURE_DMA_HWV3
        /* Set arbitration mode */
        EDMA_SetChannelArbitrationMode(edmaRegBase, userConfig->chnArbitration);
#else /* FEATURE_DMA_HWV3 */
        /* Set arbitration mode */
        EDMA_SetChannelArbitrationMode(edmaRegBase, userConfig->chnArbitration);
#if (FEATURE_DMA_CHANNEL_GROUP_COUNT > 0x1U)        
        EDMA_SetGroupArbitrationMode(edmaRegBase, userConfig->groupArbitration);
        EDMA_SetGroupPriority(edmaRegBase, userConfig->groupPriority);
#endif /* (FEATURE_DMA_CHANNEL_GROUP_COUNT > 0x1U) */
#endif /* FEATURE_DMA_HWV3 */
        /* Set 'Halt on error' configuration */
        EDMA_SetHaltOnErrorCmd(edmaRegBase, userConfig->haltOnError);
    }

#if defined FEATURE_DMA_HAS_ERROR_IRQ
    /* Enable the error interrupts for eDMA module. */
    for (index = 0U; index < (uint32_t)FEATURE_DMA_VIRTUAL_ERROR_INTERRUPT_LINES; index++)
    {
        /* Enable channel interrupt ID. */
        irqNumber = s_edmaErrIrqId[index];
        INT_SYS_EnableIRQ(irqNumber);
    }
#endif

    /* Register all edma channel interrupt handlers into vector table. */
    for (index = 0U; index < (uint32_t)FEATURE_DMA_VIRTUAL_CHANNELS_INTERRUPT_LINES; index++)
    {
        /* Enable channel interrupt ID. */
        irqNumber = s_edmaIrqId[index];
        INT_SYS_EnableIRQ(irqNumber);
    }
    
#ifdef FEATURE_DMAMUX_AVAILABLE
    /* Initialize all DMAMUX instances */
    for (index = 0U; index < (uint32_t)DMAMUX_INSTANCE_COUNT; index++)
    {
        DMAMUX_Init(s_dmaMuxBase[index]);
    }
#endif

    /* Initialize the channels based on configuration list */
    if ((chnStateArray != NULL) && (chnConfigArray != NULL))
    {
        for (index = 0U; index < chnCount; index++)
        {
            chnInitStatus = EDMA_DRV_ChannelInit(chnStateArray[index], chnConfigArray[index]);
            if (chnInitStatus != STATUS_SUCCESS)
            {
                edmaStatus = chnInitStatus;
            }
        }
    }

    return edmaStatus;
}

EDMA_DRV_Deinit

逆初始化接口

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_Deinit
 * Description   : Deinitialize EDMA.
 *
 * Implements    : EDMA_DRV_Deinit_Activity
 *END**************************************************************************/
status_t EDMA_DRV_Deinit(void)
{
    uint32_t index = 0U;
    IRQn_Type irqNumber = NotAvail_IRQn;
    const edma_chn_state_t *chnState = NULL;

#if defined FEATURE_DMA_HAS_ERROR_IRQ
    /* Disable the error interrupts for eDMA module. */
    for (index = 0U; index < (uint32_t)FEATURE_DMA_VIRTUAL_ERROR_INTERRUPT_LINES; index++)
    {
        /* Enable channel interrupt ID. */
        irqNumber = s_edmaErrIrqId[index];
        INT_SYS_DisableIRQ(irqNumber);
    }
#endif

    if (s_virtEdmaState != NULL)
    {
        /* Release all edma channel. */
        for (index = 0U; index < (uint32_t)FEATURE_DMA_VIRTUAL_CHANNELS; index++)
        {
            /* Release all channels. */
            chnState = s_virtEdmaState->virtChnState[index];
            if (chnState != NULL)
            {
                (void) EDMA_DRV_ReleaseChannel(chnState->virtChn);
            }
        }
        for (index = 0U; index < (uint32_t)FEATURE_DMA_VIRTUAL_CHANNELS_INTERRUPT_LINES; index++)
        {
            /* Disable channel interrupts. */
            irqNumber = s_edmaIrqId[index];
            INT_SYS_DisableIRQ(irqNumber);
        }
    }

    s_virtEdmaState = NULL;

    return STATUS_SUCCESS;
}

EDMA_DRV_ChannelInit

通道初始化,在初始化接口里面有调用,不用再另外调用。

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ChannelInit
 * Description   : Initialize EDMA channel.
 *
 * Implements    : EDMA_DRV_ChannelInit_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ChannelInit(edma_chn_state_t *edmaChannelState,
                              const edma_channel_config_t *edmaChannelConfig)
{
    /* Check the state and configuration structure pointers are valid */
    DEV_ASSERT((edmaChannelState != NULL) && (edmaChannelConfig != NULL));

    /* Check if the module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);
    
    /* Check the channel has not already been allocated */
    DEV_ASSERT(s_virtEdmaState->virtChnState[edmaChannelConfig->virtChnConfig] == NULL);    
    
    /* Check if the channel defined by user in the channel configuration structure is valid */
    DEV_ASSERT(edmaChannelConfig->virtChnConfig < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(edmaChannelConfig->virtChnConfig);

    /* Get DMA channel from virtual channel */
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(edmaChannelConfig->virtChnConfig);

    /* Get virtual channel value */
    uint8_t virtualChannel = edmaChannelConfig->virtChnConfig;
    
    /* Get status */
    status_t retStatus = STATUS_SUCCESS;
    
    /* Load corresponding DMA instance pointer */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
        
    /* Reset the channel state structure to default value. */
    EDMA_DRV_ClearStructure((uint8_t *)edmaChannelState, sizeof(edma_chn_state_t));

#ifdef FEATURE_DMAMUX_AVAILABLE     
    retStatus = EDMA_DRV_SetChannelRequestAndTrigger(edmaChannelConfig->virtChnConfig, (uint8_t)edmaChannelConfig->source, edmaChannelConfig->enableTrigger);
#endif    

    /* Clear the TCD registers for this channel */
    EDMA_TCDClearReg(edmaRegBase, dmaChannel);

#ifdef FEATURE_DMAMUX_AVAILABLE 
    if (retStatus == STATUS_SUCCESS)
#endif
    {
        /* Set virtual channel state */
        s_virtEdmaState->virtChnState[virtualChannel] = edmaChannelState;    
        /* Set virtual channel value */
        s_virtEdmaState->virtChnState[virtualChannel]->virtChn = virtualChannel;        
        /* Set virtual channel status to normal */
        s_virtEdmaState->virtChnState[virtualChannel]->status = EDMA_CHN_NORMAL;
        
        /* Enable error interrupt for this channel */
        EDMA_SetErrorIntCmd(edmaRegBase, dmaChannel, true);        
#ifdef FEATURE_DMA_HWV3
        /* Put the channel in a priority group, as defined in configuration */
        EDMA_SetChannelPriorityGroup(edmaRegBase, dmaChannel, edmaChannelConfig->groupPriority);
#endif

        /* Set the channel priority, as defined in the configuration, only if fixed arbitration mode is selected */
        if ((EDMA_GetChannelArbitrationMode(edmaRegBase) == EDMA_ARBITRATION_FIXED_PRIORITY) &&
            (edmaChannelConfig->channelPriority != EDMA_CHN_DEFAULT_PRIORITY))
        {
            EDMA_SetChannelPriority(edmaRegBase, dmaChannel, edmaChannelConfig->channelPriority);
        }
        /* Install the user callback */
        retStatus = EDMA_DRV_InstallCallback(edmaChannelConfig->virtChnConfig, edmaChannelConfig->callback, edmaChannelConfig->callbackParam);
    }

    return retStatus;
}

EDMA_DRV_InstallCallback

安装回调函数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_InstallCallback
 * Description   : Register callback function and parameter.
 *
 * Implements    : EDMA_DRV_InstallCallback_Activity
 *END**************************************************************************/
status_t EDMA_DRV_InstallCallback(uint8_t virtualChannel,
                                  edma_callback_t callback,
                                  void *parameter)
{
    /* Check the channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check the channel is allocated */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    s_virtEdmaState->virtChnState[virtualChannel]->callback = callback;
    s_virtEdmaState->virtChnState[virtualChannel]->parameter = parameter;

    return STATUS_SUCCESS;
}

EDMA_DRV_ReleaseChannel

释放通道软硬件

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ReleaseChannel
 * Description   : Free eDMA channel's hardware and software resource.
 *
 * Implements    : EDMA_DRV_ReleaseChannel_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ReleaseChannel(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check the DMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Get pointer to channel state */
    edma_chn_state_t *chnState = s_virtEdmaState->virtChnState[virtualChannel];

    /* Check that virtual channel is initialized */
    DEV_ASSERT(chnState != NULL);

    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];

    /* Stop edma channel. */
    EDMA_SetDmaRequestCmd(edmaRegBase, dmaChannel, false);

    /* Reset the channel state structure to default value. */
    EDMA_DRV_ClearStructure((uint8_t *)chnState, sizeof(edma_chn_state_t));

    s_virtEdmaState->virtChnState[virtualChannel] = NULL;

    return STATUS_SUCCESS;
}

EDMA_DRV_ClearIntStatus

清除所有中断状态

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ClearIntStatus
 * Description   : Clear done and interrupt retStatus.
 *
 *END**************************************************************************/
static void EDMA_DRV_ClearIntStatus(uint8_t virtualChannel)
{
    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_ClearDoneStatusFlag(edmaRegBase, dmaChannel);
    EDMA_ClearIntStatusFlag(edmaRegBase, dmaChannel);
}

EDMA_DRV_ClearSoftwareTCD

清除软件TCD结构体

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ClearSoftwareTCD
 * Description   : Clear the software tcd structure.
 *
 *END**************************************************************************/
static void EDMA_DRV_ClearSoftwareTCD(edma_software_tcd_t *stcd)
{
    EDMA_DRV_ClearStructure((uint8_t *)stcd, sizeof(edma_software_tcd_t));
}

EDMA_DRV_IRQHandler

默认的中断处理函数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_IRQHandler
 * Description   : EDMA IRQ handler.
 *END**************************************************************************/
void EDMA_DRV_IRQHandler(uint8_t virtualChannel)
{
    const edma_chn_state_t *chnState = s_virtEdmaState->virtChnState[virtualChannel];

    EDMA_DRV_ClearIntStatus(virtualChannel);

    if (chnState != NULL)
    {
        if (chnState->callback != NULL)
        {
            chnState->callback(chnState->parameter, chnState->status);
        }
    }
}

EDMA_DRV_ErrorIRQHandler

错误中断处理函数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ErrorIRQHandler
 * Description   : EDMA error IRQ handler
 *END**************************************************************************/
void EDMA_DRV_ErrorIRQHandler(uint8_t virtualChannel)
{
    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_SetDmaRequestCmd(edmaRegBase, dmaChannel, false);
    edma_chn_state_t *chnState = s_virtEdmaState->virtChnState[virtualChannel];
    if (chnState != NULL)
    {
        EDMA_DRV_ClearIntStatus(virtualChannel);
        EDMA_ClearErrorIntStatusFlag(edmaRegBase, dmaChannel);
        chnState->status = EDMA_CHN_ERROR;
        if (chnState->callback != NULL)
        {
            chnState->callback(chnState->parameter, chnState->status);
        }
    }
}

EDMA_DRV_ConfigSingleBlockTransfer

配置信号块传输

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ConfigSingleBlockTransfer
 * Description   : Configures a DMA single block transfer.
 *
 * Implements    : EDMA_DRV_ConfigSingleBlockTransfer_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ConfigSingleBlockTransfer(uint8_t virtualChannel,
                                            edma_transfer_type_t type,
                                            uint32_t srcAddr,
                                            uint32_t destAddr,
                                            edma_transfer_size_t transferSize,
                                            uint32_t dataBufferSize)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

#if defined (CUSTOM_DEVASSERT) || defined (DEV_ERROR_DETECT)
    /* Check if the value passed for 'transferSize' is valid */
    DEV_ASSERT(EDMA_DRV_ValidTransferSize(transferSize));
#endif

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    uint8_t transferOffset;
    status_t retStatus = STATUS_SUCCESS;

    /* Compute the transfer offset, based on transfer size.
     * The number of bytes transferred in each source read/destination write
     * is obtained with the following formula:
     *    source_read_size = 2^SSIZE
     *    destination_write_size = 2^DSIZE
     */
    transferOffset = (uint8_t) (1U << ((uint8_t)transferSize));

    /* The number of bytes to be transferred (buffer size) must
     * be a multiple of the source read/destination write size
     */
    if ((dataBufferSize % transferOffset) != 0U)
    {
        retStatus = STATUS_ERROR;
    }

    if (retStatus == STATUS_SUCCESS)
    {
        /* Clear transfer control descriptor for the current channel */
        EDMA_TCDClearReg(edmaRegBase, dmaChannel);  

#ifdef FEATURE_DMA_ENGINE_STALL
        /* Configure the DMA Engine to stall for a number of cycles after each R/W */
        EDMA_TCDSetEngineStall(edmaRegBase, dmaChannel, EDMA_ENGINE_STALL_4_CYCLES);
#endif

#ifdef FEATURE_DMA_HWV3
        EDMA_SetMinorLoopMappingCmd(edmaRegBase, dmaChannel, false);
#else
        EDMA_SetMinorLoopMappingCmd(edmaRegBase, false);
#endif

        /* Configure source and destination addresses */
        EDMA_TCDSetSrcAddr(edmaRegBase, dmaChannel, srcAddr);
        EDMA_TCDSetDestAddr(edmaRegBase, dmaChannel, destAddr);

        /* Set transfer size (1B/2B/4B/16B/32B) */
        EDMA_TCDSetAttribute(edmaRegBase, dmaChannel, EDMA_MODULO_OFF, EDMA_MODULO_OFF, transferSize, transferSize);

        /* Configure source/destination offset. */
        switch (type)
        {
            case EDMA_TRANSFER_PERIPH2MEM:
                EDMA_TCDSetSrcOffset(edmaRegBase, dmaChannel, 0);
                EDMA_TCDSetDestOffset(edmaRegBase, dmaChannel, (int8_t) transferOffset);
                break;
            case EDMA_TRANSFER_MEM2PERIPH:
                EDMA_TCDSetSrcOffset(edmaRegBase, dmaChannel, (int8_t) transferOffset);
                EDMA_TCDSetDestOffset(edmaRegBase, dmaChannel, 0);
                break;
            case EDMA_TRANSFER_MEM2MEM:
                EDMA_TCDSetSrcOffset(edmaRegBase, dmaChannel, (int8_t) transferOffset);
                EDMA_TCDSetDestOffset(edmaRegBase, dmaChannel, (int8_t) transferOffset);
                break;
            case EDMA_TRANSFER_PERIPH2PERIPH:
                EDMA_TCDSetSrcOffset(edmaRegBase, dmaChannel, 0);
                EDMA_TCDSetDestOffset(edmaRegBase, dmaChannel, 0);
                break;
            default:
                /* This should never be reached - all the possible values have been handled. */
                break;
        }

        /* Set the total number of bytes to be transfered */
        EDMA_TCDSetNbytes(edmaRegBase, dmaChannel, dataBufferSize);

        /* Set major iteration count to 1 (single block mode) */
        EDMA_TCDSetMajorCount(edmaRegBase, dmaChannel, 1U);

        /* Enable interrupt when the transfer completes */
        EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, dmaChannel, true);
        
        /* Set virtual channel status to normal */
        s_virtEdmaState->virtChnState[virtualChannel]->status = EDMA_CHN_NORMAL;    
    }

    return retStatus;
}

EDMA_DRV_ConfigMultiBlockTransfer

配置复合信号块传输

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ConfigMultiBlockTransfer
 * Description   : Configures a DMA single block transfer.
 *
 * Implements    : EDMA_DRV_ConfigMultiBlockTransfer_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ConfigMultiBlockTransfer(uint8_t virtualChannel,
                                           edma_transfer_type_t type,
                                           uint32_t srcAddr,
                                           uint32_t destAddr,
                                           edma_transfer_size_t transferSize,
                                           uint32_t blockSize,
                                           uint32_t blockCount,
                                           bool disableReqOnCompletion)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    status_t retStatus = STATUS_SUCCESS;

    /* Configure the transfer for one data block */
    retStatus = EDMA_DRV_ConfigSingleBlockTransfer(virtualChannel, type, srcAddr, destAddr, transferSize, blockSize);

    if (retStatus == STATUS_SUCCESS)
    {
        DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];

        /* Set the number of data blocks */
        EDMA_TCDSetMajorCount(edmaRegBase, dmaChannel, blockCount);

        /* Enable/disable requests upon completion */
        EDMA_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaRegBase, dmaChannel, disableReqOnCompletion);
    }

    return retStatus;
}

EDMA_DRV_ConfigLoopTransfer

配置轮询传输

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ConfigLoopTransfer
 * Description   : Configures the DMA transfer in a loop.
 *
 * Implements    : EDMA_DRV_ConfigLoopTransfer_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ConfigLoopTransfer(uint8_t virtualChannel,
                                     const edma_transfer_config_t *transferConfig)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Check the transfer configuration structure is valid */
    DEV_ASSERT(transferConfig != NULL);

    /* Check the minor/major loop properties are defined */
    DEV_ASSERT(transferConfig->loopTransferConfig != NULL);
    
    /* If the modulo feature is enabled, check alignment of addresses */
    DEV_ASSERT((transferConfig->srcModulo == EDMA_MODULO_OFF) ||
               ((transferConfig->srcAddr % (((uint32_t)1U) << (uint32_t)transferConfig->srcModulo)) == 0U));
    DEV_ASSERT((transferConfig->destModulo == EDMA_MODULO_OFF) ||
               ((transferConfig->destAddr % (((uint32_t)1U) << (uint32_t)transferConfig->destModulo)) == 0U));

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

#ifdef FEATURE_DMA_HWV3
    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);
#endif

    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];

#ifdef FEATURE_DMA_HWV3
    EDMA_SetMinorLoopMappingCmd(edmaRegBase, dmaChannel, true);
#else
    EDMA_SetMinorLoopMappingCmd(edmaRegBase, true);
#endif
    /* Write the configuration in the transfer control descriptor registers */
    EDMA_DRV_PushConfigToReg(virtualChannel, transferConfig);
    
    /* Set virtual channel status to normal */
    s_virtEdmaState->virtChnState[virtualChannel]->status = EDMA_CHN_NORMAL;

    return STATUS_SUCCESS;
}

EDMA_DRV_ConfigScatterGatherTransfer

配置分散或者聚集操作

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ConfigScatterGatherTransfer
 * Description   : Configure eDMA for scatter/gather operation
 *
 * Implements    : EDMA_DRV_ConfigScatterGatherTransfer_Activity
 *END**************************************************************************/
status_t EDMA_DRV_ConfigScatterGatherTransfer(uint8_t virtualChannel,
                                              edma_software_tcd_t *stcd,
                                              edma_transfer_size_t transferSize,
                                              uint32_t bytesOnEachRequest,
                                              const edma_scatter_gather_list_t *srcList,
                                              const edma_scatter_gather_list_t *destList,
                                              uint8_t tcdCount)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Check the input arrays for scatter/gather operation are valid */
    DEV_ASSERT((stcd != NULL) && (srcList != NULL) && (destList != NULL));

#if defined (CUSTOM_DEVASSERT) || defined (DEV_ERROR_DETECT)
    /* Check if the value passed for 'transferSize' is valid */
    DEV_ASSERT(EDMA_DRV_ValidTransferSize(transferSize));
#endif

    uint8_t i = 0U;
    uint16_t transferOffset = 0U;
    uint32_t stcdAlignedAddr = STCD_ADDR(stcd);
    edma_software_tcd_t *edmaSwTcdAddr = (edma_software_tcd_t *)stcdAlignedAddr;
    edma_loop_transfer_config_t edmaLoopConfig;
    edma_transfer_config_t edmaTransferConfig;
    status_t retStatus = STATUS_SUCCESS;

    /* Set virtual channel status to normal */
    s_virtEdmaState->virtChnState[virtualChannel]->status = EDMA_CHN_NORMAL;    
    
    /* Compute the transfer offset, based on transfer size.
     * The number of bytes transferred in each source read/destination write
     * is obtained with the following formula:
     *    source_read_size = 2^SSIZE
     *    destination_write_size = 2^DSIZE
     */
    transferOffset = (uint16_t) (1UL << ((uint16_t)transferSize));

    /* The number of bytes to be transferred on each request must
     * be a multiple of the source read/destination write size
     */
    if ((bytesOnEachRequest % transferOffset) != 0U)
    {
        retStatus = STATUS_ERROR;
    }

    /* Clear the configuration structures before initializing them. */
    EDMA_DRV_ClearStructure((uint8_t *)(&edmaTransferConfig), sizeof(edma_transfer_config_t));
    EDMA_DRV_ClearStructure((uint8_t *)(&edmaLoopConfig), sizeof(edma_loop_transfer_config_t));

    /* Configure the transfer for scatter/gather mode. */
    edmaTransferConfig.srcLastAddrAdjust = 0;
    edmaTransferConfig.destLastAddrAdjust = 0;
    edmaTransferConfig.srcModulo = EDMA_MODULO_OFF;
    edmaTransferConfig.destModulo = EDMA_MODULO_OFF;
    edmaTransferConfig.srcTransferSize = transferSize;
    edmaTransferConfig.destTransferSize = transferSize;
    edmaTransferConfig.minorByteTransferCount = bytesOnEachRequest;
    edmaTransferConfig.interruptEnable = true;
    edmaTransferConfig.scatterGatherEnable = true;
    edmaTransferConfig.loopTransferConfig = &edmaLoopConfig;
    edmaTransferConfig.loopTransferConfig->srcOffsetEnable = false;
    edmaTransferConfig.loopTransferConfig->dstOffsetEnable = false;
    edmaTransferConfig.loopTransferConfig->minorLoopChnLinkEnable = false;
    edmaTransferConfig.loopTransferConfig->majorLoopChnLinkEnable = false;

    /* Copy scatter/gather lists to transfer configuration*/
    for (i = 0U; (i < tcdCount) && (retStatus == STATUS_SUCCESS); i++)
    {
        edmaTransferConfig.srcAddr = srcList[i].address;
        edmaTransferConfig.destAddr = destList[i].address;
        if ((srcList[i].length != destList[i].length) || (srcList[i].type != destList[i].type))
        {
            retStatus = STATUS_ERROR;
            break;
        }
        edmaTransferConfig.loopTransferConfig->majorLoopIterationCount = srcList[i].length/bytesOnEachRequest;

        switch (srcList[i].type)
        {
            case EDMA_TRANSFER_PERIPH2MEM:
                /* Configure Source Read. */
                edmaTransferConfig.srcOffset = 0;
                /* Configure Dest Write. */
                edmaTransferConfig.destOffset = (int16_t) transferOffset;
                break;
            case EDMA_TRANSFER_MEM2PERIPH:
                /* Configure Source Read. */
                edmaTransferConfig.srcOffset = (int16_t) transferOffset;
                /* Configure Dest Write. */
                edmaTransferConfig.destOffset = 0;
                break;
            case EDMA_TRANSFER_MEM2MEM:
                /* Configure Source Read. */
                edmaTransferConfig.srcOffset = (int16_t) transferOffset;
                /* Configure Dest Write. */
                edmaTransferConfig.destOffset = (int16_t) transferOffset;
                break;
            case EDMA_TRANSFER_PERIPH2PERIPH:
                /* Configure Source Read. */
                edmaTransferConfig.srcOffset = 0;
                /* Configure Dest Write. */
                edmaTransferConfig.destOffset = 0;
                break;
            default:
                /* This should never be reached - all the possible values have been handled. */
                break;
        }

        /* Configure the pointer to next software TCD structure; for the last one, this address should be 0 */
        if (i == ((uint8_t)(tcdCount - 1U)))
        {
            edmaTransferConfig.scatterGatherNextDescAddr = 0U;
        }
        else
        {
            edma_software_tcd_t * ptNextAddr = &edmaSwTcdAddr[i];
            edmaTransferConfig.scatterGatherNextDescAddr = ((uint32_t) ptNextAddr);
        }

        if (i == 0U)
        {
            /* Push the configuration for the first descriptor to registers */
            EDMA_DRV_PushConfigToReg(virtualChannel, &edmaTransferConfig);
        }
        else
        {
            /* Copy configuration to software TCD structure */
            EDMA_DRV_PushConfigToSTCD(&edmaTransferConfig, &edmaSwTcdAddr[i - 1U]);
        }
    }

    return retStatus;
}

EDMA_DRV_StartChannel

开启通道,这个在SPI里面调用到

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_StartChannel
 * Description   : Starts an eDMA channel.
 *
 * Implements    : EDMA_DRV_StartChannel_Activity
 *END**************************************************************************/
status_t EDMA_DRV_StartChannel(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Enable requests for current channel */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_SetDmaRequestCmd(edmaRegBase, dmaChannel, true);

    return STATUS_SUCCESS;
}

EDMA_DRV_StopChannel

暂停通道

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_StopChannel
 * Description   : Stops an eDMA channel.
 *
 * Implements    : EDMA_DRV_StopChannel_Activity
 *END**************************************************************************/
status_t EDMA_DRV_StopChannel(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Disable requests for current channel */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_SetDmaRequestCmd(edmaRegBase, dmaChannel, false);

    return STATUS_SUCCESS;
}

EDMA_DRV_SetChannelRequestAndTrigger

设置通道请求和触发

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetChannelRequestAndTrigger
 * Description   : Sets DMA channel request source in DMAMUX and controls
 *                 the DMA channel periodic triggering.
 *
 * Implements    : EDMA_DRV_SetChannelRequestAndTrigger_Activity
 *END**************************************************************************/
status_t EDMA_DRV_SetChannelRequestAndTrigger(uint8_t virtualChannel,
                                              uint8_t request,
                                              bool enableTrigger)
{
    /* Check the virtual channel number is valid */
    DEV_ASSERT(virtualChannel < (uint32_t)FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

#ifdef FEATURE_DMAMUX_AVAILABLE
    /* Retrieve the DMAMUX instance serving this request */
    uint8_t dmaMuxInstance = (uint8_t)FEATURE_DMAMUX_REQ_SRC_TO_INSTANCE(request);

    /* Get request index for the corresponding DMAMUX instance */
    uint8_t dmaMuxRequest = (uint8_t)FEATURE_DMAMUX_REQ_SRC_TO_CH(request);

    /* Get DMAMUX channel for the selected request */
    uint8_t dmaMuxChannel = (uint8_t)FEATURE_DMAMUX_DMA_CH_TO_CH(virtualChannel);

    /* Retrieve the appropriate DMAMUX instance */
    DMAMUX_Type *dmaMuxRegBase = s_dmaMuxBase[dmaMuxInstance];

    /* Set request and trigger */
	DMAMUX_SetChannelCmd(dmaMuxRegBase, dmaMuxChannel, false);
    DMAMUX_SetChannelSource(dmaMuxRegBase, dmaMuxChannel, dmaMuxRequest);
#ifdef FEATURE_DMAMUX_HAS_TRIG	
	DMAMUX_SetChannelTrigger(dmaMuxRegBase, dmaMuxChannel, enableTrigger);
#else
    (void)enableTrigger;	
#endif	
	DMAMUX_SetChannelCmd(dmaMuxRegBase, dmaMuxChannel, true);
    
    return STATUS_SUCCESS;
#else
    (void)virtualChannel;    
    (void)request;
    (void)enableTrigger;    
    return STATUS_UNSUPPORTED;
#endif
}

EDMA_DRV_ClearTCD

清除TCD结构体

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ClearTCD
 * Description   : Clears all registers to 0 for the hardware TCD.
 *
 * Implements    : EDMA_DRV_ClearTCD_Activity
 *END**************************************************************************/
void EDMA_DRV_ClearTCD(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Clear the TCD memory */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDClearReg(edmaRegBase, dmaChannel);
}

EDMA_DRV_SetSrcAddr

设置源地址

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetSrcAddr
 * Description   : Configures the source address for the eDMA channel.
 *
 * Implements    : EDMA_DRV_SetSrcAddr_Activity
 *END**************************************************************************/
void EDMA_DRV_SetSrcAddr(uint8_t virtualChannel,
                         uint32_t address)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source address */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetSrcAddr(edmaRegBase, dmaChannel, address);
}

EDMA_DRV_SetSrcOffset

设置原地址偏移

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetSrcOffset
 * Description   : Configures the source address signed offset for the eDMA channel.
 *
 * Implements    : EDMA_DRV_SetSrcOffset_Activity
 *END**************************************************************************/
void EDMA_DRV_SetSrcOffset(uint8_t virtualChannel,
                           int16_t offset)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source offset */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetSrcOffset(edmaRegBase, dmaChannel, offset);
}

EDMA_DRV_SetSrcReadChunkSize

配置源读数据块大小

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetSrcReadChunkSize
 * Description   : Configures the source read data chunk size (transferred in a read sequence).
 *
 * Implements    : EDMA_DRV_SetSrcReadChunkSize_Activity
 *END**************************************************************************/
void EDMA_DRV_SetSrcReadChunkSize(uint8_t virtualChannel,
                                  edma_transfer_size_t size)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source transfer size */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetSrcTransferSize(edmaRegBase, dmaChannel, size);
}

EDMA_DRV_SetSrcLastAddrAdjustment

配置源地址最后一次调整

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetSrcLastAddrAdjustment
 * Description   : Configures the source address last adjustment.
 *
 * Implements    : EDMA_DRV_SetSrcLastAddrAdjustment_Activity
 *END**************************************************************************/
void EDMA_DRV_SetSrcLastAddrAdjustment(uint8_t virtualChannel,
                                       int32_t adjust)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source last adjustment */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetSrcLastAdjust(edmaRegBase, dmaChannel, adjust);
}

EDMA_DRV_SetDestLastAddrAdjustment

配置目标地址最后一次调整

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetDestLastAddrAdjustment
 * Description   : Configures the source address last adjustment.
 *
 * Implements    : EDMA_DRV_SetDestLastAddrAdjustment_Activity
 *END**************************************************************************/
void EDMA_DRV_SetDestLastAddrAdjustment(uint8_t virtualChannel,
                                        int32_t adjust)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source last adjustment */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetDestLastAdjust(edmaRegBase, dmaChannel, adjust);
}

EDMA_DRV_SetDestAddr

设置目标地址

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetDestAddr
 * Description   : Configures the destination address for the eDMA channel.
 *
 * Implements    : EDMA_DRV_SetDestAddr_Activity
 *END**************************************************************************/
void EDMA_DRV_SetDestAddr(uint8_t virtualChannel,
                          uint32_t address)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD destination address */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetDestAddr(edmaRegBase, dmaChannel, address);
}

EDMA_DRV_SetDestOffset

设置目标地址偏移

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetDestOffset
 * Description   : Configures the destination address signed offset for the eDMA channel.
 *
 * Implements    : EDMA_DRV_SetDestOffset_Activity
 *END**************************************************************************/
void EDMA_DRV_SetDestOffset(uint8_t virtualChannel,
                            int16_t offset)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD destination offset */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetDestOffset(edmaRegBase, dmaChannel, offset);
}

EDMA_DRV_SetDestWriteChunkSize

配置写入目标地址数据块大小

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetDestWriteChunkSize
 * Description   : Configures the destination data chunk size (transferred in a write sequence).
 *
 * Implements    : EDMA_DRV_SetDestWriteChunkSize_Activity
 *END**************************************************************************/
void EDMA_DRV_SetDestWriteChunkSize(uint8_t virtualChannel,
                                    edma_transfer_size_t size)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD source transfer size */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetDestTransferSize(edmaRegBase, dmaChannel, size);
}

EDMA_DRV_SetMinorLoopBlockSize

配置通道的每个服务请求中传输的字节数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetMinorLoopBlockSize
 * Description   : Configures the number of bytes to be transferred in each service request of the channel.
 *
 * Implements    : EDMA_DRV_SetMinorLoopBlockSize_Activity
 *END**************************************************************************/
void EDMA_DRV_SetMinorLoopBlockSize(uint8_t virtualChannel,
                                    uint32_t nbytes)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set channel TCD minor loop block size */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetNbytes(edmaRegBase, dmaChannel, nbytes);
}

EDMA_DRV_SetMajorLoopIterationCount

配置主循环迭代的次数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetMajorLoopIterationCount
 * Description   : Configures the number of major loop iterations.
 *
 * Implements    : EDMA_DRV_SetMajorLoopIterationCount_Activity
 *END**************************************************************************/
void EDMA_DRV_SetMajorLoopIterationCount(uint8_t virtualChannel,
                                         uint32_t majorLoopCount)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Set the major loop iteration count */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetMajorCount(edmaRegBase, dmaChannel, majorLoopCount);
}

EDMA_DRV_GetRemainingMajorIterationsCount

返回剩余的主循环迭代计数

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_GetRemainingMajorIterationsCount
 * Description   : Returns the remaining major loop iteration count.
 *
 * Implements    : EDMA_DRV_GetRemainingMajorIterationsCount_Activity
 *END**************************************************************************/
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Retrieve the number of minor loops yet to be triggered */
    const DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    uint32_t count = EDMA_TCDGetCurrentMajorCount(edmaRegBase, dmaChannel);

    return count;
}

EDMA_DRV_SetScatterGatherLink

配置下一个TCD的内存地址

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_SetScatterGatherLink
 * Description   : Configures the memory address of the next TCD, in scatter/gather mode.
 *
 * Implements    : EDMA_DRV_SetScatterGatherLink_Activity
 *END**************************************************************************/
void EDMA_DRV_SetScatterGatherLink(uint8_t virtualChannel,
                                   uint32_t nextTCDAddr)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Configures the memory address of the next TCD */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetScatterGatherLink(edmaRegBase, dmaChannel, nextTCDAddr);
}

EDMA_DRV_DisableRequestsOnTransferComplete

在TCD的主循环完成后禁用/启用DMA请求

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_DisableRequestsOnTransferComplete
 * Description   : Disables/Enables the DMA request after the major loop completes for the TCD.
 *
 * Implements    : EDMA_DRV_DisableRequestsOnTransferComplete_Activity
 *END**************************************************************************/
void EDMA_DRV_DisableRequestsOnTransferComplete(uint8_t virtualChannel,
                                                bool disable)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Disables/Enables the DMA request upon TCD completion */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TCDSetDisableDmaRequestAfterTCDDoneCmd(edmaRegBase, dmaChannel, disable);
}

EDMA_DRV_ConfigureInterrupt

使能失能通道中断

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_ConfigureInterrupt
 * Description   : Disables/Enables the channel interrupt requests.
 *
 * Implements    : EDMA_DRV_ConfigureInterrupt_Activity
 *END**************************************************************************/
void EDMA_DRV_ConfigureInterrupt(uint8_t virtualChannel,
                                 edma_channel_interrupt_t intSrc,
                                 bool enable)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Disables/Enables the channel interrupt requests. */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    switch (intSrc)
    {
        case EDMA_CHN_ERR_INT:
            /* Enable channel interrupt request when error conditions occur */
            EDMA_SetErrorIntCmd(edmaRegBase, dmaChannel, enable);
            break;
        case EDMA_CHN_HALF_MAJOR_LOOP_INT:
            /* Enable channel interrupt request when major iteration count reaches halfway point */
            EDMA_TCDSetMajorHalfCompleteIntCmd(edmaRegBase, dmaChannel, enable);
            break;
        case EDMA_CHN_MAJOR_LOOP_INT:
            /* Enable channel interrupt request when major iteration count reaches zero */
            EDMA_TCDSetMajorCompleteIntCmd(edmaRegBase, dmaChannel, enable);
            break;
        default:
            /* This branch should never be reached if driver API is used properly */
            break;
    }
}

EDMA_DRV_CancelTransfer

取消传输

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_CancelTransfer
 * Description   : Cancels the running transfer for this channel.
 *
 * Implements    : EDMA_DRV_CancelTransfer_Activity
 *END**************************************************************************/
void EDMA_DRV_CancelTransfer(bool error)
{
    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    uint32_t dmaInstance = 0U;

    for(dmaInstance = 0U; dmaInstance < (uint32_t)DMA_INSTANCE_COUNT; dmaInstance++)
    {
        /* Cancel the running transfer. */
        DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
        if (error)
        {
            EDMA_CancelTransferWithError(edmaRegBase);
        }
        else
        {
            EDMA_CancelTransfer(edmaRegBase);
        }
    }
}

EDMA_DRV_TriggerSwRequest

触发DMA请求

/*FUNCTION**********************************************************************
 *
 * Function Name : EDMA_DRV_TriggerSwRequest
 * Description   : Triggers a sw request for the current channel.
 *
 * Implements    : EDMA_DRV_TriggerSwRequest_Activity
 *END**************************************************************************/
void EDMA_DRV_TriggerSwRequest(uint8_t virtualChannel)
{
    /* Check that virtual channel number is valid */
    DEV_ASSERT(virtualChannel < FEATURE_DMA_VIRTUAL_CHANNELS);

    /* Check that eDMA module is initialized */
    DEV_ASSERT(s_virtEdmaState != NULL);

    /* Check that virtual channel is initialized */
    DEV_ASSERT(s_virtEdmaState->virtChnState[virtualChannel] != NULL);

    /* Get DMA instance from virtual channel */
    uint8_t dmaInstance = (uint8_t)FEATURE_DMA_VCH_TO_INSTANCE(virtualChannel);

    /* Get DMA channel from virtual channel*/
    uint8_t dmaChannel = (uint8_t)FEATURE_DMA_VCH_TO_CH(virtualChannel);

    /* Trigger the channel transfer. */
    DMA_Type *edmaRegBase = s_edmaBase[dmaInstance];
    EDMA_TriggerChannelStart(edmaRegBase, dmaChannel);
}

相关推荐

  1. 什么是DMA? STM32如何配置DMA

    2024-03-20 13:02:06       35 阅读
  2. STM<span style='color:red;'>32</span><span style='color:red;'>DMA</span>

    STM32DMA

    2024-03-20 13:02:06      38 阅读
  3. stm32 DMA

    2024-03-20 13:02:06       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-20 13:02:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-20 13:02:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-20 13:02:06       82 阅读
  4. Python语言-面向对象

    2024-03-20 13:02:06       91 阅读

热门阅读

  1. openssl3.2 - exp - aes-128-cbc

    2024-03-20 13:02:06       30 阅读
  2. Spring Boot + Vue 实现文件导入导出功能

    2024-03-20 13:02:06       41 阅读
  3. Rust 中的 Vec<u8> 类型

    2024-03-20 13:02:06       37 阅读
  4. golang踩坑记录

    2024-03-20 13:02:06       38 阅读
  5. Flutter插件开发与发布指南

    2024-03-20 13:02:06       40 阅读
  6. Flutter项目组件模块化开发的实践与搭建

    2024-03-20 13:02:06       43 阅读
  7. flutter-elinux的基本介绍及安装调试

    2024-03-20 13:02:06       42 阅读
  8. mysql建表&索引语句

    2024-03-20 13:02:06       45 阅读
  9. Flutter中自定义Dialog

    2024-03-20 13:02:06       40 阅读