/**
  ******************************************************************************
  * @file    stm32h5xx_ll_dma.c
  * @author  MCD Application Team
  * @brief   DMA LL module driver.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
 @verbatim
  ==============================================================================
                        ##### LL DMA driver acronyms #####
  ==============================================================================
  [..]  Acronyms table :
                   =========================================
                   || Acronym ||                          ||
                   =========================================
                   || SRC     ||  Source                  ||
                   || DEST    ||  Destination             ||
                   || ADDR    ||  Address                 ||
                   || ADDRS   ||  Addresses               ||
                   || INC     ||  Increment / Incremented ||
                   || DEC     ||  Decrement / Decremented ||
                   || BLK     ||  Block                   ||
                   || RPT     ||  Repeat / Repeated       ||
                   || TRIG    ||  Trigger                 ||
                   =========================================
 @endverbatim
  ******************************************************************************
  */

#if defined (USE_FULL_LL_DRIVER)

/* Includes ------------------------------------------------------------------*/
#include "stm32h5xx_ll_dma.h"
#include "stm32h5xx_ll_bus.h"
#ifdef  USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */

/** @addtogroup STM32H5xx_LL_Driver
  * @{
  */

#if defined (GPDMA1)

/** @addtogroup DMA_LL
  * @{
  */

/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/

/** @addtogroup DMA_LL_Private_Macros
  * @{
  */
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, Channel) ((((INSTANCE) == GPDMA1)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_1)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_2)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_3)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_4)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_5)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_ALL))) || \
                                                           (((INSTANCE) == GPDMA2)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_1)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_2)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_3)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_4)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_5)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_ALL))))

#define IS_LL_GPDMA_CHANNEL_INSTANCE(INSTANCE, Channel)   ((((INSTANCE) == GPDMA1)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_1)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_2)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_3)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_4)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_5)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7))) || \
                                                           (((INSTANCE) == GPDMA2)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_1)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_2)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_3)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_4)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_5)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7))))

#define IS_LL_DMA_2D_CHANNEL_INSTANCE(INSTANCE, Channel)  ((((INSTANCE) == GPDMA1)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7))) || \
                                                           (((INSTANCE) == GPDMA2)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_6)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7))))

#define IS_LL_DMA_MODE(__VALUE__)                         (((__VALUE__) == LL_DMA_NORMAL) || \
                                                           ((__VALUE__) == LL_DMA_PFCTRL))

#define IS_LL_DMA_PFREQ_INSTANCE(INSTANCE, Channel)       ((((INSTANCE) == GPDMA1)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7)))   || \
                                                           (((INSTANCE) == GPDMA2)                && \
                                                            (((Channel)  == LL_DMA_CHANNEL_0)     || \
                                                             ((Channel)  == LL_DMA_CHANNEL_7))))

#define IS_LL_DMA_DIRECTION(__VALUE__)                    (((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY) || \
                                                           ((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
                                                           ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH))

#define IS_LL_DMA_DATA_ALIGNMENT(__VALUE__)               (((__VALUE__) == LL_DMA_DATA_ALIGN_ZEROPADD)    || \
                                                           ((__VALUE__) == LL_DMA_DATA_ALIGN_SIGNEXTPADD) || \
                                                           ((__VALUE__) == LL_DMA_DATA_PACK_UNPACK))

#define IS_LL_DMA_BURST_LENGTH(__VALUE__)                 (((__VALUE__) > 0U) && ((__VALUE__) <= 64U))

#define IS_LL_DMA_SRC_DATA_WIDTH(__VALUE__)               (((__VALUE__) == LL_DMA_SRC_DATAWIDTH_BYTE)     || \
                                                           ((__VALUE__) == LL_DMA_SRC_DATAWIDTH_HALFWORD) || \
                                                           ((__VALUE__) == LL_DMA_SRC_DATAWIDTH_WORD))

#define IS_LL_DMA_DEST_DATA_WIDTH(__VALUE__)              (((__VALUE__) == LL_DMA_DEST_DATAWIDTH_BYTE)     || \
                                                           ((__VALUE__) == LL_DMA_DEST_DATAWIDTH_HALFWORD) || \
                                                           ((__VALUE__) == LL_DMA_DEST_DATAWIDTH_WORD))

#define IS_LL_DMA_SRC_INCREMENT_MODE(__VALUE__)           (((__VALUE__) == LL_DMA_SRC_FIXED) || \
                                                           ((__VALUE__) == LL_DMA_SRC_INCREMENT))

#define IS_LL_DMA_DEST_INCREMENT_MODE(__VALUE__)          (((__VALUE__) == LL_DMA_DEST_FIXED) || \
                                                           ((__VALUE__) == LL_DMA_DEST_INCREMENT))

#define IS_LL_DMA_PRIORITY(__VALUE__)                     (((__VALUE__) == LL_DMA_LOW_PRIORITY_LOW_WEIGHT)  || \
                                                           ((__VALUE__) == LL_DMA_LOW_PRIORITY_MID_WEIGHT)  || \
                                                           ((__VALUE__) == LL_DMA_LOW_PRIORITY_HIGH_WEIGHT) || \
                                                           ((__VALUE__) == LL_DMA_HIGH_PRIORITY))

#define IS_LL_DMA_BLK_DATALENGTH(__VALUE__)                ((__VALUE__) <= 0xFFFFU)

#define IS_LL_DMA_BLK_REPEATCOUNT(__VALUE__)               ((__VALUE__) <= 0x0EFFU)

#define IS_LL_DMA_TRIGGER_MODE(__VALUE__)                 (((__VALUE__) == LL_DMA_TRIGM_BLK_TRANSFER)      || \
                                                           ((__VALUE__) == LL_DMA_TRIGM_RPT_BLK_TRANSFER)  || \
                                                           ((__VALUE__) == LL_DMA_TRIGM_LLI_LINK_TRANSFER) || \
                                                           ((__VALUE__) == LL_DMA_TRIGM_SINGLBURST_TRANSFER ))

#define IS_LL_DMA_TRIGGER_POLARITY(__VALUE__)             (((__VALUE__) == LL_DMA_TRIG_POLARITY_MASKED) || \
                                                           ((__VALUE__) == LL_DMA_TRIG_POLARITY_RISING) || \
                                                           ((__VALUE__) == LL_DMA_TRIG_POLARITY_FALLING))

#define IS_LL_DMA_BLKHW_REQUEST(__VALUE__)                (((__VALUE__) == LL_DMA_HWREQUEST_SINGLEBURST) || \
                                                           ((__VALUE__) == LL_DMA_HWREQUEST_BLK))

#if defined (I3C2)
#define IS_LL_DMA_TRIGGER_SELECTION(__VALUE__)             ((__VALUE__) <= LL_GPDMA1_TRIGGER_EVENTOUT)
#else
#define IS_LL_DMA_TRIGGER_SELECTION(__VALUE__)             ((__VALUE__) <= LL_GPDMA1_TRIGGER_LPTIM6_CH2)
#endif /* I3C2 */

#if defined (I3C2)
#define IS_LL_DMA_REQUEST_SELECTION(__VALUE__)             ((__VALUE__) <= LL_GPDMA1_REQUEST_I3C2_RS)
#else
#define IS_LL_DMA_REQUEST_SELECTION(__VALUE__)             ((__VALUE__) <= LL_GPDMA1_REQUEST_LPTIM6_UE)
#endif /* I3C2 */

#define IS_LL_DMA_TRANSFER_EVENT_MODE(__VALUE__)          (((__VALUE__) == LL_DMA_TCEM_BLK_TRANSFER)         || \
                                                           ((__VALUE__) == LL_DMA_TCEM_RPT_BLK_TRANSFER)     || \
                                                           ((__VALUE__) == LL_DMA_TCEM_EACH_LLITEM_TRANSFER) || \
                                                           ((__VALUE__) == LL_DMA_TCEM_LAST_LLITEM_TRANSFER))

#define IS_LL_DMA_DEST_HALFWORD_EXCHANGE(__VALUE__)       (((__VALUE__) == LL_DMA_DEST_HALFWORD_PRESERVE) || \
                                                           ((__VALUE__) == LL_DMA_DEST_HALFWORD_EXCHANGE))

