828eco基于GD32H7mcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1311 lines
63 KiB

/*!
\file gd32h75e_mdma.c
\brief MDMA driver
\version 2025-08-07, V1.2.0, firmware for GD32H75E
*/
/*
Copyright (c) 2025, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h75e_mdma.h"
#define MDMA_ADDRESS_MASK ((uint32_t)0x0000FFFFU) /*!< MDMA multi-block update address mask */
#define STAT1_FLAG_MASK ((uint32_t)0x00000F00U) /*!< MDMA_STAT1 flag mask */
#define CHXMBADDRU_DADDRUV_OFFSET (16U) /*!< destination update address offset */
#define CHXCFG_BTLEN_OFFSET (18U) /*!< bit offset of BTLEN in MDMA_CHxCFG */
#define CHXBTCFG_BRNUM_OFFSET (20U) /*!< bit offset of BRNUM in MDMA_CHxBTCFG */
/*!
\brief deinitialize MDMA (API_ID(0x0001U))
\param[in] none
\param[out] none
\retval none
*/
void mdma_deinit(void)
{
/* reset MDMA */
rcu_periph_reset_enable(RCU_MDMARST);
rcu_periph_reset_disable(RCU_MDMARST);
}
/*!
\brief deinitialize MDMA registers of a channel (API_ID(0x0002U))
\param[in] channelx: specify which MDMA channel is deinitialized
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_deinit(mdma_channel_enum channelx)
{
MDMA_CHXSTATC(channelx) = 0x0000001FU;
MDMA_CHXCTL0(channelx) = 0U;
MDMA_CHXCFG(channelx) = 0U;
MDMA_CHXBTCFG(channelx) = 0U;
MDMA_CHXSADDR(channelx) = 0U;
MDMA_CHXDADDR(channelx) = 0U;
MDMA_CHXMBADDRU(channelx) = 0U;
MDMA_CHXLADDR(channelx) = 0U;
MDMA_CHXCTL1(channelx) = 0U;
MDMA_CHXMADDR(channelx) = 0U;
MDMA_CHXMDATA(channelx) = 0U;
}
/*!
\brief initialize the MDMA single data mode parameters structure with the default values (API_ID(0x0003U))
\param[in] none
\param[out] init_struct: the initialization data needed to initialize MDMA channel
\retval none
*/
void mdma_para_struct_init(mdma_parameter_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0003U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* set the MDMA struct with the default values */
init_struct->request = 0U;
init_struct->trans_trig_mode = MDMA_BUFFER_TRANSFER;
init_struct->priority = MDMA_PRIORITY_LOW;
init_struct->endianness = MDMA_LITTLE_ENDIANNESS;
init_struct->source_inc = MDMA_SOURCE_INCREASE_DISABLE;
init_struct->dest_inc = MDMA_DESTINATION_INCREASE_DISABLE;
init_struct->source_data_size = MDMA_SOURCE_DATASIZE_8BIT;
init_struct->dest_data_size = MDMA_DESTINATION_DATASIZE_8BIT;
init_struct->data_alignment = MDMA_DATAALIGN_RIGHT;
init_struct->buff_trans_len = 0U;
init_struct->source_burst = MDMA_SOURCE_BURST_SINGLE;
init_struct->dest_burst = MDMA_DESTINATION_BURST_SINGLE;
init_struct->mask_addr = 0x00000000U;
init_struct->mask_data = 0x00000000U;
init_struct->source_addr = 0x00000000U;
init_struct->dest_addr = 0x00000000U;
init_struct->tbytes_num_in_block = 0U;
init_struct->source_bus = MDMA_SOURCE_AXI;
init_struct->dest_bus = MDMA_DESTINATION_AXI;
init_struct->bufferable_write_mode = MDMA_BUFFERABLE_WRITE_DISABLE;
}
}
/*!
\brief initialize the MDMA multi block transfer mode parameters structure with the default values (API_ID(0x0004U))
\param[in] none
\param[out] block_init_struct: the initialization data needed to initialize MDMA multi block transfer
\retval none
*/
void mdma_multi_block_para_struct_init(mdma_multi_block_parameter_struct *block_init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(block_init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0004U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
block_init_struct->block_num = 0U;
block_init_struct->saddr_update_val = 0U;
block_init_struct->dstaddr_update_val = 0U;
block_init_struct->saddr_update_dir = UPDATE_DIR_INCREASE;
block_init_struct->dstaddr_update_dir = UPDATE_DIR_INCREASE;
}
}
/*!
\brief initialize the MDMA link node configuration structure with the default values (API_ID(0x0005U))
\param[in] none
\param[out] node: the initialization data needed to initialize link node
\retval none
*/
void mdma_link_node_para_struct_init(mdma_link_node_parameter_struct *node)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0005U), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
node->chxcfg_reg = 0U;
node->chxbtcfg_reg = 0U;
node->chxsaddr_reg = 0U;
node->chxdaddr_reg = 0U;
node->chxmbaddru_reg = 0U;
node->chxladdr_reg = 0U;
node->chxctl1_reg = 0U;
node->reserved = 0U;
node->chxmaddr_reg = 0U;
node->chxmdata_reg = 0U;
}
}
/*!
\brief initialize MDMA channel with MDMA parameter structure (API_ID(0x0006U))
\param[in] channelx: specify which MDMA channel is initialized
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] init_struct: the data needed to initialize MDMA single data mode
and the member values are shown as below:
request: MDMA_REQUEST_DMA0_CH0_FTFIF, MDMA_REQUEST_DMA0_CH1_FTFIF, MDMA_REQUEST_DMA0_CH2_FTFIF, MDMA_REQUEST_DMA0_CH3_FTFIF, MDMA_REQUEST_DMA0_CH4_FTFIF,
MDMA_REQUEST_DMA0_CH5_FTFIF, MDMA_REQUEST_DMA0_CH6_FTFIF, MDMA_REQUEST_DMA0_CH7_FTFIF, MDMA_REQUEST_DMA1_CH0_FTFIF, MDMA_REQUEST_DMA1_CH1_FTFIF,
MDMA_REQUEST_DMA1_CH2_FTFIF, MDMA_REQUEST_DMA1_CH3_FTFIF, MDMA_REQUEST_DMA1_CH4_FTFIF, MDMA_REQUEST_DMA1_CH5_FTFIF, MDMA_REQUEST_DMA1_CH6_FTFIF,
MDMA_REQUEST_DMA1_CH7_FTFIF, MDMA_REQUEST_OSPI0_FT, MDMA_REQUEST_OSPI0_TC, MDMA_REQUEST_OSPI1_FT, MDMA_REQUEST_OSPI1_TC, MDMA_REQUEST_SW
trans_trig_mode: MDMA_BUFFER_TRANSFER, MDMA_BLOCK_TRANSFER, MDMA_MULTI_BLOCK_TRANSFER, MDMA_COMPLETE_TRANSFER
priority: MDMA_PRIORITY_LOW, MDMA_PRIORITY_MEDIUM, MDMA_PRIORITY_HIGH, MDMA_PRIORITY_ULTRA_HIGH
endianness: MDMA_LITTLE_ENDIANNESS, MDMA_BYTE_ENDIANNESS_EXCHANGE, MDMA_HALFWORD_ENDIANNESS_EXCHANGE, MDMA_WORD_ENDIANNESS_EXCHANGE
source_inc: MDMA_SOURCE_INCREASE_DISABLE, MDMA_SOURCE_INCREASE_8BIT, MDMA_SOURCE_INCREASE_16BIT, MDMA_SOURCE_INCREASE_32BIT, MDMA_SOURCE_INCREASE_64BIT,
MDMA_SOURCE_DECREASE_8BIT, MDMA_SOURCE_DECREASE_16BIT, MDMA_SOURCE_DECREASE_32BIT, MDMA_SOURCE_DECREASE_64BIT
dest_inc: MDMA_DESTINATION_INCREASE_DISABLE, MDMA_DESTINATION_INCREASE_8BIT, MDMA_DESTINATION_INCREASE_16BIT, MDMA_DESTINATION_INCREASE_32BIT, MDMA_DESTINATION_INCREASE_64BIT,
MDMA_DESTINATION_DECREASE_8BIT, MDMA_DESTINATION_DECREASE_16BIT, MDMA_DESTINATION_DECREASE_32BIT, MDMA_DESTINATION_DECREASE_64BIT
source_data_size: MDMA_SOURCE_DATASIZE_8BIT, MDMA_SOURCE_DATASIZE_16BIT, MDMA_SOURCE_DATASIZE_32BIT, MDMA_SOURCE_DATASIZE_64BIT
dest_data_size: MDMA_DESTINATION_DATASIZE_8BIT, MDMA_DESTINATION_DATASIZE_16BIT, MDMA_DESTINATION_DATASIZE_32BIT, MDMA_DESTINATION_DATASIZE_64BIT
data_alignment: MDMA_DATAALIGN_PKEN, MDMA_DATAALIGN_RIGHT, MDMA_DATAALIGN_RIGHT_SIGNED, MDMA_DATAALIGN_LEFT
buff_trans_len: the number of bytes to be transferred is (buff_trans_len+1), buff_trans_len ranges from 0 to 127
source_burst: MDMA_SOURCE_BURST_SINGLE, MDMA_SOURCE_BURST_2BEATS, MDMA_SOURCE_BURST_4BEATS, MDMA_SOURCE_BURST_8BEATS, MDMA_SOURCE_BURST_16BEATS,
MDMA_SOURCE_BURST_32BEATS, MDMA_SOURCE_BURST_64BEATS, MDMA_SOURCE_BURST_128BEATS
dest_burst: MDMA_DESTINATION_BURST_SINGLE, MDMA_DESTINATION_BURST_2BEATS, MDMA_DESTINATION_BURST_4BEATS, MDMA_DESTINATION_BURST_8BEATS, MDMA_DESTINATION_BURST_16BEATS,
MDMA_DESTINATION_BURST_32BEATS, MDMA_DESTINATION_BURST_64BEATS, MDMA_DESTINATION_BURST_128BEATS
mask_addr: mask address, ranges from 0x00000000 to 0xFFFFFFFF
mask_data: mask data, ranges from 0x00000000 to 0xFFFFFFFF
source_addr: source address, ranges from 0x00000000 to 0xFFFFFFFF
destination_addr: destination address, ranges from 0x00000000 to 0xFFFFFFFF
tbytes_num_in_block: transfer byte number of a block transfer, ranges from 0x00000000 to 0x0001FFFF
source_bus: MDMA_SOURCE_AXI, MDMA_SOURCE_AHB_TCM
dest_bus: MDMA_DESTINATION_AXI, MDMA_DESTINATION_AHB_TCM
bufferable_write_mode: MDMA_BUFFERABLE_WRITE_ENABLE, MDMA_BUFFERABLE_WRITE_DISABLE
\param[out] none
\retval none
*/
void mdma_init(mdma_channel_enum channelx, mdma_parameter_struct *init_struct)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_POINTER);
} else if(NOT_MDMA_REQUEST(init_struct->request)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_TRANS_TRIG(init_struct->trans_trig_mode)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_PRIORITY(init_struct->priority)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_ENDIANNESS(init_struct->endianness)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_INC(init_struct->source_inc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_INC(init_struct->dest_inc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_DATA_SIZE(init_struct->source_data_size)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_DATA_SIZE(init_struct->dest_data_size)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DATA_ALIGN(init_struct->data_alignment)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_BUFF_TRANS_LEN(init_struct->buff_trans_len)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_MDMA_SOURCE_BURST(init_struct->source_burst)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_BURST(init_struct->dest_burst)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_TBYTES_NUM(init_struct->tbytes_num_in_block)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_BUS(init_struct->source_bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_BUS(init_struct->dest_bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_BUFFERABLE_WRITE(init_struct->bufferable_write_mode)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0006U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
mdma_channel_disable(channelx);
/* configure endianness and priority */
MDMA_CHXCTL0(channelx) &= ~(MDMA_CHXCTL0_BES | MDMA_CHXCTL0_HWES | MDMA_CHXCTL0_WES | MDMA_CHXCTL0_PRIO);
MDMA_CHXCTL0(channelx) |= (init_struct->endianness | init_struct->priority);
/* configure MDMA transfer width, memory transfer width, channel priority */
MDMA_CHXCFG(channelx) = (init_struct->data_alignment | init_struct->dest_burst | init_struct->dest_data_size | init_struct->dest_inc | \
init_struct->source_burst | init_struct->source_data_size | init_struct->source_inc | init_struct->trans_trig_mode | \
((init_struct->buff_trans_len << CHXCFG_BTLEN_OFFSET) & MDMA_CHXCFG_BTLEN) | init_struct->bufferable_write_mode);
/* configure mask address, mask data */
MDMA_CHXMADDR(channelx) = init_struct->mask_addr;
MDMA_CHXMDATA(channelx) = init_struct->mask_data;
/* configure source address */
MDMA_CHXSADDR(channelx) = init_struct->source_addr;
/* configure destination address */
MDMA_CHXDADDR(channelx) = init_struct->dest_addr;
/* configure block transfer byte number */
if(MDMA_BUFFER_TRANSFER == init_struct->trans_trig_mode) {
MDMA_CHXBTCFG(channelx) = (init_struct->tbytes_num_in_block & MDMA_CHXBTCFG_TBNUM);
} else if(MDMA_BLOCK_TRANSFER == init_struct->trans_trig_mode) {
MDMA_CHXBTCFG(channelx) = (init_struct->tbytes_num_in_block & MDMA_CHXBTCFG_TBNUM);
} else if(MDMA_MULTI_BLOCK_TRANSFER == init_struct->trans_trig_mode) {
MDMA_CHXBTCFG(channelx) &= ~MDMA_CHXBTCFG_TBNUM;
MDMA_CHXBTCFG(channelx) |= (init_struct->tbytes_num_in_block & MDMA_CHXBTCFG_TBNUM);
} else if(MDMA_COMPLETE_TRANSFER == init_struct->trans_trig_mode) {
MDMA_CHXBTCFG(channelx) &= ~MDMA_CHXBTCFG_TBNUM;
MDMA_CHXBTCFG(channelx) |= (init_struct->tbytes_num_in_block & MDMA_CHXBTCFG_TBNUM);
} else {
/* illegal parameters */
}
/* configure request source */
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_SWREQMOD;
if(MDMA_REQUEST_SW == init_struct->request) {
MDMA_CHXCFG(channelx) |= MDMA_CHXCFG_SWREQMOD;
} else {
MDMA_CHXCTL1(channelx) &= ~MDMA_CHXCTL1_TRIGSEL;
MDMA_CHXCTL1(channelx) |= init_struct->request;
}
/* configure bus type for source and destination */
MDMA_CHXCTL1(channelx) &= ~(MDMA_CHXCTL1_SBSEL | MDMA_CHXCTL1_DBSEL);
MDMA_CHXCTL1(channelx) |= (init_struct->source_bus | init_struct->dest_bus);
}
}
/*!
\brief configure MDMA buffer/block transfer mode (API_ID(0x0007U))
\param[in] channelx: specify which MDMA channel is initialized
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] saddr: source address, ranges from 0x00000000 to 0xFFFFFFFF
\param[in] daddr: destination address, ranges from 0x00000000 to 0xFFFFFFFF
\param[in] tbnum: number of bytes to transfer, ranges from 0x00000000 to 0x00010000
\param[out] none
\retval none
*/
void mdma_buffer_block_mode_config(mdma_channel_enum channelx, uint32_t saddr, uint32_t daddr, uint32_t tbnum)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_TBNUM_OF_BLOCK_TRANS_MODE(tbnum)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0007U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXSADDR(channelx) = saddr;
MDMA_CHXDADDR(channelx) = daddr;
MDMA_CHXBTCFG(channelx) &= ~MDMA_CHXBTCFG_TBNUM;
MDMA_CHXBTCFG(channelx) |= (tbnum & MDMA_CHXBTCFG_TBNUM);
}
}
/*!
\brief configure MDMA multi block transfer mode (API_ID(0x0008U))
\param[in] channelx: specify which MDMA channel is initialized
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] tbnum: number of bytes to transfer in block, range from 0x00000000 to 0x00000FFF
\param[in] block_init_struct: the data needed to initialize MDMA multi block mode,
the member values are shown as below:
block_num: multi block number, ranges from 0x00000000 to 0x00000FFF
saddr_update_val: source address update value, ranges from 0x0000 to 0xFFFF
dstaddr_update_val: destination address update value, ranges from 0x0000 to 0xFFFF
saddr_update_dir: source address update direction, UPDATE_DIR_INCREASE, UPDATE_DIR_DECREASE
dstaddr_update_dir: destination address update direction, UPDATE_DIR_INCREASE, UPDATE_DIR_DECREASE
\param[out] none
\retval none
*/
void mdma_multi_block_mode_config(mdma_channel_enum channelx, uint32_t tbnum, mdma_multi_block_parameter_struct *block_init_struct)
{
uint32_t blockoffset;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_TBNUM_OF_MULTI_BLOCK_TRANS_MODE(tbnum)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0008U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_VALID_POINTER(block_init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0008U), ERR_PARAM_POINTER);
} else if(NOT_MDMA_MULTI_BLOCK_NUM(block_init_struct->block_num)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0008U), ERR_PARAM_OUT_OF_RANGE);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXBTCFG(channelx) = (((block_init_struct->block_num << CHXBTCFG_BRNUM_OFFSET) & MDMA_CHXBTCFG_BRNUM) | (tbnum & MDMA_CHXBTCFG_TBNUM));
MDMA_CHXMBADDRU(channelx) &= ~(MDMA_CHXMBADDRU_SADDRUV | MDMA_CHXMBADDRU_DADDRUV);
/* if block source address offset is negative, set the block repeat source address update mode to decrement */
if(UPDATE_DIR_DECREASE == block_init_struct->saddr_update_dir) {
MDMA_CHXBTCFG(channelx) |= MDMA_CHXBTCFG_SADDRUM;
/* write new chxmbaddru register value: source repeat block offset */
blockoffset = (uint32_t)block_init_struct->saddr_update_val;
MDMA_CHXMBADDRU(channelx) |= (blockoffset & MDMA_ADDRESS_MASK);
} else {
MDMA_CHXBTCFG(channelx) &= ~MDMA_CHXBTCFG_SADDRUM;
/* write new chxmbaddru register value: source repeat block offset */
MDMA_CHXMBADDRU(channelx) |= (((uint32_t)block_init_struct->saddr_update_val) & MDMA_ADDRESS_MASK);
}
if(UPDATE_DIR_DECREASE == block_init_struct->dstaddr_update_dir) {
MDMA_CHXBTCFG(channelx) |= MDMA_CHXBTCFG_DADDRUM;
/* write new chxmbaddru register value: destination repeat block offset */
blockoffset = (uint32_t)block_init_struct->dstaddr_update_val;
MDMA_CHXMBADDRU(channelx) |= ((uint32_t)(blockoffset & MDMA_ADDRESS_MASK) << CHXMBADDRU_DADDRUV_OFFSET);
} else {
MDMA_CHXBTCFG(channelx) &= ~MDMA_CHXBTCFG_DADDRUM;
/* write new chxmbaddru register value: destination repeat block offset */
MDMA_CHXMBADDRU(channelx) |= ((((uint32_t)block_init_struct->dstaddr_update_val) & MDMA_ADDRESS_MASK) << CHXMBADDRU_DADDRUV_OFFSET);
}
}
}
/*!
\brief create MDMA link list node (API_ID(0x0009U))
\param[in] channelx: specify which MDMA channel is initialized
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] node: link node structure to create, members of the structure are shown as below:
chxcfg_reg: channel configure register
chxbtcfg_reg: channel block transfer configure register
chxsaddr_reg: channel source address register
chxdaddr_reg: channel destination address register
chxmbaddru_reg: channel multi-block address update register
chxladdr_reg: channel link address register
chxctl1_reg: channel control register 1
chxmaddr_reg: channel mask address register
chxmdata_reg: channel mask data register
\param[in] block_init_struct: mdma muti block structure, members of the structure and the member values are shown as below:
block_num: multi-block number, ranges from 0x00000000 to 0x00000FFF
saddr_update_val: source address update value, ranges from 0x0000 to 0xFFFF
dstaddr_update_val: destination address update value, ranges from 0x0000 to 0xFFFF
saddr_update_dir: source address update direction, UPDATE_DIR_INCREASE, UPDATE_DIR_DECREASE
dstaddr_update_dir: destination address update direction, UPDATE_DIR_INCREASE, UPDATE_DIR_DECREASE
\param[in] init_struct: the data needed to initialize MDMA single data mode,
members of the structure and the member values are shown as below:
request: MDMA_REQUEST_x, x is the type of request
trans_trig_mode: MDMA_BUFFER_TRANSFER, MDMA_BLOCK_TRANSFER, MDMA_MULTI_BLOCK_TRANSFER, MDMA_COMPLETE_TRANSFER
priority: MDMA_PRIORITY_LOW, MDMA_PRIORITY_MEDIUM, MDMA_PRIORITY_HIGH, MDMA_PRIORITY_ULTRA_HIGH
endianness: MDMA_LITTLE_ENDIANNESS, MDMA_BYTE_ENDIANNESS_EXCHANGE, MDMA_HALFWORD_ENDIANNESS_EXCHANGE, MDMA_WORD_ENDIANNESS_EXCHANGE
source_inc: MDMA_SOURCE_INCREASE_DISABLE, MDMA_SOURCE_INCREASE_8BIT, MDMA_SOURCE_INCREASE_16BIT, MDMA_SOURCE_INCREASE_32BIT, MDMA_SOURCE_INCREASE_64BIT,
MDMA_SOURCE_DECREASE_8BIT, MDMA_SOURCE_DECREASE_16BIT, MDMA_SOURCE_DECREASE_32BIT, MDMA_SOURCE_DECREASE_64BIT
dest_inc: MDMA_DESTINATION_INCREASE_DISABLE, MDMA_DESTINATION_INCREASE_8BIT, MDMA_DESTINATION_INCREASE__16BIT, MDMA_DESTINATION_INCREASE_32BIT, MDMA_DESTINATION_INCREASE_64BIT,
MDMA_DESTINATION_DECREASE_8BIT, MDMA_DESTINATION_DECREASE_16BIT, MDMA_DESTINATION_DECREASE_32BIT, MDMA_DESTINATION_DECREASE_64BIT
source_data_size: MDMA_SOURCE_DATASIZE_8BIT, MDMA_SOURCE_DATASIZE_16BIT, MDMA_SOURCE_DATASIZE_32BIT, MDMA_SOURCE_DATASIZE_64BIT
dest_data_size: MDMA_DESTINATION_DATASIZE_8BIT, MDMA_DESTINATION_DATASIZE_16BIT, MDMA_DESTINATION_DATASIZE_32BIT, MDMA_DESTINATION_DATASIZE_64BIT
data_alignment: MDMA_DATAALIGN_PKEN, MDMA_DATAALIGN_RIGHT, MDMA_DATAALIGN_RIGHT_SIGNED, MDMA_DATAALIGN_LEFT
buff_trans_len: the number of bytes to be transferred is (buff_trans_len+1), buff_trans_len ranges from 0 to 127
source_burst: MDMA_SOURCE_BURST_SINGLE, MDMA_SOURCE_BURST_2BEATS, MDMA_SOURCE_BURST_4BEATS, MDMA_SOURCE_BURST_8BEATS, MDMA_SOURCE_BURST_16BEATS,
MDMA_SOURCE_BURST_32BEATS, MDMA_SOURCE_BURST_64BEATS, MDMA_SOURCE_BURST_128BEATS
dest_burst: MDMA_DESTINATION_BURST_SINGLE, MDMA_DESTINATION_BURST_2BEATS, MDMA_DESTINATION_BURST_4BEATS, MDMA_DESTINATION_BURST_8BEATS, MDMA_DESTINATION_BURST_16BEATS,
MDMA_DESTINATION_BURST_32BEATS, MDMA_DESTINATION_BURST_64BEATS, MDMA_DESTINATION_BURST_128BEATS
mask_addr: mask address, ranges from 0x00000000 to 0xFFFFFFFF
mask_data: mask data, ranges from 0x00000000 to 0xFFFFFFFF
source_addr: source address, ranges from 0x00000000 to 0xFFFFFFFF
dest_addr: destination address, ranges from 0x00000000 to 0xFFFFFFFF
tbytes_num_in_block: transfer byte number of a block transfer, ranges from 0x00000000 to 0x0001FFFF
source_bus: MDMA_SOURCE_AXI, MDMA_SOURCE_AHB_TCM
dest_bus: MDMA_DESTINATION_AXI, MDMA_DESTINATION_AHB_TCM
bufferable_write_mode: MDMA_BUFFERABLE_WRITE_ENABLE, MDMA_BUFFERABLE_WRITE_DISABLE
\retval none
*/
void mdma_node_create(mdma_link_node_parameter_struct *node, mdma_multi_block_parameter_struct *block_init_struct, mdma_parameter_struct *init_struct)
{
uint32_t cfg, blockoffset;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_POINTER);
} else if(NOT_VALID_POINTER(block_init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_POINTER);
} else if(NOT_MDMA_MULTI_BLOCK_NUM(block_init_struct->block_num)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_VALID_POINTER(init_struct)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_POINTER);
} else if(NOT_MDMA_REQUEST(init_struct->request)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_TRANS_TRIG(init_struct->trans_trig_mode)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_PRIORITY(init_struct->priority)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_ENDIANNESS(init_struct->endianness)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_INC(init_struct->source_inc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_INC(init_struct->dest_inc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_DATA_SIZE(init_struct->source_data_size)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_DATA_SIZE(init_struct->dest_data_size)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DATA_ALIGN(init_struct->data_alignment)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_BUFF_TRANS_LEN(init_struct->buff_trans_len)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_OUT_OF_RANGE);
} else if(NOT_MDMA_SOURCE_BURST(init_struct->source_burst)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_BURST(init_struct->dest_burst)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_TBYTES_NUM(init_struct->tbytes_num_in_block)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_SOURCE_BUS(init_struct->source_bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_DEST_BUS(init_struct->dest_bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else if(NOT_MDMA_BUFFERABLE_WRITE(init_struct->bufferable_write_mode)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0009U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure channel configure register */
cfg = (init_struct->data_alignment | init_struct->dest_burst | init_struct->dest_data_size | init_struct->dest_inc | \
init_struct->source_burst | init_struct->source_data_size | init_struct->source_inc | init_struct->trans_trig_mode | \
((init_struct->buff_trans_len << CHXCFG_BTLEN_OFFSET) & MDMA_CHXCFG_BTLEN) | init_struct->bufferable_write_mode);
node->chxcfg_reg = cfg;
/* configure channel request source */
if(MDMA_REQUEST_SW == init_struct->request) {
node->chxcfg_reg |= MDMA_CHXCFG_SWREQMOD;
} else {
node->chxctl1_reg &= ~MDMA_CHXCTL1_TRIGSEL;
node->chxctl1_reg |= init_struct->request;
}
/* configure bus type for source and destination */
node->chxctl1_reg &= ~(MDMA_CHXCTL1_SBSEL | MDMA_CHXCTL1_DBSEL);
node->chxctl1_reg |= (init_struct->source_bus | init_struct->dest_bus);
/* configure channel block transfer configure register */
cfg = (((block_init_struct->block_num << CHXBTCFG_BRNUM_OFFSET) & MDMA_CHXBTCFG_BRNUM)| (init_struct->tbytes_num_in_block & MDMA_CHXBTCFG_TBNUM));
node->chxbtcfg_reg = cfg;
/* configure source address, destination address, mask address and mask data */
node->chxsaddr_reg = init_struct->source_addr;
node->chxdaddr_reg = init_struct->dest_addr;
node->chxmaddr_reg = init_struct->mask_addr;
node->chxmdata_reg = init_struct->mask_data;
node->chxmbaddru_reg &= ~(MDMA_CHXMBADDRU_SADDRUV | MDMA_CHXMBADDRU_DADDRUV);
/* if block source address offset is negative, set the block repeat source address update mode to decrement */
if(UPDATE_DIR_DECREASE == block_init_struct->saddr_update_dir) {
node->chxbtcfg_reg |= MDMA_CHXBTCFG_SADDRUM;
/* write new chxmbaddru register value: source repeat block offset */
blockoffset = (uint32_t)block_init_struct->saddr_update_val;
node->chxmbaddru_reg |= (blockoffset & MDMA_ADDRESS_MASK);
} else {
node->chxbtcfg_reg &= ~MDMA_CHXBTCFG_SADDRUM;
/* write new chxmbaddru register value: source repeat block offset */
node->chxmbaddru_reg |= (((uint32_t)block_init_struct->saddr_update_val) & MDMA_ADDRESS_MASK);
}
if(UPDATE_DIR_DECREASE == block_init_struct->dstaddr_update_dir) {
node->chxbtcfg_reg |= MDMA_CHXBTCFG_DADDRUM;
/* write new chxmbaddru register value: destination repeat block offset */
blockoffset = (uint32_t)block_init_struct->dstaddr_update_val;
node->chxmbaddru_reg |= ((uint32_t)(blockoffset & MDMA_ADDRESS_MASK) << CHXMBADDRU_DADDRUV_OFFSET);
} else {
node->chxbtcfg_reg &= ~MDMA_CHXBTCFG_DADDRUM;
/* write new chxmbaddru register value: destination repeat block offset */
node->chxmbaddru_reg |= ((((uint32_t)block_init_struct->dstaddr_update_val) & MDMA_ADDRESS_MASK) << CHXMBADDRU_DADDRUV_OFFSET);
}
node->chxladdr_reg = 0U;
node->reserved = 0U;
}
}
/*!
\brief MDMA add node to link list (API_ID(0x000AU))
\param[in] pre_node: previous structure node pointer, members of the structure and the member values are shown as below:
chxcfg_reg: channel configure register
chxbtcfg_reg: channel block transfer configure register
chxsaddr_reg: channel source address register
chxdaddr_reg: channel destination address register
chxmbaddru_reg: channel multi-block address update register
chxladdr_reg: channel link address register
chxctl1_reg: channel control register 1
chxmaddr_reg: channel mask address register
chxmdata_reg: channel mask data register
\param[in] new_node: new node pointer, members of the structure and the member values are shown as below:
chxcfg_reg: channel configure register
chxbtcfg_reg: channel block transfer configure register
chxsaddr_reg: channel source address register
chxdaddr_reg: channel destination address register
chxmbaddru_reg: channel multi-block address update register
chxladdr_reg: channel link address register
chxctl1_reg: channel control register 1
chxmaddr_reg: channel mask address register
chxmdata_reg: channel mask data register
\param[out] none
\retval none
*/
void mdma_node_add(mdma_link_node_parameter_struct *pre_node, mdma_link_node_parameter_struct *new_node)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(pre_node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000AU), ERR_PARAM_POINTER);
} else if(NOT_VALID_POINTER(new_node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000AU), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
pre_node->chxladdr_reg = (uint32_t)new_node;
}
}
/*!
\brief MDMA disconnect link list node (API_ID(0x000BU))
\param[in] pre_node: previous structure node pointer, members of the structure and the member values are shown as below:
chxcfg_reg: channel configure register
chxbtcfg_reg: channel block transfer configure register
chxsaddr_reg: channel source address register
chxdaddr_reg: channel destination address register
chxmbaddru_reg: channel multi-block address update register
chxladdr_reg: channel link address register
chxctl1_reg: channel control register 1
chxmaddr_reg: channel mask address register
chxmdata_reg: channel mask data register
\param[in] unused_node: unused link list node pointer, members of the structure and the member values are shown as below:
chxcfg_reg: channel configure register
chxbtcfg_reg: channel block transfer configure register
chxsaddr_reg: channel source address register
chxdaddr_reg: channel destination address register
chxmbaddru_reg: channel multi-block address update register
chxladdr_reg: channel link address register
chxctl1_reg: channel control register 1
chxmaddr_reg: channel mask address register
chxmdata_reg: channel mask data register
\param[out] none
\retval ErrStatus: SUCCESS or ERROR
*/
ErrStatus mdma_node_delete(mdma_link_node_parameter_struct *pre_node, mdma_link_node_parameter_struct *unused_node)
{
ErrStatus reval = ERROR;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_VALID_POINTER(pre_node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000BU), ERR_PARAM_POINTER);
} else if(NOT_VALID_POINTER(unused_node)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000BU), ERR_PARAM_POINTER);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(pre_node->chxladdr_reg != (uint32_t)unused_node) {
/* link address unmatched */
reval = ERROR;
} else {
/* link address matched, disconnect the unused node from link list */
pre_node->chxladdr_reg = 0U;
reval = SUCCESS;
}
}
return reval;
}
/*!
\brief configure MDMA destination base address (API_ID(0x000CU))
\param[in] channelx: specify which MDMA channel to set peripheral base address
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] address: destination base address, ranges from 0x00000000 to 0xFFFFFFFF
\param[out] none
\retval none
*/
void mdma_destination_address_config(mdma_channel_enum channelx, uint32_t address)
{
MDMA_CHXDADDR(channelx) = address;
}
/*!
\brief configure MDMA source base address (API_ID(0x000DU))
\param[in] channelx: specify which MDMA channel to set Memory base address
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] address: source base address, ranges from 0x00000000 to 0xFFFFFFFF
\param[out] none
\retval none
*/
void mdma_source_address_config(mdma_channel_enum channelx, uint32_t address)
{
MDMA_CHXSADDR(channelx) = address;
}
/*!
\brief configure MDMA destination bus (API_ID(0x000EU))
\param[in] channelx: specify which MDMA channel to set bus
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] bus: destination bus
\arg MDMA_DESTINATION_AXI: destination bus is the system bus or AXI bus
\arg MDMA_DESTINATION_AHB_TCM: destination bus is AHB bus or TCM
\param[out] none
\retval none
*/
void mdma_destination_bus_config(mdma_channel_enum channelx, uint32_t bus)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_DEST_BUS(bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000EU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXCTL1(channelx) &= ~MDMA_CHXCTL1_DBSEL;
MDMA_CHXCTL1(channelx) |= bus;
}
}
/*!
\brief configure MDMA source bus (API_ID(0x000FU))
\param[in] channelx: specify which MDMA channel to set bus
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] bus: source bus
\arg MDMA_SOURCE_AXI: source bus is the system bus or AXI bus
\arg MDMA_SOURCE_AHB_TCM: source bus is AHB bus or TCM
\param[out] none
\retval none
*/
void mdma_source_bus_config(mdma_channel_enum channelx, uint32_t bus)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_SOURCE_BUS(bus)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x000FU), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXCTL1(channelx) &= ~MDMA_CHXCTL1_SBSEL;
MDMA_CHXCTL1(channelx) |= bus;
}
}
/*!
\brief configure priority level of MDMA channel (API_ID(0x0010U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] priority: priority level of this channel
only one parameter can be selected which is shown as below:
\arg MDMA_PRIORITY_LOW: low priority
\arg MDMA_PRIORITY_MEDIUM: medium priority
\arg MDMA_PRIORITY_HIGH: high priority
\arg MDMA_PRIORITY_ULTRA_HIGH: ultra high priority
\param[out] none
\retval none
*/
void mdma_priority_config(mdma_channel_enum channelx, uint32_t priority)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_PRIORITY(priority)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0010U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure priority level */
MDMA_CHXCTL0(channelx) &= ~MDMA_CHXCTL0_PRIO;
MDMA_CHXCTL0(channelx) |= priority;
}
}
/*!
\brief configure endianness of MDMA channel (API_ID(0x0011U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] endianness: MDMA endianness
only one parameter can be selected which is shown as below:
\arg MDMA_LITTLE_ENDIANNESS: little endianness preserve
\arg MDMA_BYTE_ENDIANNESS_EXCHANGE: exchange the order of the bytes in a half-word
\arg MDMA_HALFWORD_ENDIANNESS_EXCHANGE: exchange the order of the half-words in a word
\arg MDMA_WORD_ENDIANNESS_EXCHANGE: exchange the order of the words in a double word
\param[out] none
\retval none
*/
void mdma_endianness_config(mdma_channel_enum channelx, uint32_t endianness)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_ENDIANNESS(endianness)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0011U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure MDMA endianness */
MDMA_CHXCTL0(channelx) &= ~(MDMA_CHXCTL0_BES | MDMA_CHXCTL0_HWES | MDMA_CHXCTL0_WES);
MDMA_CHXCTL0(channelx) |= endianness;
}
}
/*!
\brief configure data alignment of MDMA channel (API_ID(0x0012U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] alignment: MDMA data alignment
only one parameter can be selected which is shown as below:
\arg MDMA_DATAALIGN_PKEN: pack/unpack the source data to match the destination data size
\arg MDMA_DATAALIGN_RIGHT: right aligned, padded with 0s (default)
\arg MDMA_DATAALIGN_RIGHT_SIGNED: right aligned with sign extended, note: this mode is allowed only if the source data size is smaller than destination data size
\arg MDMA_DATAALIGN_LEFT: left aligned, padded with 0s in low bytes position when source data size smaller than destination data size, and only high byte of source is written when source data size larger than destination data size
\param[out] none
\retval none
*/
void mdma_alignment_config(mdma_channel_enum channelx, uint32_t alignment)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_DATA_ALIGN(alignment)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0012U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure MDMA endianness */
MDMA_CHXCFG(channelx) &= ~(MDMA_CHXCFG_PKEN | MDMA_CHXCFG_PAMOD);
MDMA_CHXCFG(channelx) |= alignment;
}
}
/*!
\brief configure transfer burst beats of source (API_ID(0x0013U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] sbeat: source transfer burst beats
\arg MDMA_SOURCE_BURST_SINGLE: single burst
\arg MDMA_SOURCE_BURST_2BEATS: 2-beat incrementing burst
\arg MDMA_SOURCE_BURST_4BEATS: 4-beat incrementing burst
\arg MDMA_SOURCE_BURST_8BEATS: 8-beat incrementing burst
\arg MDMA_SOURCE_BURST_16BEATS: 16-beat incrementing burst
\arg MDMA_SOURCE_BURST_32BEATS: 32-beat incrementing burst
\arg MDMA_SOURCE_BURST_64BEATS: 64-beat incrementing burst
\arg MDMA_SOURCE_BURST_128BEATS: 128-beat incrementing burst
\param[out] none
\retval none
*/
void mdma_source_burst_beats_config(mdma_channel_enum channelx, uint32_t sbeat)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_SOURCE_BURST(sbeat)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0013U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure transfer burst beats of source */
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_SBURST;
MDMA_CHXCFG(channelx) |= sbeat;
}
}
/*!
\brief configure transfer burst beats of destination (API_ID(0x0014U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] dbeat: destination transfer burst beats
only one parameter can be selected which is shown as below:
\arg MDMA_DESTINATION_BURST_SINGLE: single burst
\arg MDMA_DESTINATION_BURST_2BEATS: 2-beat incrementing burst
\arg MDMA_DESTINATION_BURST_4BEATS: 4-beat incrementing burst
\arg MDMA_DESTINATION_BURST_8BEATS: 8-beat incrementing burst
\arg MDMA_DESTINATION_BURST_16BEATS: 16-beat incrementing burst
\arg MDMA_DESTINATION_BURST_32BEATS: 32-beat incrementing burst
\arg MDMA_DESTINATION_BURST_64BEATS: 64-beat incrementing burst
\arg MDMA_DESTINATION_BURST_128BEATS: 128-beat incrementing burst
\param[out] none
\retval none
*/
void mdma_destination_burst_beats_config(mdma_channel_enum channelx, uint32_t dbeat)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_DEST_BURST(dbeat)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0014U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure transfer burst beats of destination */
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_DBURST;
MDMA_CHXCFG(channelx) |= dbeat;
}
}
/*!
\brief configure data size of source (API_ID(0x0015U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] swidth: source data size
only one parameter can be selected which is shown as below:
\arg MDMA_SOURCE_DATASIZE_8BIT: data size of source is 8-bit
\arg MDMA_SOURCE_DATASIZE_16BIT: data size of source is 16-bit
\arg MDMA_SOURCE_DATASIZE_32BIT: data size of source is 32-bit
\arg MDMA_SOURCE_DATASIZE_64BIT: data size of source is 64-bit
\param[out] none
\retval none
*/
void mdma_source_width_config(mdma_channel_enum channelx, uint32_t swidth)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_SOURCE_DATA_SIZE(swidth)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0015U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure data size of source */
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_SWIDTH;
MDMA_CHXCFG(channelx) |= swidth;
}
}
/*!
\brief configure data size of destination (API_ID(0x0016U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] dwidth: destination data size
only one parameter can be selected which is shown as below:
\arg MDMA_DESTINATION_DATASIZE_8BIT: data size of destination is 8-bit
\arg MDMA_DESTINATION_DATASIZE_16BIT: data size of destination is 16-bit
\arg MDMA_DESTINATION_DATASIZE_32BIT: data size of destination is 32-bit
\arg MDMA_DESTINATION_DATASIZE_64BIT: data size of destination is 64-bit
\param[out] none
\retval none
*/
void mdma_destination_width_config(mdma_channel_enum channelx, uint32_t dwidth)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_DEST_DATA_SIZE(dwidth)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0016U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure data size of source */
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_DWIDTH;
MDMA_CHXCFG(channelx) |= dwidth;
}
}
/*!
\brief configure source address increment mode (API_ID(0x0017U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] sinc: source address increment mode
only one parameter can be selected which is shown as below:
\arg MDMA_SOURCE_INCREASE_DISABLE: no increment
\arg MDMA_SOURCE_INCREASE_8BIT: source address is increased by 8-bit
\arg MDMA_SOURCE_INCREASE_16BIT: source address is increased by 16-bit
\arg MDMA_SOURCE_INCREASE_32BIT: source address is increased by 32-bit
\arg MDMA_SOURCE_INCREASE_64BIT: source address is increased by 64-bit
\arg MDMA_SOURCE_DECREASE_8BIT: source address is decreased by 8-bit
\arg MDMA_SOURCE_DECREASE_16BIT: source address is decreased by 16-bit
\arg MDMA_SOURCE_DECREASE_32BIT: source address is decreased by 32-bit
\arg MDMA_SOURCE_DECREASE_64BIT: source address is decreased by 64-bit
\param[out] none
\retval none
*/
void mdma_source_increment_config(mdma_channel_enum channelx, uint32_t sinc)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_SOURCE_INC(sinc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0017U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure address increment mode of source */
MDMA_CHXCFG(channelx) &= ~(MDMA_CHXCFG_SIMOD | MDMA_CHXCFG_SIOS);
MDMA_CHXCFG(channelx) |= sinc;
}
}
/*!
\brief configure destination address increment mode (API_ID(0x0018U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] dinc: destination address increment mode
only one parameter can be selected which is shown as below:
\arg MDMA_DESTINATION_INCREASE_DISABLE: no increment
\arg MDMA_DESTINATION_INCREASE_8BIT: destination address is increased by 8-bit
\arg MDMA_DESTINATION_INCREASE_16BIT: destination address is increased by 16-bit
\arg MDMA_DESTINATION_INCREASE_32BIT: destination address is increased by 32-bit
\arg MDMA_DESTINATION_INCREASE_64BIT: destination address is increased by 64-bit
\arg MDMA_DESTINATION_DECREASE_8BIT: destination address is decreased by 8-bit
\arg MDMA_DESTINATION_DECREASE_16BIT: destination address is decreased by 16-bit
\arg MDMA_DESTINATION_DECREASE_32BIT: destination address is decreased by 32-bit
\arg MDMA_DESTINATION_DECREASE_64BIT: destination address is decreased by 64-bit
\param[out] none
\retval none
*/
void mdma_destination_increment_config(mdma_channel_enum channelx, uint32_t dinc)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_DEST_INC(dinc)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0018U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
/* configure address increment mode of destination */
MDMA_CHXCFG(channelx) &= ~(MDMA_CHXCFG_DIMOD | MDMA_CHXCFG_DIOS);
MDMA_CHXCFG(channelx) |= dinc;
}
}
/*!
\brief enable MDMA channel bufferable write mode (API_ID(0x0019U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_bufferable_write_enable(mdma_channel_enum channelx)
{
MDMA_CHXCFG(channelx) |= MDMA_CHXCFG_BWMOD;
}
/*!
\brief disable MDMA channel bufferable write mode (API_ID(0x001AU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_bufferable_write_disable(mdma_channel_enum channelx)
{
MDMA_CHXCFG(channelx) &= ~MDMA_CHXCFG_BWMOD;
}
/*!
\brief enable MDMA channel software request (API_ID(0x001BU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_software_request_enable(mdma_channel_enum channelx)
{
MDMA_CHXCTL0(channelx) |= MDMA_CHXCTL0_SWREQ;
}
/*!
\brief enable MDMA channel (API_ID(0x001CU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_enable(mdma_channel_enum channelx)
{
MDMA_CHXCTL0(channelx) |= MDMA_CHXCTL0_CHEN;
}
/*!
\brief disable MDMA channel (API_ID(0x001DU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval none
*/
void mdma_channel_disable(mdma_channel_enum channelx)
{
MDMA_CHXCTL0(channelx) &= ~MDMA_CHXCTL0_CHEN;
}
/*!
\brief get MDMA transfer error direction (API_ID(0x001EU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval transfer error direction: MDMA_READ_ERROR or MDMA_WRITE_ERROR
*/
uint32_t mdma_transfer_error_direction_get(mdma_channel_enum channelx)
{
return (MDMA_CHXSTAT1(channelx) & MDMA_CHXSTAT1_TERRD);
}
/*!
\brief get MDMA transfer error address (API_ID(0x001FU))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[out] none
\retval the low 7 bits of the transfer error address
*/
uint32_t mdma_transfer_error_address_get(mdma_channel_enum channelx)
{
return (uint32_t)(MDMA_CHXSTAT1(channelx) & MDMA_CHXSTAT1_ERRADDR);
}
/*!
\brief get MDMA flag (API_ID(0x0020U))
\param[in] channelx: specify which MDMA channel to clear flag
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] flag: specify get which flag
only one parameter can be selected which is shown as below:
\arg MDMA_FLAG_ERR: transfer error flag
\arg MDMA_FLAG_CHTCF: channel transfer complete flag
\arg MDMA_FLAG_MBTCF: multi-block transfer complete flag
\arg MDMA_FLAG_BTCF: block transfer complete flag
\arg MDMA_FLAG_TCF: buffer transfer complete flag
\arg MDMA_FLAG_REQAF: request active flag
\arg MDMA_FLAG_LDTERR: link data transfer error flag in the last transfer of the channel
\arg MDMA_FLAG_MDTERR: mask data error flag
\arg MDMA_FLAG_ASERR: address and size error flag
\arg MDMA_FLAG_BZERR: block size error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus mdma_flag_get(mdma_channel_enum channelx, uint32_t flag)
{
FlagStatus reval = RESET;
uint32_t flag_pos = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_FLAG(flag)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0020U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(STAT1_FLAG & flag) {
/* get the flag in CHXSTAT1 */
flag_pos = (flag & STAT1_FLAG_MASK);
if(MDMA_CHXSTAT1(channelx) & flag_pos) {
reval = SET;
} else {
reval = RESET;
}
} else {
/* get the flag in CHXSTAT0 */
if(MDMA_CHXSTAT0(channelx) & flag) {
reval = SET;
} else {
reval = RESET;
}
}
}
return reval;
}
/*!
\brief clear MDMA flag (API_ID(0x0021U))
\param[in] channelx: specify which MDMA channel to clear flag
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] flag: specify clear which flag
only one parameter can be selected which is shown as below:
\arg MDMA_FLAG_ERR: transfer error flag
\arg MDMA_FLAG_CHTCF: channel transfer complete flag
\arg MDMA_FLAG_MBTCF: multi-block transfer complete flag
\arg MDMA_FLAG_BTCF: block transfer complete flag
\arg MDMA_FLAG_TCF: buffer transfer complete flag
\arg MDMA_FLAG_LDTERR: link data transfer error flag in the last transfer of the channel
\arg MDMA_FLAG_MDTERR: mask data error flag
\arg MDMA_FLAG_ASERR: address and size error flag
\arg MDMA_FLAG_BZERR: block size error flag
\param[out] none
\retval none
*/
void mdma_flag_clear(mdma_channel_enum channelx, uint32_t flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_CLEAR_FLAG(flag)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0021U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
if(STAT1_FLAG & flag) {
MDMA_CHXSTATC(channelx) |= MDMA_CHXSTATC_ERRC;
} else {
MDMA_CHXSTATC(channelx) |= flag;
}
}
}
/*!
\brief enable MDMA interrupt (API_ID(0x0022U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] interrupt: specify which interrupt to enbale
one or more parameters can be selected which are shown as below:
\arg MDMA_INT_ERR: transfer error interrupt
\arg MDMA_INT_CHTC: channel transfer complete interrupt
\arg MDMA_INT_MBTC: multi-block transfer complete interrupt
\arg MDMA_INT_BTC: block transfer complete interrupt
\arg MDMA_INT_TC: buffer transfer complete interrupt
\param[out] none
\retval none
*/
void mdma_interrupt_enable(mdma_channel_enum channelx, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_INT(interrupt)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0022U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXCTL0(channelx) |= interrupt;
}
}
/*!
\brief disable MDMA interrupt (API_ID(0x0023U))
\param[in] channelx: specify which MDMA channel
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] interrupt: specify which interrupt to disbale
one or more parameters can be selected which are shown as below:
\arg MDMA_INT_ERR: transfer error interrupt
\arg MDMA_INT_CHTC: channel transfer complete interrupt
\arg MDMA_INT_MBTC: multi-block transfer complete interrupt
\arg MDMA_INT_BTC: block transfer complete interrupt
\arg MDMA_INT_TC: buffer transfer complete interrupt
\param[out] none
\retval none
*/
void mdma_interrupt_disable(mdma_channel_enum channelx, uint32_t interrupt)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_INT(interrupt)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0023U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXCTL0(channelx) &= ~interrupt;
}
}
/*!
\brief get MDMA interrupt flag (API_ID(0x0024U))
\param[in] channelx: specify which MDMA channel to get flag
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] int_flag: specify get which flag
only one parameter can be selected which is shown as below:
\arg MDMA_INT_FLAG_ERR: transfer error interrupt flag
\arg MDMA_INT_FLAG_CHTCF: channel transfer complete interrupt flag
\arg MDMA_INT_FLAG_MBTCF: multi-block transfer complete interrupt flag
\arg MDMA_INT_FLAG_BTCF: block transfer complete interrupt flag
\arg MDMA_INT_FLAG_TCF: buffer transfer complete interrupt flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus mdma_interrupt_flag_get(mdma_channel_enum channelx, uint32_t int_flag)
{
FlagStatus reval = RESET;
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_INT_FLAG(int_flag)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0024U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
switch(int_flag) {
case MDMA_INT_FLAG_ERR:
/* get error interrupt enable bit and flag bit */
interrupt_enable = (MDMA_CHXCTL0(channelx) & MDMA_CHXCTL0_ERRIE);
interrupt_flag = (MDMA_CHXSTAT0(channelx) & int_flag);
break;
case MDMA_INT_FLAG_CHTCF:
/* get channel transfer complete interrupt enable bit and flag bit */
interrupt_enable = (MDMA_CHXCTL0(channelx) & MDMA_CHXCTL0_CHTCIE);
interrupt_flag = (MDMA_CHXSTAT0(channelx) & int_flag);
break;
case MDMA_INT_FLAG_MBTCF:
/* get multi-block transfer complete interrupt enable bit and flag bit */
interrupt_enable = (MDMA_CHXCTL0(channelx) & MDMA_CHXCTL0_MBTCIE);
interrupt_flag = (MDMA_CHXSTAT0(channelx) & int_flag);
break;
case MDMA_INT_FLAG_BTCF:
/* get block transfer complete interrupt enable bit and flag bit */
interrupt_enable = (MDMA_CHXCTL0(channelx) & MDMA_CHXCTL0_BTCIE);
interrupt_flag = (MDMA_CHXSTAT0(channelx) & int_flag);
break;
case MDMA_INT_FLAG_TCF:
/* get buffer transfer complete interrupt enable bit and flag bit */
interrupt_enable = (MDMA_CHXCTL0(channelx) & MDMA_CHXCTL0_TCIE);
interrupt_flag = (MDMA_CHXSTAT0(channelx) & int_flag);
break;
default:
break;
}
if(interrupt_flag && interrupt_enable) {
reval = SET;
} else {
reval = RESET;
}
}
return reval;
}
/*!
\brief clear MDMA interrupt flag (API_ID(0x0025U))
\param[in] channelx: specify which MDMA channel to clear flag
only one parameter can be selected which is shown as below:
\arg MDMA_CHx(x=0..15)
\param[in] int_flag: specify clear which flag
only one parameter can be selected which is shown as below:
\arg MDMA_INT_FLAG_ERR: transfer error interrupt flag
\arg MDMA_INT_FLAG_CHTCF: channel transfer complete interrupt flag
\arg MDMA_INT_FLAG_MBTCF: multi-block transfer complete interrupt flag
\arg MDMA_INT_FLAG_BTCF: block transfer complete interrupt flag
\arg MDMA_INT_FLAG_TCF: buffer transfer complete interrupt flag
\param[out] none
\retval none
*/
void mdma_interrupt_flag_clear(mdma_channel_enum channelx, uint32_t int_flag)
{
#ifdef FW_DEBUG_ERR_REPORT
/* check parameter */
if(NOT_MDMA_INT_FLAG(int_flag)) {
fw_debug_report_err(MDMA_MODULE_ID, API_ID(0x0025U), ERR_PARAM_INVALID);
} else
#endif /* FW_DEBUG_ERR_REPORT */
{
MDMA_CHXSTATC(channelx) |= int_flag;
}
}