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.

C6748 UART Tx EDMA callback fires sporadic

Dear experts,

I have was hoping you could provide me with some advice.

I am using the C6748 together with DSP/BIOS (v5.42.1.09) and the EDMA3 LLD (v1.11.03.01).

I have recently moved the Tx part of our UART driver over to EDMA in order to reduce CPU load. The UART Rx part of the driver has been using the EDMA3 for a while now and is considered stable.

Due to the asynchronous nature of UART Tx, the typical PING/PONG buffering approach cannot be used. Instead a new EDMA Tx transfer is initiated as new bytes become available for transmission. This is obviously a bit inefficient for small transmissions, but the CPU load reduction at continuous high-speed transmissions are very significant, which is the typical use-case.

The basic concept of the driver is as follows:

- The user calls the UART transmit function, which essentially buffers the user's data in a large process buffer and posts a semaphore.

- A dedicated UART transmit task pends on this semaphore and when awoken, it programs the EDMA to transfer the available bytes, up until a maximum of 1024 bytes at a turn. An "EDMA busy" flag is also set to indicate that an UART EDMA Tx transfer is in progress, to prevent the EDMA from being programmed again, while it has not yet completed.

- Since the UART Rx is also using the EDMA3, the UART FIFO buffering cannot be enabled/disabled to trigger a UART Tx event for the EDMA3. Instead a single byte is written to the UART Tx FIFO (which is empty at this point) through the THR register, followed by enabling the EDMA transfer with a EDMA3_DRV_enableTransfer() call.

- When the EDMA UART Tx transfer has completed, a callback is executed to disable the UART Tx channel [EDMA3_DRV_disableTransfer() and EDMA3_DRV_disableLogicalChannel()] and clear the TCC flag [EDMA3_DRV_checkAndClearTcc()]. The "EDMA busy" flag is also cleared to indicate that a new UART EDMA Tx transfer can now be programmed. Finally, the semaphore is posted again to awake the task to check if there are still bytes available for transfer.

My problem is as follows:

- At an UART baud rate of 115200, the driver works perfectly

- At an UART baud rate of 230400, bytes are sometimes dropped or swapped

I have put in some statistic variables to count the amount of EDMA UART Tx transfers initiated and the amount of callbacks received. At a baud rate of 115200, these two variables stay exactly in sync, i.e. one callback for every transfer initiated. However, at a baud rate of 230400 I found that the callback function fires more than actual transfers initiated. I believe that this would explain my data errors, but I just can't explain why this is happening.

