sdk-hwV1.3/lichee/xr806/appos/include/driver/chip/hal_dma.h

366 lines
14 KiB
C
Executable File

/**
* @file hal_dma.h
* @author XRADIO IOT WLAN Team
*/
/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* 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 XRADIO TECHNOLOGY CO., LTD. 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
* OWNER 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.
*/
#ifndef _DRIVER_CHIP_HAL_DMA_H_
#define _DRIVER_CHIP_HAL_DMA_H_
#include "driver/chip/hal_def.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Options of supporting DMA half transfer complete IRQ */
#ifndef CONFIG_BOOTLOADER
#define HAL_DMA_OPT_TRANSFER_HALF_IRQ 1
#else
#define HAL_DMA_OPT_TRANSFER_HALF_IRQ 0
#endif
/**
* @brief DMA channel definition
*/
typedef enum {
DMA_CHANNEL_0 = 0U,
DMA_CHANNEL_1 = 1U,
DMA_CHANNEL_2 = 2U,
DMA_CHANNEL_3 = 3U,
DMA_CHANNEL_4 = 4U,
DMA_CHANNEL_5 = 5U,
DMA_CHANNEL_6 = 6U,
DMA_CHANNEL_7 = 7U,
DMA_CHANNEL_NUM = 8U,
DMA_CHANNEL_INVALID = 0xFFU
} DMA_Channel;
/**
* @brief DMA channel register block structure
*/
typedef struct {
__IO uint32_t CTRL; /* offset: 0x00, DMA channel configuration register */
__IO uint32_t SRC_ADDR; /* offset: 0x04, DMA channel source address register */
__IO uint32_t DST_ADDR; /* offset: 0x08, DMA channel destination address register */
/* NOTE: BYTE_CNT read is 0 before DMA start when set DMA_BYTE_CNT_MODE is 1. */
__IO uint32_t BYTE_CNT; /* offset: 0x0C, DMA channel byte counter register */
uint32_t RESERVED0[4];
} DMA_CHANNEL_T;
/**
* @brief DMA register block structure
*/
typedef struct {
__IO uint32_t IRQ_EN; /* offset: 0x00, DMA IRQ enable register */
__IO uint32_t IRQ_STATUS; /* offset: 0x04, DMA IRQ status register */
__IO uint32_t CONFIG; /* offset: 0x08, DMA Auto_Clock_Gating, Priority config register */
uint32_t RESERVED0[61];
DMA_CHANNEL_T CHANNEL[DMA_CHANNEL_NUM]; /* offset: 0x100, DMA channels register blocks */
} DMA_T;
#define DMA ((DMA_T *)DMA_BASE) /* address: 0x40001000 */
/*
* Bit field definition of
* - DMA->IRQ_EN
* - DMA->IRQ_STATUS
*/
#define DMA_IRQ_TYPE_VMASK 0x3U
typedef enum {
DMA_IRQ_TYPE_NONE = 0,
#if HAL_DMA_OPT_TRANSFER_HALF_IRQ
DMA_IRQ_TYPE_HALF = HAL_BIT(0),
#endif
DMA_IRQ_TYPE_END = HAL_BIT(1),
#if HAL_DMA_OPT_TRANSFER_HALF_IRQ
DMA_IRQ_TYPE_BOTH = HAL_BIT(0) | HAL_BIT(1),
#endif
} DMA_IRQType;
/*
* Bit field definition of DMA->CONFIG
*/
#define DMA_AUTO_CLK_GAT_BIT HAL_BIT(16) /* R/W */
/*
* Bit field definition of DMA->CHANNEL[x].CTRL
*/
#define DMA_START_BIT HAL_BIT(31) /* R/W */
#define DMA_BUSY_BIT HAL_BIT(30) /* R */
#define DMA_WORK_MODE_SHIFT 29 /* R/W */
#define DMA_WORK_MODE_VMASK 0x1U
typedef enum {
DMA_WORK_MODE_SINGLE = 0U, /* one-shot DMA transfer */
DMA_WORK_MODE_CIRCULAR = 1U /* repeat DMA transfer */
} DMA_WorkMode;
#define DMA_WAIT_CYCLE_SHIFT 26 /* R/W */
#define DMA_WAIT_CYCLE_VMASK 0x7U
typedef enum {
DMA_WAIT_CYCLE_1 = 0U,
DMA_WAIT_CYCLE_2 = 1U,
DMA_WAIT_CYCLE_4 = 2U,
DMA_WAIT_CYCLE_8 = 3U,
DMA_WAIT_CYCLE_16 = 4U,
DMA_WAIT_CYCLE_32 = 5U,
DMA_WAIT_CYCLE_64 = 6U,
DMA_WAIT_CYCLE_128 = 7U
} DMA_WaitCycle; /* waiting cycles between two burst transaction */
#define DMA_DATA_WIDTH_VMASK 0x3U
typedef enum {
DMA_DATA_WIDTH_8BIT = 0U,
DMA_DATA_WIDTH_16BIT = 1U,
DMA_DATA_WIDTH_32BIT = 2U
} DMA_DataWidth;
#define DMA_BURST_LEN_VMASK 0x1U
typedef enum {
DMA_BURST_LEN_1 = 0U,
DMA_BURST_LEN_4 = 1U
} DMA_BurstLen;
#define DMA_ADDR_MODE_VMASK 0x1U
typedef enum {
DMA_ADDR_MODE_INC = 0U, /* address is increased when DMA transferring */
DMA_ADDR_MODE_FIXED = 1U /* address is not changed when DMA transferring */
} DMA_AddrMode;
#define DMA_PERIPH_VMASK 0x1F
typedef enum {
DMA_PERIPH_SRAM = 0U,
DMA_PERIPH_SPI0 = 1U,
#if (CONFIG_CHIP_ARCH_VER == 2)
DMA_PERIPH_SPI1 = 2U,
#endif
DMA_PERIPH_UART0 = 3U,
DMA_PERIPH_UART1 = 4U,
DMA_PERIPH_CE = 5U,
DMA_PERIPH_DAUDIO = 6U,
DMA_PERIPH_FLASHC = 7U,
#if (CONFIG_CHIP_ARCH_VER == 2)
DMA_PERIPH_DMIC = 8U,
#endif
DMA_PERIPH_UART2 = 9U,
DMA_PERIPH_AUDIO_CODEC = 10U,
DMA_PERIPH_GPADC = 11U, /* for RX only */
#if (CONFIG_CHIP_ARCH_VER == 2)
DMA_PERIPH_PSRAMC = 12U,
#endif
} DMA_Periph;
#define DMA_BYTE_CNT_MODE_SHIFT 15 /* R/W */
#define DMA_BYTE_CNT_MODE_VMASK 0x1U
#define DMA_BYTE_CNT_MODE_MASK (DMA_BYTE_CNT_MODE_VMASK << DMA_BYTE_CNT_MODE_SHIFT)
typedef enum {
DMA_BYTE_CNT_MODE_NORMAL = 0U, /* DMA->CHANNEL[x].BYTE_CNT is the data length of the DAM transfer */
DMA_BYTE_CNT_MODE_REMAIN = 1U /* DMA->CHANNEL[x].BYTE_CNT is the length of the remaining data not transferred */
} DMA_ByteCntMode;
#define DMA_DST_DATA_WIDTH_SHIFT 24 /* R/W */
#define DMA_DST_BURST_LEN_SHIFT 23 /* R/W */
#define DMA_DST_ADDR_MODE_SHIFT 21 /* R/W */
#define DMA_DST_PERIPH_SHIFT 16 /* R/W */
#define DMA_SRC_DATA_WIDTH_SHIFT 8 /* R/W */
#define DMA_SRC_BURST_LEN_SHIFT 7 /* R/W */
#define DMA_SRC_ADDR_MODE_SHIFT 5 /* R/W */
#define DMA_SRC_PERIPH_SHIFT 0
/* DMA->CHANNEL[x].SRC_ADDR */
/* DMA->CHANNEL[x].DST_ADDR */
/* DMA->CHANNEL[x].BYTE_CNT */
#define DMA_BYTE_CNT_VMASK 0x3FFFF
/* Maximum data length of one DMA transfer */
#define DMA_DATA_MAX_LEN (128 * 1024U)
/******************************************************************************/
/** @brief Type define of DMA IRQ callback function */
typedef void (*DMA_IRQCallback)(void *arg);
/**
* @brief DMA channel initialization parameters
*/
typedef struct {
uint32_t cfg; /* created by HAL_DMA_MakeInitCfg() */
DMA_IRQType irqType; /* DMA IRQ type to be enabled */
DMA_IRQCallback endCallback; /* DMA transfer complete callback fucntion */
void *endArg; /* argument of DMA transfer complete callback fucntion */
#if HAL_DMA_OPT_TRANSFER_HALF_IRQ
DMA_IRQCallback halfCallback; /* DMA half transfer complete callback fucntion */
void *halfArg; /* argument of DMA half transfer complete callback fucntion */
#endif
} DMA_ChannelInitParam;
/**
* @brief Make configuration value for DMA_ChannelInitParam::cfg
* @param[in] workMode DMA transfer working mode
* @param[in] waitCycle Waiting cycles between two DMA burst transaction
* @param[in] byteCntMode DMA byte count mode
* @arg DMA_BYTE_CNT_MODE_NORMAL In normal mode, DMA->CHANNEL[x].BYTE_CNT is
* not changed in the whole DMA transfer, and
* its value is the data length of the DAM
* transfer.
* @arg DMA_BYTE_CNT_MODE_REMAIN In remaining mode, DMA->CHANNEL[x].BYTE_CNT
* is decreased when DMA transferring, and its
* value is the length of the remaining data
* not transferred.
* @param[in] dstDataWidth Destination DMA transaction data width
* @param[in] dstBurstLen Destination DMA transaction burst length
* @param[in] dstAddrMode Destination DMA address mode
* @param[in] dstPeriph Destination DMA peripheral type
* @param[in] srcDataWidth Source DMA transaction data width
* @param[in] srcBurstLen Source DMA transaction burst length
* @param[in] srcAddrMode Source DMA address mode
* @param[in] srcPeriph Source DMA peripheral type
* @return configuration value for DMA_ChannelInitParam::cfg
*
* @note
* - A DMA transaction is not interruptible
* - A DMA transaction data length = data width * burst length
*/
__STATIC_INLINE uint32_t HAL_DMA_MakeChannelInitCfg(DMA_WorkMode workMode,
DMA_WaitCycle waitCycle,
DMA_ByteCntMode byteCntMode,
DMA_DataWidth dstDataWidth,
DMA_BurstLen dstBurstLen,
DMA_AddrMode dstAddrMode,
DMA_Periph dstPeriph,
DMA_DataWidth srcDataWidth,
DMA_BurstLen srcBurstLen,
DMA_AddrMode srcAddrMode,
DMA_Periph srcPeriph)
{
return ((((uint32_t)workMode & DMA_WORK_MODE_VMASK) << DMA_WORK_MODE_SHIFT) |
(((uint32_t)waitCycle & DMA_WAIT_CYCLE_VMASK) << DMA_WAIT_CYCLE_SHIFT) |
(((uint32_t)byteCntMode & DMA_BYTE_CNT_MODE_VMASK) << DMA_BYTE_CNT_MODE_SHIFT) |
(((uint32_t)dstDataWidth & DMA_DATA_WIDTH_VMASK) << DMA_DST_DATA_WIDTH_SHIFT) |
(((uint32_t)dstBurstLen & DMA_BURST_LEN_VMASK) << DMA_DST_BURST_LEN_SHIFT) |
(((uint32_t)dstAddrMode & DMA_ADDR_MODE_VMASK) << DMA_DST_ADDR_MODE_SHIFT) |
(((uint32_t)dstPeriph & DMA_PERIPH_VMASK) << DMA_DST_PERIPH_SHIFT) |
(((uint32_t)srcDataWidth & DMA_DATA_WIDTH_VMASK) << DMA_SRC_DATA_WIDTH_SHIFT) |
(((uint32_t)srcBurstLen & DMA_BURST_LEN_VMASK) << DMA_SRC_BURST_LEN_SHIFT) |
(((uint32_t)srcAddrMode & DMA_ADDR_MODE_VMASK) << DMA_SRC_ADDR_MODE_SHIFT) |
(((uint32_t)srcPeriph & DMA_PERIPH_VMASK) << DMA_SRC_PERIPH_SHIFT));
}
/**
* @brief Request an available DMA channel
* @note Before using DMA, an available DMA channel MUST be requested first
* @retval DMA_Channel, DMA_CHANNEL_INVALID on failed
*/
DMA_Channel HAL_DMA_Request(void);
/**
* @brief Request the specified DMA channel if it is available
* @param[in] chan the specified DMA channel
* @retval DMA_Channel, DMA_CHANNEL_INVALID on failed
*/
DMA_Channel HAL_DMA_RequestSpecified(DMA_Channel chan);
/**
* @brief Release the DMA channel
* @param[in] chan DMA channel to be released
* @return None
*/
void HAL_DMA_Release(DMA_Channel chan);
/**
* @brief Initialize the DMA channel according to the specified parameters
* @param[in] chan DMA channel
* @param[in] param Pointer to DMA_ChannelInitParam structure
* @retval HAL_Status, HAL_OK on success
*/
HAL_Status HAL_DMA_Init(DMA_Channel chan, const DMA_ChannelInitParam *param);
/**
* @brief DeInitialize the specified DMA channel
* @param[in] chan DMA channel
* @retval HAL_Status, HAL_OK on success
*/
HAL_Status HAL_DMA_DeInit(DMA_Channel chan);
/**
* @brief Start the DMA transfer of the specified DMA channel
* @param[in] chan DMA channel
* @param[in] srcAddr The source address of DMA transfer
* @param[in] dstAddr The destination address of DMA transfer
* @param[in] datalen The length of data to be transferred from source to destination
* @retval HAL_Status, HAL_OK on success
*
* @note The source/destination address MUST be aligned to the
* source/destination DMA transaction data width defined by DMA_DataWidth.
* @note The date length MUST not be more than DMA_DATA_MAX_LEN.
* @note The srcAddr and dstAddr not spupport reentrant
Before dma start, clean src address part of dcache to sram;
After dma end, flush dest address part of dcache.
*/
HAL_Status HAL_DMA_Start(DMA_Channel chan, uint32_t srcAddr, uint32_t dstAddr, uint32_t datalen);
/**
* @brief Stop the DMA transfer of the specified DMA channel
* @param[in] chan DMA channel
* @retval HAL_Status, HAL_OK on success
*/
HAL_Status HAL_DMA_Stop(DMA_Channel chan);
/**
* @brief Check the busy status of the specified DMA channel
* @param[in] chan DMA channel
* @return 1 on busy, 0 on idle
*/
int HAL_DMA_IsBusy(DMA_Channel chan);
/**
* @brief Get the byte counter of the specified DMA channel
* @param[in] chan DMA channel
* @return The byte counter of the specified DMA channel
* - If DMA byte count mode is DMA_BYTE_CNT_MODE_NORMAL, the return value
* is the data length set by HAL_DMA_Start().
* - If DMA byte count mode is DMA_BYTE_CNT_MODE_REMAIN, the return value
* is the length of the remaining data not transferred.
*/
uint32_t HAL_DMA_GetByteCount(DMA_Channel chan);
uint32_t HAL_DMA_FlashSbus_Iscoexist(void);
#ifdef __cplusplus
}
#endif
#endif /* _DRIVER_CHIP_HAL_DMA_H_ */