#define IS_LL_DMA_DEST_BYTE_EXCHANGE(__VALUE__)           (((__VALUE__) == LL_DMA_DEST_BYTE_PRESERVE) || \
                                                           ((__VALUE__) == LL_DMA_DEST_BYTE_EXCHANGE))

#define IS_LL_DMA_SRC_BYTE_EXCHANGE(__VALUE__)            (((__VALUE__) == LL_DMA_SRC_BYTE_PRESERVE) || \
                                                           ((__VALUE__) == LL_DMA_SRC_BYTE_EXCHANGE))

#define IS_LL_DMA_LINK_ALLOCATED_PORT(__VALUE__)          (((__VALUE__) == LL_DMA_LINK_ALLOCATED_PORT0) || \
                                                           ((__VALUE__) == LL_DMA_LINK_ALLOCATED_PORT1))

#define IS_LL_DMA_SRC_ALLOCATED_PORT(__VALUE__)           (((__VALUE__) == LL_DMA_SRC_ALLOCATED_PORT0) || \
                                                           ((__VALUE__) == LL_DMA_SRC_ALLOCATED_PORT1))

#define IS_LL_DMA_DEST_ALLOCATED_PORT(__VALUE__)          (((__VALUE__) == LL_DMA_DEST_ALLOCATED_PORT0) || \
                                                           ((__VALUE__) == LL_DMA_DEST_ALLOCATED_PORT1))

#define IS_LL_DMA_LINK_STEP_MODE(__VALUE__)               (((__VALUE__) == LL_DMA_LSM_FULL_EXECUTION) || \
                                                           ((__VALUE__) == LL_DMA_LSM_1LINK_EXECUTION))

#define IS_LL_DMA_BURST_SRC_ADDR_UPDATE(__VALUE__)        (((__VALUE__) == LL_DMA_BURST_SRC_ADDR_INCREMENT) || \
                                                           ((__VALUE__) == LL_DMA_BURST_SRC_ADDR_DECREMENT))

#define IS_LL_DMA_BURST_DEST_ADDR_UPDATE(__VALUE__)       (((__VALUE__) == LL_DMA_BURST_DEST_ADDR_INCREMENT) || \
                                                           ((__VALUE__) == LL_DMA_BURST_DEST_ADDR_DECREMENT))

#define IS_LL_DMA_BURST_ADDR_UPDATE_VALUE(__VALUE__)       ((__VALUE__) <= 0x1FFFU)

#define IS_LL_DMA_BLKRPT_SRC_ADDR_UPDATE(__VALUE__)       (((__VALUE__) == LL_DMA_BLKRPT_SRC_ADDR_INCREMENT) || \
                                                           ((__VALUE__) == LL_DMA_BLKRPT_SRC_ADDR_DECREMENT))

#define IS_LL_DMA_BLKRPT_DEST_ADDR_UPDATE(__VALUE__)      (((__VALUE__) == LL_DMA_BLKRPT_DEST_ADDR_INCREMENT) || \
                                                           ((__VALUE__) == LL_DMA_BLKRPT_DEST_ADDR_DECREMENT))

#define IS_LL_DMA_BLKRPT_ADDR_UPDATE_VALUE(__VALUE__)      ((__VALUE__) <= 0xFFFFU)

#define IS_LL_DMA_LINK_BASEADDR(__VALUE__)                (((__VALUE__) & 0xFFFFU) == 0U)

#define IS_LL_DMA_LINK_ADDR_OFFSET(__VALUE__)             (((__VALUE__) & 0x03U) == 0U)

#define IS_LL_DMA_LINK_UPDATE_REGISTERS(__VALUE__)       ((((__VALUE__) & 0x01FE0000U) == 0U) && ((__VALUE__) != 0U))

#define IS_LL_DMA_LINK_NODETYPE(__VALUE__)                (((__VALUE__) == LL_DMA_GPDMA_2D_NODE)     || \
                                                           ((__VALUE__) == LL_DMA_GPDMA_LINEAR_NODE))

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
#define IS_LL_DMA_CHANNEL_SRC_SEC(__VALUE__)              (((__VALUE__) == LL_DMA_CHANNEL_SRC_NSEC) || \
                                                           ((__VALUE__) == LL_DMA_CHANNEL_SRC_SEC))

#define IS_LL_DMA_CHANNEL_DEST_SEC(__VALUE__)             (((__VALUE__) == LL_DMA_CHANNEL_DEST_NSEC) || \
                                                           ((__VALUE__) == LL_DMA_CHANNEL_DEST_SEC))

#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
/**
  * @}
  */

/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

/** @addtogroup DMA_LL_Exported_Functions
  * @{
  */

/** @addtogroup DMA_LL_EF_Init
  * @{
  */

/**
  * @brief De-initialize the DMA registers to their default reset values.
  * @note  This API is used for all available DMA channels.
  * @note  To convert DMAx_Channely Instance to DMAx Instance and Channely, use
  *        helper macros :
  *        @arg @ref LL_DMA_GET_INSTANCE
  *        @arg @ref LL_DMA_GET_CHANNEL
  * @param  DMAx DMAx Instance
  * @param  Channel This parameter can be one of the following values:
  *         @arg @ref LL_DMA_CHANNEL_0
  *         @arg @ref LL_DMA_CHANNEL_1
  *         @arg @ref LL_DMA_CHANNEL_2
  *         @arg @ref LL_DMA_CHANNEL_3
  *         @arg @ref LL_DMA_CHANNEL_4
  *         @arg @ref LL_DMA_CHANNEL_5
  *         @arg @ref LL_DMA_CHANNEL_6
  *         @arg @ref LL_DMA_CHANNEL_7
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS : DMA registers are de-initialized.
  *          - ERROR   : DMA registers are not de-initialized.
  */
uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
{
  DMA_Channel_TypeDef *tmp;
  ErrorStatus status = SUCCESS;

  /* Check the DMA Instance DMAx and Channel parameters */
  assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));

  if (Channel == LL_DMA_CHANNEL_ALL)
  {
    if (DMAx == GPDMA1)
    {
      /* Force reset of DMA clock */
      LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPDMA1);

      /* Release reset of DMA clock */
      LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPDMA1);
    }
    else
    {
      /* Force reset of DMA clock */
      LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPDMA2);

      /* Release reset of DMA clock */
      LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPDMA2);
    }
  }
  else
  {
    /* Get the DMA Channel Instance */
    tmp = (DMA_Channel_TypeDef *)(LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));

    /* Suspend DMA channel */
    LL_DMA_SuspendChannel(DMAx, Channel);

    /* Disable the selected Channel */
    LL_DMA_ResetChannel(DMAx, Channel);

    /* Reset DMAx_Channely control register */
    LL_DMA_WriteReg(tmp, CLBAR, 0U);

    /* Reset DMAx_Channely control register */
    LL_DMA_WriteReg(tmp, CCR, 0U);

    /* Reset DMAx_Channely Configuration register */
    LL_DMA_WriteReg(tmp, CTR1, 0U);

    /* Reset DMAx_Channely transfer register 2 */
    LL_DMA_WriteReg(tmp, CTR2, 0U);

    /* Reset DMAx_Channely block number of data register */
    LL_DMA_WriteReg(tmp, CBR1, 0U);

    /* Reset DMAx_Channely source address register */
    LL_DMA_WriteReg(tmp, CSAR, 0U);

    /* Reset DMAx_Channely destination address register */
    LL_DMA_WriteReg(tmp, CDAR, 0U);

    /* Check DMA channel */
    if (IS_LL_DMA_2D_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
    {
      /* Reset DMAx_Channely transfer register 3 */
      LL_DMA_WriteReg(tmp, CTR3, 0U);

      /* Reset DMAx_Channely Block register 2 */
      LL_DMA_WriteReg(tmp, CBR2, 0U);
    }

    /* Reset DMAx_Channely Linked list address register */
    LL_DMA_WriteReg(tmp, CLLR, 0U);

    /* Reset DMAx_Channely pending flags */
    LL_DMA_WriteReg(tmp, CFCR, 0x00003F00U);

    /* Reset DMAx_Channely attribute */
    LL_DMA_DisableChannelPrivilege(DMAx, Channel);

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
    LL_DMA_DisableChannelSecure(DMAx, Channel);
#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
  }

  return (uint32_t)status;
}

