Hi,
I have a question about EDMA transfer when I using McASP TDM format on C6A8168. I porting the McASP driver form ARM, and I have checked the register's value with McASP data manual.
[DSP] globalctl:0x0
[DSP] pwremumgt:0x2
[DSP] txditctl:0x0
[DSP] lopbakctl:0x0
[DSP] amutectl:0x0
[DSP] rxmask:0xff
[DSP] txformat:0x8032
[DSP] rxformat:0x8030
[DSP] txframectl:0x1010
[DSP] rxframectl:0x1010
[DSP] aclkxctl:0x180040
[DSP] aclkrctl:0x180000
[DSP] ahclkxctl:0x180000
[DSP] ahclkrctl:0x180000
[DSP] xrsrctl:0x11
[DSP] xrsrctl:0x2
[DSP] pindir:0x1
[DSP] pinfunc:0x0
[DSP] evtctlx:0x0
[DSP] evtctlr:0x0
[DSP] txclkchk:0xff0008
[DSP] rxclkchk:0xff0008
[DSP] xevtctl:0x0
[DSP] revtctl:0x0
EDMA initialization program
[DSP] wfifosts:0x0
[DSP] rfifosts:0x0
[DSP] wfifoctl:0x10101
[DSP] rfifoctl:0x10101
[DSP] wfifosts:0x40
[DSP] rfifosts:0x0
[DSP] fifo value:0x0
[DSP] fifo value:0x0
[DSP] fifo value:0x0
[DSP] gblctlx:0x1f1d
[DSP] gblctlr:0x1f1d
[DSP] txstat:0x40
[DSP] rxstat:0x40
[DSP] txbuf:0x0
[DSP] rxbuf:0x0
[DSP] xrsrctl:0x1
[DSP] rstat:0x40, xstat:0x40
EDMA initialization application parameters set normally, but can''t transfer data correctlly, can anyone give me some advice for EDMA driver?
This is my EDMA3 parameter application
/*
* edma_ping_pong.c
*
* EDMA3 ping-pong buffers based McASP initialise driver, using two DMA channel
* (tx channel and rx channel) and four link channel(two tx link channel and
* two rx link channel).
*
*/
#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/family/c64p/EventCombiner.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/System.h>
#include <string.h>
#include <stdlib.h>
#include <ti/sdo/edma3/drv/edma3_drv.h>
#include "ys_edma3.h"
#define EDMA3_DRV_DEBUG
/* To enable/disable the cache .*/
#define EDMA3_ENABLE_DCACHE (1u)
/* OPT Field specific defines */
#define OPT_SYNCDIM_SHIFT (0x00000002u)
#define OPT_TCC_MASK (0x0003F000u)
#define OPT_TCC_SHIFT (0x0000000Cu)
#define OPT_ITCINTEN_SHIFT (0x00000015u)
#define OPT_TCINTEN_SHIFT (0x00000014u)
/**
* Cache line size on the underlying SoC. It needs to be modified
* for different cache line sizes, if the Cache is Enabled.
*/
#define EDMA3_CACHE_LINE_SIZE_IN_BYTES (128u)
/* Error returned in case of buffers are not aligned on the cache boundary */
#define EDMA3_NON_ALIGNED_BUFFERS_ERROR (-1)
/* Error returned in case of data mismatch */
#define EDMA3_DATA_MISMATCH_ERROR (-2)
/* */
#define PING_PONG_BUFF_SIZES 32 * 8 * 10 * 2
/**
* Shadow Region on which the executable is runnig. Its value is populated
* with the DSP Instance Number here in this case.
*/
unsigned int region_id;
/* External Global Configuration Structure */
extern EDMA3_DRV_GblConfigParams edma3GobalParams[];
/* External Instance Specific Configuration Structure */
extern EDMA3_DRV_InstanceInitConfig InstInitConfig[][EDMA3_MAX_REGIONS];
/** Number of EDMA3 controllers present in the system */
extern const unsigned int numEdma3Instances;
/** EDMA3 Driver Instance specific Semaphore handle */
extern EDMA3_OS_Sem_Handle semHandle[];
/** To Register the ISRs with the underlying OS, if required. */
extern void registerEdma3Interrupts(unsigned int edma3Id);
/** To Unregister the ISRs with the underlying OS, if previously registered.*/
extern void unregisterEdma3Interrupts(unsigned int edma3Id);
extern void call_back(unsigned int tcc, EDMA3_RM_TccStatus status, void *pid);
/* Edma global parameter pointer */
struct dma_params *edma_params[3] = {NULL};
/* Ping pong source buffer */
#ifdef EDMA3_ENABLE_DCACHE
/* Cache line aligned big source buffer. */
/**
* The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
* alignment boundary is the maximum of the symbols default alignment value
* or the value of the constant in bytes. The constant must be a power of 2.
* The syntax of the pragma in C is:
* #pragma DATA_ALIGN (symbol, constant);
*/
#pragma DATA_ALIGN(_tx_buf, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
#endif /* #ifdef EDMA3_ENABLE_DCACHE */
#pragma DATA_SECTION(_tx_buf, ".data_l2");
signed char _tx_buf[PING_PONG_BUFF_SIZES];
/* Ping pong destination buffer */
#ifdef EDMA3_ENABLE_DCACHE
/* Cache line aligned big source buffer. */
/**
* The DATA_ALIGN pragma aligns the symbol to an alignment boundary. The
* alignment boundary is the maximum of the symbols default alignment value
* or the value of the constant in bytes. The constant must be a power of 2.
* The syntax of the pragma in C is:
* #pragma DATA_ALIGN (symbol, constant);
*/
#pragma DATA_ALIGN(_rx_buf, EDMA3_CACHE_LINE_SIZE_IN_BYTES);
#endif /* #ifdef EDMA3_ENABLE_DCACHE */
#pragma DATA_SECTION(_rx_buf, ".data_l2");
signed char _rx_buf[PING_PONG_BUFF_SIZES];
/* Xmt and Rcv buffer point */
signed char *tx_buf;
signed char *rx_buf;
signed char* getGlobalAddr(signed char* addr)
{
return (addr); /* The address is already a global address */
}
/* */
#define GLOBAL_ADDR(addr) (getGlobalAddr(addr))
/* Callback function */
void call_back(unsigned int tcc, EDMA3_RM_TccStatus status, void *pid)
{
(void)tcc;
// (void)appData;
unsigned int i;
unsigned int id = *(unsigned int *)pid;
#if 0
Log_print1(Diags_USER1, "rx channel status:%d", status);
Log_print1(Diags_USER1, "rx event number:0x%x", *(unsigned int *)0x49001000);
Log_print1(Diags_USER1, "rx event missed number:0x%x", *(unsigned int *)0x49000300);
if (edma_params[id]->rece_params->chan_status == 0u)
Log_print0(Diags_USER1, "Received data ping completed!");
else
Log_print0(Diags_USER1, "Received data pong completed!");
edma_params[id]->rece_params->chan_status =
(edma_params[id]->rece_params->chan_status + 1) & 0x1;
char buf[128] = {0};
for (i = 0; i < 32; i++) {
sprintf(buf + i * 3, "%02x ", rx_buf[i]);
}
//Log_print1(Diags_USER1, "rx_buf data:%s", (IArg)buf);
#endif
for (i = 0; i < 10; i++) {
Log_print2(Diags_USER1, "rx data:0x%02x fifo value:0x%02x",
rx_buf[i], *(unsigned int *)(0x46400000 + i * 8));
}
/*
if (edma_params[id]->rece_params->chan_status == 0u)
memcpy(smem->chan_dsp[id]->rx,
(void *)edma_params[id]->rece_params->dst_address,
PING_SIZES);
else
memcpy(smem->chan_dsp[id]->rx,
(void *)(edma_params[id]->rece_params->dst_address\
+ PING_SIZES), PING_SIZES);
edma_params[id]->rece_params->chan_status =
(edma_params[id]->rece_params->chan_status + 1) & 0x1;
ys_notify_tdm_irq(id);
*/
/*
Log_print1(Diags_USER1, "tx channel 0x%x", *(unsigned int *)0x49007c14);
Log_print1(Diags_USER1, "rx channel 0x%x", *(unsigned int *)0x49007c74);
*/
}
/* Callback function */
void callback1(unsigned int tcc, EDMA3_RM_TccStatus status, void *pid)
{
(void)tcc;
// (void)appData;
unsigned int i;
// unsigned int id = *(unsigned int *)pid;
#if 0
//Log_print1(Diags_USER1, "tx channel status:%d", status);
//Log_print1(Diags_USER1, "tx event number:0x%x", *(unsigned int *)0x49001000);
//Log_print1(Diags_USER1, "tx event missed number:0x%x", *(unsigned int *)0x49000300);
if (edma_params[id]->sent_params->chan_status == 0u)
Log_print0(Diags_USER1, "Transmit data ping completed!");
else
Log_print0(Diags_USER1, "Transmit data pong completed!");
edma_params[id]->sent_params->chan_status =
(edma_params[id]->sent_params->chan_status + 1) & 0x1;
for (i = 0; i < 10; i++) {
Log_print2(Diags_USER1, "tx data:0x%02x fifo value:0x%02x",
tx_buf[i], *(unsigned int *)(0x46400000 + i * 8));
}
#endif
}
EDMA3_DRV_Handle edma3init(unsigned int edma3Id, EDMA3_DRV_Result *errorCode)
{
EDMA3_DRV_Result edma3Result = EDMA3_DRV_E_INVALID_PARAM;
Semaphore_Params semParams;
EDMA3_DRV_GblConfigParams *globalConfig = NULL;
EDMA3_DRV_InitConfig initCfg;
EDMA3_RM_MiscParam miscParam;
EDMA3_DRV_Handle hEdma = NULL;
if ((edma3Id >= numEdma3Instances) || (errorCode == NULL))
return hEdma;
globalConfig = &edma3GobalParams[edma3Id];
/*
* Only the Master is allowed to program the global EDMA3
* registers (like Queue priority, Queue water-mark level,
* error registers etc).
*/
miscParam.isSlave = FALSE;
edma3Result = EDMA3_DRV_create(edma3Id, globalConfig, (void *)&miscParam);
if (edma3Result == EDMA3_DRV_SOK) {
/**
* Driver Object created successfully.
* Create a semaphore now for driver instance.
*/
Semaphore_Params_init(&semParams);
initCfg.drvSemHandle = NULL;
edma3Result = edma3OsSemCreate(1, &semParams, &initCfg.drvSemHandle);
}
if (edma3Result == EDMA3_DRV_SOK) {
/* Save the semaphore handle for future use */
semHandle[edma3Id] = initCfg.drvSemHandle;
/* Driver instance specific config NULL */
initCfg.drvInstInitConfig = NULL;
#ifndef EDMA3_DRV_USE_DEF_RM_CFG
/* Hook for running examples with default RM config */
/* configuration structure for the Driver */
initCfg.drvInstInitConfig = &InstInitConfig[edma3Id][1];
#endif
/*
* Only the shadow region associated with this master
* instance will receive the EDMA3 interrupts (if enabled).
*/
initCfg.isMaster = TRUE;
/* Choose shadow region according to the DSP# */
initCfg.regionId = (EDMA3_RM_RegionId)1u;
/* Saving the regionId for using it in the config file */
region_id = initCfg.regionId;
/* Driver instance specific config NULL */
initCfg.gblerrCb = NULL;
initCfg.gblerrData = NULL;
/* Open the Driver Instance */
hEdma = EDMA3_DRV_open(edma3Id, (void *) &initCfg, &edma3Result);
}
if (hEdma && (edma3Result == EDMA3_DRV_SOK)) {
/**
* Register Interrupt Handlers for various interrupts
* like transfer completion interrupt, CC error
* interrupt, TC error interrupts etc, if required.
*/
registerEdma3Interrupts(edma3Id);
}
*errorCode = edma3Result;
return hEdma;
}
EDMA3_DRV_Result edma3deinit(unsigned int edma3Id, EDMA3_DRV_Handle hEdma)
{
EDMA3_DRV_Result edma3Result = EDMA3_DRV_E_INVALID_PARAM;
/* Unregister Interrupt Handlers first */
unregisterEdma3Interrupts(edma3Id);
/* Delete the semaphore */
edma3Result = edma3OsSemDelete(semHandle[edma3Id]);
if (EDMA3_DRV_SOK == edma3Result) {
/* Make the semaphore handle as NULL. */
semHandle[edma3Id] = NULL;
/* Now, close the EDMA3 Driver Instance */
edma3Result = EDMA3_DRV_close(hEdma, NULL);
}
if (EDMA3_DRV_SOK == edma3Result) {
/* Now, delete the EDMA3 Driver Object */
edma3Result = EDMA3_DRV_delete(edma3Id, NULL);
}
return edma3Result;
}
int edma3_drv_init(int id, unsigned int buffer_size, unsigned int fifo_address)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_SOK;
unsigned int link_channel = EDMA3_DRV_LINK_CHANNEL;
tx_buf = (signed char *)GLOBAL_ADDR(_tx_buf);
rx_buf = (signed char *)GLOBAL_ADDR(_rx_buf);
Log_print2(Diags_USER1, "tx_buf global addr:0x%p addr:0x%p", (IArg)tx_buf, (IArg)_tx_buf);
Log_print2(Diags_USER1, "rx_buf global addr:0x%p addr:0x%p", (IArg)rx_buf, (IArg)_rx_buf);
/* Allocate edma parameters global structure */
edma_params[id] =(struct dma_params *)malloc(sizeof(struct dma_params));
if (edma_params[id] == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "Allocate edma global params failed!");
#endif
return -1;
}
/* EDMA handle requestting here */
edma_params[id]->edma_handle = edma3init(0, &edmaResult);
if (edma_params[id]->edma_handle == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print1(Diags_USER1, "Handle request failed, error code:%d",
edmaResult);
#endif
return -1;
}
edma_params[id]->sent_params =
(struct chan_params *)malloc(sizeof(struct chan_params));
if (edma_params[id]->sent_params == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "Allocate sent parameter failed!");
#endif
return -1;
}
edma_params[id]->sent_params->chan_status = 0;
edma_params[id]->sent_params->mcasp_ident = id;
edma_params[id]->sent_params->dma_channel = 8 + id * 2;
//edma_params[id]->rece_params->dma_channel = EDMA3_DRV_HW_CHANNEL_EVENT_10;
edma_params[id]->sent_params->lnk_chan[0] = link_channel;
edma_params[id]->sent_params->lnk_chan[1] = link_channel;
/* ping pong buffer size, ping size is one half buffer size */
edma_params[id]->sent_params->ping_size = buffer_size >> 1;
edma_params[id]->sent_params->dst_address = fifo_address;
edma_params[id]->sent_params->src_address = (unsigned int)tx_buf;
//(unsigned int)malloc(buffer_size);
if (edma_params[id]->sent_params->src_address == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "Allocate sent source buffer failed!");
#endif
return -1;
}
//memset((unsigned int *)edma_params[id]->sent_params->src_address, 0xa, buffer_size);
edma_params[id]->rece_params =
(struct chan_params *)malloc(sizeof(struct chan_params));
if (edma_params[id]->rece_params == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "Allocate receive parameter failed!");
#endif
return -1;
}
edma_params[id]->rece_params->chan_status = 0;
edma_params[id]->rece_params->mcasp_ident = id;
edma_params[id]->rece_params->dma_channel = 9 + id * 2;
//edma_params[id]->rece_params->dma_channel = EDMA3_DRV_HW_CHANNEL_EVENT_11;
edma_params[id]->rece_params->lnk_chan[0] = link_channel;
edma_params[id]->rece_params->lnk_chan[1] = link_channel;
/* ping pong buffer size, ping size is one half buffer size */
edma_params[id]->rece_params->ping_size = buffer_size >> 1;
edma_params[id]->rece_params->src_address = fifo_address;
edma_params[id]->rece_params->dst_address = (unsigned int)rx_buf;
//(unsigned int)malloc(buffer_size);
if (edma_params[id]->rece_params->dst_address == NULL) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "Allocate rece source buffer failed!");
#endif
return -1;
}
memset(tx_buf, 0xa, buffer_size);
memset(rx_buf, 0xab, buffer_size);
return 0;
}
int edma3_drv_start(unsigned int id, unsigned char *received_data)
{
EDMA3_DRV_Result result = EDMA3_DRV_SOK;
unsigned int tcc_tx = EDMA3_DRV_HW_CHANNEL_EVENT_10;
unsigned int tcc_rx = EDMA3_DRV_HW_CHANNEL_EVENT_11;
EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};
#ifdef EDMA3_ENABLE_DCACHE
/*
* Note: These functions are required if the buffer is in DDR.
* For other cases, where buffer is NOT in DDR, user
* may or may not require the below functions.
*/
/* Flush the Source Buffer */
if (result == EDMA3_DRV_SOK) {
result = Edma3_CacheFlush((unsigned int)tx_buf, PING_PONG_BUFF_SIZES);
}
/* Invalidate the Destination Buffers */
if (result == EDMA3_DRV_SOK) {
result = Edma3_CacheInvalidate((unsigned int)rx_buf, PING_PONG_BUFF_SIZES);
}
#endif /* EDMA3_ENABLE_DCACHE */
/* Allocate Master channel and Link channels for sentting */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->sent_params->dma_channel,
&tcc_tx, (EDMA3_RM_EventQueue)0,
//&callback1, (void *)&edma_params[id]->rece_params->mcasp_ident);
NULL, NULL);
}
/* If successful, allocate the two link channels. */
if (result == EDMA3_DRV_SOK) {
result = (
(EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->sent_params->lnk_chan[0],
NULL, (EDMA3_RM_EventQueue)0,
//&callback1, (void *)&edma_params[id]->rece_params->mcasp_ident))
NULL, NULL))
||
(EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->sent_params->lnk_chan[1],
NULL, (EDMA3_RM_EventQueue)0,
//&callback1, (void *)&edma_params[id]->rece_params->mcasp_ident))
NULL, NULL))
);
}
Log_print1(Diags_USER1, "request channel:%d", result);
/* Allocate Master channel and Link channels for receiving */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->rece_params->dma_channel,
&tcc_rx, (EDMA3_RM_EventQueue)1, &call_back,
(void *)&edma_params[id]->rece_params->mcasp_ident);
}
/* If successful, allocate the two link channels. */
if (result == EDMA3_DRV_SOK) {
result = (
(EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->rece_params->lnk_chan[0], NULL,
(EDMA3_RM_EventQueue)1, &call_back,
(void *)&edma_params[id]->rece_params->mcasp_ident))
||
(EDMA3_DRV_requestChannel(edma_params[id]->edma_handle,
&edma_params[id]->rece_params->lnk_chan[1], NULL,
(EDMA3_RM_EventQueue)1, &call_back,
(void *)&edma_params[id]->rece_params->mcasp_ident))
);
}
Log_print1(Diags_USER1, "request channel:%d", result);
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->dma_channel,
¶mSet);
/* Program the source and dest addrs for sentting ping PaRAM */
paramSet.srcAddr = edma_params[id]->sent_params->src_address;
paramSet.destAddr = edma_params[id]->sent_params->dst_address;
paramSet.destBIdx = 0;
paramSet.destCIdx = 0;
paramSet.srcBIdx = 1;
paramSet.srcCIdx = 1;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->sent_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Program the TCC */
paramSet.opt |= ((tcc_tx << OPT_TCC_SHIFT) & OPT_TCC_MASK);
}
/* Set parameter RAM for transmitting master channel */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->dma_channel,
¶mSet);
}
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[0],
¶mSet);
/* Program the source and dest addrs for sentting ping PaRAM */
paramSet.srcAddr = edma_params[id]->sent_params->src_address;
paramSet.destAddr = edma_params[id]->sent_params->dst_address;
paramSet.destBIdx = 0;
paramSet.destCIdx = 0;
paramSet.srcBIdx = 1;
paramSet.srcCIdx = 1;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->sent_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Enable final transfer completion interrupt */
paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
}
/* Set parameter RAM for transmitting link channel0 */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[0],
¶mSet);
}
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[1],
¶mSet);
/* Program the source and dest addrs for sentting ping PaRAM */
/* Change source address for sentting pong PaRAM */
paramSet.srcAddr = edma_params[id]->sent_params->src_address + \
edma_params[id]->sent_params->ping_size;
paramSet.destAddr = edma_params[id]->sent_params->dst_address;
paramSet.destBIdx = 0;
paramSet.destCIdx = 0;
paramSet.srcBIdx = 1;
paramSet.srcCIdx = 1;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->sent_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Enable final transfer completion interrupt */
paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
}
/* Set parameter RAM for transmitting link channel1 */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[1],
¶mSet);
}
/**
* Master sentting DMA channel is linked to Link channel 1. Link
* channel 1 is linked to Link channel 0. Link channel 0 is again
* linked to Link channel 1.
*/
if (result == EDMA3_DRV_SOK) {
result = ((EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->dma_channel,
edma_params[id]->sent_params->lnk_chan[1]))
||(EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[1],
edma_params[id]->sent_params->lnk_chan[0]))
||(EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[0],
edma_params[id]->sent_params->lnk_chan[1]))
);
}
/**
* Fill the PaRAM Sets associated with all these receiving channels
* with transfer specific information.
*/
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->dma_channel,
¶mSet);
/* Program the source and dest addrs for receiving ping PaRAM */
paramSet.srcAddr = edma_params[id]->rece_params->src_address;
paramSet.destAddr = edma_params[id]->rece_params->dst_address;
paramSet.destBIdx = 1;
paramSet.destCIdx = 1;
paramSet.srcBIdx = 0;
paramSet.srcCIdx = 0;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->rece_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Program the TCC */
paramSet.opt |= ((tcc_rx << OPT_TCC_SHIFT) & OPT_TCC_MASK);
}
/* Set parameter RAM for receiving master channel */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->dma_channel,
¶mSet);
}
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[0],
¶mSet);
/* Program the source and dest addrs for receiving ping PaRAM */
paramSet.srcAddr = edma_params[id]->rece_params->src_address;
paramSet.destAddr = edma_params[id]->rece_params->dst_address;
paramSet.destBIdx = 1;
paramSet.destCIdx = 1;
paramSet.srcBIdx = 0;
paramSet.srcCIdx = 0;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->rece_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Enable final transfer completion interrupt */
paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
/* Program the TCC */
paramSet.opt |= ((tcc_rx << OPT_TCC_SHIFT) & OPT_TCC_MASK);
}
/* Set parameter RAM for receiving link channel0 */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[0],
¶mSet);
}
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_getPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[1],
¶mSet);
/* Program the source and dest addrs for receiving ping PaRAM */
paramSet.srcAddr = edma_params[id]->rece_params->src_address;
paramSet.destAddr = edma_params[id]->rece_params->dst_address + \
edma_params[id]->rece_params->ping_size;
paramSet.destBIdx = 1;
paramSet.destCIdx = 1;
paramSet.srcBIdx = 0;
paramSet.srcCIdx = 0;
paramSet.aCnt = 1;
paramSet.bCnt = 1;
paramSet.cCnt = edma_params[id]->rece_params->ping_size;
paramSet.bCntReload = 0;
/* Set link address NULL */
paramSet.linkAddr = 0xFFFFu;
/* Src & Dest are in INCR modes */
paramSet.opt &= 0xFFFFFFCu;
/* AB sync transfer mode */
paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
/* Enable final transfer completion interrupt */
paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
/* Program the TCC */
paramSet.opt |= ((tcc_rx << OPT_TCC_SHIFT) & OPT_TCC_MASK);
}
/* Set parameter RAM for receiving link channel1 */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[1],
¶mSet);
}
/**
* Master receiving DMA channel is linked to Link channel 1. Link
* channel 1 is linked to Link channel 0. Link channel 0 is again
* linked to Link channel 1.
*/
if (result == EDMA3_DRV_SOK) {
result = ((EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->dma_channel,
edma_params[id]->rece_params->lnk_chan[1]))
||(EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[1],
edma_params[id]->rece_params->lnk_chan[0]))
||(EDMA3_DRV_linkChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[0],
edma_params[id]->rece_params->lnk_chan[1]))
);
}
/* Start receive dma channel transfer */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_enableTransfer(edma_params[id]->edma_handle,
edma_params[id]->rece_params->dma_channel,
EDMA3_DRV_TRIG_MODE_EVENT);
}
Log_print1(Diags_USER1, "before transmit enable:%d", result);
/* Start sent dma channel transfer */
if (result == EDMA3_DRV_SOK) {
result = EDMA3_DRV_enableTransfer(edma_params[id]->edma_handle,
edma_params[id]->sent_params->dma_channel,
EDMA3_DRV_TRIG_MODE_EVENT);
}
Log_print1(Diags_USER1, "after transmit enable:%d", result);
return (result == EDMA3_DRV_SOK)? 0 : -1;
}
int edma3_drv_final(unsigned int id)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_SOK;
/* Free the previously allocated sent channels and link channel */
edmaResult = ((EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->dma_channel))
||(EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[0]))
||(EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->sent_params->lnk_chan[1]))
);
if (edmaResult != EDMA3_DRV_SOK) {
#ifdef EDMA3_DRV_DEBUG
Log_print1(Diags_USER1, "Free dma channel failed, error code:"
"%d", edmaResult);
#endif
return (edmaResult == EDMA3_DRV_SOK)? 0:-1;
}
/* Free the previously allocated receive channels and link channel */
edmaResult = ((EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->dma_channel))
||(EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[0]))
||(EDMA3_DRV_freeChannel(edma_params[id]->edma_handle,
edma_params[id]->rece_params->lnk_chan[1]))
);
if (edmaResult != EDMA3_DRV_SOK) {
#ifdef EDMA3_DRV_DEBUG
Log_print1(Diags_USER1, "Free dma channel failed, error code:"
"%d", edmaResult);
#endif
return (edmaResult == EDMA3_DRV_SOK)? 0:-1;
}
/* De-init the EDMA handle */
if (edma_params[id]->edma_handle != NULL)
edmaResult = edma3deinit(0, edma_params[id]->edma_handle);
if (edmaResult != EDMA3_DRV_SOK) {
#ifdef EDMA3_DRV_DEBUG
Log_print0(Diags_USER1, "EDMA free requested handle failed!");
#endif
return (edmaResult == EDMA3_DRV_SOK)? 0:-1;
}
/* Free EDMA memory buffer that receiving and sentting data */
if (edma_params[id]->sent_params->src_address != NULL)
free((unsigned int *)edma_params[id]->sent_params->src_address);
if (edma_params[id]->rece_params->dst_address != NULL)
free((unsigned int *)edma_params[id]->rece_params->dst_address);
/* Free edma parameter structure */
if (edma_params[id]->sent_params != NULL)
free(edma_params[id]->sent_params);
if (edma_params[id]->rece_params != NULL)
free(edma_params[id]->rece_params);
if (edma_params[id] != NULL)
free(edma_params[id]);
return 0;
}