This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C6424, data lost when using EDMA and AIC 33 Codec

Other Parts Discussed in Thread: TMS320C6424

Hello everyone, this is my first post on e2e forums so I hope it is not much of a bother.

I am using TMS320C6424 EVM and trying to receive a stream of messages in a wav file by using the AIC33 and a ping pong edma arrangement. There is a noticeable amount of dropped messages ( 1% - 6% ) when using the whole program.A summary of the relevent settings:

    AIC FS = 48 KHz, using FS/6 (8 KHz)
    EDMA reads from McBSP_DRR into a ping pong buffer while the processing code runs on the other buffer, semaphores prevent the processing code from accessing a non-full buffer
    EDMA is triggered by REVT1

In order to isolate the issue I tested the system from the EDMA onwards by using the following configuration:

    EDMA reads from a hard-coded array that contains the same wav file data and writes in the same ping pong buffers, EDMA is triggered manually in every ISR until the buffer is full. a-sync is used and both intermediate and final transfer complete inturrupts were enabled. The end of file is detected by a counter that counts how many ISR's were called, when the buffer is full, the edma stops until the processing on that buffer is finished at which time the processing code triggers the EDMA again.

this time all the packets were decoded successfully.

I then tried the other side and used a simple code to write in the McBSP DXR whatever it finds in the DRR and then recorded the received file in the computer; decoding this file also didn't result in any packets lost.

I suspected that there might be a timing issue between the EDMA and the McBSP so I went back to the edma code that reads from a hardcoded array and changed the edma triggering back to an event driven configuration as opposed to the manual triggering I used for the previous test. I created another channel that transfers the DRR to a dummy variable and its ISR triggers the transfer from the hard-coded array to the ping pong buffer. The amount of dropped packets decreased to less than 0.6 %. but the drop still exists.

I am now wondering where exactly does the packets loss occur? and how can I improve it

attached is the code for the edma for the intended usage (reading from DRR and writing into the buffer).