/**
  * @brief Initialize the DMA registers according to the specified parameters
  *        in DMA_InitStruct.
  * @note  This API is used for all available DMA channels.
  * @note  A software request transfer can be done once programming the direction
  *        field in memory to memory value.
  * @note  To convert DMAx_Channely Instance to DMAx Instance and Channely, use
  *        helper macros :
  *        @arg @ref LL_DMA_GET_INSTANCE
  *        @arg @ref LL_DMA_GET_CHANNEL
  * @param  DMAx DMAx Instance
  * @param  Channel This parameter can be one of the following values:
  *         @arg @ref LL_DMA_CHANNEL_0
  *         @arg @ref LL_DMA_CHANNEL_1
  *         @arg @ref LL_DMA_CHANNEL_2
  *         @arg @ref LL_DMA_CHANNEL_3
  *         @arg @ref LL_DMA_CHANNEL_4
  *         @arg @ref LL_DMA_CHANNEL_5
  *         @arg @ref LL_DMA_CHANNEL_6
  *         @arg @ref LL_DMA_CHANNEL_7
  * @param  DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS : DMA registers are initialized.
  *          - ERROR   : Not applicable.
  */
uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
{
  /* Check the DMA Instance DMAx and Channel parameters*/
  assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));

  /* Check the DMA parameters from DMA_InitStruct */
  assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));

  /* Check direction */
  if (DMA_InitStruct->Direction != LL_DMA_DIRECTION_MEMORY_TO_MEMORY)
  {
    assert_param(IS_LL_DMA_REQUEST_SELECTION(DMA_InitStruct->Request));
  }

  assert_param(IS_LL_DMA_DATA_ALIGNMENT(DMA_InitStruct->DataAlignment));
  assert_param(IS_LL_DMA_SRC_DATA_WIDTH(DMA_InitStruct->SrcDataWidth));
  assert_param(IS_LL_DMA_DEST_DATA_WIDTH(DMA_InitStruct->DestDataWidth));
  assert_param(IS_LL_DMA_SRC_INCREMENT_MODE(DMA_InitStruct->SrcIncMode));
  assert_param(IS_LL_DMA_DEST_INCREMENT_MODE(DMA_InitStruct->DestIncMode));
  assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
  assert_param(IS_LL_DMA_BLK_DATALENGTH(DMA_InitStruct->BlkDataLength));
  assert_param(IS_LL_DMA_TRIGGER_POLARITY(DMA_InitStruct->TriggerPolarity));
  assert_param(IS_LL_DMA_BLKHW_REQUEST(DMA_InitStruct->BlkHWRequest));
  assert_param(IS_LL_DMA_TRANSFER_EVENT_MODE(DMA_InitStruct->TransferEventMode));
  assert_param(IS_LL_DMA_LINK_STEP_MODE(DMA_InitStruct->LinkStepMode));
  assert_param(IS_LL_DMA_LINK_BASEADDR(DMA_InitStruct->LinkedListBaseAddr));
  assert_param(IS_LL_DMA_LINK_ADDR_OFFSET(DMA_InitStruct->LinkedListAddrOffset));
  assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
  if (DMA_InitStruct->Mode == LL_DMA_PFCTRL)
  {
    assert_param(IS_LL_DMA_PFREQ_INSTANCE(DMAx, Channel));
  }

  /* Check DMA instance */
  if (IS_LL_GPDMA_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    assert_param(IS_LL_DMA_BURST_LENGTH(DMA_InitStruct->SrcBurstLength));
    assert_param(IS_LL_DMA_BURST_LENGTH(DMA_InitStruct->DestBurstLength));
    assert_param(IS_LL_DMA_DEST_HALFWORD_EXCHANGE(DMA_InitStruct->DestHWordExchange));
    assert_param(IS_LL_DMA_DEST_BYTE_EXCHANGE(DMA_InitStruct->DestByteExchange));
    assert_param(IS_LL_DMA_SRC_BYTE_EXCHANGE(DMA_InitStruct->SrcByteExchange));
    assert_param(IS_LL_DMA_LINK_ALLOCATED_PORT(DMA_InitStruct->LinkAllocatedPort));
    assert_param(IS_LL_DMA_SRC_ALLOCATED_PORT(DMA_InitStruct->SrcAllocatedPort));
    assert_param(IS_LL_DMA_DEST_ALLOCATED_PORT(DMA_InitStruct->DestAllocatedPort));
  }

  /* Check trigger polarity */
  if (DMA_InitStruct->TriggerPolarity != LL_DMA_TRIG_POLARITY_MASKED)
  {
    assert_param(IS_LL_DMA_TRIGGER_MODE(DMA_InitStruct->TriggerMode));
    assert_param(IS_LL_DMA_TRIGGER_SELECTION(DMA_InitStruct->TriggerSelection));
  }

  /* Check DMA channel */
  if (IS_LL_DMA_2D_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    assert_param(IS_LL_DMA_BLK_REPEATCOUNT(DMA_InitStruct->BlkRptCount));
    assert_param(IS_LL_DMA_BURST_SRC_ADDR_UPDATE(DMA_InitStruct->SrcAddrUpdateMode));
    assert_param(IS_LL_DMA_BURST_DEST_ADDR_UPDATE(DMA_InitStruct->DestAddrUpdateMode));
    assert_param(IS_LL_DMA_BURST_ADDR_UPDATE_VALUE(DMA_InitStruct->SrcAddrOffset));
    assert_param(IS_LL_DMA_BURST_ADDR_UPDATE_VALUE(DMA_InitStruct->DestAddrOffset));
    assert_param(IS_LL_DMA_BLKRPT_SRC_ADDR_UPDATE(DMA_InitStruct->BlkRptSrcAddrUpdateMode));
    assert_param(IS_LL_DMA_BLKRPT_DEST_ADDR_UPDATE(DMA_InitStruct->BlkRptDestAddrUpdateMode));
    assert_param(IS_LL_DMA_BLKRPT_ADDR_UPDATE_VALUE(DMA_InitStruct->BlkRptSrcAddrOffset));
    assert_param(IS_LL_DMA_BLKRPT_ADDR_UPDATE_VALUE(DMA_InitStruct->BlkRptDestAddrOffset));
  }

  /*-------------------------- DMAx CLBAR Configuration ------------------------
   * Configure the Transfer linked list address with parameter :
   * - LinkedListBaseAdd:                              DMA_CLBAR_LBA[31:16] bits
   */
  LL_DMA_SetLinkedListBaseAddr(DMAx, Channel, DMA_InitStruct->LinkedListBaseAddr);

  /*-------------------------- DMAx CCR Configuration --------------------------
   * Configure the control parameter :
   * - LinkAllocatedPort:                              DMA_CCR_LAP bit
   * - LinkStepMode:                                   DMA_CCR_LSM bit
   * - Priority:                                       DMA_CCR_PRIO [23:22] bits
   */
  LL_DMA_ConfigControl(DMAx, Channel, DMA_InitStruct->Priority | \
                       DMA_InitStruct->LinkAllocatedPort       | \
                       DMA_InitStruct->LinkStepMode);

  /*-------------------------- DMAx CTR1 Configuration -------------------------
   * Configure the Data transfer  parameter :
   * - DestAllocatedPort:                         DMA_CTR1_DAP bit
   * - DestHWordExchange:                         DMA_CTR1_DHX bit
   * - DestByteExchange:                          DMA_CTR1_DBX bit
   * - DestIncMode:                               DMA_CTR1_DINC bit
   * - DestDataWidth:                             DMA_CTR1_DDW_LOG2 [17:16] bits
   * - SrcAllocatedPort:                          DMA_CTR1_SAP bit
   * - SrcByteExchange:                           DMA_CTR1_SBX bit
   * - DataAlignment:                             DMA_CTR1_PAM [12:11] bits
   * - SrcIncMode:                                DMA_CTR1_SINC bit
   * - SrcDataWidth:                              DMA_CTR1_SDW_LOG2 [1:0] bits
   * - SrcBurstLength:                            DMA_CTR1_SBL_1 [9:4] bits
   * - DestBurstLength:                           DMA_CTR1_DBL_1 [25:20] bits
   */
  LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->DestAllocatedPort | \
                        DMA_InitStruct->DestHWordExchange                | \
                        DMA_InitStruct->DestByteExchange                 | \
                        DMA_InitStruct->DestIncMode                      | \
                        DMA_InitStruct->DestDataWidth                    | \
                        DMA_InitStruct->SrcAllocatedPort                 | \
                        DMA_InitStruct->SrcByteExchange                  | \
                        DMA_InitStruct->DataAlignment                    | \
                        DMA_InitStruct->SrcIncMode                       | \
                        DMA_InitStruct->SrcDataWidth);
  /* Check DMA instance */
  if (IS_LL_GPDMA_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    LL_DMA_ConfigBurstLength(DMAx, Channel,  DMA_InitStruct->SrcBurstLength,
                             DMA_InitStruct->DestBurstLength);
  }

  /*-------------------------- DMAx CTR2 Configuration -------------------------
   * Configure the channel transfer parameter :
   * - TransferEventMode:                          DMA_CTR2_TCEM [31:30] bits
   * - TriggerPolarity:                            DMA_CTR2_TRIGPOL [25:24] bits
   * - TriggerMode:                                DMA_CTR2_TRIGM  [15:14] bits
   * - BlkHWRequest:                               DMA_CTR2_BREQ bit
   * - Mode:                                       DMA_CTR2_PFREQ bit
   * - Direction:                                  DMA_CTR2_DREQ bit
   * - Direction:                                  DMA_CTR2_SWREQ bit
   * - TriggerSelection:                           DMA_CTR2_TRIGSEL [21:16] bits
   * - Request:                                    DMA_CTR2_REQSEL [6:0] bits
   */
  LL_DMA_ConfigChannelTransfer(DMAx, Channel, DMA_InitStruct->TransferEventMode | \
                               DMA_InitStruct->TriggerPolarity                  | \
                               DMA_InitStruct->BlkHWRequest                     | \
                               DMA_InitStruct->Mode                             | \
                               DMA_InitStruct->Direction);

  /* Check direction */
  if (DMA_InitStruct->Direction != LL_DMA_DIRECTION_MEMORY_TO_MEMORY)
  {
    LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->Request);
  }

  /* Check trigger polarity */
  if (DMA_InitStruct->TriggerPolarity != LL_DMA_TRIG_POLARITY_MASKED)
  {
    LL_DMA_SetHWTrigger(DMAx, Channel, DMA_InitStruct->TriggerSelection);
    LL_DMA_SetTriggerMode(DMAx, Channel, DMA_InitStruct->TriggerMode);
  }

  /*-------------------------- DMAx CBR1 Configuration -------------------------
   * Configure the Transfer Block counters and update mode with parameter :
   * - BlkDataLength:                                   DMA_CBR1_BNDT[15:0] bits
   * - BlkRptCount:                                     DMA_CBR1_BRC[26:16] bits
   *   BlkRptCount field is supported only by 2D addressing channels.
   * - BlkRptSrcAddrUpdateMode:                                DMA_CBR1_BRSDEC bit
   *   BlkRptSrcAddrUpdateMode field is supported only by 2D addressing channels.
   * - BlkRptDestAddrUpdateMode:                               DMA_CBR1_BRDDEC bit
   *   BlkRptDestAddrUpdateMode field is supported only by 2D addressing channels.
   * - SrcAddrUpdateMode:                                      DMA_CBR1_SDEC bit
   *   SrcAddrUpdateMode field is supported only by 2D addressing channels.
   * - DestAddrUpdateMode:                                     DMA_CBR1_DDEC bit
   *   DestAddrUpdateMode field is supported only by 2D addressing channels.
   */
  LL_DMA_SetBlkDataLength(DMAx, Channel, DMA_InitStruct->BlkDataLength);

  /* Check DMA channel */
  if (IS_LL_DMA_2D_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    LL_DMA_SetBlkRptCount(DMAx, Channel, DMA_InitStruct->BlkRptCount);
    LL_DMA_ConfigBlkRptAddrUpdate(DMAx, Channel, DMA_InitStruct->BlkRptSrcAddrUpdateMode  | \
                                  DMA_InitStruct->BlkRptDestAddrUpdateMode                | \
                                  DMA_InitStruct->SrcAddrUpdateMode                       | \
                                  DMA_InitStruct->DestAddrUpdateMode);
  }

  /*-------------------------- DMAx CSAR and CDAR Configuration ----------------
   * Configure the Transfer source address with parameter :
   * - SrcAddress:                                        DMA_CSAR_SA[31:0] bits
   * - DestAddress:                                       DMA_CDAR_DA[31:0] bits
   */
  LL_DMA_ConfigAddresses(DMAx, Channel, DMA_InitStruct->SrcAddress, DMA_InitStruct->DestAddress);

  /* Check DMA channel */
  if (IS_LL_DMA_2D_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    /*------------------------ DMAx CTR3 Configuration -------------------------
     * Configure the Transfer Block counters and update mode with parameter :
     * - SrcAddrOffset:                                 DMA_CTR3_SAO[28:16] bits
     *   SrcAddrOffset field is supported only by 2D addressing channels.
     * - DestAddrOffset:                                DMA_CTR3_DAO[12:0] bits
     *   DestAddrOffset field is supported only by 2D addressing channels.
     */
    LL_DMA_ConfigAddrUpdateValue(DMAx, Channel, DMA_InitStruct->SrcAddrOffset, DMA_InitStruct->DestAddrOffset);

    /*------------------------ DMAx CBR2 Configuration -----------------------
     * Configure the Transfer Block counters and update mode with parameter :
     * - BlkRptSrcAddrOffset:                         DMA_CBR2_BRSAO[15:0] bits
     *   BlkRptSrcAddrOffset field is supported only by 2D addressing channels.
     * - BlkRptDestAddrOffset:                        DMA_CBR2_BRDAO[31:16] bits
     *   BlkRptDestAddrOffset field is supported only by 2D addressing channels.
     */
    LL_DMA_ConfigBlkRptAddrUpdateValue(DMAx, Channel, DMA_InitStruct->BlkRptSrcAddrOffset,
                                       DMA_InitStruct->BlkRptDestAddrOffset);
  }

  /*-------------------------- DMAx CLLR Configuration -------------------------
   * Configure the Transfer linked list address with parameter :
   * - DestAddrOffset:                                    DMA_CLLR_LA[15:2] bits
   */
  LL_DMA_SetLinkedListAddrOffset(DMAx, Channel, DMA_InitStruct->LinkedListAddrOffset);

  return (uint32_t)SUCCESS;
}

