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.

AM3352: TI-RTOS ((SYS / BIOS 6.76.3.01)) UART-driver 115200bps full-duplex communication

Part Number: AM3352
Other Parts Discussed in Thread: SYSBIOS

I am using AM3352 TI-RTOS (SYS / BIOS 6.76.3.01). I want to perform asynchronous 115200bps full-duplex communication with UART3. Currently, 10-byte packets can be received every 4 ms. In addition to that, I am trying to additionally send a command of 5 to 8 bytes and receive a response of about 6 to 21 bytes. Q1. Is the UART driver receiving by interrupt? Q2. Is full double communication possible? For now, it sometimes looks like it's not being received.

  • he functions used are UART_readPolling and UART_writePolling. The TI-RTOS timer sets a timeout of 1ms, a timeout of 1ms for reception, and a timeout of 4ms for transmission.
    The receive routine is set to read up to 16 bytes every 2 to 3 ms. Send only when requested. The maximum is about 10 bytes. Does the UART driver use interrupts? Is it working only with FIFO?
    Is there any other information needed for the investigation?
    Thank you for your investigation.

  • Hello Tetsuo,

    Thank you for your question.  I am currently consulting with my colleagues about this topic, and I hope to have an answer/update for you within the next 1-2 business days. 

    Thank you for your patience, and for the additional information.

    Best regards,

    Andrew

  • Thank you for your response.
    It seems that the problem of missing received data occurred when the required data was not available in the received data analysis part. Received data leakage can now be avoided by recursively calling UART_read_pollng () in the received data analysis part until the required data is received.
    All data is received with a timeout of 1ms.
    Is there any problem with this method?

  • Hello Tetsuo,

    Thank you for the additional information, we apologize for the delayed response due to the US holiday.  I do not see any issues with the method you described, are you observing any unintended side-effects from your implementation? 

    -Andrew 

  • thank you for your reply.

    UART communication seems to be fine for now. If you use memcpy () in an application in the same environment, it may terminate abnormally. Has the memcpy() function been proven in the environment of AM3352 TI-RTOS (SYS / BIOS 6.76.3.01).

  • Dear andrew
    I'm still debugging uart communication.
    I sent 40 bytes of data with the UART_writePolling function, but I had to set the timeout time to 20 msec or more to send all the data at once. When I actually check it with a protocol analyzer, it seems that only 2 to 4 bytes of data can be transmitted in 1 msec. Since it is 115200bps, it may be possible to send up to 11 bytes.
    Is the function you have selected appropriate?
    I would be grateful if you could give me good advice.

  • Hello andrew
    Self-less and additional questions.
    As a test, I changed the UART_writePolling function to the UART_write function, and now it sends continuously. What is the difference between the behavior of these two functions?

  • Hello Tetsuo,

    Thank you for the additional information,  I have relayed your follow-up questions to the team, I will update you with their response.

    -Andrew 

  • Hello Tetsuo,

    Thank you for your patience, in answer to your follow-up question, the team directed me to this E2E thread, explaining the difference between the two functions you specified: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/465080/what-difference-is-between-uart-functions-uart_writepolling-and-uart_write 

    here is the relevant section:

    "

    UART_writePolling() (assigned to UARTTivaDMA_writePolling on Tiva, in file UARTTivaDMA.c) calls the TivaWare API UARTCharPut(), continuously, in a while loop, writing a single character per loop iteration.  This function does not yield execution to other Tasks, it loops until all data has been transferred (hence the polling name).  This polling style will "hog" the CPU until the transfer is complete.

    UART_write() (assigned to UARTTivaDMA_write on Tiva, in file UARTTivaDMA.c) uses TivaWare APIs to set up the write of the given buffer as a DMA transaction.  The function yields by means of calling Semaphore_pend().  This allows other Tasks in the system to run while the DMA is making the transfer in the background.  Once the transfer is complete, the Semaphore will post, allowing the Task that called UART_write to unblock and continue.  This won't "hog" the CPU, as other Tasks were allowed to run while the DMA was taking care of the transfer in the background.

    You can find more info on these TivaWare APIs in this document: http://www.ti.com/lit/ug/spmu298a/spmu298a.pdf"

    Does this information give more clarity on how to adjust your implementation? 

  • Dear Andrew

    Thank you for your interesting reply.

    Does the UART_write function not give up execution to another task?

    The source code of the AM3352 UART driver is
    C: \ ti \ ppk_am335x_1_0_17 \ packages \ ti \ drv \ uart
    I think it's the code in, but is it correct?
    UARTTivaDMA.c was not found there.
    C: /ti/pdk_am335x_1_0_17/packages/ti/drv/uart/soc/dma/v1/UART_dma.c
    There was.

    So far, the process using UART_write seems to be working fine.
    I heard that UART_writePolling does not give execution to other tasks, but isn't it using a transmit FIFO?

    I'm using UART_readPolling for reception with timeout 1msec,
    Isn't this also given to other tasks?

    There is V0 / V1 / V2 in the driver source code,
    Which one is used in the AM3352 TI-RTOS?

    Thank you.

  • Hello Tetsuo,

    So I think I found a better, more in depth, thread on the UART_Write function and UART_polling function for the AM335 https://e2e.ti.com/support/processors-group/processors/f/processors-forum/863164/am3358-uart-write-callback 

    There are a couple of answers here that I think are relevant and insightful, I have copied some below:

    "

    UART_write() is used in interrupt mode. Please check if you have enabled interrupts in UART module and Cortex-A8 MPU.

    I can also suggest you to:

    - try with polling mode, UART_readPolling() and UART_writePolling(). In polling mode, no interrups are needed

    - try with the default main_uart_test.c UART test. Check if this test is running fine on your BeagleBone Black board then align your custom test to this UART test.

    pdk_am335x_1_0_16/packages/ti/drv/uart/test/am335x/armv7/bios/UART_BasicExample_bbbAM335x_armTestProject.txt

    pdk_am335x_1_0_16/packages/ti/drv/uart/test/src/main_uart_test.c

    pdk_am335x_1_0_16/packages/ti/drv/uart/soc/am335x/UART_soc.c

    pdk_am335x_1_0_16/packages/ti/drv/uart/test/am335x/armv7/bios/am335x_app_bbbam335x.cfg"

    "

    >> I need to use UART_write, or another application, to feed UART_read and trigger its callback function.

    To use UART_write() on the same core as UART_read():

    • Connect the Tx pin for the 'write' UART to the Rx pin for the 'read' UART in an external loopback
    • For UART_read()/UART_write() in the same SYSBIOS Task: issue UART_read() in UART_MODE_CALLBACK before UART_write() . This will allow the UART_read() to return so UART_write() can be called. You could issue UART_write() in UART_MODE_CALLBACK before UART_read(), but some characters might be lost if insufficient buffering is available in the UART FIFO to accommodate the delay between the write and read functions.
    • For UART_read()/UART_write() in different SYSBIOS Tasks: set the UART_read() to occur first, e.g. by setting the "reader" Task as higher priority than the "writer" Task.

    For the case of another application, I assume you mean the UART write will be performed on some other hardware (BBB or not) using some other software (PRSDK or not). In this case, simply connect the other hardware Tx pin (this app will perform the UART write) to the BBB Rx pin (this app will perform the UART_read()). You can manually synchronize the UART write and UART_read() by first running the BBB application, and then running the "other" application to avoid losing UART characters due to insufficient buffering in the UART FIFO. Additional code could be added to both applications to implement an automatic synchronization scheme (e.g. some sort of GPIO handshaking).

    There is a test program written for the UART PRU firmware which extensively uses loopback testing. Details can be found at the following locations:

    As for your question on version mapping:

    On AM335x, UART_open() (and other UART functions) are defined in src\v1\UART_v1.c. You can refer to <PDK>\packages\ti\drv\uart\soc\UART_soc.h to understand the V0 and V1 mapping for particular SoCs.

    Does this help clarify your use case?

    -Andrew 

  • Andrew
    Thank you for your detailed answer.

    AM3352 I have confirmed the source code of the UART function.
    I'm looking at the UART_readPolling_v1 function.

    Call the UART_charGet_v1 () function
    Furthermore, the UARTCharGetNonBlocking2 () function is called.

    Q1. Where is the source code of the UARTCharGetNonBlocking2 () function?
    Q2. Please tell me the specifications of this function.

    Q3. How many characters do you read?

    Q4. When called from task, UART_osalDelay (1U) is
    Is it Task_sleep (1) ;?

    Q5. In that case, do you pass the process to another task?


    The UART_readPolling task is looped around with the Task_sleep (1); code.
    In that case, the operation is once in one loop if the received data can be read immediately for the requested size.
    If it cannot be read, Task_sleep (1); is called twice in one loop, and another task is called.
    Is it correct in the operation that the processing is passed?

    Q6. SYS / BIOS -Basic RunTime Option
    Are there any necessary settings? ??

    Thank you

  • Hello  Tetsuo,

    Thank you for your patience, I have relayed your follow up questions to the team and I am working to investigate as well.  Unfortunately, responses may be delayed during this holiday season, but I will be sure to update you as soon as possible.

    Best regards,

    Andrew 

  • Hello Tetsuo,

    The team is now back in, so I have resent your follow up questions to them and I hope to be able to relay their response soon.  

    -Andrew

  • Hello Tetsuo,

    Thank you for your patience, I have an update from the team regarding your questions:

    1&2:

    Q1. Where is the source code of the UARTCharGetNonBlocking2 () function?
    Q2. Please tell me the specifications of this function.

    You can find the source code for this function in: <pdk_am335x_1_0_17\packages\ti\csl\src\ip\uart\V1\priv\uart.c> at line 1678.  

    I found some more information on this function, which I have copied below:

    Receives a character from the specified port.

    Parameters
    ulBase is the base address of the UART port.

    This function gets a character from the receive FIFO for the specified port.

    Returns
    Returns the character read from the specified port, cast as a long. A -1 is returned if there are no characters present in the receive FIFO. The UARTCharsAvail() function should be called before attempting to call this function.

    Source: http://software-dl.ti.com/ecs/cc31xx/APIs/public/cc32xx_peripherals/latest/html/group___u_a_r_t__api.html#gabb43dee3bc04bf1b96a2937659c69240

    Note: while this is for a different TI device, I believe the description is still accurate.

    3:  

    Q3. How many characters do you read?

    Could you elaborate please? Afraid I don't understand.

    4:

    When called from task, UART_osalDelay (1U) is
    Is it Task_sleep (1) ;?

    You can find more information about UART_osalDelay in <pdk_am335x_1_0_17\packages\ti\drv\uart\src\UART_osal.h>

    5: 

    Q5. In that case, do you pass the process to another task?

    In which case are you referring? 

    6

    Q6. SYS / BIOS -Basic RunTime Option
    Are there any necessary settings? ??

    I would like to direct you to the following, in depth, E2E thread on the topic of SYS/BIOS use on the AM335x: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/509743/using-system_printf-with-am335x-pdk .  Does this assist with your question?

    Best regards,

    Andrew

  • Andrew
    Thank you for answering.

    All double communication of 115200bps is possible.

    You can send up to about 8 bytes per ms with UART_write without any problem.

    I have an additional question.

    Q1. Is it necessary to call the send and receive functions of the uart driver after BIOS_start ()?
    As a test, I got an error when I called UART_wirte ().


    Q2. UART_init (), UART_Params_init (), UART_open () are called before BIOS_start (). no problems.


    Thank you.

  • Hello Tetsuo,

    Q1. Is it necessary to call the send and receive functions of the uart driver after BIOS_start ()?
    As a test, I got an error when I called UART_wirte ().

    What error did you receive?


    Q2. UART_init (), UART_Params_init (), UART_open () are called before BIOS_start (). no problems.

    Could you elaborate your question here?

    Thanks,

    Andrew

  • Andrew
    Thank you for answering.
    Q1. Is it necessary to call the send and receive functions of the uart driver after BIOS_start ()?
    As a test, I got an error when I called UART_wirte ().
    [CortxA8] ti.sysbios.knl.Semaphore: line 214: assertion failure: A_badContext: bad calling context. Must be called from a Task.
    xdc.runtime.Error.raise: terminating execution
    The error was confirmed in the following source code.
    I'm using UART_WRITE ()
    --------------------------------------------------------------------------------------
    #define DBG_PRINT(s) printUart0(s)
    UART_init(); /* シリアルドライバ初期化 */

    UART_Params_init( &g_uartParams0 ); /* シリアルドライバ初期値設定 デバッグポート用 */

    g_uartParams0.parityType = UART_PAR_NONE;
    g_uartParams0.readMode = UART_MODE_BLOCKING;
    g_uartParams0.writeMode = UART_MODE_BLOCKING;
    g_uartParams0.readTimeout = DBG_UART_RX_WAIT;      /*  1  */
    g_uartParams0.writeTimeout = DBG_UART_TX_WAIT;      /*  1  */
    g_uartParams0.readReturnMode = UART_RETURN_FULL;
    g_uartParams0.writeDataMode = UART_DATA_BINARY;
    g_uartParams0.readDataMode = UART_DATA_BINARY;
    g_uartParams0.readEcho = UART_ECHO_OFF;
    g_uartParams0.baudRate = 115200;
    g_uartParams0.dataLength = UART_LEN_8;
    g_uartParams0.stopBits = UART_STOP_ONE;
    g_uartParams0.parityType = UART_PAR_NONE;

    g_uartHandle0 = UART_open(0, &g_uartParams0); /* デバッグシリアルポート 初期化 */
    DBG_PRINT( ( UINT8 *) "\r\nUART0open " ); /* ここで呼ぶと,タスクが動作していないためエラーとなる */

    g_TASK_ID_taskMain = biosTaskCreate( taskMain, "task_Main", 27, SIZE_TASK_STACK_8K ); /* taskMain起動 */

    BIOS_start(); /* does not return */
    ---------------------------------------------------------------------------------
    #define DBG_PRINT_TX_CNT ( 8 ) /* */
    /****************************************************************************/
    /* 文字列をデバッグポートへ出力 (ダイレクト) */
    /* 最大8文字 一気に出力して残りは1ms程ソフトタイマで待って出力する */
    /* 最大64文字まで */
    /* 出力したバイト数をリターンする */
    /* 出力に失敗したら マイナスをリターンする */
    /* */
    /****************************************************************************/

    INT32 printUart0( UINT8 *uiMojibuf )
    {
    INT32 uiTxStat0;
    UINT8 uiStrbuf[ 68 ];
    INT32 ilReadNum;
    UINT8 *txptr;
    UINT32 uiUartTxNum0;
    INT32 ilRtn;

    ilRtn = 0;
    strncpy ( uiStrbuf, uiMojibuf, 64 ); /* 最大32文字 コピー */
    txptr = &uiStrbuf[ 0 ];
    // uiUartTxNum0 = strlen( uiStrbuf );
    ilReadNum = strlen( uiStrbuf );
    txptr = uiStrbuf;
    while ( 1 ) {
    if ( ilReadNum >= DBG_PRINT_TX_CNT ) {
    uiUartTxNum0 = DBG_PRINT_TX_CNT;
    uiTxStat0 = UART_WRITE( g_uartHandle0, txptr, uiUartTxNum0 ); /* デバッグポートに8文字出力 */
    if( uiTxStat0 != uiUartTxNum0 ) { /* デバッグポートに全部出力できなかったら エラーで-1を返す */
    return ( -1 );
    }
    } else {
    uiUartTxNum0 = ilReadNum;
    uiTxStat0 = UART_WRITE( g_uartHandle0, txptr, uiUartTxNum0 ); /* デバッグポートに8文字出力 */
    if( uiTxStat0 != uiUartTxNum0 ) { /* デバッグポートに全部出力できなかったら エラーで-1を返す */
    return ( -1 );
    }
    ilRtn += uiUartTxNum0; /* 送信数 カウント */
    break;
    }
    ilRtn += uiUartTxNum0; /* 送信数 カウント */
    ilReadNum -= DBG_PRINT_TX_CNT;
    txptr += DBG_PRINT_TX_CNT;
    waitus( 1000 );
    }
    return ilRtn; /* 正常送信数をリターンする */
    }
    ------------------------------------------------------

    Q2. UART_init (), UART_Params_init (), UART_open () are called before BIOS_start (). no problems.

    In the order in which the functions are called, before calling BIOS_start ()
    Is it okay to call the following function?

    UART_init (), UART_Params_init (), UART_open () 

    Thanks,

  • Hello Tetsuo,

    Thank you for the additional information,  I have relayed your follow-up questions to the team and I will update you with their response.

    -Andrew 

  • Hello Tetsuo

    [CortxA8] ti.sysbios.knl.Semaphore: line 214: assertion failure: A_badContext: bad calling context. Must be called from a Task.

    I found some more information on this error, here is a helpful explanation for what is going on here:

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/679586/rtos-tm4c1294ncpdt-timer-and-uart-communication-at-1-ms-in-ti-rtos

    I have quoted the relevant answer below:

    "

    You cannot call UART_write in this context. It must be called in a task (I'm assuming you are using TI-RTOS). You can use UART_writePolling.

    More common ways to do this is have a task that does something like this pseudo-code

    task

    {

       while (1) {

           Semaphore_pend(semHandle);

           UART_write(...)

       }

    }

    "

    In the order in which the functions are called, before calling BIOS_start ()
    Is it okay to call the following function?

    UART_init (), UART_Params_init (), UART_open () 

    I am still looking into this question and hope to have an answer shortly.

    Let me know if the answer to Q1 helps.

    -Andrew

  • Andrew
    thank you for your answer

    From the task, UART_write () is working without any problem.
    We have confirmed that UART_write () and UART_readpolling () must be called from the task.
    In the actual code, the call from the task works fine.

    The remaining question is to see if the initialization settings and opening of the UART device are okay before calling BIOS_start.
    Thank you.

  • Hello Tetsuo,

    In the order in which the functions are called, before calling BIOS_start ()
    Is it okay to call the following function?

    UART_init (), UART_Params_init (), UART_open () 

    For this question I have received the following response from the team:

    "If you look at pdk_am335x_1_0_17\packages\ti\drv\uart\src\UART_stdio.c, you'll find all these functions are called by UART_stdioInit() which is called by Board_uartStdioInit(). This function is called by Board_init() before BIOS_start() in UART example code: pdk_am335x_1_0_17\packages\ti\drv\uart\example\sample\src\main_uart_example.c."

    Does this answer your remaining question?

    -Andrew

  • Andrew

    Thank you for your answer
    The problem with my UART driver has been resolved.
    With the AM3352 SYS-BIOS (TI-RTOS) UART driver, 115200bps full duplex communication works in concert with other tasks. We will continue to evaluate the operation.

    Thank you for your support.