6087.edma.c
// ================================   EDMA.C    =====================================
//
// Authors: Scott Specker and Eric Wilbur (Technical Training Organization)
// Date: 02/16/09
// Rev: 1.4
// Target: DM6437 EVM
// BIOS ver: 5.31
// LLD version: edma3_lld_01_06_00_01
// Name: EDMA3 LLD Example7 (Audio Pass-through example with linking/sorting)
// 
// To download the latest LLD release, go to the following URL:
//   https://www-a.ti.com/downloads/sds_support/TargetContent/psp/edma3_lld/index.html
//
// Abstract: The purpose of this example is to provide users with a simple example of
//           using the Low Level Driver (LLD) libraries to program and execute transfers
//           using the EDMA3 peripheral. 
//
//           Also generates an EDMA interrupt that is sent to the CPU.
//
//           This example uses event triggering from the RCV and XMT buffers in
//           the McBSP. 
//
// NEW ***   This is a full audio pass through example using the LLD to process
//           the incoming audio data. The mcbsp init was stolen from a previous
//           4-day 6455 workshop example. We also needed the tasks.c file to
//           process the buffers (memcopy) and pend on RCV/XMT semaphores.
//
// API:	     In effect, we have created a small API in edma.c and edma.h that 
//		     encapsulates using the LLD functions. These edma_xxx functions allowed us
//           to simplify our example program (in main.c) and also let us partition the
//           LLD code in an easily digestable manner. 
//
//			 The following two functions initialize the EDMA3 and channel resources
//			 - edma_config(); 
//           - edma_createChan();
//
//			 The following three functions execute and verify completion of the transfer
//           - edma_start();
//           - edma_check();
//           - edma_wait();
//
//           The following two functions free up the channel and EDMA3 resources
//           - edma_deleteChan();
//           - edma_release();
//
//			 Our API creates a typedef (edma_object_t) in edma.h that allows the
//           calling program to define and use the following elements:
//           - hEdma: handle to the EDMA3 resources for this API
//           - iChannel: channel Id number (0-63 or EDMA3_DRV_CHANNEL_ANY)
//           - iTcc: transfer completion code (0-63 or EDMA3_DRV_TCC_ANY)
//
//           This example acts very much like a memcpy() - if this is all the
//	         functionality you need, you may be better served by using TI's ACPY
//           library.
//
//           This example is a starting point which we will add more capability to
//           such as generating an EDMA3 interrupt to the CPU and syncing
//           transfers to events from a peripheral (e.g. McBSP).	
//
// Usage:    The following libraries are required in your project:
//			 - edma3_drv_bios.lib 
//		     - edma3_drv_bios_sample.lib
//           - edma3_rm_bios.lib
//
//			 These libraries are located in the following directories respectively:
//           - [lld_root]\packages\ti\sdo\edma3\drv\lib\Debug (can also use \Release)
//           - [lld_root]\packages\ti\sdo\edma3\drv\sample\lib\c6455\Debug (platform-specific .lib)
//			 - [lld_root]\packages\ti\sdo\edma3\rm\lib\c6455\Debug (platform-specific)
//			 where [lld_root] is the installation location of the LLD driver.
//
//			 The following header files must be included with your edma code for these 
//           libraries to work properly:
//			 - <edma3_drv.h>:  LLD Driver header file 
//           - <bios_edma3_drv_sample.h>:  OS-specific and device-specific header file
//			 All other header files used are already included in the above header files. 
//           (Note, you will find them #included below these comments in this file; if you are 
//            using our framework - i.e. this file - then we've already done this work for you.)
//
//			 For the header files, you will need to specify the include search paths (-i).
//           You can accomplish this by using CCS (Project->Build Options->Compiler->Preprocessor:
//           Add the following paths:
//           - [lld_root]\packages\ti\sdo\edma3\rm
//           - [lld_root]\packages\ti\sdo\edma3\drv
//           - [lld_root]C:\edma3_lld_1_05_00\packages\ti\sdo\edma3\drv\sample
//           - [lld_root]\packages   (this path is required since some of the #includes 
//                                    found in edma3_drv.h are referenced from "packages")
//
//			 LLD is OS-agnostic and supports the following operating systems:
//			 - DSP/BIOS
//           - PROS
//           This is a BIOS project, hence the use of "bios" in the library names above. As you
//           can see, the second two libraries are platform-specific (i.e. C6455). The first
//           library (edma3_drv_bios.lib) encapsulates the "RM" (resource management) layer
//           underneath.
//
//           The user must provide a semaphore to the LLD to allow it to manage resources.
//           While the LLD provides a function to create this semaphore, we thought it was
//           easier to create it statically in the .tcf file (OsSem) and pass it to the LLD.
//           The LLD library requires a counting semaphore with an initial count of 1.
//           (Note: because semaphores are OS-specific, the OsSemCreate function must be
//            tuned for your OS - thus we thought it was easier to do directly in BIOS).
//
//
// Int Gen:  There are several steps required to get interrupts to work properly:
//
// For CPU:  1. Turn on the proper CPU IER bit (done in main.c, CPU-specific)
//			 2. Turn on global interrupts (GIE) - already done for us by DSP/BIOS when
//              we return from main() in main.c.
//           3. Create an HWI (we used HWI_INT5) in the .tcf file. You need to point this
//              HWI (i.e. the function to run) to the EDMA interrupt dispatcher which is
//              _lisrEdma3ComplHandler0. This handler checks all of the IPR bits and if it
//              finds one that is set, it calls the corresponding callback function you
//              sent via the _requestChannel API (see tccCb = &edma_isr). This handler 
//              also clears the specific IPR bit that was set. AND don't forget to set the
//              interrupt selection number corresponding to the interrupt you are tying to
//              respong to. In our case, we are using the Region 1 interrupt from the EDMA
//              which just so happens to be selection number 72. You can find a table of
//              these in the datasheet (SPRS276, Section 7.5, about page 119).
//           4. Create an ISR (such as edma_isr located at the bottom of this file). We
//              simply put a LOG_printf() there for debug purposes.
// For EDMA: 5. The EDMA IER bit is set during the _requestChannel API call. So, the user
//              does NOT need to write to the IESR manually to set the corrersponding 
//              IER bit for the TCC. 
//           6. In the Options register, TCINTEN must be enabled (however it already was
//              enabled in our previous example - so no changes were made here).
//           7. Register a callack function (edma_isr) to be used by _requestChannel(). This
//              function will be placed in a table used by the EDMA3 Completion Handler 0.
//              See tccCb = &edma_isr in the edma_createChan() function.
//           8. In edmaTsk (in main.c), with the 2 second timer interrupt, we were deleting
//              the channel resources before the EDMA completed its job. So, when the EDMA
//              finished the transfer, the EDMA ISR wasn't configured any longer. So, we added
//              a DSP/BIOS semaphore (SEM) to edmaTsk (in main.c) to PEND (i.e. wait) until
//              the EDMA had fully completed its job. A SEM_post was added to our ISR to tell
//              edmaTsk that the transfer was finished. This signaling between the ISR and
//              edmaTsk fixed the problem.    
//
//
// Evt Sync: To get event synchronization to work, we added the following to this example:
//           1. In the .tcf file - Clock Manager, we set the period to 2 seconds on Timer 0.
//              When Timer 0 reaches zero, it will send an event trigger to the EDMA and set
//              the corresponding ER (Event Register) bit.
//           2. We can still use EDMA3_TCC_ANY (see main.c), but we changed the channel
//              enumeration to channel 1 (see main.c). Reference the EDMA User Guide 
//              (SPRU966, about page 43) to see the list of events tied to various channels.
//              Timer 0 LO event is tied to channel 1. 
//           3. In the edma_start() function, notice the change to _enableTransfer
//              paramaters. We changed EDMA3_DRV_TRIG_MODE_MANUAL to
//              EDMA3_DRV_TRIG_MODE_EVENT. This will set the EER bit corresponding to the 
//              chosen channel (in our case, it is channel 1 which is passed via the EdmaObj
//              from main to edma_start()).
//
// A-sync:   1. In edma_creatChan(), the call to _setTransferParams uses A-sync vs. AB-sync
// 
// Intermediate
// Interrupts:   2. A new _setOptField was added to turn on intermediate interrupts. This
//                  will provide 14 intermediate interrupts and plus the two final interrupts
//                  enabled by TCINTEN (which we had before). The log of this activity will
//                  be logged in the LOG_printf() in edma_isr() which counts the number
//                  of times the interrupt occurred.
//
// Link:     We needed to do the following to request another PaRAM set (PSET) and link iChannel
//           (our active channel) to the reload (link) channel iReload:
//
//           1. Do another _requestChannel for iReload PSET
//           2. Copy the PaRAM set values from iChannel to iReload
//           3. Modify the Src/Dst addresses for iReload (to point to our second set of buffers)
//           4. Link iChannel to iReload using _linkChannel()
//
// Note:     The LLD Driver allocates physical PaRAM sets (PSETs) in numerical order starting
//           at PSET 0 and counting up. So, iChannel is PHYSICALLY using PSET 0 and iReload
//           is using PHYSICAL PSET 1. This can be a nightmare to debug if you don't this
//           important information. In the future, when we have two active channels (RCV and
//           XMT) and 4 reload PSETs, the LLD Driver will allocate these to the first 6
//           PSETs (0-5). That is why we used the _getPaRAM API so that we could look at 
//           both the iChannel and iReload PaRAM sets - abstracting us from the actual
//           physical PSETs used by the driver.
//
// Channel
// Sorting: The following changes were made to get channel sorting to work:
//          1. ACNT remains the same (2)
//          2. BCNT is now 2 instead of BUFFSIZE.
//          3. SRC BIDX is still 2 bytes
//          4. SRC CIDX is 2 bytes.
//          5. CCNT is now 8 instead of 1. This will move 8 values for the first transfer
//             and then 8 more after linking occurs.
//          6. BCNTRLD must now be modified because CCNT > 1. BCNTRLD = 2.
//          7. DST BIDX must be set to BUFFSIZE*2 bytes so after the first value is
//             transferred to SrcBufEven, it can index to the first value in DstBufOdd.
//          8. DST CIDX will allow us to move backwards from DstBufOdd to the next value
//             in DstBufEven - about 2-(BUFFSIZE-2) bytes.
//
//          These values were changed in both iChannel and therefore iReload as well.
//
//          Note: when you halt the processor and look at the values (View-Memory), type in
//                SrcBuf1 and use "Hex 16-bit TI Style" to view the values. It looks better
//                that way.
//
// ***************************     NEW TO THIS EXAMPLE7    ***********************************
//
// Audio:   Many items were added and modified to make this example work:
//          1. The sync event is now coming from the Rcv/Xmt McBSP vs. a timer event. In main.c
//             this is accomplished by choosing the proper channels (REVT1, XEVT1) which are
//             hardwired to the ER bits in the EDMA
//          2. For a sync'd ping/pong transfer, we need 6 PSETs. Two are our active channels
//             (one for RCV and one for XMT). The RCV side uses the McBSP DRR as the source
//             and gBufferRcv as the destination. The XMT side uses gBufferXmt as the source
//             and the McBSP DXR register as its destination. The other 4 PSETs are used for
//             linking ping and pong. The active channels are set as "ping" and are linked to
//             the pong reload PSETs. The pong reload PSET is linked back to ping. Hence,
//             we have two active channels and 4 reload PSETs.
//          3. Channel sorting is also occurring. The incoming data from the McBSP comes into
//             the DRR as LRLRLRLR samples. We channel sort these into left and right buffers
//             within the ping and pong buffers. This is accomplished on the incoming data
//             (into gBufferRcv) and outgoing data (from gBufferXmt) by setting the proper
//             index values as shown in the code below.
//          4. Because this system runs forever, we will never require the _deleteChan and
//             _release functions in this example application. 
//          5. You could possibly improve this system in a couple different ways:
//             a. By checking error conditions returned from the LLD functions and handling
//                them appropriately.
//             b. While outside the scope of this example, you could use other system control
//                inputs to signal an exit from audio processing, using the _deleteChan and
//                 _release functions to free up the EDMA resources.
//
// *************************** END OF NEW TO THIS EXAMPLE7 ***********************************

//
// Diagrams: This simple diagram may help provide some context to how the LLD driver (DRV)
//           and Resource Manager (RM) work together. The user's responsibility is to 
//           use the DRV APIs - the RM is accessed solely by DRV. Also notice that if you
//           are using ACPY3 & DMAN framework, it actually uses the LLD's Resource Manager.
//
//           	                        ------------------------
//           	     -------            | Framework Components |
//                   | APP |            |      DMAN, ACPY      |
//               	 -------            ------------------------
//                      |                          |
//                      |                          |
//            --------------------     -------------------------
//            | LLD Driver (DRV) | --> | Resource Manager (RM) |
//            --------------------     -------------------------
//                                                |
//                                                |
//                                       ------------------
//                                       | EDMA3 Hardware |
//                                       ------------------
//
//           PSP is the Platform Support Package (peripheral drivers) supplied by TI:
//           It includes the LLD libraries among other libraries
//
// Build    
// Warnings: When we built this project, we saw several warnings that edma3Result
//           was declared but never used. We did not write in the error-checking code
//           to check the results returned from some functions. You may add that code
//           if so desired. In Build Options -> Compiler -> Diagnostics, we figured out
//           which warning id number it was by using -pden, then suppressed that warning
//           id (552) using -pds552.
//
// ==================================================================================