Do you guys maybe have any ideas? Am I maybe triggering the UART Tx EDMA event incorrectly? 

  • Hi,

    We are working on your request and will get back to you at the earliest.

    Thanks & regards,
    Sivaraj K
  • Hi Sivaraj,

    Thank you for your response.

    I am also doing some further testing on my side to consistently reproduce the problem.

    So far I have found that although the UART baud rate does aggravate the problem, it might not be the main cause.

    I am using UART 0 and 1 of the C6748. When I am exclusively using UART0 for continuous transmissions, I never see errors at 115200 and very rarely at 230400. However, when I am using both UART0 and UART1 for continuous transmissions, I consistently start to see errors after a while at both 115200 and 230400. By errors I mean loss of transmitted data and more EDMA callbacks than EDMA transfers initiated.

    Not sure if this is relevant, but I am also using the EDMA3 LLD for our McASP driver, which interfaces with a codec running at a sampling rate of 96 kHz.
  • Hi,

    May be, you can walkthrough the below E2E post which would help you better, I hope there are better suggestion on the same.

    https://e2e.ti.com/support/embedded/tirtos/f/355/t/183633

    Thanks & regards,

    Sivaraj K

  • Hi Sivaraj,

    I am afraid nothing of that thread is really relevant to my problem. I am not using BIOSPSP for the UART driver, it is completely my own driver. I am only using the EDMA3 LLD since our McASP driver is using it and I do not want two different drivers controlling the EDMA3.
  • Hi,

    Ok understood.

    Is your  RTS/CTS Flow control disabled while you are running UART @ higher baudrates like 230400 etc?

    For debugging purposes, do not enable the DMA EER bit for the UART event in the EDMA3 register set. This will prevent the DMA channel from running, but you will see the ER register bit set if the event is getting from the UART to the EDMA3 module. This is a first starting point to determine if the problem is on the UART side or the EDMA3 side.

    Thanks & regards,

    Sivaraj K

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

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

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

  • Hi Sivaraj,

    No, RTS/CTS is enabled, but not by the UART peripheral itself, we manually handle RTS/CTS on a higher level. The problem is not related to RTS/CTS.

    I actually went through related forum posts before making this post.

    The text you posted below:

    For debugging purposes, do not enable the DMA EER bit for the UART event in the EDMA3 register set. This will prevent the DMA channel from running, but you will see the ER register bit set if the event is getting from the UART to the EDMA3 module. This is a first starting point to determine if the problem is on the UART side or the EDMA3 side.

    was simply copied and pasted from this thread (a response for RandyP):

    As mentioned before, I am using the EDMA3 LLD and I would therefore prefer not to fiddle with the EDMA3 registers directly as not to interfere with the EDMA3 LLD.

    Can you please put me into touch with one of TI's experts on this topic?

  • Hi,

    Just some further relevant information:

    - I am using the FIFO on the UART

    - Current users of the EDMA3 channel controller 0 [configured by edma3init() of the EDMA3 LLD for the C6748]:

    1) McASP Tx and Rx both on event queue 0

    The McASP interfaces with a codec running at a sampling rate of 96kHz, with 16-bit stereo samples per frame, i.e. a 32-bit EDMA transfer per frame sync

    2) UART0 Tx and Rx both on event queue 1 (baud rate 115200 or 230400)

    3) UART1 Tx and Rx both on event queue 1 (baud rate 115200 or 230400)

  • My UART Tx EDMA programming:

    bool Rm_c6748_uart_edma::_init_tx_edma() {
    
    	bool success = true;
    
    	CSL_UartRegsOvly uart_regs = (CSL_UartRegsOvly)_uart_base_addr;
    	EDMA3_DRV_Result edma3_result = EDMA3_DRV_SOK;
    
    	_edma_tx_busy_flag = false;
    
    	_tx_event_que = 1;
    
    	// Request the DMA channels
    	// ------------------------
    
    	// Request the logical channel for event triggering. For this channel request the
    	// following items are allocated:
    	// - logical channel (particular UART EDMA Tx event)
    	// - TCC
    	// - PaRAM set
    
    	_tx_logical_chan_id = _edma_uart_tx_evt;
    	_tx_tcc_id = _edma_uart_tx_evt;
    
    	edma3_result |= EDMA3_DRV_requestChannel(_edma_handle,
                                                     &_tx_logical_chan_id,
    						 &_tx_tcc_id,
    					         _tx_event_que,
    						 _tx_edma_callback,
    						 NULL
    					         );
    
    	// ------------------------
    
    	// Get PaRAM sets
    	// --------------
    
    	// Initial trigger channel
    	edma3_result |= EDMA3_DRV_getPaRAM(_edma_handle,
    					   _tx_logical_chan_id,
    					   &_tx_edma_params
    					   );
    
    	// --------------
    
    	// Configure the various transfer parameters
    	// -----------------------------------------
    
    	// Initial trigger channel
    	_tx_edma_params.opt  = (CSL_EDMA3CC_OPT_ITCCHEN_DISABLE << CSL_EDMA3CC_OPT_ITCCHEN_SHIFT) 	                |
    						   (CSL_EDMA3CC_OPT_TCCHEN_DISABLE << CSL_EDMA3CC_OPT_TCCHEN_SHIFT) 	|
    						   (CSL_EDMA3CC_OPT_ITCINTEN_DISABLE << CSL_EDMA3CC_OPT_ITCINTEN_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_TCINTEN_ENABLE << CSL_EDMA3CC_OPT_TCINTEN_SHIFT)  	|
    						   (_edma_uart_tx_evt << CSL_EDMA3CC_OPT_TCC_SHIFT)			|
    						   (CSL_EDMA3CC_OPT_TCCMOD_NORMAL << CSL_EDMA3CC_OPT_TCCMOD_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_FWID_8BIT << CSL_EDMA3CC_OPT_FWID_SHIFT)		|
    						   (CSL_EDMA3CC_OPT_STATIC_NORMAL << CSL_EDMA3CC_OPT_STATIC_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_SYNCDIM_ASYNC << CSL_EDMA3CC_OPT_SYNCDIM_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_DAM_INCR << CSL_EDMA3CC_OPT_DAM_SHIFT)		|
    						   (CSL_EDMA3CC_OPT_SAM_INCR << CSL_EDMA3CC_OPT_SAM_SHIFT);
    
    	_tx_edma_params.srcAddr 	= (Uint32)&_uart_edma_tx_src_buf[1];	// First byte transmitted manually to trigger EDMA
    	_tx_edma_params.destAddr	= (Uint32)&uart_regs->THR;
    	_tx_edma_params.aCnt 		= 1;
    	_tx_edma_params.bCnt 		= 0;									// Dummy value, to be set every time
    	_tx_edma_params.cCnt 		= 1;
    	_tx_edma_params.srcBIdx 	= 1;
    	_tx_edma_params.destBIdx 	= 0;
    	_tx_edma_params.srcCIdx 	= 0;
    	_tx_edma_params.destCIdx 	= 0;
    
    	// -----------------------------------------
    
    	// Enable the initial trigger channel to trigger on a peripheral event
    	edma3_result |= EDMA3_DRV_enableTransfer(_edma_handle,
    						 _tx_logical_chan_id,
    						 EDMA3_DRV_TRIG_MODE_EVENT
    						 );
    
    	if(edma3_result != EDMA3_DRV_SOK) {
    		success = false;
    	}
    
    	_edma_tx_transfers_started = 0;
    	_edma_tx_transfers_finished = 0;
    	_edma_single_byte_tx_cntr = 0;
    	_edma_tx_tcc_mismatch_cntr = 0;
    	_edma_tx_xfer_complete_cntr = 0;
    	_edma_tx_xfer_miss_evt_cntr = 0;
    	_edma_tx_qdma_miss_evt_cntr = 0;
    
    	return success;
    }

    The BCNT parameter is intentionally initially set to 0 so that an EDMA transfer does not occur when the UART generates a Tx event. The idea is that the specific UART Tx EDMA channel is enabled once and then never disabled again. When data becomes for transfer, the EDMA Tx event is triggered manually by writing a single byte to the THR register of the UART.

    _uart_edma_tx_src_buf is a buffer defined in internal memory, so that cache coherence is not necessary.

    When a user wants to transmit data over the UART, the following function is called:

    bool Rm_c6748_uart::transmit(
    		unsigned char const *tx_buf,	// A pointer to the user defined buffer containing the data to be transmitted
    		int data_len					// The length of the user's data to be transmitted
    		) {
    
    	int i;
    	int free_space;
    
    	RTOS_Mutex_Arg arg = RTOS_mutex_enter(_lock_tx_buf);
    
    	if(_tx_buf_wr_idx >= _tx_buf_rd_idx) {
    		free_space = _tx_buf_size - _tx_buf_wr_idx + _tx_buf_rd_idx;
    	} else {
    		free_space = _tx_buf_rd_idx - _tx_buf_wr_idx;
    	}
    
    	// Check if there is enough space in the Tx buffer for the transmission
    	if(data_len > free_space) {
    
    		RTOS_mutex_leave(_lock_tx_buf,arg);
    
    		// Insufficient space!
    		return false;
    	}
    
    	// If there is enough space, copy the data to be transmitted to the Tx buffer
    	for(i = 0; i < data_len; i++) {
    
    		_tx_buf[_tx_buf_wr_idx++] = tx_buf[i];
    
    		// Check if the Tx buffer write index should wrap around
    		if(_tx_buf_wr_idx == _tx_buf_size) {
    			_tx_buf_wr_idx = 0;
    		}
    	}
    
    	RTOS_semaphore_post(_tx_sem_handle);
    
    	RTOS_mutex_leave(_lock_tx_buf,arg);
    
    	return true;
    }

    This awakes a dedicated UART do transmission task in DSP/BIOS, which initiates the EDMA transfer

    void Rm_c6748_uart_edma::do_transmission() {
    
    	CSL_UartRegsOvly uart_regs = (CSL_UartRegsOvly)_uart_base_addr;
    	//EDMA3_DRV_Result edma3_result = EDMA3_DRV_SOK;
    	unsigned int num_bytes_available;
    	int i;
    
    	// Wait for a transmission request to activate this function executing
    	RTOS_semaphore_pend(_tx_sem_handle, RTOS_SYS_FOREVER);
    
    	// Only initiate a UART transmission if an EDMA transfer is not busy.
    	// This can happen when the user calls transmit() while EDMA is still
    	// in progress. When the EDMA has completed, it will post this semaphore
    	// again, so the bytes will eventually be transmitted.
    	if(!_edma_tx_busy_flag && (_tx_buf_wr_idx != _tx_buf_rd_idx)) {
    
    		if(_tx_buf_wr_idx > _tx_buf_rd_idx) {
    			num_bytes_available = _tx_buf_wr_idx - _tx_buf_rd_idx;
    		} else {
    			num_bytes_available = _tx_buf_size - _tx_buf_rd_idx + _tx_buf_wr_idx;
    		}
    
    		// Limit the available bytes to the size of the internal RAM buffer
    		if(num_bytes_available > C6748_UART_EDMA_TX_BUF_SIZE) {
    			num_bytes_available = C6748_UART_EDMA_TX_BUF_SIZE;
    		}
    
    		if(num_bytes_available > 1) {
    
    			_edma_tx_busy_flag = true;
    
    			// Copy the bytes to internal memory so that cache coherence is not necessary
    			for(i = 0; i < num_bytes_available; i++) {
    
    				_uart_edma_tx_src_buf[i] = _tx_buf[_tx_buf_rd_idx++];
    				_tx_buf_rd_idx = _tx_buf_rd_idx % _tx_buf_size;
    			}
    
    			_program_tx_edma(num_bytes_available);
    
    
    		} else {	// else of if(num_bytes_available >= 2)
    
    			_edma_single_byte_tx_cntr++;
    
    			uart_regs->THR = _tx_buf[_tx_buf_rd_idx++];
    			_tx_buf_rd_idx = _tx_buf_rd_idx % _tx_buf_size;
    
    		}
    
    	}	// if(!_edma_tx_busy_flag && (_tx_buf_wr_idx != _tx_buf_rd_idx))
    
    }

    The programming of the UART Tx EDMA is done by this function:

    bool Rm_c6748_uart_edma::_program_tx_edma(
    	unsigned int tx_num_bytes
    	) {
    
    	CSL_UartRegsOvly uart_regs = (CSL_UartRegsOvly)_uart_base_addr;
    	EDMA3_DRV_Result edma3_result = EDMA3_DRV_SOK;
    	bool success = true;
    
    
    	// Get PaRAM sets
    	// --------------
    
    	// Initial trigger channel
    	edma3_result |= EDMA3_DRV_getPaRAM(_edma_handle,
    					   _tx_logical_chan_id,
    					   &_tx_edma_params
    					   );
    
    	// --------------
    
    	// Configure the various transfer parameters
    	// -----------------------------------------
    
    	// Initial trigger channel
    	_tx_edma_params.opt  = (CSL_EDMA3CC_OPT_ITCCHEN_DISABLE << CSL_EDMA3CC_OPT_ITCCHEN_SHIFT) 	                |
    						   (CSL_EDMA3CC_OPT_TCCHEN_DISABLE << CSL_EDMA3CC_OPT_TCCHEN_SHIFT) 	|
    						   (CSL_EDMA3CC_OPT_ITCINTEN_DISABLE << CSL_EDMA3CC_OPT_ITCINTEN_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_TCINTEN_ENABLE << CSL_EDMA3CC_OPT_TCINTEN_SHIFT)  	|
    						   (_edma_uart_tx_evt << CSL_EDMA3CC_OPT_TCC_SHIFT)			|
    						   (CSL_EDMA3CC_OPT_TCCMOD_NORMAL << CSL_EDMA3CC_OPT_TCCMOD_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_FWID_8BIT << CSL_EDMA3CC_OPT_FWID_SHIFT)		|
    						   (CSL_EDMA3CC_OPT_STATIC_NORMAL << CSL_EDMA3CC_OPT_STATIC_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_SYNCDIM_ASYNC << CSL_EDMA3CC_OPT_SYNCDIM_SHIFT)	|
    						   (CSL_EDMA3CC_OPT_DAM_INCR << CSL_EDMA3CC_OPT_DAM_SHIFT)		|
    						   (CSL_EDMA3CC_OPT_SAM_INCR << CSL_EDMA3CC_OPT_SAM_SHIFT);
    
    	_tx_edma_params.srcAddr 	= (Uint32)&_uart_edma_tx_src_buf[1];	// First byte transmitted manually to trigger EDMA
    	_tx_edma_params.destAddr	= (Uint32)&uart_regs->THR;
    	_tx_edma_params.aCnt 		= 1;
    	_tx_edma_params.bCnt 		= tx_num_bytes-1;									
    	_tx_edma_params.cCnt 		= 1;
    	_tx_edma_params.srcBIdx 	= 1;
    	_tx_edma_params.destBIdx 	= 0;
    	_tx_edma_params.srcCIdx 	= 0;
    	_tx_edma_params.destCIdx 	= 0;
    
    	// -----------------------------------------
    
    	// UART logical Tx channel
    	edma3_result |= EDMA3_DRV_setPaRAM(_edma_handle,
    					   _tx_logical_chan_id,
    					   &_tx_edma_params
    					   );
    
    	// --------------
    
    	EDMA3_DRV_checkAndClearTcc(_edma_handle,
    				   _tx_logical_chan_id,
    				   &_tx_tcc_status
    				   );
    
    	if(edma3_result == EDMA3_DRV_SOK) {
    
    		_edma_tx_transfers_started++;
    
    		// Manually write the first byte to the THR register so that the
    		// EDMA event can be triggered
    		uart_regs->THR = _uart_edma_tx_src_buf[0];
    
    
    	} else {
    
    		success = false;
    	}
    
    	return success;
    }

    The EDMA UART Tx callback function:

    void Rm_c6748_uart_edma::edma_tx_complete_callback(
    		unsigned int tcc,
    		EDMA3_RM_TccStatus status,
    		void *app_data
    		) {
    
    	_edma_tx_transfers_finished++;
    
    	if(_edma_tx_transfers_finished != _edma_tx_transfers_started) {
    
    		dummy_func();
    	}
    
    	if(tcc != _tx_tcc_id) {
    		_edma_tx_tcc_mismatch_cntr++;
    	}
    
    	if(status == EDMA3_RM_XFER_COMPLETE) {
    		_edma_tx_xfer_complete_cntr++;
    	}
    
    	if(status == EDMA3_RM_E_CC_DMA_EVT_MISS) {
    		_edma_tx_xfer_miss_evt_cntr++;
    	}
    
    	if(status == EDMA3_RM_E_CC_QDMA_EVT_MISS) {
    		_edma_tx_qdma_miss_evt_cntr++;
    	}
    
    	_disable_tx_edma();
    
    	_edma_tx_busy_flag = false;
    
    	// Notify the reception task that a buffer has become available
    	RTOS_semaphore_post(_tx_sem_handle);
    }

  • Doing some further testing, I have found that the EDMA callback function is called more than the amount of EDMA transfers initiated. I have also noticed that I am EDMA event miss callbacks (i.e. status == EDMA3_RM_E_CC_DMA_EVT_MISS), which I cannot explain yet.

    Two questions so far:

    1) Am I programming the UART Tx EDMA correctly?
    2) Am I handling the EDMA callbacks correctly?
  • Hi,

    I believe, if the transfer configuration params (BCNT=0, kept intentionally) are not valid for the triggered DMA channel, I don't think specific UART Tx EDMA channel would be enabled even once and no scope for disabling thereafter. Kindly validate bCnt = 0 when aCnt =1 on the function Rm_c6748_uart_edma::_init_tx_edma( ) below:

    _tx_edma_params.aCnt = 1;

    _tx_edma_params.bCnt = 0; // Dummy value, to be set every time

    _tx_edma_params.cCnt = 1;

    _tx_edma_params.srcBIdx = 1;

    _tx_edma_params.destBIdx = 0;

    _tx_edma_params.srcCIdx = 0;

    _tx_edma_params.destCIdx = 0;



    How come destBIdx can be 0 when srcBIdx is 1? could you please validate the below snippet on the function Rm_c6748_uart_edma::_program_tx_edma( )

    _tx_edma_params.srcBIdx = 1;

    _tx_edma_params.destBIdx = 0;


    Kindly validate the above code excerpts while initializing tx edma and program tx edma. I believe, the above bCnt=0 wouldn't be valid even for enabling UART Tx EDMA channel once though it is kept intentionally. Again the same too for destBidx =0 which is also not valid when srcBIdx =1 .

    Thanks & regards,
    Sivaraj K
  • Reinier,

    Some general comments/questions:

    1. The EVT_MISS will occur when your transfer has completed, the default linkAddr=0xFFFF (I assume), and another UART Tx event gets to the EDMA. The error handler will take care of clearing EMR/EMRH, but nothing can happen on that DMA channel until that is taken care of. There is a better write-up about EMR in the EDMA3 User's Guide or the TRM. You can avoid these by creating a Dummy Param set with one of the three count fields 0 and the others 1, and link each transfer channel to that Dummy Param set.

    2. It is possible that your Tx problem could be solved by doing the above with the Dummy Param and letting it generate your interrupt. That would mean turning off TCINTEN for the main transfer Param. This would mean that when your UART Tx DMA sends the last byte (n-1) of a transfer, it will not immediately send an interrupt, but when that last byte gets shifted out and the UART sends an extra event for data then the Tx DMA channel will have a Dummy Param set (so it will not send a new byte) but it will still generate an interrupt saying the transmission is complete.

    3. My original thought was that you have some big stalls in the EDMA3 operation which causes something bad to happen with the DMA channels operating too slowly. But that only explains missing bytes, not swapped bytes and not excess callbacks.

    4. To test for #3, you could move the two UART Rx channels to TC0 so they do not compete with the Tx channels so much. If that changes things + or -, then at least you would have some good information.

    5. Another good test for #3 is to turn off the McASP operation or the UART Rx or one of the UART Tx channels, and see if that changes things + or -.

    6. When you get swapped bytes, is it always the first two bytes of a transfer set that get swapped?

    My thought now is that you have a race condition between the last byte coming in and the next transfer starting. If you get the Tx event that triggers the last byte to be sent, you will get the interrupt immediately. This will cause a new transfer Param to be created and a new write to THR to start the next transfer.

    But there will be an event coming in after that last byte is moved to the UART Tx shifter, and now you have a race condition. That extra event will occur one byte time after the last good byte was written out. In that amount of time, you could have

    - written a new Param set to the DMA channel, or not; if written, then a new byte will get copied out unintentionally; if not written, then an event missed could occur.

    - written a new first byte to THR, or not; if written before the 'one byte time', then this byte will be ready to go out and might cause an event to be skipped or the event might cause a new second byte to be written already and the transfer count could be off by 1.

    I will wait to hear back before more speculations.

    Regards,
    RandyP
  • Hi Randy,

    Thank you for your detailed response, it was definitely very helpful.

    I decided to abandon the idea of configuring the EDMA once and then modifying the PaRAM set before each transfer (without ever disabling the logical channel). This approach was simply not reliable. Instead I program an EDMA transfer every time new bytes become available. This approach still feels messy, especially if you are not transmitting a lot of data, but I really do not know of an alternative way to use the EDMA. I would prefer to program the EDMA once and leave it to do its thing. 

    In the meantime, it also occurred to me that the "additional" EDMA callbacks I am receiving, were indeed EDMA miss events, which was due to the last user byte being transmitted followed by the UART EDMA FIFO empty event. Of course at this point there are no more user bytes to transmit so the UART Tx EDMA event is not handled. This is basically what you described in 1).

    Your idea to link a dummy PaRAM set is a very good one, I am not sure why this did not occur to me! 

    I disabled TCINTEN on the main PaRAM set and enabled it on the dummy link PaRAM set. I configured the dummy link PaRAM set to transfer one byte to the UART's scratch pad (SCR) register, i.e. ACNT = BCNT = CCNT = 1.

    Having done this, I get an exact 1:1 mapping for EDMA transfers initiated and callbacks. I believe my main problem was the UART and EDMA synchronization due to the miss events. For good measure I also discovered that under certain conditions, the data arriving at the UART was already corrupted, which added further uncertainty (but this is a separate topic).

    So far the UART driver seems to be stable, but I am busy with more extensive tests to verify that it is working properly.

    Thank you again for the assistance, I will let you know if I encounter further problems.

  • Hi,

    Thanks for your update.

    May be, it is good to sort out the corrupted data arriving at the UART which is uncertain and hopefully, this could also fix the missed events overcoming the UART and EDMA synchronization.

    Thanks & regards,
    Sivaraj K