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.

[C6747] UART EDMA Sample Questions

Hi,

I have an C6747 starter kit with CCS v3.3 and BIOS 5.33.05.  I am reviewing the UART EDMA sample code from
C:\Program Files\Texas Instruments\pspdrivers_01_20_00\packages\ti\pspiom\examples\evm6747\uart\edma\src\uartSample
I have the following questions:
1. This sample code is using UART0 and it is using BIOS configuration to configure the user function.  Since the starter kit has the UART2 available with RS232 DB9 connector, I want to use UART2 instead.  The sample code is not easy to follow fo this effort.  Could you provide a sample code fo UART2?  If not, please provide all information need to be changed for UART2.

2. In the BIOS 'UART0 properties', what is the 'device id' of 2 means?

3. I am reading the C6747 EDMA3 Controller User's Guide SPRUFL1C.  This is a complex DMA setup with EDMACC and EDMATC.  I do not see any of this in the sample code instead of the GIO_create() and GIO_submit().  My guess of the "/UART0" in the GIO_create() function is it has to match with the BIOS 'User-Defined Devices'.  Is this correct?

4. Is GIO_submit(hUart_OUT,IOM_WRITE, buf, &len, NULL) is a blocking function?  If I am sending 200 bytes out, will this function will be blocked and the rest of my tasks still running?

5. This example is not a good DMA example.  In my past experiences, the typical DMA example code with other processors to send a block of data, the application fills up the Tx buffer and calls the DMA function.  This DMA function returns right away.  When the Tx complete, the application will get an interrupt.  Similarly, the applicaton setup a DMA channel for UART Rx, the Rx buffer is fill up with data.  The application will get an interrupt when there is data available either due to a timeout after the last receive byte or the buffer length.  Do you have this type of UART EDMA sample code?

6. My last question is how reliable of using UART EDMA with baud rate 115200 at any DSP clock speed (25MHz-300MHz)?  My concern is I read some problems from the forums that people experienced dropped data with UART EDMA.  Is there any information or tips for reliable UART EDMA data transferring?  There are times in my applications will transfer 80K bytes of data in battery powered device.  I will try to minimize the retries as much as possible.

Thanks,

