Caching seg_ext_dma for DMA
Hi,
I need to us SDRAM for storage of date that needs to be loaded and saved in L1. The DMA should be able to transfer data at 450 MB/sec using the cache. I am seeing numbers which are an order of magnitude slower indicating that the cache is not enabled for SDRAM and DMA transfers to L1. I have looked at cache and DMA examples and they indicate that cache needs to be setup in the .ldf. When I add the seg_ext_pmda to cache there is no performance change.
Are there any specific instructions, examples or documentation that specifies how to setup caching SDRAM for DMA?
dxe_l2_pm_data PM 32
{
// L2 pm data.
INPUT_SECTIONS( $OBJS_LIBS(seg_pmda_nw seg_pmda seg_ext_pmda) )
} > MY_L2_CACHED_MEM
dxe_l2_pm_data_bw BW
{
// L2 pm data.
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS( $OBJS_LIBS(seg_pmda seg_ext_pmda) )
} > MY_L2_CACHED_MEM
-Steve
ADSP-21569
Audio Signal Processors
software
Cross Core Embedded Studio version 2.9.4.0
SHARC Audio Processors/SoCs
Hi Steve,
We are looking into this and we will get back to as soon as possible.
Regards,
Divya.P
Hi Steve,
Apologies for the delay
To use cache, you have to place the code/data in external memory and enable the Cache in "Cache Configuration tab" from system.svc > Startup Code/LDF. This will automatically execute externally located functions and data from cache memory.
Also if issue still exists, Please share your project.
Regards,
Anand Selvaraj.
Hi Anand Selvaraj,
How do I share a project?
Can you confirm the DMA xfer rate for the ADSP-21569 is 450 MB/sec.
My project has 2 sets of coefficients and echo path buffers to transfer.
#define AEC_COEF_SIZE_I8 102400 // size in 8-bit byte
#define AEC_ECHOPATH_SIZE_I8 54008 // size in 8-bit byte
Total 312,816 bytes.
My program DMAs to and from L1 and SDRAM.
The transfer is split into 4 separate DMA operations since 4 different memory locations are used.
The expected xfer rate would be:
312,816 / (48x1000000) = 0.006517 seconds
I am seeing 174 MIPS = .69 seconds.
Our target is less than half (80 MIPs) ~= .34 seconds.
Something seems wrong with my numbers.
This would make my actual DMA numbers off by a factor of 100.
I am seeing 174 MIPs performing 4 sequential DMA transfers.
I expected it to be half using 2 DMAs, instead it doubled. There must be conflict with caching when 2 DMAs are actively accessing L1 and SDRAM?
I want to straighten out the numbers.
From all the documentation, examples and support that I have received the cache should be enabled:
Instruction cache: 16KB
PM cache: 64KB
DM cache: 32KB
These are the max cache values that can be set while running a small test progam.
I would like to send the program for your review.
* ADSP_21569_MDMA1.c
*****************************************************************************/
#include <sys/platform.h>
#include "adi_initialize.h"
#include "ADSP_21569_MDMA1.h"
#include "stdio.h"
#include <services/int/adi_int.h>
void MDMA0_Write();
void MDMA_Completion_ISR0();
/*********************************************************************************
Copyright(c) 2018 Analog Devices, Inc. All Rights Reserved.
This software is proprietary and confidential. By using this software you agree
to the terms of the associated Analog Devices License Agreement.
*********************************************************************************/
/*!
* @file MemCopyArrayMode.c
* @brief Example to demonstrate memory copy using Array mode.
* @version: $Revision: 37126 $
* @date: $Date: 2018-10-10 11:20:31 +0530 (Wed, 10 Oct 2018) $
*
* @details
* This is the primary source file to demonstrate
* memory copy using DMA Array mode with Memory DMA manager APIs.
*
*/
/*============= I N C L U D E S =============*/
/* Array mode Memory Copy example includes */
#include "MemCopyArrayMode1.h"
/* Managed drivers and/or services include */
#include "adi_initialize.h"
#include <sys/platform.h>
#define AEC_COEF_SIZE_I8 102400 // size in 8-bit byte
#define AEC_ECHOPATH_SIZE_I8 54008 // size in 8-bit byte
#pragma section("seg_l1_block1")
_Pragma("align 64")
float Buffer_For_Coef_Ping[(AEC_COEF_SIZE_I8)/sizeof(float)];
#pragma section("seg_l1_block3")
_Pragma("align 64")
float Buffer_For_Coef_Pong[(AEC_COEF_SIZE_I8)/sizeof(float)];
#pragma section("seg_l1_block2")
_Pragma("align 64")
float Buffer_For_EchoPath_Ping[(AEC_ECHOPATH_SIZE_I8)/sizeof(float)];
#pragma section("seg_l1_block1")
_Pragma("align 64")
float Buffer_For_EchoPath_Pong[(AEC_ECHOPATH_SIZE_I8)/sizeof(float)];
#if !defined(ADI_CACHE_LINE_LENGTH)
/* The ADI_CACHE_* macros were introduced in CCES 2.4.0 in <sys/platform.h>.
* If using an older toolchain, define them here.
*/
#if defined(__ADSPARM__)
#define ADI_CACHE_LINE_LENGTH (32uL)
#define ADI_CACHE_ALIGN_MIN_4 __attribute__((aligned(ADI_CACHE_LINE_LENGTH)))
#elif defined(__ADSP215xx__)
#define ADI_CACHE_LINE_LENGTH (64uL)
#define ADI_CACHE_ALIGN_MIN_4 _Pragma("align 64")
#else
#error Unknown ADI_CACHE_LINE_LENGTH
#endif
#define ADI_CACHE_ROUND_UP_SIZE(size, type) \
(((((((size) * sizeof(type)) \
+ (ADI_CACHE_LINE_LENGTH - 1uL)) \
/ ADI_CACHE_LINE_LENGTH) * ADI_CACHE_LINE_LENGTH) \
+ (sizeof(type) - 1uL)) / sizeof(type))
#endif
/*============= LOCAL DEFINES =============*/
/* When the processor's L1 and/or L2 cache is enabled the receive data buffers must */
/* be aligned on cache line boundaries. If they are not then any data access by the core may */
/* pull a buffer into the cache while the DMA is operating on the data buffer. Both the core and */
/* the DMA are masters on the bus. The core will be performing cache operations. The DMA engine will*/
/* not be. So it is important for the application to both align data that will be operated on by the*/
/* DMA and to separate this data from other application data. */
#if defined(__ICCARM__)
#define SRCALIGN _Pragma("data_alignment=4")
#define DSTALIGN _Pragma("data_alignment=32")
#elif defined(__ADSPGCC__)
#define DSTALIGN ADI_CACHE_ALIGN_MIN_4
#define SRCALIGN __attribute__ ((aligned (4)))
#else
#define DSTALIGN ADI_CACHE_ALIGN_MIN_4
#define SRCALIGN _Pragma("align 4")
#endif
/*============= D A T A =============*/
/* Source and Destination channel data buffer.
* Aligned at least to an MSIZE-byte boundary.
*/
//static float Buffer_For_Coef[(0x0001fc00)/sizeof(float)];
#pragma section("seg_ext_pmda")
DSTALIGN static uint8_t CoefDataBuf[ADI_CACHE_ROUND_UP_SIZE(MEMCOPY_BYTES_ALLOC_PER_CHANNEL_DESC_COEF, uint8_t)];
#pragma section("seg_ext_pmda")
DSTALIGN static uint8_t EchoPathDataBuf[ADI_CACHE_ROUND_UP_SIZE(MEMCOPY_BYTES_ALLOC_PER_CHANNEL_DESC_ECHOPATH, uint8_t)];
static uint8_t* CoefPingBuf;
static uint8_t* CoefPongBuf;
static uint8_t* EchoPathPingBuf;
static uint8_t* EchoPathPongBuf;
/*============= L O C A L F U N C T I O N S =============*/
/* Prepares data buffers for Memory DMA copy */
static void PrepareDataBuffers (void);
static void UpdateDataBuffers (void);
typedef enum
{
ADI_DMA_SUCCESS = 0, /*!< 0x00 - Generic success */
ADI_DMA_FAILURE, /*!< 0x01 - Generic failure */
ADI_DMA_IN_USE, /*!< 0x02 - Supplied DMA channel/stream ID is already open and in use */
ADI_DMA_NOT_OPEN, /*!< 0x03 - Channel is not open to preform the requested task */
ADI_DMA_ALREADY_RUNNING, /*!< 0x04 - Function not permitted since DMA is already running */
ADI_DMA_BAD_HANDLE, /*!< 0x05 - Bad channel/stream handle */
ADI_DMA_BAD_STREAM_ID, /*!< 0x06 - No such memory stream ID */
ADI_DMA_BAD_MSIZE, /*!< 0x07 - Bad memory transfer size */
ADI_DMA_BAD_PSIZE, /*!< 0x08 - Bad peripheral transfer size */
ADI_DMA_BAD_XCOUNT, /*!< 0x09 - An invalid XCount value was supplied */
ADI_DMA_BAD_YCOUNT, /*!< 0x0A - An invalid YCount value was supplied */
ADI_DMA_BAD_START_ADDR, /*!< 0x0B - Supplied start address in invalid */
ADI_DMA_ADDR_ALIGNMENT_ERROR, /*!< 0x0C - Start address alignment error */
ADI_DMA_INT_REGISTER_FAILED, /*!< 0x0D - Can't register an interrupt */
ADI_DMA_INT_UNREGISTER_FAILED, /*!< 0x0E - Can't unregister an interrupt */
ADI_DMA_INVALID_NULL_POINTER, /*!< 0x0F - Specified pointer is invalid and pointing to NULL. */
ADI_DMA_NO_BUFFER_TO_PROCESS /*!< 0x10 - Can't start DMA data transfer as there is no valid buffer to process */
} ADI_DMA_RESULT;
/* Verifies memory DMA copy by comparing destination data with source */
static ADI_DMA_RESULT VerifyDataCopy (void);
/*============= C O D E =============*/
bool PingPong = 0;
volatile uint32_t Current_Channel = 0;
unsigned long Applyatime, Applybtime;
static float facc_time=0;
static float avgtime = 0;
static uint8_t *pSourceAddress;
static uint8_t *pDestAddress;
volatile int DMA_Completed0 = 0;
volatile int DMA_Completed1 = 0;
void MDMA0_Write(uint8_t * pReadAddress, uint8_t * pWriteAddress, uint32_t iXCount);
void MDMA_Completion_ISR0(void);
void MDMA1_Write(uint8_t * pReadAddress, uint8_t * pWriteAddress, uint32_t iXCount);
void MDMA_Completion_ISR1(void);
void MDMA0_Write(uint8_t * pReadAddress, uint8_t * pWriteAddress, uint32_t iXCount)
{
*pREG_DMA8_ADDRSTART = (uint32_t *)pReadAddress; //Initialize start address
*pREG_DMA8_XCNT = iXCount/4; //Initialize X count
*pREG_DMA8_XMOD = 4; //Initialize DMA X modifier
*pREG_DMA8_YCNT = 0; //Initialize Y count
*pREG_DMA8_YMOD = 0; //Initialize DMA Y modifier
*pREG_DMA9_ADDRSTART = (uint32_t *)pWriteAddress; //Initialize start address
*pREG_DMA9_XCNT = iXCount/4; //Initialize DMA X count
*pREG_DMA9_XMOD = 4; //Initialize DMA X modifier
*pREG_DMA9_YCNT = 0; //Initialize DMA Y count
*pREG_DMA9_YMOD = 0; //Initialize DMA Y modifier
*pREG_DMA9_CFG = ENUM_DMA_CFG_EN | ENUM_DMA_CFG_PSIZE04 |ENUM_DMA_CFG_MSIZE04 |ENUM_DMA_CFG_WRITE | ENUM_DMA_CFG_XCNT_INT; //Initialize DMA config register
*pREG_DMA8_CFG = ENUM_DMA_CFG_EN | ENUM_DMA_CFG_PSIZE04 |ENUM_DMA_CFG_MSIZE04;//Initialize DMA config register
}
void MDMA1_Write(uint8_t * pReadAddress, uint8_t * pWriteAddress, uint32_t iXCount)
{
// MDMA0 uses DMA channel 18 and 19 on GUL
*pREG_DMA18_ADDRSTART = (uint32_t *)pReadAddress; //Initialize start address
*pREG_DMA18_XCNT = iXCount/4; //Initialize X count
*pREG_DMA18_XMOD = 4; //Initialize DMA X modifier
*pREG_DMA18_YCNT = 0; //Initialize Y count
*pREG_DMA18_YMOD = 0; //Initialize DMA Y modifier
*pREG_DMA19_ADDRSTART = (uint32_t *)pWriteAddress; //Initialize start address
*pREG_DMA19_XCNT = iXCount/4; //Initialize DMA X count
*pREG_DMA19_XMOD = 4; //Initialize DMA X modifier
*pREG_DMA19_YCNT = 0; //Initialize DMA Y count
*pREG_DMA19_YMOD = 0; //Initialize DMA Y modifier
*pREG_DMA19_CFG = ENUM_DMA_CFG_EN | ENUM_DMA_CFG_PSIZE04 |ENUM_DMA_CFG_MSIZE04 |ENUM_DMA_CFG_WRITE | ENUM_DMA_CFG_XCNT_INT; //Initialize DMA config register
*pREG_DMA18_CFG = ENUM_DMA_CFG_EN | ENUM_DMA_CFG_PSIZE04 |ENUM_DMA_CFG_MSIZE04;//Initialize DMA config register
}
#if 0
void MDMA_Completion_ISR0(void)
{
*pREG_DMA9_STAT |= 0x1;
if(DMA_Completed0 == 0)
{
if(PingPong == 0)
{
pSourceAddress = &EchoPathPingBuf[0];
}
else
{
pSourceAddress = &EchoPathPongBuf[0];
}
pDestAddress = &EchoPathDataBuf[(Current_Channel) * MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH];
MDMA0_Write((uint8_t *)((uint32_t)pSourceAddress|(uint32_t)0x28000000),(uint8_t *)((uint32_t)pDestAddress),MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH);
DMA_Completed0 = 1;
}
else
{
DMA_Completed0 = 2;
}
}
#endif
#if 1
void MDMA_Completion_ISR0(void)
{
*pREG_DMA9_STAT |= 0x1;
DMA_Completed0 = 1;
}
#endif
#if 1
void MDMA_Completion_ISR1(void)
{
*pREG_DMA19_STAT |= 0x1;
DMA_Completed1 = 1;
}
#endif
#if 0
void MDMA_Completion_ISR1(void)
{
*pREG_DMA19_STAT |= 0x1;
if(DMA_Completed1 == 0)
{
if((Current_Channel +2) < MEMCOPY_NUM_CHANNELS)
{
/* Load the next set of Coeficients from Ax +2 */
pSourceAddress = &CoefDataBuf[(Current_Channel +2) * MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF];
}
else if((Current_Channel +1) < MEMCOPY_NUM_CHANNELS)
{
/* Wrap. Load the next set of Coeficients from A1*/
pSourceAddress = &CoefDataBuf[0];
}
else
{
/* Wrap. Load the next set of Coeficients from A2*/
pSourceAddress = &CoefDataBuf[MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF];
}
if(PingPong == 0)
{
pDestAddress = &CoefPingBuf[0];
}
else
{
pDestAddress = &CoefPongBuf[0];
}
MDMA1_Write((uint8_t *)((uint32_t)pSourceAddress),(uint8_t *)((uint32_t)pDestAddress|(uint32_t)0x28000000),MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF);
DMA_Completed1 = 1;
}
else
{
DMA_Completed1 = 2;
}
}
#endif
/*********************************************************************
*
* Function: DMAcopy
*
*********************************************************************/
int DMAcopy()
{
unsigned long time,max_time = 0, atime,btime;
/* DMA Return code */
ADI_DMA_RESULT eResult = ADI_DMA_SUCCESS;
if(Current_Channel == (MEMCOPY_NUM_CHANNELS ))
{
Current_Channel = 0;
}
#if 1
/* Verify data copy */
eResult = VerifyDataCopy ();
if (eResult != ADI_DMA_SUCCESS)
{
DBG_MSG("Data verification failed\n");
return(1);
}
/* Modify contents of Ping Pong buffers */
UpdateDataBuffers();
Applybtime = __builtin_emuclk();
#endif
if(PingPong == 0)
{
pSourceAddress = &CoefPingBuf[0];
}
else
{
pSourceAddress = &CoefPongBuf[0];
}
pDestAddress = &CoefDataBuf[(Current_Channel) * MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF];
MDMA0_Write((uint8_t *)((uint32_t)pSourceAddress|(uint32_t)0x28000000),(uint8_t *)((uint32_t)pDestAddress),MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF);
while(DMA_Completed0 == 0);
DMA_Completed0 = 0;
#if 1
if(PingPong == 0)
{
pSourceAddress = &EchoPathPingBuf[0];
}
else
{
pSourceAddress = &EchoPathPongBuf[0];
}
pDestAddress = &EchoPathDataBuf[(Current_Channel) * MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH];
MDMA0_Write((uint8_t *)((uint32_t)pSourceAddress|(uint32_t)0x28000000),(uint8_t *)((uint32_t)pDestAddress),MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH);
while(DMA_Completed0 == 0);
DMA_Completed0 = 0;
#endif
if((Current_Channel +2) < MEMCOPY_NUM_CHANNELS)
{
/* Load the next set of Coeficients from Ax +2 */
pSourceAddress = &EchoPathDataBuf[(Current_Channel +2) * MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH];
}
else if((Current_Channel +1) < MEMCOPY_NUM_CHANNELS)
{
/* Wrap. Load the next set of Coeficients from A1*/
pSourceAddress = &EchoPathDataBuf[0];
}
else
{
/* Wrap. Load the next set of Coeficients from A2*/
pSourceAddress = &EchoPathDataBuf[MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH];
}
if(PingPong == 0)
{
pDestAddress = &EchoPathPingBuf[0];
}
else
{
pDestAddress = &EchoPathPongBuf[0];
}
MDMA1_Write((uint8_t *)((uint32_t)pSourceAddress),(uint8_t *)((uint32_t)pDestAddress|(uint32_t)0x28000000),MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH);
while(DMA_Completed1 == 0);
DMA_Completed1 = 0;
#if 1
if((Current_Channel +2) < MEMCOPY_NUM_CHANNELS)
{
/* Load the next set of Coeficients from Ax +2 */
pSourceAddress = &CoefDataBuf[(Current_Channel +2) * MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF];
}
else if((Current_Channel +1) < MEMCOPY_NUM_CHANNELS)
{
/* Wrap. Load the next set of Coeficients from A1*/
pSourceAddress = &CoefDataBuf[0];
}
else
{
/* Wrap. Load the next set of Coeficients from A2*/
pSourceAddress = &CoefDataBuf[MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF];
}
if(PingPong == 0)
{
pDestAddress = &CoefPingBuf[0];
}
else
{
pDestAddress = &CoefPongBuf[0];
}
MDMA1_Write((uint8_t *)((uint32_t)pSourceAddress),(uint8_t *)((uint32_t)pDestAddress|(uint32_t)0x28000000),MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF);
while(DMA_Completed1 == 0);
DMA_Completed1 = 0;
#endif
Applyatime = __builtin_emuclk();
Applyatime = Applyatime-Applybtime;
facc_time = (float)Applyatime;
avgtime = facc_time;
avgtime /= 1000000.;
printf("Time = %f seconds\n",avgtime);
avgtime *= 250;
printf("Mips = %f\n",avgtime);
Current_Channel++;
PingPong ^= 1;
return 0;
}
int DMAinit(void)
{
/* Time-out counter to make sure the example exits */
unsigned long time, max_time = 0, atime,btime;
float facc_time=0;
/* DMA Return code */
ADI_DMA_RESULT eResult = ADI_DMA_SUCCESS;
CoefPingBuf = Buffer_For_Coef_Ping;
CoefPongBuf = Buffer_For_Coef_Pong;
EchoPathPingBuf = Buffer_For_EchoPath_Ping;
EchoPathPongBuf = Buffer_For_EchoPath_Pong;
/* Prepare data buffers */
PrepareDataBuffers ();
adi_int_InstallHandler(INTR_SYS_MDMA1_DST,MDMA_Completion_ISR1,0,true);
adi_int_InstallHandler(INTR_SYS_MDMA0_DST,MDMA_Completion_ISR0,0,true);
//Configure MDMA0 Source and Destination channels as secure masters
*pREG_SPU0_SECUREP110 = BITM_SPU_SECUREP_MSEC;
*pREG_SPU0_SECUREP111 = BITM_SPU_SECUREP_MSEC;
//Configure MDMA1 Source and Destination channels as secure masters
*pREG_SPU0_SECUREP112 = BITM_SPU_SECUREP_MSEC;
*pREG_SPU0_SECUREP113 = BITM_SPU_SECUREP_MSEC;
return(0);
}
/*
* Prepares data buffers for Memory DMA copy.
*
* Parameters
* None
*
* Returns
* None
*
*/
static void PrepareDataBuffers (void)
{
/* Loop variable */
uint32_t i;
/* Generate Source data, Clear destination buffer */
for (i = 0u; i < CHANNEL_MEMCOPY_BUF_SIZE_COEF; i++)
{
CoefDataBuf[i] = (uint8_t)rand();
}
for (i = 0u; i < CHANNEL_MEMCOPY_BUF_SIZE_ECHOPATH; i++)
{
EchoPathDataBuf[i] = (uint8_t)rand();
}
memcpy(CoefPingBuf, CoefDataBuf, MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF);
memcpy(CoefPongBuf, CoefDataBuf+MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF, MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF);
memcpy(EchoPathPingBuf, EchoPathDataBuf, MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH);
memcpy(EchoPathPongBuf, EchoPathDataBuf+MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH, MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH);
}
static void UpdateDataBuffers (void)
{
/* Loop variable */
uint32_t i;
if(PingPong == 0)
{
/* Generate Source data, Clear destination buffer */
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF; i++)
{
CoefPingBuf[i] += 1;
}
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH; i++)
{
EchoPathPingBuf[i] += 1;
}
}
else
{
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF; i++)
{
CoefPongBuf[i] += 1;
}
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH; i++)
{
EchoPathPongBuf[i] += 1;
}
}
}
/*
* Verifies memory DMA copy by comparing destination data with source.
*
* Parameters
* None
*
* Returns
* - ADI_DMA_SUCCESS - Data verification success
* - ADI_DMA_FAILURE - Data verification failed
*
*/
static ADI_DMA_RESULT VerifyDataCopy (void)
{
/* Loop variable */
uint32_t i;
/* Compare the destination data with source */
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF; i++)
{
if(PingPong == 0)
{
if (CoefPingBuf[i] != CoefDataBuf[(Current_Channel * MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF) + i])
{
/* Return error */
DBG_MSG("Failed compare 1: Current_Channel\n", Current_Channel);
return ADI_DMA_FAILURE;
}
}
else
{
if (CoefPongBuf[i] != CoefDataBuf[(Current_Channel * MEMCOPY_BYTES_PER_CHANNEL_DESC_COEF) + i])
{
/* Return error */
DBG_MSG("Failed compare 2: Current_Channel\n", Current_Channel);
return ADI_DMA_FAILURE;
}
}
/* IF (Destination data not same as source) */
}
for (i = 0u; i < MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH; i++)
{
if(PingPong == 0)
{
if (EchoPathPingBuf[i] != EchoPathDataBuf[(Current_Channel * MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH) + i])
{
/* Return error */
DBG_MSG("Failed compare 3: Current_Channel\n", Current_Channel);
return ADI_DMA_FAILURE;
}
}
else
{
if (EchoPathPongBuf[i] != EchoPathDataBuf[(Current_Channel * MEMCOPY_BYTES_PER_CHANNEL_DESC_ECHOPATH) + i])
{
/* Return error */
DBG_MSG("Failed compare 4: Current_Channel\n", Current_Channel);
return ADI_DMA_FAILURE;
}
}
/* IF (Destination data not same as source) */
}
/* Return success */
return (ADI_DMA_SUCCESS);
}
/*****/
/*
** EOF
*/
int main(int argc, char *argv[])
{
/**
* Initialize managed drivers and/or services that have been added to
* the project.
* @return zero on success
*/
adi_initComponents();
DMAinit();
while(1)
{
DMAcopy();
}
return 0;
}
review.
Seems to be some fundamental issues that need to be resolved.
-Steve
Hi Anand Selvaraj,
I was able to verify DMA transfers happen at the SCLK0 rate of 125MHz, or 1/8 of the core clock. My DMA results confirm that they are running cached. This being the case, investigating the use of multiple DMAs.
Adding a second DMA to the project and performing 2 DMAs together doubles the transfer time from when each DMA is performed sequentially.
Is there a way to architect the 2 DMAs in order to realize an increased data transfer rate from SDRAM <-> L1.?
-Steve
Hi Steve,
Apologies for the delay
For better optimization and performance we recommend to refer EE-412, Please find the Application note and associated code link below
www.analog.com/.../ee412v02.pdf
Associated code zip: www.analog.com/.../ee412v02.zip
Regards,
Anand Selvaraj.
Please log in to reply.