313 lines
11 KiB
C
Executable File
313 lines
11 KiB
C
Executable File
/*
|
|
* 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.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "kernel/os/os.h"
|
|
#include "driver/chip/hal_dma.h"
|
|
#include "driver/chip/hal_flashctrl.h"
|
|
#include "data_header.h"
|
|
|
|
#define DMA_SRAM_MODE
|
|
//#define DMA_UART0_MODE
|
|
|
|
#define MAX_DATAWIDTH 3
|
|
#define MAX_BUSTLEN 2
|
|
|
|
#define DMA_START(chan, srcAddr, dstAddr, datalen) HAL_DMA_Start(chan, srcAddr, dstAddr, datalen)
|
|
/*
|
|
* @return If DMA byte count mode is DMA_BYTE_CNT_MODE_REMAIN,
|
|
* the DMA_GET_BYTE_COUNT(chan) return value is the length of the remaining data not transferred,
|
|
* but DMA_BYTE_CNT_MODE_NORMAL mode is the data length set by HAL_DMA_Start().
|
|
*/
|
|
#define DMA_GET_BYTE_COUNT(chan) HAL_DMA_GetByteCount(chan)
|
|
#if (defined(DMA_SRAM_MODE))
|
|
#define DMA_IRQ_TYPE DMA_PERIPH_SRAM
|
|
#elif (defined(DMA_UART0_MODE))
|
|
#define DMA_IRQ_TYPE DMA_PERIPH_UART0 /* write to uart0, but no receive by user send to uart0 */
|
|
#endif
|
|
|
|
#define SRAM_SRC_FIFO_ADDR 0x00230000 /* free memory addr */
|
|
#define SRAM_DST_FIFO_ADDR 0x00230000 /* free memory addr */
|
|
#define UART0_SRC_FIFO_ADDR 0x40040C00 /* uart0 rx addr */
|
|
#define UART0_DST_FIFO_ADDR 0x40040C00 /* uart0 tx addr */
|
|
#define SRAM_FIFO_SIZE (64 * 1024) /* send & receive data size */
|
|
#define UART0_FIFO_SIZE 9 /* send & receive data size */
|
|
|
|
typedef struct dmaPriv {
|
|
uint8_t workMode;
|
|
uint8_t waitCycle;
|
|
uint8_t byteCntMode;
|
|
uint8_t addrMode;
|
|
uint32_t srcFifo;
|
|
uint32_t dstFifo;
|
|
uint32_t fifoSize;
|
|
} dmaPriv_t;
|
|
|
|
typedef struct dmaChanalPriv {
|
|
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;
|
|
} dmaChanalPriv_T;
|
|
|
|
typedef enum {
|
|
DMA_WRITE_CHANAL,
|
|
DMA_READ_CHANAL
|
|
} dmaInitMode;
|
|
|
|
dmaPriv_t dmaPriv[] = {
|
|
[DMA_PERIPH_SRAM] = {DMA_WORK_MODE_SINGLE, DMA_WAIT_CYCLE_1, DMA_BYTE_CNT_MODE_REMAIN, DMA_ADDR_MODE_INC, (SRAM_SRC_FIFO_ADDR), (SRAM_DST_FIFO_ADDR), SRAM_FIFO_SIZE},
|
|
[DMA_PERIPH_UART0] = {DMA_WORK_MODE_SINGLE, DMA_WAIT_CYCLE_1, DMA_BYTE_CNT_MODE_REMAIN, DMA_ADDR_MODE_FIXED, (UART0_SRC_FIFO_ADDR), (UART0_DST_FIFO_ADDR), UART0_FIFO_SIZE},
|
|
/*
|
|
* @note The following are all channels supported by the DMA, but the corresponding configuration is required to be used.
|
|
* If you need to use it, you can go to the corresponding sample project to view.
|
|
* [DMA_PERIPH_SPI0],
|
|
* [DMA_PERIPH_SPI1],
|
|
* [DMA_PERIPH_UART1],
|
|
* [DMA_PERIPH_CE],
|
|
* [DMA_PERIPH_DAUDIO],
|
|
* [DMA_PERIPH_FLASHC],
|
|
* [DMA_PERIPH_DMIC],
|
|
* #if (CONFIG_CHIP_ARCH_VER > 1)
|
|
* [DMA_PERIPH_UART2],
|
|
* [DMA_PERIPH_AUDIO_CODEC],
|
|
* [DMA_PERIPH_GPADC],
|
|
* [DMA_PERIPH_PSRAMC],
|
|
* #endif
|
|
*/
|
|
};
|
|
|
|
void Stop_Dma(void *arg)
|
|
{
|
|
DMA_Channel chanal = (DMA_Channel)arg;
|
|
|
|
HAL_DMA_Stop(chanal);
|
|
HAL_DMA_Release(chanal);
|
|
}
|
|
|
|
DMA_Channel Dma_Request(dmaChanalPriv_T dmaChanalPriv)
|
|
{
|
|
DMA_Channel chanal;
|
|
DMA_ChannelInitParam param;
|
|
/*request a free channel.*/
|
|
chanal = HAL_DMA_Request();
|
|
if (chanal == DMA_CHANNEL_INVALID) {
|
|
return DMA_CHANNEL_INVALID;
|
|
}
|
|
param.cfg = HAL_DMA_MakeChannelInitCfg(dmaChanalPriv.workMode,
|
|
dmaChanalPriv.waitCycle,
|
|
dmaChanalPriv.byteCntMode,
|
|
dmaChanalPriv.dstDataWidth,
|
|
dmaChanalPriv.dstBurstLen,
|
|
dmaChanalPriv.dstAddrMode,
|
|
dmaChanalPriv.dstPeriph,
|
|
|
|
dmaChanalPriv.srcDataWidth,
|
|
dmaChanalPriv.srcBurstLen,
|
|
dmaChanalPriv.srcAddrMode,
|
|
dmaChanalPriv.srcPeriph);
|
|
param.endArg = (void *)chanal;
|
|
param.endCallback = Stop_Dma;
|
|
param.irqType = DMA_IRQ_TYPE_END;
|
|
HAL_DMA_Init(chanal, ¶m);
|
|
return chanal;
|
|
}
|
|
|
|
DMA_Channel Dma_Init(uint8_t src_DataWidth, uint8_t src_BustLen,
|
|
uint8_t dest_DataWidth, uint8_t dest_BustLen, dmaInitMode mode)
|
|
{
|
|
DMA_Channel chanal;
|
|
dmaChanalPriv_T dmaChanalPri;
|
|
|
|
dmaChanalPri.workMode = dmaPriv[DMA_IRQ_TYPE].workMode;
|
|
dmaChanalPri.waitCycle = dmaPriv[DMA_IRQ_TYPE].waitCycle;
|
|
dmaChanalPri.byteCntMode = dmaPriv[DMA_IRQ_TYPE].byteCntMode;
|
|
|
|
if (mode == DMA_WRITE_CHANAL) {
|
|
dmaChanalPri.dstDataWidth = dest_DataWidth;
|
|
dmaChanalPri.dstBurstLen = dest_BustLen;
|
|
dmaChanalPri.srcDataWidth = src_DataWidth;
|
|
dmaChanalPri.srcBurstLen = src_BustLen;
|
|
dmaChanalPri.dstAddrMode = dmaPriv[DMA_IRQ_TYPE].addrMode;
|
|
dmaChanalPri.srcAddrMode = DMA_ADDR_MODE_INC;
|
|
dmaChanalPri.dstPeriph = DMA_IRQ_TYPE;
|
|
dmaChanalPri.srcPeriph = DMA_PERIPH_SRAM;
|
|
} else if (mode == DMA_READ_CHANAL) {
|
|
dmaChanalPri.dstDataWidth = src_DataWidth;
|
|
dmaChanalPri.dstBurstLen = src_BustLen;
|
|
dmaChanalPri.srcDataWidth = dest_DataWidth;
|
|
dmaChanalPri.srcBurstLen = dest_BustLen;
|
|
dmaChanalPri.dstAddrMode = DMA_ADDR_MODE_INC;
|
|
dmaChanalPri.srcAddrMode = dmaPriv[DMA_IRQ_TYPE].addrMode;
|
|
dmaChanalPri.dstPeriph = DMA_PERIPH_SRAM;
|
|
dmaChanalPri.srcPeriph = DMA_IRQ_TYPE;
|
|
} else {
|
|
printf("dmaInitMode error!\n");
|
|
return -1;
|
|
}
|
|
|
|
chanal = Dma_Request(dmaChanalPri);
|
|
if (chanal == DMA_CHANNEL_INVALID) {
|
|
printf("DMA request error\n");
|
|
return DMA_CHANNEL_INVALID;
|
|
}
|
|
|
|
return chanal;
|
|
}
|
|
|
|
void Dma_DeInit(DMA_Channel chan)
|
|
{
|
|
HAL_DMA_DeInit(chan);
|
|
HAL_DMA_Release(chan);
|
|
}
|
|
|
|
int Dma_Write_Read(DMA_Channel ch_Write, DMA_Channel ch_Read)
|
|
{
|
|
uint32_t writeByteCount, readByteCount, writeSrcFifo, writeDstFifo, readSrcFifo, readDstFifo;
|
|
|
|
readSrcFifo = writeDstFifo = dmaPriv[DMA_IRQ_TYPE].dstFifo;
|
|
#if (defined(DMA_SRAM_MODE))
|
|
uint32_t *dataBuf = NULL;
|
|
|
|
dataBuf = malloc(dmaPriv[DMA_IRQ_TYPE].fifoSize);
|
|
if (dataBuf == NULL) {
|
|
printf("malloc failed\n");
|
|
return -1;
|
|
}
|
|
memset(dataBuf, 0, dmaPriv[DMA_IRQ_TYPE].fifoSize);
|
|
writeSrcFifo = (uint32_t)arrData;
|
|
readDstFifo = (uint32_t)dataBuf;
|
|
#elif (defined(DMA_UART0_MODE))
|
|
char uartStr[] = {"123456789"};
|
|
char *strdata = NULL;
|
|
|
|
strdata = (char *)malloc(dmaPriv[DMA_IRQ_TYPE].fifoSize * sizeof(char));
|
|
if (strdata == NULL) {
|
|
printf("malloc failed\n");
|
|
return -1;
|
|
}
|
|
memset(strdata, 0, dmaPriv[DMA_IRQ_TYPE].fifoSize * sizeof(char));
|
|
writeSrcFifo = (uint32_t)uartStr;
|
|
readDstFifo = (uint32_t)strdata;
|
|
#endif
|
|
|
|
DMA_START(ch_Write, writeSrcFifo, writeDstFifo, dmaPriv[DMA_IRQ_TYPE].fifoSize);
|
|
while (DMA_GET_BYTE_COUNT(ch_Write)) /* Suitable for DMA_BYTE_CNT_MODE_REMAIN mode */
|
|
;
|
|
writeByteCount = DMA_GET_BYTE_COUNT(ch_Write);
|
|
printf("\nwriteByteCount: %u, write over.\n", writeByteCount);
|
|
|
|
DMA_START(ch_Read, readSrcFifo, readDstFifo, dmaPriv[DMA_IRQ_TYPE].fifoSize);
|
|
while (DMA_GET_BYTE_COUNT(ch_Read)) /* Suitable for DMA_BYTE_CNT_MODE_REMAIN mode */
|
|
;
|
|
readByteCount = DMA_GET_BYTE_COUNT(ch_Read);
|
|
printf("\nreadByteCount: %u, read over.\n", readByteCount);
|
|
|
|
#if (defined(DMA_SRAM_MODE))
|
|
if (memcmp(arrData, dataBuf, dmaPriv[DMA_IRQ_TYPE].fifoSize) != 0)
|
|
#elif (defined(DMA_UART0_MODE))
|
|
if (strncmp(&uartStr[0], strdata, dmaPriv[DMA_IRQ_TYPE].fifoSize))
|
|
#endif
|
|
printf("Write & Read data compare failed!\n");
|
|
else
|
|
printf("Write & Read data compare OK.\n");
|
|
#if (defined(DMA_SRAM_MODE))
|
|
free(dataBuf);
|
|
dataBuf = NULL;
|
|
#elif (defined(DMA_UART0_MODE))
|
|
free(strdata);
|
|
strdata = NULL;
|
|
#endif
|
|
writeByteCount = 0;
|
|
readByteCount = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Dma_Show(void)
|
|
{
|
|
DMA_Channel ch_Write;
|
|
DMA_Channel ch_Read;
|
|
uint8_t src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen;
|
|
|
|
#if (defined(DMA_SRAM_MODE))
|
|
for (src_DataWidth = 0; src_DataWidth <= MAX_DATAWIDTH; src_DataWidth++) {
|
|
for (src_BustLen = 0; src_BustLen <= MAX_BUSTLEN; src_BustLen++) {
|
|
for (dest_DataWidth = 0; dest_DataWidth <= MAX_DATAWIDTH; dest_DataWidth++) {
|
|
for (dest_BustLen = 0; dest_BustLen <= MAX_BUSTLEN; dest_BustLen++) {
|
|
printf("module %d:src_DataWidth=%d, src_BustLen=%d, dest_DataWidth=%d, dest_BustLen=%d\n",
|
|
DMA_IRQ_TYPE, src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen);
|
|
ch_Write = Dma_Init(src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen, DMA_WRITE_CHANAL);
|
|
ch_Read = Dma_Init(src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen, DMA_READ_CHANAL);
|
|
Dma_Write_Read(ch_Write, ch_Read);
|
|
Dma_DeInit(ch_Write);
|
|
Dma_DeInit(ch_Read);
|
|
OS_MSleep(10);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#elif (defined(DMA_UART0_MODE))
|
|
src_DataWidth = 0;
|
|
src_BustLen = 0;
|
|
dest_DataWidth = 0;
|
|
dest_BustLen = 0;
|
|
|
|
printf("module %d:src_DataWidth=%d, src_BustLen=%d, dest_DataWidth=%d, dest_BustLen=%d\n",
|
|
DMA_IRQ_TYPE, src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen);
|
|
ch_Write = Dma_Init(src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen, DMA_WRITE_CHANAL);
|
|
ch_Read = Dma_Init(src_DataWidth, src_BustLen, dest_DataWidth, dest_BustLen, DMA_READ_CHANAL);
|
|
Dma_Write_Read(ch_Write, ch_Read);
|
|
Dma_DeInit(ch_Write);
|
|
Dma_DeInit(ch_Read);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* this example just show use SRAM/Uart0 for DMA , other chanal can be view on corresponding example or demo */
|
|
/* SRAM mode:using dma to copy data to another memory */
|
|
/* Uart0 mode:using dma to send & receive data to uart0 */
|
|
int main(void)
|
|
{
|
|
printf("dma example started\n\n");
|
|
Dma_Show();
|
|
printf("dma example end\n\n");
|
|
|
|
return 0;
|
|
}
|