/**
  * @brief  Set each @ref LL_DMA_InitTypeDef field to default value.
  * @param  DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
  * @retval None.
  */
void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
{
  /* Set DMA_InitStruct fields to default values */
  DMA_InitStruct->SrcAddress               = 0x00000000U;
  DMA_InitStruct->DestAddress              = 0x00000000U;
  DMA_InitStruct->Direction                = LL_DMA_DIRECTION_MEMORY_TO_MEMORY;
  DMA_InitStruct->BlkHWRequest             = LL_DMA_HWREQUEST_SINGLEBURST;
  DMA_InitStruct->DataAlignment            = LL_DMA_DATA_ALIGN_ZEROPADD;
  DMA_InitStruct->SrcBurstLength           = 1U;
  DMA_InitStruct->DestBurstLength          = 1U;
  DMA_InitStruct->SrcDataWidth             = LL_DMA_SRC_DATAWIDTH_BYTE;
  DMA_InitStruct->DestDataWidth            = LL_DMA_DEST_DATAWIDTH_BYTE;
  DMA_InitStruct->SrcIncMode               = LL_DMA_SRC_FIXED;
  DMA_InitStruct->DestIncMode              = LL_DMA_DEST_FIXED;
  DMA_InitStruct->Priority                 = LL_DMA_LOW_PRIORITY_LOW_WEIGHT;
  DMA_InitStruct->BlkDataLength            = 0x00000000U;
  DMA_InitStruct->Mode                     = LL_DMA_NORMAL;
  DMA_InitStruct->BlkRptCount              = 0x00000000U;
  DMA_InitStruct->TriggerMode              = LL_DMA_TRIGM_BLK_TRANSFER;
  DMA_InitStruct->TriggerPolarity          = LL_DMA_TRIG_POLARITY_MASKED;
  DMA_InitStruct->TriggerSelection         = 0x00000000U;
  DMA_InitStruct->Request                  = 0x00000000U;
  DMA_InitStruct->TransferEventMode        = LL_DMA_TCEM_BLK_TRANSFER;
  DMA_InitStruct->DestHWordExchange        = LL_DMA_DEST_HALFWORD_PRESERVE;
  DMA_InitStruct->DestByteExchange         = LL_DMA_DEST_BYTE_PRESERVE;
  DMA_InitStruct->SrcByteExchange          = LL_DMA_SRC_BYTE_PRESERVE;
  DMA_InitStruct->SrcAllocatedPort         = LL_DMA_SRC_ALLOCATED_PORT0;
  DMA_InitStruct->DestAllocatedPort        = LL_DMA_DEST_ALLOCATED_PORT0;
  DMA_InitStruct->LinkAllocatedPort        = LL_DMA_LINK_ALLOCATED_PORT0;
  DMA_InitStruct->LinkStepMode             = LL_DMA_LSM_FULL_EXECUTION;
  DMA_InitStruct->SrcAddrUpdateMode        = LL_DMA_BURST_SRC_ADDR_INCREMENT;
  DMA_InitStruct->DestAddrUpdateMode       = LL_DMA_BURST_DEST_ADDR_INCREMENT;
  DMA_InitStruct->SrcAddrOffset            = 0x00000000U;
  DMA_InitStruct->DestAddrOffset           = 0x00000000U;
  DMA_InitStruct->BlkRptSrcAddrUpdateMode  = LL_DMA_BLKRPT_SRC_ADDR_INCREMENT;
  DMA_InitStruct->BlkRptDestAddrUpdateMode = LL_DMA_BLKRPT_DEST_ADDR_INCREMENT;
  DMA_InitStruct->BlkRptSrcAddrOffset      = 0x00000000U;
  DMA_InitStruct->BlkRptDestAddrOffset     = 0x00000000U;
  DMA_InitStruct->LinkedListBaseAddr       = 0x00000000U;
  DMA_InitStruct->LinkedListAddrOffset     = 0x00000000U;
}