// ==============================   INCLUDES    =====================================
#include "main.h" // contains BUFFSIZE, PSET_EDMA and externs for Src/Dst arrays
#include "edma.h" // includes prototypes for all edma functions
#include <edma3_drv.h> // LLD Driver header file 
#include <bios_edma3_drv_sample.h> // OS-specific and device-specific header file
//#include <src\edma3_rl_cc.h> //needed for the EDMA3_CCRL_RegsOvly global (for debug) 
#include <edma3_rl_cc.h> //needed for the EDMA3_CCRL_RegsOvly global (for debug) 

// ==============================  PROTOTYPES   =====================================
void edma_rcv_isr();
void edma_xmt_isr();

// ===============================   GLOBALS    =====================================

// used for EDMA3_DRV_create() API, edma3InstanceId also used in EDMA3_DRV_delete()
static unsigned int edma3InstanceId = 0; //only one hardware EDMA3 instance

// declare sample Params for 6455 - this list of parameters is DEVICE SPECIFIC
extern EDMA3_DRV_GblConfigParams sampleEdma3GblCfgParams;

// External Instance Specific Configuration Structure - resources owned by region 1 (PARAM sets, channels, TCCs, etc.) 
// DEVICE-SPECIFIC
extern EDMA3_DRV_InstanceInitConfig sampleInstInitConfig;

// Used for debug purposes and hence we kept it global. This pointer will point to the
// entire set of the CC Regs (like the EDMA's IPR and IER regs) so you can view them
// while debugging. Simply add CCRegsPtr to a watch window. We also use this pointer to
// write to the EDMA IER register via the EDMA IESR register in edma_createChan().
EDMA3_CCRL_RegsOvly CCRegsPtr; 


// ============================    EDMA CONFIG    ===================================
// 
// This function will:
// - create an instance (edma3InstanceId) for each EDMA3 hardware peripheral
// - provide a handle (hEdma) to the user instance of the EDMA mdoule
//
// DRV_create requires a globalConfig structure which contains the hardware resources
// available for this device (we used sampleEdma3GblCfgParams to accomplish this).
//
// DRV_open requires the initCfg structure to initialize the Driver Instance.
//
// Note: this function CLEARS all ER (Event Register) bits. So, if you are using
//       sync'd transfers, your sync event must occur AFTER this function is 
//       finished - otherwise, it may not work properly
// ===================================================================================

void edma_config(edma_object_t *EdmaObj)
{
// set initial value of edma3Result which can be used for error-checking (we opted NOT to put
// error-checking in this example, but users could improve this code by doing so).
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;

// set global config to defaults in sample Params (located in bios_edma3_drv_sample_C6455_cfg.c)
	EDMA3_DRV_GblConfigParams *globalConfig = &sampleEdma3GblCfgParams; 

// used in DRV_create() function to specify master/slave
	EDMA3_RM_MiscParam miscParam; 

// used for EDMA3_DRV_open() API and initCfg structure, defined in <edma3_drv.h>
	EDMA3_DRV_InitConfig initCfg;

// initial values for C6455 EDMA hardware - used to pass into the _open call via initCfg
// the values are actually located in bios_edma3_drv_sample_C6455_cfg.c
	EDMA3_DRV_InstanceInitConfig *instanceConfig = &sampleInstInitConfig; 


// Declare Config structure used to initialize the Driver Instance (needed by DRV_open)
	initCfg.isMaster    =    TRUE; 				 // we are a master, not a slave on this device
	initCfg.regionId = (EDMA3_RM_RegionId)1u;    // user must specify region (LLD/DRV does not support "global" region)
	initCfg.drvSemHandle = &OsSem;               // OsSem added statically in the .tcf file with an initial count of 1
	initCfg.drvInstInitConfig = instanceConfig;  // device-specific configuration - resources owned by region 1
	initCfg.gblerrCb = NULL;                     // callback function to catch channel controller errors such as TCC error, queue threshold exceeded, etc.
	initCfg.gblerrData = NULL;                   // any data required by the error callback function
	
// ARM + DSP, specify who is the master, single-chip C6455 = use FALSE
	miscParam.isSlave = FALSE; 

// EDMA3 Driver Create (called only once for each EDMA3 hardware instance)
	edma3Result = EDMA3_DRV_create(edma3InstanceId, globalConfig, (void *)&miscParam);

// Open user instance to EDMA Module (hEdma)
    EdmaObj->hEdma = EDMA3_DRV_open (edma3InstanceId, (void *) &initCfg, &edma3Result);

// The following is used for debug and programming purposes - to be able to access the CC Regs.
// To use, simply add CCRegsPtr to your watch window (to view the EDMA registers
// such as IPR, IER, etc.). This pointer is set to the TOP of the CC Registers - the
// location of this pointer (0x02A00000) is found in the Global Config Params for C6455.
// This pointer is also used in edma_createChan to set the EDMA's IER bit to enable 
// EDMA interrupts after the corresponding IPR bit (TCC) is set when the transfer completes.

	CCRegsPtr = sampleEdma3GblCfgParams.globalRegs;

}


// ============================    EDMA CREATE CHANNEL   ============================
// 
// This function will:
// - allocate all the necessary channel resources and assign them to a channel Id
// - initialize the allocated PARAM registers (like ACNT, BCNT, IDXs, etc.)
// - set the Options register to all default values (done by _requestChannel automatically)
// - EDMA IER register bit is enabled by _requestChannel for each channel used
// - allocates another channel for reload and links iChannel to iReload
// - sets the counts and indexes to the proper amounts to perform channel sorting.
// - this function is called TWICE (once for RCV and once for XMT). As is shown below,
//   we perform 6 _requestChannels - two for the active RCV/XMT channels and 4 others to 
//   allow us to link to Rcv (ping, pong) and Xmt (ping, pong).
// 
// The following are the default values that are used for the OPT register and LINK
// fields. If you desire to overide any of these defaults, copy this code and make the
// necessary modifications (as you can see we did below for the TCINTEN bit and ITCINTEN):
//
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_ITCCHEN, EDMA3_DRV_ITCCHEN_DIS);   //Intermediate Chaining DISABLED - default is DIS if not called
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_TCCHEN, EDMA3_DRV_TCCHEN_DIS);     //Chaining DISABLE - default is DIS if not called
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_ITCINTEN, EDMA3_DRV_ITCINTEN_DIS); //Intermediate interrupt enable DISABLED - default is DIS if not called
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_TCINTEN, EDMA3_DRV_TCINTEN_DIS);   //Interrupt enable DISABLED - default is DIS if not called
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_TCC, 0u);  //already set in EDMA3_DRV_requestChannel	 //TCC value - arbitrary
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_STATIC, EDMA3_DRV_STATIC_DIS);     //FIFO mode not used - so, we set it to zero - default is DIS if not called
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_SYNCDIM, EDMA3_DRV_SYNC_AB); 	    //Sync set to AB (we want an AB transfer after the manual start - not needed - already set to AB
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_SAM, EDMA3_DRV_ADDR_MODE_INCR); 		//Src Addr Mode = INCR - already set in EDMA3_DRV_setSrc/DstParams	//Address mode is INCR (not FIFO)
//	EDMA3_DRV_setOptField (hEdma,iChannel, EDMA3_DRV_OPT_FIELD_DAM, EDMA3_DRV_ADDR_MODE_INCR); 	    //Dst Addr Mode = INCR - already set in EDMA3_DRV_setSrc/DstParams
//
//  EDMA3_DRV_linkChannel (hEdma, iChannel, 0xFFFFu);	//Set link field to FFFF - no linking - this is the default if this API is not called
//
// ===================================================================================

