/* * 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 #include #include #include #include #include #include #include #include #include "ys_edma3.h" /* 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) /** * 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 edma3GblCfgParams[]; /* 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}; unsigned char tx_buf[32 * 8 * 10 * 2]; unsigned char rx_buf[32 * 8 * 10 * 2]; /* 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; 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 0 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); for (i = 0; i < 10; i++) { Log_print3(Diags_USER1, "tx data:0x%02x rx data:0x%02x fifo value:0x%02x", tx_buf[i], rx_buf[i], *(unsigned int *)(0x46400000 + i * 8)); } #endif /* 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; 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 0 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!"); for (i = 0; i < 10; i++) { Log_print3(Diags_USER1, "tx data:0x%02x rx data:0x%02x fifo value:0x%02x", tx_buf[i], rx_buf[i], *(unsigned int *)(0x46400000 + i * 8)); } edma_params[id]->sent_params->chan_status = (edma_params[id]->sent_params->chan_status + 1) & 0x1; #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 = &edma3GblCfgParams[edma3Id]; /* Configure it as master, if required */ miscParam.isSlave = TRUE; 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 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; /* 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_print1(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_print1(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]->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_print1(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->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_TCC_ANY; unsigned int tcc_rx = EDMA3_DRV_TCC_ANY; EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0}; /* Allocate Master channel and Link channels for sentting */ result = EDMA3_DRV_requestChannel(edma_params[id]->edma_handle, &edma_params[id]->sent_params->dma_channel, &tcc_tx, (EDMA3_RM_EventQueue)0, //NULL, NULL); &callback1, (void *)&edma_params[id]->rece_params->mcasp_ident); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Request sent dma channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* If successful, allocate the two link channels. */ result = ((EDMA3_DRV_requestChannel(edma_params[id]->edma_handle, &edma_params[id]->sent_params->lnk_chan[0], NULL, (EDMA3_RM_EventQueue)0, //NULL, NULL)) &callback1, (void *)&edma_params[id]->rece_params->mcasp_ident)) ||(EDMA3_DRV_requestChannel(edma_params[id]->edma_handle, &edma_params[id]->sent_params->lnk_chan[1], NULL, (EDMA3_RM_EventQueue)0, //NULL, NULL)) &callback1, (void *)&edma_params[id]->rece_params->mcasp_ident)) ); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Request sent link channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Allocate Master channel and Link channels for receiving */ result = EDMA3_DRV_requestChannel(edma_params[id]->edma_handle, &edma_params[id]->rece_params->dma_channel, &tcc_rx, (EDMA3_RM_EventQueue)0, &call_back, (void *)&edma_params[id]->rece_params->mcasp_ident); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Request receive dma channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* If successful, allocate the two link channels. */ result = ((EDMA3_DRV_requestChannel(edma_params[id]->edma_handle, &edma_params[id]->rece_params->lnk_chan[0], NULL, (EDMA3_RM_EventQueue)0, &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)0, &call_back, (void *)&edma_params[id]->rece_params->mcasp_ident)) ); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Request receive link channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Common parameter RAM setting */ 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); /* A sync transfer mode */ //paramSet.opt &= 0xFFFFFFDu; /** * Fill the PaRAM Sets associated with all these tx channels with * transfer specific information. */ paramSet.aCnt = 1; paramSet.bCnt = 1; paramSet.cCnt = edma_params[id]->sent_params->ping_size; paramSet.srcBIdx = 1; paramSet.destBIdx = 0; paramSet.srcCIdx = 1; paramSet.destCIdx = 0; /* Program the TCC */ paramSet.opt |= ((tcc_tx << OPT_TCC_SHIFT) & OPT_TCC_MASK); /* Program the source and dest addresses for sentting ping PaRAM */ paramSet.srcAddr = edma_params[id]->sent_params->src_address; paramSet.destAddr = edma_params[id]->sent_params->dst_address; /* Set parameter RAM for sentting master channel */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->sent_params->dma_channel, ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Transfer channel set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Enable final transfer completion interrupt */ paramSet.opt |= (1 << OPT_TCINTEN_SHIFT); /* Set parameter RAM for sentting link channel0 */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->sent_params->lnk_chan[0], ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Linking channel0 set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Change source address for sentting pong PaRAM */ paramSet.srcAddr = edma_params[id]->sent_params->src_address + \ edma_params[id]->sent_params->ping_size; /* Set parameter RAM for sentting link channel1 */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->sent_params->lnk_chan[1], ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Linking channel1 set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /** * 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. */ 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])) ); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Transfer channel linking failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /** * Fill the PaRAM Sets associated with all these receiving channels * with transfer specific information. */ paramSet.aCnt = 1; paramSet.bCnt = 1; paramSet.cCnt = edma_params[id]->rece_params->ping_size; paramSet.srcBIdx = 0; paramSet.destBIdx = 1; paramSet.srcCIdx = 0; paramSet.destCIdx = 1; /* Program the TCC */ paramSet.opt |= ((tcc_rx << OPT_TCC_SHIFT) & OPT_TCC_MASK); /* Program the source and dest addresses for receiving ping PaRAM */ paramSet.srcAddr = edma_params[id]->rece_params->src_address; paramSet.destAddr = edma_params[id]->rece_params->dst_address; /* Set parameter RAM for receiving master channel */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->rece_params->dma_channel, ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Transfer channel set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Enable final transfer completion interrupt */ paramSet.opt |= (1 << OPT_TCINTEN_SHIFT); /* Set parameter RAM for receiving link channel0 */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->rece_params->lnk_chan[0], ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Linking channel0 set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Change dest address for receiving pong PaRAM */ paramSet.destAddr = edma_params[id]->rece_params->dst_address + \ edma_params[id]->rece_params->ping_size; /* Set parameter RAM for receiving link channel1 */ result = EDMA3_DRV_setPaRAM(edma_params[id]->edma_handle, edma_params[id]->rece_params->lnk_chan[1], ¶mSet); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Linking channel1 set PaRAM failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /** * 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. */ 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])) ); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "Transfer channel linking failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Start receive dma channel transfer */ result = EDMA3_DRV_enableTransfer(edma_params[id]->edma_handle, edma_params[id]->rece_params->dma_channel, EDMA3_DRV_TRIG_MODE_EVENT); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "enabletransfer rx channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } /* Start sent dma channel transfer */ result = EDMA3_DRV_enableTransfer(edma_params[id]->edma_handle, edma_params[id]->sent_params->dma_channel, EDMA3_DRV_TRIG_MODE_EVENT); if (result != EDMA3_DRV_SOK) { Log_print0(Diags_USER1, "enabletransfer tx channel failed!"); return (result == EDMA3_DRV_SOK)? 0 : -1; } return 0; } 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; }