/**
  * @brief  Set each @ref LL_DMA_InitLinkedListTypeDef field to default value.
  * @param  DMA_InitLinkedListStruct Pointer to
  *         a @ref LL_DMA_InitLinkedListTypeDef structure.
  * @retval None.
  */
void LL_DMA_ListStructInit(LL_DMA_InitLinkedListTypeDef *DMA_InitLinkedListStruct)
{
  /* Set LL_DMA_InitLinkedListTypeDef fields to default values */
  DMA_InitLinkedListStruct->Priority          = LL_DMA_LOW_PRIORITY_LOW_WEIGHT;
  DMA_InitLinkedListStruct->LinkStepMode      = LL_DMA_LSM_FULL_EXECUTION;
  DMA_InitLinkedListStruct->TransferEventMode = LL_DMA_TCEM_LAST_LLITEM_TRANSFER;
  DMA_InitLinkedListStruct->LinkAllocatedPort = LL_DMA_LINK_ALLOCATED_PORT0;
}

/**
  * @brief De-initialize the DMA linked list.
  * @note  This API is used for all available DMA channels.
  * @note  To convert DMAx_Channely Instance to DMAx Instance and Channely, use
  *        helper macros :
  *        @arg @ref LL_DMA_GET_INSTANCE
  *        @arg @ref LL_DMA_GET_CHANNEL
  * @param  DMAx DMAx Instance
  * @param  Channel This parameter can be one of the following values:
  *         @arg @ref LL_DMA_CHANNEL_0
  *         @arg @ref LL_DMA_CHANNEL_1
  *         @arg @ref LL_DMA_CHANNEL_2
  *         @arg @ref LL_DMA_CHANNEL_3
  *         @arg @ref LL_DMA_CHANNEL_4
  *         @arg @ref LL_DMA_CHANNEL_5
  *         @arg @ref LL_DMA_CHANNEL_6
  *         @arg @ref LL_DMA_CHANNEL_7
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS : DMA registers are de-initialized.
  *          - ERROR   : DMA registers are not de-initialized.
  */
uint32_t LL_DMA_List_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
{
  return LL_DMA_DeInit(DMAx, Channel);
}

/**
  * @brief Initialize the DMA linked list according to the specified parameters
  *        in LL_DMA_InitLinkedListTypeDef.
  * @note  This API is used for all available DMA channels.
  * @note  To convert DMAx_Channely Instance to DMAx Instance and Channely, use
  *        helper macros :
  *        @arg @ref LL_DMA_GET_INSTANCE
  *        @arg @ref LL_DMA_GET_CHANNEL
  * @param  DMAx DMAx Instance
  * @param  Channel This parameter can be one of the following values:
  *         @arg @ref LL_DMA_CHANNEL_0
  *         @arg @ref LL_DMA_CHANNEL_1
  *         @arg @ref LL_DMA_CHANNEL_2
  *         @arg @ref LL_DMA_CHANNEL_3
  *         @arg @ref LL_DMA_CHANNEL_4
  *         @arg @ref LL_DMA_CHANNEL_5
  *         @arg @ref LL_DMA_CHANNEL_6
  *         @arg @ref LL_DMA_CHANNEL_7
  * @param  DMA_InitLinkedListStruct pointer to
  *         a @ref LL_DMA_InitLinkedListTypeDef structure.
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS : DMA registers are initialized.
  *          - ERROR   : Not applicable.
  */
uint32_t LL_DMA_List_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitLinkedListTypeDef *DMA_InitLinkedListStruct)
{
  /* Check the DMA Instance DMAx and Channel parameters*/
  assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));

  /* Check the DMA parameters from DMA_InitLinkedListStruct */
  assert_param(IS_LL_DMA_PRIORITY(DMA_InitLinkedListStruct->Priority));
  assert_param(IS_LL_DMA_LINK_STEP_MODE(DMA_InitLinkedListStruct->LinkStepMode));
  assert_param(IS_LL_DMA_TRANSFER_EVENT_MODE(DMA_InitLinkedListStruct->TransferEventMode));
  /* Check DMA instance */
  if (IS_LL_GPDMA_CHANNEL_INSTANCE(DMAx, Channel) != 0U)
  {
    assert_param(IS_LL_DMA_LINK_ALLOCATED_PORT(DMA_InitLinkedListStruct->LinkAllocatedPort));
  }

  /*-------------------------- DMAx CCR Configuration --------------------------
   * Configure the control parameter :
   * - LinkAllocatedPort:                              DMA_CCR_LAP bit
   *   LinkAllocatedPort field is supported only by GPDMA channels.
   * - LinkStepMode:                                   DMA_CCR_LSM bit
   * - Priority:                                       DMA_CCR_PRIO [23:22] bits
   */
  LL_DMA_ConfigControl(DMAx, Channel, DMA_InitLinkedListStruct->Priority | \
                       DMA_InitLinkedListStruct->LinkAllocatedPort       | \
                       DMA_InitLinkedListStruct->LinkStepMode);

  /*-------------------------- DMAx CTR2 Configuration -------------------------
   * Configure the channel transfer parameter :
   * - TransferEventMode:                          DMA_CTR2_TCEM [31:30] bits
   */
  LL_DMA_SetTransferEventMode(DMAx, Channel, DMA_InitLinkedListStruct->TransferEventMode);

  return (uint32_t)SUCCESS;
}

