I was trying the example uartEcho_edma (C:\Program Files\Texas Instruments\StarterWare_02_00_00_04\examples\beaglebone\uart_edma) on beaglebone. The first DMA transfer worked and printed out the first line ("StarterWare AM335X UART DMA application"). The second DMA transfer didn't work. The program didn't print the second line ("Please Enter 08 bytes from keyboard"). The program kept waiting for the completion of the second DMA transfer. If I re-initialized the UART after the first DMA transfer, then the second DMA transfer would work.
What's the correct way to configure UART and DMA for repeated DMA transfers? Thanks for your help!
Hello Yanli,
Firstly, have you defined the macro UART_ENABLE_FIFO in the application file ? If so, then the application would not work and this has come to our notice during our regular software tests.
I would like to briefly explain the issue so that you gain an insight into the same.
There are two modes in which UART could be operated - non-FIFO mode and FIFO mode. The FIFO mode of operation is where a dedicated 64 byte FIFO for transmission and a similar one for reception are used by the UART during transmission and reception. Whereas in the non-FIFO mode of operation, the above mentioned FIFOs are not used during transmission and reception. We observed in the UART EDMA application that consecutive transmissions are not happening in FIFO mode of operation of UART (the first TX transaction happens but the immediate next one does not start) and that the same works well in non-FIFO mode.
You would have observed the problem that you stated when FIFO mode of UART operation is used (UART_ENABLE_FIFO macro is defined). The application in its default form does not use FIFOs and therefore the application works as expected.
An internal communication in TI regarding this issue is in progress. This issue when fixed shall be included in the future releases.
Please revert back for any queries.
Thanks and Regards.
Gurudutt
Hello Gurudutt,
Thanks for your reply. I didn't define UART_ENABLE_FIFO, but the second DMA transfer still didn't work. The release notes (ReleaseNotes_02_00_00_04.pdf) had this on page 3:
"UART EDMA example not working consistently with AM335X EVM and Beagle Bone"
If it is "not working consistently", do you know when it does work? Thanks!
--Yanli
I suppose you are referring to StarterWare 02.00.00.04 release. I tested the ELF executable (.out) of UART EDMA application (found in the path - binary\armv7a\cgttms470_ccs\am335x\beaglebone\uart_edma) through CCS on a Revision A1 BeagleBone board and it works as expected. Both the strings get displayed and reception also works.
As I had mentioned before, the default state of the file does not define the macro UART_ENABLE_FIFO. Since the non-FIFO mode is used, the application should work.
Are you testing the ELF executable or the binary image of the application ?
Could you test the pre-built executable of this release and post me about the results ?
The pre-built executable worked for me too. The one I built through CCS (without any changes to the source codes) didn't work.
Thanks,
Yanli
Gurudutt,
Can you confirm that you can rebuild the UART_DMA example and that the .out file runs correctly?
Thanks,Charles
Hello Charles/Yanli,
I tested the executable of UART EDMA application obtained through CCS build and Cygwin build on a Revision A1 Beaglebone board. The application worked successfully and desired results were obtained.
I have attached a compressed file with this post containing the executable that I used for my tests.
I would like to explain the method I followed to build the application, load the executable through CCS and test it on a Beaglebone board.
CCS Build
The CCS project for UART EDMA application is present in the following path:
“<StarterWare_02_00_00_04 Installation path>\build\armv7a\cgttms470_ccs\am335x\beaglebone\uart_edma”
Steps to import and build the CCS project:
The executable will be available in the following path:
“<StarterWare_02_00_00_04 Installation path>\binary\armv7a\cgttms470_ccs\am335x\beaglebone\uart_edma”
Steps to load the executable:
Cygwin Build
Steps to build the GCC makefile through Cygwin:
“<StarterWare_02_00_00_04 Installation path>\binary\armv7a\gcc\am335x\beaglebone\uart_edma”.
Load and test the executable by following the procedure mentioned above.
The information mentioned above shall be redundant to you if you are adept in using CCS.
But I wanted to make sure that we are standing on a common ground before going ahead.
Gurudutt.
The attachment which I mentioned before is with this post.
Compiling with Optimization Level 0 (in TMS470 Compiler Basic Options) made the example work as expected. But if I modified the source codes in the example without changing configuration of UART or EDMA, it stopped working again...
I see that you have mentioned two observations in your email.
- Compiling with Optimization Level 0 (in TMS470 Compiler Basic Options) made the example work as expected.
- But if I modified the source codes in the example without changing configuration of UART or EDMA, it stopped working again...
I am working with Yanli on this project.
According to the TMS470 compiler documentation, leaving the optimization setting blank does not assume level 0. Level 0 and no optimization are different as shown below.
• --opt_level=0 or -O0– Performs control-flow-graph simplification– Allocates variables to registers– Performs loop rotation– Eliminates unused code– Simplifies expressions and statements– Expands calls to functions declared inline
Although enabling various levels of optimization does sometimes make the code work, it is not a permanent fix. There appears to be some problem, perhaps hardware related, that requires a full reset of the UART before a message can be transmitted using DMA. We would like to get to the root cause of this in order to determine the best way to handle it without having to fly blind.
Our applications rely heavily on multiple asynch serial communications and we must have confidence that they will function properly.
Randy Ott
Hello Randy,
I appreciate your effort in enlightening me about the fact that No Optimization and Optimization Level 0 are different.
I am equally coherent with your proposal that a permanent solution should be arrived at regarding this issue. Experimenting with various Optimization Levels and making the application work shall truly be a temporary solution.
As I have already mentioned, a discussion thread is underway in TI and people are investigating this issue. Currently, I do not have updated information about the progress they have made. I will certainly get back to you once I am abreast with the latest information. If situation demands, a person who is well versed with this problem will pitch in and give his opinion. If a fix has been arrived at for this problem, then it shall be incorporated as a part of the future releases.
I will get back to you with the latest information as early as possible.
static void callback(unsigned int tccNum, unsigned int status)
{
/* Disabling DMA Mode of operation in UART. */
UARTDMADisable(SOC_UART_0_REGS);
/* Disabling DMA transfer on the specified channel. */
EDMA3DisableTransfer(SOC_EDMA30CC_0_REGS, tccNum, EDMA3_TRIG_MODE_EVENT);
clBackFlag = 1;
}
If you set a breakpoint at "UARTDMADisable(SOC_UART_0_REGS);",The program will TX "StarterWare AM335X UART DMA application" only.
Or, If you add same code at the front of the "UARTDMADisable(SOC_UART_0_REGS);",The program will TX "StarterWare AM335X UART DMA application" only.
So I think the problem is :
If the program can not disabling DMA Mode of operation in UART immediately after the EDMA3 Completion,the EDMA3 will not miss the uart request, but the uart will not send the request anymore. So if you reinitializes the UART0,the EDMA3 will receive the uart request again.
The EDMA3EnableTransfer is in the edma.c of the drivers.
If I add "if( chNum==26 ) EDMA3SetEvt(baseAdd, chNum);" at the front of "EDMA3EnableDmaEvt(baseAdd, chNum);" at the EDMA3EnableTransfer.
The problem is resolved. But why?
unsigned int EDMA3EnableTransfer(unsigned int baseAdd, unsigned int chNum, unsigned int trigMode)
unsigned int retVal = FALSE;
switch (trigMode)
{ case EDMA3_TRIG_MODE_MANUAL :
if (chNum < SOC_EDMA3_NUM_DMACH) { EDMA3SetEvt(baseAdd, chNum); retVal = TRUE; } break;
case EDMA3_TRIG_MODE_QDMA :
if (chNum < SOC_EDMA3_NUM_QDMACH)
{ EDMA3EnableQdmaEvt(baseAdd, chNum); retVal = TRUE; } break;
case EDMA3_TRIG_MODE_EVENT :
if (chNum < SOC_EDMA3_NUM_DMACH)
/*clear SECR & EMCR to clean any previous NULL request */
EDMA3ClrMissEvt(baseAdd, chNum);
if( chNum==26 ) EDMA3SetEvt(baseAdd, chNum);
/* Set EESR to enable event */
EDMA3EnableDmaEvt(baseAdd, chNum);
retVal = TRUE;
} break;
default : retVal = FALSE; break;
} return retVal;
If I del "EDMA3ClrMissEvt(baseAdd, chNum);" at the EDMA3EnableTransfer.
The problem is resolved, too. I think it better than add "if( chNum==26 ) EDMA3SetEvt(baseAdd, chNum);" at the front of "EDMA3EnableDmaEvt(baseAdd, chNum);" at the EDMA3EnableTransfer.
//EDMA3ClrMissEvt(baseAdd, chNum);