void edma_createChan(edma_object_t *EdmaObj, int16_t *Src, int16_t *Dst)
{
// return value for some driver calls so they can return an error (we don't check for errors in this example)
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;  

// used for debug purposes in EDMA3_DRV_getPaRAM() - also can set one PSET equal to another (handy)
	EDMA3_DRV_PaRAMRegs channelParam; // ACTIVE logical channel
	EDMA3_DRV_PaRAMRegs pingParam; 	  // Ping Reload PSET (set to same values as initial channelParam)
	EDMA3_DRV_PaRAMRegs pongParam;    // Pong Reload PSET

// Queue (0-3) that you want your channel tied to (Q1 on C6455 is the only queue tied to McBSP
// (see SCR connnection matrix) - so if you choose any queue other than "1", this app will NOT work
	EDMA3_RM_EventQueue eventQ = 1;

	EDMA3_RM_TccCallback tccCbRcv = &edma_rcv_isr; // callback function from EDMA handler (see HWI_INT5 in .tcf file)
	EDMA3_RM_TccCallback tccCbXmt = &edma_xmt_isr; // callback function from EDMA handler (see HWI_INT5 in .tcf file)


// get channel for transfer - iChannel - for either Rcv or Xmt
	if (EdmaObj->iChannel == EDMA_HW_EVENT_REVT1)
	{

	// RECEIVE (input) channel

	// get iChannel for Rcv and set queue and EDMA dispatcher callback function
		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iChannel, &EdmaObj->iTcc, eventQ, tccCbRcv, NULL); 

	// set Src address for Rcv (i.e. DRR) and set SAM/DAM to INCR mode
		//EDMA3_DRV_setSrcParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (Src), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 
		EDMA3_DRV_setSrcParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (0x01D00800), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 

	// set Dst address for Rcv (i.e. gBufferRcv[0]) and set SAM/DAM to INCR mode
		EDMA3_DRV_setDestParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (Dst), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 

	// set Rcv channel indexes (SRC BIDX/CIDX are zero because DRR is a fixed location)
		EDMA3_DRV_setSrcIndex(EdmaObj->hEdma, EdmaObj->iChannel, 0, 0); 

	// set Dst channel indexes (DST BIDX increments by BUFFSIZE bytes, DST CIDX is set to bump the
	// address pointer back to sort L/R channels of audio // not valid, not channel sorting is used
		EDMA3_DRV_setDestIndex(EdmaObj->hEdma, EdmaObj->iChannel, 0, 2);
		// DST BIDX = 0 means no offset will occur after gettnig ACNT bytes from DRR of the McBSP
		//              that means, Both left and roght samples (2bytes each) will be written in the same
		//              location at the destination buffer
		// DST CIDX = 2 means after reading BCNT times, ACNT bytes each
		//              offset the dst by 2 from the last known address
		EDMA3_DRV_setTransferParams(EdmaObj->hEdma, EdmaObj->iChannel, 2, 2, BUFFSIZE, 2, EDMA3_DRV_SYNC_A);

	}
	else
	{

	// TRANSMIT (output) channel

	// get iChannel for Xmt and set queue and EDMA dispatcher callback function
		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iChannel, &EdmaObj->iTcc, eventQ, tccCbXmt, NULL); 

	// set Src address for Xmt (i.e. gBufferXmt[0]) and set SAM/DAM to INCR mode
		EDMA3_DRV_setSrcParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (Src), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 
	
	// set Dst address for Xmt (i.e. DXR) and set SAM/DAM to INCR mode
		//EDMA3_DRV_setDestParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (Dst), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 
		EDMA3_DRV_setDestParams (EdmaObj->hEdma, EdmaObj->iChannel, (unsigned int) (0x01D00804), EDMA3_DRV_ADDR_MODE_INCR, EDMA3_DRV_W8BIT); 

	// set Xmt channel Src indexes (SRC BIDX increments by BUFFSIZE bytes, SRC CIDX is set to bump the
	// address pointer back to sort L/R channels of audio) // this comment in no longer valid
		EDMA3_DRV_setSrcIndex(EdmaObj->hEdma, EdmaObj->iChannel, 0, 2); 
		// SRC BIDX = 0 means no offset will occur after sending ACNT bytes to DXR of the McBSP
		//              that means, the same sample (2bytes) will be send out again
		//              to the DXR but this time as a Left sample
		// SRC CIDX = 2 means after sending out BCNT times, ACNT bytes each
		//              offset the src by 2 from the last known address


	// set Xmt channel Dst indexes (DST BIDX/CIDX are zero because DXR is a fixed location)
		EDMA3_DRV_setDestIndex(EdmaObj->hEdma, EdmaObj->iChannel, 0, 0);

		EDMA3_DRV_setTransferParams(EdmaObj->hEdma, EdmaObj->iChannel, 2, 2, BUFFSIZE_TX, 2, EDMA3_DRV_SYNC_A);

	}

// Regardless of whether we are setting up RCV or XMT, these values are the same for both.
// Because this example requires A-sync, notice the parameter EDMA3_DRV_SYNC_A was used vs. _AB
// ACNT=2, BCNT=2, CCNT=BUFFSIZE, BCNTRLD=2, SYNC=A
//**********	//EDMA3_DRV_setTransferParams(EdmaObj->hEdma, EdmaObj->iChannel, 2, 2, BUFFSIZE, 2, EDMA3_DRV_SYNC_A);

// Interrupt enable ENABLED - FINAL interrupt after transfer complete is enabled
	EDMA3_DRV_setOptField (EdmaObj->hEdma,EdmaObj->iChannel, EDMA3_DRV_OPT_FIELD_TCINTEN, EDMA3_DRV_TCINTEN_EN);   

// Get pingParam values so we can set pong = ping and change a few PSET values for pong
	EDMA3_DRV_getPaRAM(EdmaObj->hEdma, EdmaObj->iChannel, &pingParam);

// set Pong = Ping (then shortly we will change a few of the pong PSET values)
	pongParam = pingParam;

// if we're setting up Rcv or Xmt, pongParam needs to be modified to set the src/dest
// addresses appropriately. Must also do two _requestChannels for the reload PSETs
	if (EdmaObj->iChannel == EDMA_HW_EVENT_REVT1)
	{
		pongParam.destAddr = (unsigned int)&gBufferRcv[1]; // gBufferRcv[1] (half way thru buffer)

		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iReloadPing, &EdmaObj->iTcc, eventQ, tccCbRcv, NULL); 
		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iReloadPong, &EdmaObj->iTcc, eventQ, tccCbRcv, NULL); 
	}
	else
	{
		pongParam.srcAddr = (unsigned int)&gBufferXmt[1]; // gBufferXmt[1] (half way thru buffer)

		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iReloadPing, &EdmaObj->iTcc, eventQ, tccCbXmt, NULL); 
		edma3Result = EDMA3_DRV_requestChannel (EdmaObj->hEdma, &EdmaObj->iReloadPong, &EdmaObj->iTcc, eventQ, tccCbXmt, NULL); 
	}


// set iReload equal to iChannel PARAM values
    EDMA3_DRV_setPaRAM (EdmaObj->hEdma, EdmaObj->iReloadPing, &pingParam);
    EDMA3_DRV_setPaRAM (EdmaObj->hEdma, EdmaObj->iReloadPong, &pongParam);

// link channels
    edma3Result = EDMA3_DRV_linkChannel (EdmaObj->hEdma, EdmaObj->iChannel, EdmaObj->iReloadPong); 
    edma3Result = EDMA3_DRV_linkChannel (EdmaObj->hEdma, EdmaObj->iReloadPong, EdmaObj->iReloadPing); 
    edma3Result = EDMA3_DRV_linkChannel (EdmaObj->hEdma, EdmaObj->iReloadPing, EdmaObj->iReloadPong); 