/**
  * @brief  Set each @ref LL_DMA_InitNodeTypeDef field to default value.
  * @param  DMA_InitNodeStruct Pointer to a @ref LL_DMA_InitNodeTypeDef
  *         structure.
  * @retval None.
  */
void LL_DMA_NodeStructInit(LL_DMA_InitNodeTypeDef *DMA_InitNodeStruct)
{
  /* Set DMA_InitNodeStruct fields to default values */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
  DMA_InitNodeStruct->DestSecure               = LL_DMA_CHANNEL_DEST_NSEC;
#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
  DMA_InitNodeStruct->DestAllocatedPort        = LL_DMA_DEST_ALLOCATED_PORT0;
  DMA_InitNodeStruct->DestHWordExchange        = LL_DMA_DEST_HALFWORD_PRESERVE;
  DMA_InitNodeStruct->DestByteExchange         = LL_DMA_DEST_BYTE_PRESERVE;
  DMA_InitNodeStruct->DestBurstLength          = 1U;
  DMA_InitNodeStruct->DestIncMode              = LL_DMA_DEST_FIXED;
  DMA_InitNodeStruct->DestDataWidth            = LL_DMA_DEST_DATAWIDTH_BYTE;
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
  DMA_InitNodeStruct->SrcSecure                = LL_DMA_CHANNEL_SRC_NSEC;
#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
  DMA_InitNodeStruct->SrcAllocatedPort         = LL_DMA_SRC_ALLOCATED_PORT0;
  DMA_InitNodeStruct->SrcByteExchange          = LL_DMA_SRC_BYTE_PRESERVE;
  DMA_InitNodeStruct->DataAlignment            = LL_DMA_DATA_ALIGN_ZEROPADD;
  DMA_InitNodeStruct->SrcBurstLength           = 1U;
  DMA_InitNodeStruct->SrcIncMode               = LL_DMA_SRC_FIXED;
  DMA_InitNodeStruct->SrcDataWidth             = LL_DMA_SRC_DATAWIDTH_BYTE;
  DMA_InitNodeStruct->TransferEventMode        = LL_DMA_TCEM_BLK_TRANSFER;
  DMA_InitNodeStruct->TriggerPolarity          = LL_DMA_TRIG_POLARITY_MASKED;
  DMA_InitNodeStruct->TriggerSelection         = 0x00000000U;
  DMA_InitNodeStruct->TriggerMode              = LL_DMA_TRIGM_BLK_TRANSFER;
  DMA_InitNodeStruct->BlkHWRequest             = LL_DMA_HWREQUEST_SINGLEBURST;
  DMA_InitNodeStruct->Direction                = LL_DMA_DIRECTION_MEMORY_TO_MEMORY;
  DMA_InitNodeStruct->Request                  = 0x00000000U;
  DMA_InitNodeStruct->Mode                     = LL_DMA_NORMAL;
  DMA_InitNodeStruct->BlkRptDestAddrUpdateMode = LL_DMA_BLKRPT_DEST_ADDR_INCREMENT;
  DMA_InitNodeStruct->BlkRptSrcAddrUpdateMode  = LL_DMA_BLKRPT_SRC_ADDR_INCREMENT;
  DMA_InitNodeStruct->DestAddrUpdateMode       = LL_DMA_BURST_DEST_ADDR_INCREMENT;
  DMA_InitNodeStruct->SrcAddrUpdateMode        = LL_DMA_BURST_SRC_ADDR_INCREMENT;
  DMA_InitNodeStruct->BlkRptCount              = 0x00000000U;
  DMA_InitNodeStruct->BlkDataLength            = 0x00000000U;
  DMA_InitNodeStruct->SrcAddress               = 0x00000000U;
  DMA_InitNodeStruct->DestAddress              = 0x00000000U;
  DMA_InitNodeStruct->DestAddrOffset           = 0x00000000U;
  DMA_InitNodeStruct->SrcAddrOffset            = 0x00000000U;
  DMA_InitNodeStruct->BlkRptDestAddrOffset     = 0x00000000U;
  DMA_InitNodeStruct->BlkRptSrcAddrOffset      = 0x00000000U;
  DMA_InitNodeStruct->UpdateRegisters          = (LL_DMA_UPDATE_CTR1 | LL_DMA_UPDATE_CTR2 | \
                                                  LL_DMA_UPDATE_CBR1 | LL_DMA_UPDATE_CSAR | \
                                                  LL_DMA_UPDATE_CDAR | LL_DMA_UPDATE_CTR3 | \
                                                  LL_DMA_UPDATE_CBR2 | LL_DMA_UPDATE_CLLR);
  DMA_InitNodeStruct->NodeType                 = LL_DMA_GPDMA_LINEAR_NODE;
}

/**
  * @brief  Initializes DMA linked list node according to the specified
  *         parameters in the DMA_InitNodeStruct.
  * @param  DMA_InitNodeStruct Pointer to a LL_DMA_InitNodeTypeDef structure
  *         that contains linked list node
  *         registers configurations.
  * @param  pNode Pointer to linked list node to fill according to
  *         LL_DMA_LinkNodeTypeDef parameters.
  * @retval None
  */