Dennis

  • Dennis Nguyen said:
    6. My last question is how reliable of using UART EDMA with baud rate 115200 at any DSP clock speed (25MHz-300MHz)?  My concern is I read some problems from the forums that people experienced dropped data with UART EDMA.  Is there any information or tips for reliable UART EDMA data transferring?  There are times in my applications will transfer 80K bytes of data in battery powered device.  I will try to minimize the retries as much as possible.

    From a hardware throughput standpoint, 115200 Baud should not be a problem: http://processors.wiki.ti.com/index.php/OMAP-L1x/C674x/AM1x_UART_Throughput_and_Optimization_Techniques

    I will need to defer to the BIOS experts for the other questions.

    -Tommy

  • Hi Dennis,

    Dennis Nguyen said:
    This sample code is using UART0 and it is using BIOS configuration to configure the user function.

    The uartSample.tci specifies the name of the device as "UART0". However what is being used is UART instance 2. This can be seen by the "deviceId" being specified as 2. This deviceId actually tells the driver to instantiate the respective device instance. This can be seen in mdBindDev driver function (uartMdBindDev()), which is called when the driver driver/instance is being created or instantiated. The sample application binary provided in the package should thus run out-of-the box on the EVM/starter-kit.

    Dennis Nguyen said:
    In the BIOS 'UART0 properties', what is the 'device id' of 2 means?

    This is to specify which device instance is being instantiated by the driver/sample application.

    Dennis Nguyen said:
    I am reading the C6747 EDMA3 Controller User's Guide SPRUFL1C.  This is a complex DMA setup with EDMACC and EDMATC.  I do not see any of this in the sample code instead of the GIO_create() and GIO_submit().

    The driver supports three mode of operation - Polled mode, Interrupt mode and DMA-Interrupt mode (EDMA mode). If one is intending to use the EDMA mode of operation, then in the driver parameters Uart_params the "opMode" should be specified as Uart_OpMode_DMAINTERRUPT. Please refer to user_uart0_init() of the sample application. Also, the driver should be compiled with UArt_EDMA_ENABLE option. Please refer to the driver project file uart.pjt and the source files. Once this is done, the driver takes care of EDMA related routines/initialization like request EDMA channels, setting up EDMA parameters etc. Please refer to driver Uart.c/uartMdCreateChan() and Uart_edma.c/Uart_localStartEdmaTransfer() for more details. The driver takes care of EDMA related initialization and parameter programming, which is distributed across the driver . The user needs to just specify that EDMA mode of operation is intended and the driver needs to be enabled for EDMA related code. It is also required to instantiate the EDMA driver by calling its sole edma3inti() function and passing appropriate handle to the driver as in the case of sample application.

    Dennis Nguyen said:
    My guess of the "/UART0" in the GIO_create() function is it has to match with the BIOS 'User-Defined Device.  Is this correct?

    Yes. The UART device "/UART0" is created as a user defined device.  If the uartSample.tcf file is opened using CCS3 in GUI mode, it appears under "Input/Output"->"Device drivers"->"User-Defined devices".

    Dennis Nguyen said:
    Is GIO_submit(hUart_OUT,IOM_WRITE, buf, &len, NULL) is a blocking function?  If I am sending 200 bytes out, will this function will be blocked and the rest of my tasks still running?

    Since the callback function is specified as NULL, the GIO_submit(...) is a synchronous call. Thus this call would block and the respective task (calling this function) would sleep. While other task can still run. However, by design, the drivers are asynchronous and the application can make an synchronous call to the driver with the application callback being specified. This would not be a blocking call. Please refer to DSP/BIOS API reference guide for more details on making asynchronous GIO_submit calls.

    Dennis Nguyen said:
    . This example is not a good DMA example.  In my past experiences, the typical DMA example code with other processors to send a block of data, the application fills up the Tx buffer and calls the DMA function.  This DMA function returns right away.  When the Tx complete, the application will get an interrupt.  Similarly, the applicaton setup a DMA channel for UART Rx, the Rx buffer is fill up with data.  The application will get an interrupt when there is data available either due to a timeout after the last receive byte or the buffer length.  Do you have this type of UART EDMA sample code?

    The sample applications demonstrate the interfacing with the driver. The driver is designed to provide a level of abstraction - like EDMA channel allocation/request, EDMA parameter programming etc. Thus the application may not worry much about these and proceed with simply specifying the mode of operation and the driver does the rest. If the user is interested in the low level operations/initialization one can always browse through the driver code.

    Dennis Nguyen said:
    My last question is how reliable of using UART EDMA with baud rate 115200 at any DSP clock speed (25MHz-300MHz)?  My concern is I read some problems from the forums that people experienced dropped data with UART EDMA.  Is there any information or tips for reliable UART EDMA data transferring?  There are times in my applications will transfer 80K bytes of data in battery powered device.  I will try to minimize the retries as much as possible.

    The later versions of the driver have improved upon the configuration of EDMA parameters, for better handling of faster data rate. These releases are available on the download site. The latest versions are 01.30.01. Please note that in these versions there has been addition of more features and hence the driver parameters may contain additional members.

  • If I read your response right, the uartSample project shold work with the C6747 starter kit.  I have the UART2 connector with a loop back Tx/Rx wite.  The tx 'status' of

     status = GIO_submit(hUart_OUT,IOM_WRITE, buf, &len, NULL);

    is zero which is good.  However, I could not get the reading complete.  The sample code hangs at:

        status = GIO_submit(hUart_IN,IOM_READ,buf,&len,NULL);

    from genericUartTest() function in uartSample.c.  Please let me know what could cause this issue.

    Thanks,

    Dennis

  • Dennis Nguyen said:
    If I read your response right, the uartSample project shold work with the C6747 starter kit.

    Yes. The application setup is explained in the "Uart sample application" section of the User guide.

    Dennis Nguyen said:
    I have the UART2 connector with a loop back Tx/Rx wite.

    So, the UART is connected in the external loopback mode. In the case of GIO request, the sequence followed as seen above, is the write request is submitted first and then the read request.

    However, when the write starts and the written bytes are not read (a read request is not yet issued to the driver), then there will be receive overruns occurring and the received bytes are discarded. The write would complete successfully though. Now, subsequently when the read request is issued, there are no writes to satisfy the entire request length and thus the read request blocks waiting for the data.

    Thus in case of loopback mode options below could be used:-

    1. Use asynchronous GIO_submit (with a valid callback argument.. refer to DSP/BIOS API reference guide). First issue a read request to the driver. The driver queues this request, while the control comes back to the application. The status of the operation is via callback (supplied in the callback argument of the GIO_submit) notification. Now, issue write request. This write can be asynchronous or synchronous call.
    2. Else, if only synchronous GIO_submit calls are preferred. Use two tasks, one for read and one for write. The read task must be of higher priority that the write and read task must be first created. The read task comes up first and issues read request to the driver, blocks/sleeps. Now the write task comes up and proceeds with the write request.

    In both options above, the read request is already present in the driver to consume any incoming data thus preventing receive overruns.

    It is also recommended that you use the latest release package from here:

     

    http://software-dl.ti.com/dsps/dsps_public_sw/psp/BIOSPSP/01_30_01/index_FDS.html

    This release contains some improvements in handling concurrent read/write operations inside the UART driver. Please also note that this version contains additional features and hence you may see some additional parameters for the driver creation/channel creation and thus have to adapt you application for the same.

  • Hi,

    Your reply: "Use asynchronous GIO_submit (with a valid callback argument.. refer to DSP/BIOS API reference guide). First issue a read request to the driver. The driver queues this request, while the control comes back to the application. The status of the operation is via callback (supplied in the callback argument of the GIO_submit) notification. Now, issue write request. This write can be asynchronous or synchronous call."

    This scenario work ok if the Rx length is known.  I looked in the BIOS PSP User Guide document but I could not find a way to set up the UART EDMA driver to interrupt my call back function when there is a time gap in the receiving channel.  My application will receive UART Rx data with undetermined data length.  It could be from 1 byte to hundred of bytes.  I would like to get the interrupt as soon as the pachet(s) arrive may be after a couple msec.  Please point me to the right direction.

    Thanks,

    Dennis

  • Dennis,

    There is a timeout member in the GIO_Obj struct which can be used to specify a timeout for the blocking function. You can pick an appropriate value for timeout other than SYS_FOREVER to get a return call after a delay.

    I did a search on E2E within the ARM & DSP forums for "UART GIO" (no quotes), and found a very applicable thread at http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/112/p/11690/45653.aspx . This thread discusses determining how many bytes were actually placed in the buffer in the event of a timeout. This should be very helpful if the GIO timeout feature will work for you.

    In addition, you will want to make a decision on the size of the buffer to get the best tradeoff between buffer size and timeout. This is because the timeout will be counted from the beginning when the GIO_submit() call is made rather than from the end when the most recent byte was received. Depending on the specific nature of your expected data flow, this may work for you or a more customized driver will be needed.

    For example, if the incoming data will be continuous until it ends, the timeout tradeoff will only have to consider the time before the incoming data begins. But there could be a significant chance of a race condition if the incoming data might not start for a long time, and you need to restart the GIO_read() after a lot of empty timeouts.

    But what you have described may be a very specific requirement with a very customized data flow specification. I will hope that you can find a solution with the sample applications in the PSP, or with a slight modification. But you may have to make some changes at the lowest level to how the EDMA is used and add the use of a timer. For example, after every byte is received by the EDMA, that EDMA channel could chain to a transfer channel that writes a value to a running timer to reset its count. After each byte is received, the timer would get reset to allow 2ms, for example, before expiring and generating a timer interrupt. You might even find a clever way to have the very first byte received to cause the timer to start, so that you do not get an interrupt 2ms after the initial GIO_read is submitted.

    Just food for thought. Let us know if this helps or if you have additional questions.