// this is not required, but for debug purposes we are reading back currentParam so that
// we can view that the LINK field changed in the iChannel PaRAM set.
	EDMA3_DRV_getPaRAM(EdmaObj->hEdma, EdmaObj->iChannel, &channelParam);
	EDMA3_DRV_getPaRAM(EdmaObj->hEdma, EdmaObj->iReloadPing, &pingParam);
	EDMA3_DRV_getPaRAM(EdmaObj->hEdma, EdmaObj->iReloadPong, &pongParam);
}


// ============================    EDMA START   =======================================
// 
// This function will set the Event Enable Register (EER) bit corresponding to the
// channel we are using. To do this, we use EDMA3_DRV_TRIG_MODE_EVENT in the 
// _enableTransfer call below. After the first "A-size" transfer is complete, an 
// interrupt to the CPU is generated (intermediate interrupts turned on), then we wait
// for another sync event (from Timer 0) and this goes on until all 16 transfers are
// complete. Then, the semaphore is posted in edma_isr that signals edmaTsk that we
// are finished.
// 
// This function could be improved by returning the result. 
// ===================================================================================

void edma_start(edma_object_t EdmaObj)
{
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;
	edma3Result = EDMA3_DRV_enableTransfer(EdmaObj.hEdma, EdmaObj.iChannel, EDMA3_DRV_TRIG_MODE_EVENT);
}



// ============================    EDMA DELETE CHANNEL  =============================
// 
// Delete (free) the current channel from the resource pool
// ===================================================================================

void edma_deleteChan(edma_object_t EdmaObj)
{
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;
    edma3Result = EDMA3_DRV_freeChannel(EdmaObj.hEdma, EdmaObj.iChannel);
}

// ============================    EDMA WAIT   =======================================
// 
// Check to see if the EDMA3 interrupt pending register (IPR) is set to one indicating
// that the transfer has completed. This is a blocking function - it will continue to
// poll the IPR bit and won't return until it becomes a 1.
// 
// This function could be improved by returning the result. Also, adding a timeout
// feature would be an improvement.
// ===================================================================================

void edma_wait(edma_object_t EdmaObj)
{
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;
    edma3Result = EDMA3_DRV_waitAndClearTcc(EdmaObj.hEdma, EdmaObj.iTcc);
}



// ============================    EDMA CHECK   ======================================
// 
// Check to see if the EDMA3 interrupt pending register (IPR) is set to one indicating
// that the transfer has completed. This is a one-time check - not a blocking
// function. The calling code can check the status and respond accordingly.
// 
// tccStatus = TRUE or FALSE
// ===================================================================================

unsigned short edma_check(edma_object_t EdmaObj)
{
	unsigned short tccStatus;
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;

    edma3Result = EDMA3_DRV_checkAndClearTcc(EdmaObj.hEdma, EdmaObj.iTcc, &tccStatus);
    return(tccStatus);
}

// ============================    EDMA RELEASE   ======================================
// 
// EDMA3_DRV_close is used to close an already opened EDMA3 Driver instance.
//
// EDMA3_DRV_delete deletes the driver instance and driver object.
// =====================================================================================

void edma_release(edma_object_t EdmaObj)
{
	EDMA3_DRV_Result edma3Result = EDMA3_DRV_SOK;
	
	edma3Result = EDMA3_DRV_close(EdmaObj.hEdma, NULL);

	edma3Result = EDMA3_DRV_delete(edma3InstanceId, NULL);
}

// ===============================    EDMA ISRS   ======================================
// 
// When RCV transfer is complete, the interrupt dispatcher calls the "callback" function
// for RCV (tccCbRcv) which is set to edma_rcv_isr. The ISR simply posts the semaphore
// to procBuffTsk (in tasks.c) to copy Rcv to Xmt. Same method applies for Xmt.
//
// EDMA3_DRV_delete deletes the driver instance and driver object.
// =====================================================================================

void edma_rcv_isr(void)
{
	SEM_post(&rcvBuffReady);
}

void edma_xmt_isr(void)
{
	SEM_post(&xmtBuffReady);
}

/* ==========================    END OF FILE    =========================== */

edma_codec_config.c
// =============================   INCLUDES  =========================================
#include <stdint.h> 		// used for int16_t definitions
#include "edma_codec_config.h"    // includes definitions for BUFFSIZE and externs for Src/Dst
#include "edma.h"    // includes prototypes for all edma functions

#include "main.h"
//#include "mcbsp_aic23.h" // contains definitions used in mcbsp_aic23.c
#include <stdint.h>  // used for definitions like uint32_t, ...
//#include <string.h>  // used for memset/memcpy commands
#include <std.h>    
#include <c6x.h>	// interrupt functions/defines
#include <c64.h>
//#include <src\edma3_rl_cc.h> // needed for CCRegsPtr overlay - for debug
#include <edma3_rl_cc.h> // needed for CCRegsPtr overlay - for debug
#include "codec.h"

#pragma DATA_SECTION(gBufferXmt,".TX_FIFOS")
int16_t gBufferXmt[2][BUFFSIZE_TX]; // Transmit PING & PONG buffers
//#pragma DATA_SECTION(gBufferRcv,".TX_FIFOS")
int16_t gBufferRcv[2][BUFFSIZE]; // Receive PING & PONG  buffers

extern EDMA3_CCRL_RegsOvly CCRegsPtr;


int16_t *pDRR;// = (void *) 0x01D00800;
int16_t *pDXR;// = (void *) 0x01D00804; 
 
void init_buffers(void);

void edma_codec_init_config()
{
// Initialize our Edma Rcv/Xmt objects - passed to edma_config() and edma_createChan() in edma.c
	edma_object_t EdmaObjRcv = {NULL,					 // hEdma: handle to be returned by our edma_config function
							    EDMA_HW_EVENT_REVT1,     // iRcv: need to use Event 15 - because it is tied to McBSP1 Rcv
							    EDMA3_DRV_TCC_ANY,       // iRcvTcc: use ANY TCC
							    EDMA3_DRV_LINK_CHANNEL,  // RcvPing link PSET
							    EDMA3_DRV_LINK_CHANNEL}; // RcvPong link PSET
	edma_object_t EdmaObjXmt = {NULL,					 // hEdma: handle to be returned by our edma_config function
							    EDMA_HW_EVENT_XEVT1,     // iChannel: need to use Event 14 - because it is tied to McBSP1 Xmt
							    EDMA3_DRV_TCC_ANY,       // iTcc: use ANY TCC
							    EDMA3_DRV_LINK_CHANNEL,   // XmtPing link PSET
							    EDMA3_DRV_LINK_CHANNEL}; // XmtPong link PSET

	*pDRR =  MCBSP1_DRR_32BIT; //0x01D00800;
	*pDXR =  MCBSP1_DXR_32BIT; //0x01D00804; 

	EVM6424_init();							// init EVM6437 HW
	(void)initCodec();							// init McBSP1; s/u AIC via I2C 
	init_buffers();

// Create and open edma3 driver and instance
	edma_config(&EdmaObjRcv); 
	EdmaObjXmt.hEdma = EdmaObjRcv.hEdma;

	edma_createChan(&EdmaObjRcv, pDRR, gBufferRcv[0]); 
	edma_createChan(&EdmaObjXmt, gBufferXmt[0], pDXR); 

	edma_start(EdmaObjRcv);
	edma_start(EdmaObjXmt); 

// enable EINT5 - please refer to HWI_INT5 in .tcf file for proper settings
	C64_enableIER(C64_EINT5);

//    MCBSP1_SPCR = 0x00010001;					// start McBSP
}

void do_nothing(void)
{
	while(1);
}