uint32_t LL_DMA_CreateLinkNode(LL_DMA_InitNodeTypeDef *DMA_InitNodeStruct, LL_DMA_LinkNodeTypeDef *pNode)
{
  uint32_t reg_counter = 0U;

  /* Check the DMA Node type */
  assert_param(IS_LL_DMA_LINK_NODETYPE(DMA_InitNodeStruct->NodeType));

  /* Check the DMA parameters from DMA_InitNodeStruct */
  assert_param(IS_LL_DMA_DIRECTION(DMA_InitNodeStruct->Direction));

  /* Check direction */
  if (DMA_InitNodeStruct->Direction != LL_DMA_DIRECTION_MEMORY_TO_MEMORY)
  {
    assert_param(IS_LL_DMA_REQUEST_SELECTION(DMA_InitNodeStruct->Request));
  }

  assert_param(IS_LL_DMA_DATA_ALIGNMENT(DMA_InitNodeStruct->DataAlignment));
  assert_param(IS_LL_DMA_SRC_DATA_WIDTH(DMA_InitNodeStruct->SrcDataWidth));
  assert_param(IS_LL_DMA_DEST_DATA_WIDTH(DMA_InitNodeStruct->DestDataWidth));
  assert_param(IS_LL_DMA_SRC_INCREMENT_MODE(DMA_InitNodeStruct->SrcIncMode));
  assert_param(IS_LL_DMA_DEST_INCREMENT_MODE(DMA_InitNodeStruct->DestIncMode));
  assert_param(IS_LL_DMA_BLK_DATALENGTH(DMA_InitNodeStruct->BlkDataLength));
  assert_param(IS_LL_DMA_TRIGGER_POLARITY(DMA_InitNodeStruct->TriggerPolarity));
  assert_param(IS_LL_DMA_BLKHW_REQUEST(DMA_InitNodeStruct->BlkHWRequest));
  assert_param(IS_LL_DMA_TRANSFER_EVENT_MODE(DMA_InitNodeStruct->TransferEventMode));
  assert_param(IS_LL_DMA_LINK_UPDATE_REGISTERS(DMA_InitNodeStruct->UpdateRegisters));
  assert_param(IS_LL_DMA_MODE(DMA_InitNodeStruct->Mode));

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
  assert_param(IS_LL_DMA_CHANNEL_SRC_SEC(DMA_InitNodeStruct->SrcSecure));
  assert_param(IS_LL_DMA_CHANNEL_DEST_SEC(DMA_InitNodeStruct->DestSecure));
#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */

  /* Check trigger polarity */
  if (DMA_InitNodeStruct->TriggerPolarity != LL_DMA_TRIG_POLARITY_MASKED)
  {
    assert_param(IS_LL_DMA_TRIGGER_MODE(DMA_InitNodeStruct->TriggerMode));
    assert_param(IS_LL_DMA_TRIGGER_SELECTION(DMA_InitNodeStruct->TriggerSelection));
  }

  /* Check node type */
  if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_LINEAR_NODE)
  {
    assert_param(IS_LL_DMA_BURST_LENGTH(DMA_InitNodeStruct->SrcBurstLength));
    assert_param(IS_LL_DMA_BURST_LENGTH(DMA_InitNodeStruct->DestBurstLength));
    assert_param(IS_LL_DMA_DEST_HALFWORD_EXCHANGE(DMA_InitNodeStruct->DestHWordExchange));
    assert_param(IS_LL_DMA_DEST_BYTE_EXCHANGE(DMA_InitNodeStruct->DestByteExchange));
    assert_param(IS_LL_DMA_SRC_BYTE_EXCHANGE(DMA_InitNodeStruct->SrcByteExchange));
    assert_param(IS_LL_DMA_SRC_ALLOCATED_PORT(DMA_InitNodeStruct->SrcAllocatedPort));
    assert_param(IS_LL_DMA_DEST_ALLOCATED_PORT(DMA_InitNodeStruct->DestAllocatedPort));
  }

  /* Check DMA channel */
  if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_2D_NODE)
  {
    assert_param(IS_LL_DMA_BLK_REPEATCOUNT(DMA_InitNodeStruct->BlkRptCount));
    assert_param(IS_LL_DMA_BURST_SRC_ADDR_UPDATE(DMA_InitNodeStruct->SrcAddrUpdateMode));
    assert_param(IS_LL_DMA_BURST_DEST_ADDR_UPDATE(DMA_InitNodeStruct->DestAddrUpdateMode));
    assert_param(IS_LL_DMA_BURST_ADDR_UPDATE_VALUE(DMA_InitNodeStruct->SrcAddrOffset));
    assert_param(IS_LL_DMA_BURST_ADDR_UPDATE_VALUE(DMA_InitNodeStruct->DestAddrOffset));
    assert_param(IS_LL_DMA_BLKRPT_SRC_ADDR_UPDATE(DMA_InitNodeStruct->BlkRptSrcAddrUpdateMode));
    assert_param(IS_LL_DMA_BLKRPT_DEST_ADDR_UPDATE(DMA_InitNodeStruct->BlkRptDestAddrUpdateMode));
    assert_param(IS_LL_DMA_BLKRPT_ADDR_UPDATE_VALUE(DMA_InitNodeStruct->BlkRptSrcAddrOffset));
    assert_param(IS_LL_DMA_BLKRPT_ADDR_UPDATE_VALUE(DMA_InitNodeStruct->BlkRptDestAddrOffset));
  }

  /* Check if CTR1 register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CTR1) == LL_DMA_UPDATE_CTR1)
  {
    /*-------------------------- DMAx CTR1 Configuration -----------------------
    * Configure the Data transfer  parameter :
    * - DestAllocatedPort:                        DMA_CTR1_DAP bit
    * - DestHWordExchange:                        DMA_CTR1_DHX bit
    * - DestByteExchange:                         DMA_CTR1_DBX bit
    * - DestIncMode:                              DMA_CTR1_DINC bit
    * - DestDataWidth:                            DMA_CTR1_DDW_LOG2 [17:16] bits
    * - SrcAllocatedPort:                         DMA_CTR1_SAP bit
    * - SrcByteExchange:                          DMA_CTR1_SBX bit
    * - DataAlignment:                            DMA_CTR1_PAM [12:11] bits
    * - SrcIncMode:                               DMA_CTR1_SINC bit
    * - SrcDataWidth:                             DMA_CTR1_SDW_LOG2 [1:0] bits
    * - SrcBurstLength:                           DMA_CTR1_SBL_1 [9:4] bits
    * - DestBurstLength:                          DMA_CTR1_DBL_1 [25:20] bits
    */

    pNode->LinkRegisters[reg_counter] = (DMA_InitNodeStruct->DestIncMode   | \
                                         DMA_InitNodeStruct->DestDataWidth | \
                                         DMA_InitNodeStruct->DataAlignment | \
                                         DMA_InitNodeStruct->SrcIncMode    | \
                                         DMA_InitNodeStruct->SrcDataWidth);

#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
    pNode->LinkRegisters[reg_counter] |= (DMA_InitNodeStruct->DestSecure | \
                                          DMA_InitNodeStruct->SrcSecure);
#endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */

    /* Update CTR1 register fields */
    pNode->LinkRegisters[reg_counter] |= (DMA_InitNodeStruct->DestAllocatedPort                              | \
                                          DMA_InitNodeStruct->DestHWordExchange                              | \
                                          DMA_InitNodeStruct->DestByteExchange                               | \
                                          ((DMA_InitNodeStruct->DestBurstLength - 1U) << DMA_CTR1_DBL_1_Pos) | \
                                          DMA_InitNodeStruct->SrcAllocatedPort                               | \
                                          DMA_InitNodeStruct->SrcByteExchange                                | \
                                          ((DMA_InitNodeStruct->SrcBurstLength - 1U) << DMA_CTR1_SBL_1_Pos));

    /* Increment counter for the next register */
    reg_counter++;
  }


  /* Check if CTR2 register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CTR2) == LL_DMA_UPDATE_CTR2)
  {
    /*-------------------------- DMAx CTR2 Configuration -----------------------
     * Configure the channel transfer parameter :
     * - TransferEventMode:                        DMA_CTR2_TCEM [31:30] bits
     * - TriggerPolarity:                          DMA_CTR2_TRIGPOL [25:24] bits
     * - TriggerMode:                              DMA_CTR2_TRIGM  [15:14] bits
     * - Mode:                                     DMA_CTR2_PFREQ bit
     * - BlkHWRequest:                             DMA_CTR2_BREQ bit
     * - Direction:                                DMA_CTR2_DREQ bit
     * - Direction:                                DMA_CTR2_SWREQ bit
     * - TriggerSelection:                         DMA_CTR2_TRIGSEL [21:16] bits
     * - Request:                                  DMA_CTR2_REQSEL [6:0] bits
     */
    pNode->LinkRegisters[reg_counter] = (DMA_InitNodeStruct->TransferEventMode | \
                                         DMA_InitNodeStruct->TriggerPolarity   | \
                                         DMA_InitNodeStruct->BlkHWRequest      | \
                                         DMA_InitNodeStruct->Mode              | \
                                         DMA_InitNodeStruct->Direction);

    /* Check direction */
    if (DMA_InitNodeStruct->Direction != LL_DMA_DIRECTION_MEMORY_TO_MEMORY)
    {
      pNode->LinkRegisters[reg_counter] |= DMA_InitNodeStruct->Request & DMA_CTR2_REQSEL;
    }

    /* Check trigger polarity */
    if (DMA_InitNodeStruct->TriggerPolarity != LL_DMA_TRIG_POLARITY_MASKED)
    {
      pNode->LinkRegisters[reg_counter] |= (((DMA_InitNodeStruct->TriggerSelection << DMA_CTR2_TRIGSEL_Pos) & \
                                             DMA_CTR2_TRIGSEL) | DMA_InitNodeStruct->TriggerMode);
    }


    /* Increment counter for the next register */
    reg_counter++;
  }

  /* Check if CBR1 register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CBR1) == LL_DMA_UPDATE_CBR1)
  {
    /*-------------------------- DMAx CBR1 Configuration -----------------------
     * Configure the Transfer Block counters and update mode with parameter :
     * - BlkDataLength:                                 DMA_CBR1_BNDT[15:0] bits
     * - BlkRptCount:                                   DMA_CBR1_BRC[26:16] bits
     *   BlkRptCount field is supported only by 2D addressing channels.
     * - BlkRptSrcAddrUpdateMode:                              DMA_CBR1_BRSDEC bit
     *   BlkRptSrcAddrUpdateMode field is supported only by 2D addressing channels.
     * - BlkRptDestAddrUpdateMode:                             DMA_CBR1_BRDDEC bit
     *   BlkRptDestAddrUpdateMode field is supported only by 2D addressing channels.
     * - SrcAddrUpdateMode:                                    DMA_CBR1_SDEC bit
     *   SrcAddrUpdateMode field is supported only by 2D addressing channels.
     * - DestAddrUpdateMode:                                   DMA_CBR1_DDEC bit
     *   DestAddrUpdateMode field is supported only by 2D addressing channels.
     */
    pNode->LinkRegisters[reg_counter] = DMA_InitNodeStruct->BlkDataLength;

    /* Update CBR1 register fields for 2D addressing channels */
    if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_2D_NODE)
    {
      pNode->LinkRegisters[reg_counter] |= (DMA_InitNodeStruct->BlkRptDestAddrUpdateMode | \
                                            DMA_InitNodeStruct->BlkRptSrcAddrUpdateMode  | \
                                            DMA_InitNodeStruct->DestAddrUpdateMode       | \
                                            DMA_InitNodeStruct->SrcAddrUpdateMode        | \
                                            ((DMA_InitNodeStruct->BlkRptCount << DMA_CBR1_BRC_Pos) & DMA_CBR1_BRC));
    }

    /* Increment counter for the next register */
    reg_counter++;
  }

  /* Check if CSAR register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CSAR) == LL_DMA_UPDATE_CSAR)
  {
    /*-------------------------- DMAx CSAR Configuration -----------------------
     * Configure the Transfer Block counters and update mode with parameter :
     * - SrcAddress:                                         DMA_CSAR_SA[31:0] bits
     */
    pNode->LinkRegisters[reg_counter] = DMA_InitNodeStruct->SrcAddress;

    /* Increment counter for the next register */
    reg_counter++;
  }


  /* Check if CDAR register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CDAR) == LL_DMA_UPDATE_CDAR)
  {
    /*-------------------------- DMAx CDAR Configuration -----------------------
     * Configure the Transfer Block counters and update mode with parameter :
     * - DestAddress:                                        DMA_CDAR_DA[31:0] bits
     */
    pNode->LinkRegisters[reg_counter] = DMA_InitNodeStruct->DestAddress;

    /* Increment counter for the next register */
    reg_counter++;
  }


  /* Update CTR3 register fields for 2D addressing channels */
  if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_2D_NODE)
  {
    /* Check if CTR3 register update is enabled */
    if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CTR3) == LL_DMA_UPDATE_CTR3)
    {
      /*-------------------------- DMAx CTR3 Configuration ---------------------
      * Configure the Block counters and update mode with parameter :
      * - DestAddressOffset:                             DMA_CTR3_DAO[12:0] bits
      *   DestAddressOffset field is supported only by 2D addressing channels.
      * - SrcAddressOffset:                              DMA_CTR3_SAO[12:0] bits
      *   SrcAddressOffset field is supported only by 2D addressing channels.
      */
      pNode->LinkRegisters[reg_counter] = (DMA_InitNodeStruct->SrcAddrOffset | \
                                           ((DMA_InitNodeStruct->DestAddrOffset << DMA_CTR3_DAO_Pos) & DMA_CTR3_DAO));

      /* Increment counter for the next register */
      reg_counter++;
    }
  }


  /* Update CBR2 register fields for 2D addressing channels */
  if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_2D_NODE)
  {
    /* Check if CBR2 register update is enabled */
    if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CBR2) == LL_DMA_UPDATE_CBR2)
    {
      /*-------------------------- DMAx CBR2 Configuration ---------------------
      * Configure the Block counters and update mode with parameter :
      * - BlkRptDestAddrOffset:                       DMA_CBR2_BRDAO[31:16] bits
      *   BlkRptDestAddrOffset field is supported only by 2D addressing channels.
      * - BlkRptSrcAddrOffset:                        DMA_CBR2_BRSAO[15:0] bits
      *   BlkRptSrcAddrOffset field is supported only by 2D addressing channels.
      */
      pNode->LinkRegisters[reg_counter] = (DMA_InitNodeStruct->BlkRptSrcAddrOffset | \
                                           ((DMA_InitNodeStruct->BlkRptDestAddrOffset << DMA_CBR2_BRDAO_Pos) & \
                                            DMA_CBR2_BRDAO));

      /* Increment counter for the next register */
      reg_counter++;
    }
  }

  /* Check if CLLR register update is enabled */
  if ((DMA_InitNodeStruct->UpdateRegisters & LL_DMA_UPDATE_CLLR) == LL_DMA_UPDATE_CLLR)
  {
    /*-------------------------- DMAx CLLR Configuration -----------------------
    * Configure the Transfer Block counters and update mode with parameter :
    * - UpdateRegisters                                         DMA_CLLR_UT1 bit
    * - UpdateRegisters                                         DMA_CLLR_UT2 bit
    * - UpdateRegisters                                         DMA_CLLR_UB1 bit
    * - UpdateRegisters                                         DMA_CLLR_USA bit
    * - UpdateRegisters                                         DMA_CLLR_UDA bit
    * - UpdateRegisters                                         DMA_CLLR_UT3 bit
    *   DMA_CLLR_UT3 bit is discarded for linear addressing channels.
    * - UpdateRegisters                                         DMA_CLLR_UB2 bit
    *   DMA_CLLR_UB2 bit is discarded for linear addressing channels.
    * - UpdateRegisters                                         DMA_CLLR_ULL bit
    */
    pNode->LinkRegisters[reg_counter] = ((DMA_InitNodeStruct->UpdateRegisters & (DMA_CLLR_UT1 | DMA_CLLR_UT2 | \
                                                                                 DMA_CLLR_UB1 | DMA_CLLR_USA | \
                                                                                 DMA_CLLR_UDA | DMA_CLLR_ULL)));

    /* Update CLLR register fields for 2D addressing channels */
    if (DMA_InitNodeStruct->NodeType == LL_DMA_GPDMA_2D_NODE)
    {
      pNode->LinkRegisters[reg_counter] |= (DMA_InitNodeStruct->UpdateRegisters & (DMA_CLLR_UT3 | DMA_CLLR_UB2));
    }
  }

  return (uint32_t)SUCCESS;
}

/**
  * @brief  Connect Linked list Nodes.
  * @param  pPrevLinkNode Pointer to previous linked list node to be connected to new Linked list node.
  * @param  PrevNodeCLLRIdx Offset of Previous Node CLLR register.
  *         This parameter can be a value of @ref DMA_LL_EC_CLLR_OFFSET.
  * @param  pNewLinkNode Pointer to new Linked list.
  * @param  NewNodeCLLRIdx Offset of New Node CLLR register.
  *         This parameter can be a value of @ref DMA_LL_EC_CLLR_OFFSET.
  * @retval None
  */
void LL_DMA_ConnectLinkNode(LL_DMA_LinkNodeTypeDef *pPrevLinkNode, uint32_t PrevNodeCLLRIdx,
                            LL_DMA_LinkNodeTypeDef *pNewLinkNode, uint32_t NewNodeCLLRIdx)
{
  pPrevLinkNode->LinkRegisters[PrevNodeCLLRIdx] = (((uint32_t)pNewLinkNode & DMA_CLLR_LA)                        | \
                                                   (pNewLinkNode->LinkRegisters[NewNodeCLLRIdx] & (DMA_CLLR_UT1  | \
                                                       DMA_CLLR_UT2 | DMA_CLLR_UB1 | DMA_CLLR_USA | DMA_CLLR_UDA | \
                                                       DMA_CLLR_UT3 | DMA_CLLR_UB2 | DMA_CLLR_ULL)));
}

/**
  * @brief  Disconnect the next linked list node.
  * @param  pLinkNode Pointer to linked list node to be disconnected from the next one.
  * @param  LinkNodeCLLRIdx Offset of Link Node CLLR register.
  * @retval None.
  */
void LL_DMA_DisconnectNextLinkNode(LL_DMA_LinkNodeTypeDef *pLinkNode, uint32_t LinkNodeCLLRIdx)
{
  pLinkNode->LinkRegisters[LinkNodeCLLRIdx] = 0;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

#endif /* GPDMA1 */

/**
  * @}
  */

#endif /* USE_FULL_LL_DRIVER */