void init_buffers(void)
{

// clear the destination buffers
	memset(gBufferRcv, 0, sizeof(gBufferRcv));
	memset(gBufferXmt, 0, sizeof(gBufferXmt));

}
// ================================  END OF FILE  ====================================

  • Welcome to the TI E2E forum. I hope you will find many good answers here and in the TI.com documents and in the TI Wiki Pages (for processor issues). Be sure to search those for helpful information and to browse for the questions others may have asked on similar topics (e2e.ti.com). Please read all the links below my signature.

    Moving this thread to C64x Single core forum for appropriate response. Thank you for your patience.

    Thank you.

    Note: We strongly recommend you to create new e2e thread for your queries instead of following up on an old/closed e2e thread, new threads gets more attention than old threads and can provide link of old threads or information on the new post for clarity and faster response.

  • Hi,

    Thanks for your post.

    The most common cause of McBSP + EDMA3 problem would be, not having enough time for the EDMA3 to service the events from the McBSP. The speed of the McBSP and the word size of the transfers will contribute to this (fast and small size leave less time between events), and other tasks using the same TC for other things will also contribute to this problem, as it will conflict stalls at the destination (like external memory). You can try lowering the clock of the McBSP to see if the failures go away. Or you can try reducing other system activity or moving other transfers to another TC. And you can try changing the destination to an internal address.

    There are also other few possibilities described below to met this condition:

    1.  DRR would have not been read since the last RBR-to-DRR transfer

    2. RBR is full and a RBR-to-DRR copy wouldn't have occured

    3. RSR is full and a RSR-to-RBR transfer also have not occured.

    Basically, if DRR is not been read by the CPU or the EDMA controller since the last RBR-to-DRR transfer (RRDY = 1), an RBR-to-DRR copy would not take place until RRDY = 0. and this prevents an RSR-to-RBR copy. New data arriving on the DR pin would be shifted into RSR, and the previous contents of RSR would have been lost and there results a receive overrun issue which sets the RFULL to 1. Kindly evaluate the above condition and validate the error condition as you suspect.

    In order to allow for subsequent transfers to be read properly, you could clear the RFULL bit to 0 through executing the below events:

    •Reading DRR

    •Resetting the receiver (RRST = 0) or the device and always, another frame sync. is needed to restart the receiver

    Also, please validate the initialization procedure as mentioned in section 2.11.1 in McBSP user guide (SPRUEN2B.pdf) and ensure all the steps have been properly taken care in the code.

    Thanks & regards,

    Sivaraj K

    ------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Ayman,

    What is the size of a sample, 16 bits?

    What is the size of a packet?

    What is the clock rate of the McBSP?

    Can you slow the sample rate down easily, to confirm the problem is with the time between samples as opposed to some other method of dropping data?

    What else is the EDMA doing in your system while this is running? Simple copies, movement from external to internal memories?

    What is the destination memory for the McBSP reads? L2, OCMC, SDRAM?

    What else is going on in the system while this is running? DSP heavy processing, heavy SDRAM access, etc.?

    Regards,
    RandyP
  • I am sorry for my late response. I didn't expect my question to get a response this fast so I didn't bother checking, my bad !
    With the apology out of the way, let me thank you; your answer was very enlightening.
    I tried the following:
    - I went through the McBSP initialization and I couldn't spot anything particularly wrong. Moreover, I copied the initialization code to a simple codec loopin code that reads the linein and writes at the lineout, it worked perfectly.
    - I couldn't figure out how to lower the McBSP clock since I am already setting the sampling frequency to 8 KHz and using continuous transfer mode. As far as I can tell, these result in the lowest FSR_int and CLCKR_int. I also think that lowering the FSR_int might result in aliasing since the wav file is sampled at 8 KHz.
    -I moved the receiving buffer to the internal RAM, though I had to make it a lot shorter, but the results were almost the same.

    I don't know how to check for an RFULL condition so I couldn't test this part. Any help in checking it or help in general will be great.
    Thanks a lot for your response.
  • First let my apologize for my late response. I guess I gravely underestimated the dedication of this forum's members and didn't check until quite some time has passed. For that I extend my apologies, and for your engaging answer I extend my thanks.
    About your questions:
    - The size of the sample is 16 bits
    - The size of the packet is around 9600 samples of data (1.2 seconds), padded by around 22600 samples of zeroes (2.82 seconds). The zeroes are inserted between the packets to provide a sufficient time for the processing of the packets.
    - The McBSP is clocked externally using the codec. The codec in turn is set to Fs = 8 KHz, 16 bits of data, and continuous transfer mode. Therefore I think the clocking frequency of the McBSP is 256 KHz if I am not misinterpreting the documentation.
    - I don't think I can slow down the sampling rate any further. it seems that 8 KHz is the lowest sampling rate provided by the codec. Besides, I am afraid some aliasing might occur since the wav data is sampled at 8KHz.
    - The EDMA has two channels one of them reads the DRR and writes it in a receving buffer, and the other one reads from a transmitting buffer and writes into the DXR. In my tests I am not writing anything to the transmitting buffer so I guess the DXR is receiving garbage, the McBSP is never set to transmit anyway. The transmitting buffer is in the IRAM. The receiving buffer is in the DDR2, I transferred it to the IRAM with no avail.
    -The destination is DDR2
    - Both DSP heavy processing and SDRAM access are happening when there is data, when zeroes are being read then almost nothing happens.
    Thanks for your response, looking forward to more of your input.
  • Ayman,

    How are you padding with 0's between packets? I would normally expect a continuous stream of samples coming from the AIC.

    Since the size of the zero padding is not a multiple of the size of a packet, how are you handling the end of a packet (before zero padding) and the beginning of a packet (after zero padding)?

    When you detect a packet loss, what exactly are you observing? The implication is a loss of an entire 9600 sample packet.

    The sample rate is pretty low so that should not be an issue with the DMA's ability to read each sample from the McBSP quickly enough to get the next sample. That is the most common data loss issue, but it usually happens at faster sample rates or with many more channels of data coming in. We cannot completely eliminate it but I would not work hard to reduce that rate for now.

    Since you are not using the McBSP transmit side during your tests, please try it without even having the transmit DMA channel enabled. This will remove one more obstacle.

    Another obstacle is having the receiving buffer in DDR2, since that can have contention with DSP activity. Even though you have already said it did not help to move the receive buffer to IRAM, please leave it there for the remaining testing. Once you get it working, you can experiment with putting things back, such as moving this buffer back to DDR2.

    For your testing, please reduce the DSP activity as much as possible. Ideally, reduce it to simply trying to detect whether a packet was lost and not doing any actual processing.

    How is the McBSP receive channel being serviced during the time of the zero padding?

    Regards,
    RandyP
  • I think I've caused a misunderstanding .. the 0's are in the wav file .. basically the wav file consists of a 1.2 seconds of data followed by 2.825 seconds of silence, which is what I referred to as zeroes, and repeat.

    Each packet of data starts with a preample. When the preample is detected, the rest of the code is executed. Similarly, the end of the packet is a predefined End of Message sequence.

    When I mention a packet loss I mean not being able to detect the preample which will result in the rest of the processing not happening until the next preample is detected in the next packet.

    Ok, at least that is one less thing to worry about :)

    I have disabled the McBSP transmit side and will keep it so for now as you suggested. So far no changes where noticed.

    Regarding receiving buffer placement; when I put it into the IRAM it eventually results in some sort of exception being raised and a sys_abort call that halts the system. I guess I should have mentioned that many changes I do to the code result in the same result. I can't figure what exactly causes the exception and I don't know how can I figure that out.

    I will disable the rest of the processing. It might need some work so I will update you on the results as soon as I get it to work.

    When an end of message is detected, only the preample detection is called until a preample is actually found. As far as the McBSP and edma are concerned no changes occur whether there is data or not, but the processing code is what changes.

    please expect an update from me regarding the effect of using minimal processing. And any other suggestions or questions you might have are very welcomed.

    Cheers,

  • I believe I have finally thoroughly tested the effect of disabling the majority of the DSP processing. Now my code only detects whether a preample exists. Nevertheless, the drop in the packets remains the same.
  • Update: I modified the edma channel to link the McBSP's DRR and DXR thereby changing the code into a simple loopback. I played a wav file and recorded the output and tested it using the PC. The result was packet losses, again!

    I think this makes it clear that the issue is with the configuration linking the Codec and McBSP so I attached the file including that configuration. I hope it will suffice to determine where is the problem.

    Let me repeat my thanks for your help so far. I truly appreciate it .

    Cheers,

    Ayman

    0246.codec.c
    // EVM6437 AIC33 raw driver. Jan'08. Courtesy L.Lotzenburger. 
    
    #include "codec.h"
    
    /* ------------------------------------------------------------------------ *
     *                                                                          *
     *  AIC33 Setup                                                             *
     *                                                                          *
     *      AIC33.MCLK = 12.0000 MHz                                            *
     *      FS = ( AIC33.MCLK * K ) / ( 2048 * P )                              *
     *                                                                          *
     *      For a FS=[48 kHz] & MCLK=[12.0000 MHz]                              *
     *          : 48 kHz = ( 12.0000 MHz * K ) / ( 2048 * P )                   *
     *          : P = 1, K[J.D] = 8.1920                                        *
     *                                                                          *
     * ------------------------------------------------------------------------ */
    static AIC33_Config aic33config = {
           0, // 0  Page Select                     <- [Page=0]
    READONLY, // 1  Software Reset                  <- [ResetOnly]
        0xAA, // 2  Codec Sample Rate Select        <- [ADC=Fsref/6][DAC=Fsref/6]
    
        // For: [FS=12 kHz][MCLK=12.0000 MHz]
        0x91, // 3  PLL A                           <- [PLL=ON][P=1][Q=2]
    
        0x20, // 4  PLL B                           <- [J=8]
    
    	0x1E, // 5  PLL C                           <- [D=1920]
           0, // 6  PLL D                           <- [D=1920]
    
        0x0A, // 7  Codec Datapath Setup            <- [FS=8 kHz][LeftDAC=LEFT][RightDAC=RIGHT]
    
        0xC0, // 8  Audio Serial Data A             <- [BCLK=Master][WCLK=Master][3DEffects=OFF][DigitalMIC=OFF]
           0, // 9  Audio Serial Data B             <- [Mode=I2S][Length=16-bit][TransferMode=Continous]
           0, // 10 Audio Serial Data C             <- [DataOffset=0]
    READONLY, // 11 Audio Codec Overflow Flag       <- [ReadOnly]
           0, // 12 Audio Codec Digital Filter      <- [OFF]
    
           0, // 13 Headset Detection A             <- [OFF]
           0, // 14 Headset Detection B             <- []
    
           0, // 15  Left ADC PGA Gain              <- [Mute=OFF]
           0, // 16 Right ADC PGA Gain              <- [Mute=OFF]
        0xFF, // 17 MIC3L/R to  Left ADC            <- [OFF]
        0xFF, // 18 MIC3L/R to Right ADC            <- [OFF]
    0x34, // 19  LINE1L to  Left ADC            <- [SingleEnd][Gain=0dB][Power=ON][SoftStep=OncePerFS]
    0x78,  //  0x78, // 20  LINE2L to  Left ADC            <- [OFF]
    0x78,   // 0x78, // 21  LINE1R to  Left ADC            <- [OFF]
    0x34,   // 0x04, // 22  LINE1R to Right ADC            <- [SingleEnd][Gain=0dB][Power=ON][SoftStep=OncePerFS]
    0x78,  //  0x78, // 23  LINE2R to Right ADC            <- [OFF]
    0x78,  //  0x78, // 24  LINE1L to Right ADC            <- [OFF]
           0, // 25 MICBIAS                         <- [Power=OFF]
    
          0, // 26  Left AGC A                     <- [LeftAGC=OFF]  //changed to 1 by abdalla  (was 0 value )
         0, // 27  Left AGC B                     <- [OFF]			//changed to 1 by abdalla
          0, // 28  Left AGC C                     <- [OFF]			//changed to 1 by abdalla
           0, // 29 Right AGC A                     <- [RightAGC=OFF]  //changed to 1 by abdalla
          0, // 30 Right AGC B                     <- [OFF]			//changed to 1 by abdalla
           0, // 31 Right AGC C                     <- [OFF]			//changed to 1 by abdalla
    READONLY, // 32  Left AGC Gain                  <- [ReadOnly]	
    READONLY, // 33 Right AGC Gain                  <- [ReadOnly]
           0, // 34  Left AGC Noise Debounce        <- []
           0, // 35 Right AGC Noise Debounce        <- []
    READONLY, // 36 ADC Flag                        <- [ReadOnly]
    
        0xE0, // 37 DAC Power & Output Dvr          <- [LeftDAC=ON][RightDAC=ON][HPLCOM=SingleEnd]
        0x10, // 38 High Power Output Dvr           <- [HPRCOM=SingleEnd][ShortCircuit=OFF]
    RESERVED, // 39                                 <- [Reserved]
           0, // 40 High Power Output Stage         <- []
           0, // 41 DAC Output Switching            <- []
           0, // 42 Output Driver Pop Reduction     <- []
    
           0, // 43  Left DAC Digital Volume        <- [Mute=OFF][Gain=0dB]
           0, // 44 Right DAC Digital Volume        <- [Mute=OFF][Gain=0dB]
    
           0, // 45 Line2L to HPLOUT Volume         <- []
           0, // 46 PGA_L  to HPLOUT Volume         <- []
        0x80, // 47 DAC_L1 to HPLOUT Volume         <- []  //[Routed] was 0
           0, // 48 LINE2R to HPLOUT Volume         <- []
           0, // 49 PGA_R  to HPLOUT Volume         <- []
           0, // 50 DAC_R1 to HPLOUT Volume         <- []
        0x09, // 51           HPLOUT Output         <- []  //[Mute=OFF][Power=ON] was 0
    
           0, // 52 LINE2L to HPLCOM Volume         <- []
           0, // 53 PGA_L  to HPLCOM Volume         <- []
           0, // 54 DAC_L1 to HPLCOM Volume         <- []
           0, // 55 LINE2R to HPLCOM Volume         <- []
           0, // 56 PGA_R  to HPLCOM Volume         <- []
           0, // 57 DAC_R1 to HPLCOM Volume         <- []
           0, // 58           HPLCOM Output         <- []
    
           0, // 59 LINE2L to HPROUT Volume         <- []
           0, // 60 PGA_L  to HPROUT Volume         <- []
           0, // 61 DAC_L1 to HPROUT Volume         <- []
           0, // 62 LINE2R to HPROUT Volume         <- []
           0, // 63 PGA_R  to HPROUT Volume         <- []
        0x08, // 64 DAC_R1 to HPROUT Volume         <- [] //[Routed] was 0
        0x09, // 65           HPROUT Output         <- [] //[Mute=OFF][Power=ON] was 0
    
           0, // 66 LINE2L to HPRCOM Volume         <- []
           0, // 67 PGA_L  to HPRCOM Volume         <- []
           0, // 68 DAC_L1 to HPRCOM Volume         <- []
           0, // 69 LINE2R to HPRCOM Volume         <- []
           0, // 70 PGA_R  to HPRCOM Volume         <- []
           0, // 71 DAC_R1 to HPRCOM Volume         <- []
           0, // 72           HPRCOM Output         <- []
    
           0, // 73 LINE2L to MONO_LOP/M Volume     <- []
           0, // 74 PGA_L  to MONO_LOP/M Volume     <- []
           0, // 75 DAC_L1 to MONO_LOP/M Volume     <- []
           0, // 76 LINE2R to MONO_LOP/M Volume     <- []
           0, // 77 PGA_R  to MONO_LOP/M Volume     <- []
           0, // 78 DAC_R1 to MONO_LOP/M Volume     <- []
           0, // 79           MONO_LOP/M Output     <- []
    
           0, // 80 LINE2L to LEFT_LOP/M Volume     <- []
           0, // 81 PGA_L  to LEFT_LOP/M Volume     <- []
        0x80, // 82 DAC_L1 to LEFT_LOP/M Volume     <- [Routed]
           0, // 83 LINE2R to LEFT_LOP/M Volume     <- []
           0, // 84 PGA_R  to LEFT_LOP/M Volume     <- []
           0, // 85 DAC_R1 to LEFT_LOP/M Volume     <- []
        0x09, // 86           LEFT_LOP/M Output     <- [Mute=OFF][Power=ON]
    
           0, // 87 LINE2L to RIGHT_LOP/M Volume    <- []
           0, // 88 PGA_L  to RIGHT_LOP/M Volume    <- []
           0, // 89 DAC_L1 to RIGHT_LOP/M Volume    <- []
           0, // 90 LINE2R to RIGHT_LOP/M Volume    <- []
           0, // 91 PGA_R  to RIGHT_LOP/M Volume    <- []
        0x80, // 92 DAC_R1 to RIGHT_LOP/M Volume    <- [Routed]
        0x09, // 93           RIGHT_LOP/M Output    <- [Mute=OFF][Power=ON]
    
    READONLY, // 94 Module Power Status             <- [ReadOnly]
    READONLY, // 95 Short Circuit Detection         <- [ReadOnly]
    
    RESERVED, // 96                                 <- [Reserved]
    RESERVED, // 97                                 <- [Reserved]
    
           0, // 98 GPIO1                           <- [GPIO1=OFF]
           0, // 99 GPIO2                           <- [GPIO2=OFF]
           TDT_GAIN, // 100 Additional GPIO Control A      <- []   // modified by abdalla (old value = 0)
           TDT_GAIN  // 101 Additional GPIO Control B      <- []
    };
    
    unsigned short readback[128];
    
    AIC33_CodecHandle aic33handle =	AIC33_MCBSP_ID;
    
    AIC33_CodecHandle initCodec(void)
    {
    	//AIC33_CodecHandle aic33handle = MCBSP_INTERFACE|0x1B;
    	//AIC33_CodecHandle aic33handle = AIC33_MCBSP_ID;
    
    
    //    EVM6424_clrPinMux( 0, ( 3 << 24 ) | ( 3 << 22 ) );
    //    EVM6424_setPinMux( 0, ( 1 << 24 ) | ( 1 << 22 ) );    // MCBSP0/1
    
        // Initialize MCBSP1 
    	MCBSP1_SPCR = 0x00000000;
        MCBSP1_PCR  = 0x00000003;
        MCBSP1_RCR  = 0x80010140;
        MCBSP1_XCR  = 0x80010140;
        MCBSP1_SRGR = 0x00000000;
    
    
        // Set Buffer controls 
        EVM6424_I2C_GPIO_setOutput( I2C_GPIO_GROUP_3, 0, 1 ); // MCBSP on
        EVM6424_I2C_GPIO_setOutput( I2C_GPIO_GROUP_3, 1, 1 ); // MCASP off
        EVM6424_I2C_GPIO_setOutput( I2C_GPIO_GROUP_3, 2, 1 ); // SPDIF off
    
        // Configure AIC33 
        EVM6424_AIC33_rset( aic33handle, AIC33_PAGESELECT, 0 );// Set to Page0
        EVM6424_AIC33_rset( aic33handle, AIC33_RESET, 0x80 ); // Reset AIC33
        EVM6424_AIC33_config( aic33handle, &aic33config );          // Setup AIC33
    
        return aic33handle;
    }
    

  • Ayman,

    Do you reliably detect the first preamble when you start the wav file playing or start the processor running? Which order do you run the test?

    How long is the preamble? What does it consist of?

    When you detect a valid preamble, start a timer that will trigger an interrupt after the next preamble should be detected. You can use that interrupt to halt the DSP and look at the data to see how the received preamble appears differently that what is needed for detection. If you do detect that next preamble, then restore the timer to a full count to wait for the next preamble after that one.

    You will need to disable the EDMA when the timer interrupt hits. Turning off the EDMA receive channel's IER bit should be sufficient.

    I assume you are using a multi-buffer scheme so you can be filling one buffer while processing the data in the other buffer. The descriptions in the original post were about the real application plus some test scenarios so some of my assumptions could be confused, but I am pretty sure you are using ping/pong buffers throughout.

    What is the reason for the receive buffers to be exactly the size of the data portion of the packet? Are you using some interrupt-driven method to look at each sample until a preamble is found and then start the EDMA servicing the data? Or is it just a coincidence that you use that size?

    Do you ever stop the receive operation during normal activity?

    Regards,
    RandyP
  • Ayman,

    You are doing great testing, so I do want to help you progress. I will say that it is not in my skillset to be able to look at McBSP configuration code and figure out a problem like this. I do not know who has that skill, but maybe someone will join the discussion if that is the path you see as your solution.

    Ayman Gumaa said:
    I modified the edma channel to link the McBSP's DRR and DXR thereby changing the code into a simple loopback. I played a wav file and recorded the output and tested it using the PC. The result was packet losses, again!

    Does this mean that your DMA source address is the DRR and your destination address is the DXR? If so, then set your BCNT to 65535 and CCNT to 65535 so it will run for a long time and then see if you get any packets lost on the outside.

    If that is not what you are doing, then you are copying to an internal buffer and then transmitting from that same internal buffer, so you have not changed anything on the receive side as far as I can tell. The answers to my previous questions (we are interleaving our posts) are still useful.


    What value are you using for ACNT? It would be worthwhile to set it to 4 since that is required for some of our devices, but I am not sure if that is the case for this DSP or not. My multi-year memory tells me it does need to be 4 (specifically not 1 or 2) to properly service the peripheral.

    Regards,
    RandyP

  • Yes, the source is DRR and destination is DXR. I did as you recommended for the BCNT and CCNT. I also changed the ACNT from 2, because the sample is 16 bits, to 4 as recommended. There is still some loss somewhere.
  • Ayman,

    How do you detect that there has been a loss in the DRR->DXR case? I assume you have no ISR running or needed in this case and no data is being captured to DSP buffers.

    Regards,
    RandyP
  • Randy,

    I record the output from the DXR with a PC application and run a PC version of the code to detect the preamples and end of messages.

    Another update: based on your question of whether I can detect the first preample correctly, I detected that the first two packets are lost sometimes. I suspected that the gain adjustment have something to do with the issue so I disabled the gain soft-stepping  implemented in the codec. So far the packets seem to arrive perfectly but I am doing more thorough tests to confirm that this is the issue. If it passes these tests I am going to return the code to the previous Ping Pong setup and run only preample detection to verify that nothing else was responsible for the packets drop.

    Cheers,

    Ayman

  • Hi Ayman,

    My two cents might be worth something and here goes:
    I had a similar problem when using the MCASP/edma transfer where I was loosing data. I found that this was due to the cache not updating the destination memory when execution is halting. Also you should look at aligning your destination memory to something like 128 or 256 bytes as this makes it easier for the cache to update. You should purge cache on the final update. There is all about this in the Cache memory user guide.
    Hope this might be another avenue to look at.
    Best regards
    Manjula