AM6442: Uart_readCancel in dma callback mode

Part Number: AM6442

Tool/software:

Hi experts 

I want to use Uart_readCancel function in uart dma echo example but I changed the read mode to callback.

When i tried to use Uart_readCancel function status returns failed.

When i debugged it looks like in UART_readCancelNoCb there is an if controlling readSizeRemaning==0 and I cant find any dma function set this value so it's always 0. What is the purpose of this if control? 

How can I use read cancel in callback dma mode?

 I am using sdk 09.01.00.41

  • Hello Berlam,

    I am checking with the dev team on this if there is an already existing bug on this.

    Regards,

    Vaibhav

  • Hello,

    So I have gone through few references, I think this would guide you to using read cancel properly.

    Please read through the following: https://github.com/TexasInstruments/mcupsdk-core/blob/next/test/drivers/uart/test_uart.c

    Regards,

    Vaibhav

  • Hi 

    I check the github link and my test case is pretty much same with uart_read_cancel_external_loopback_full_test.

    In my test cases interrupt or polling mode read cancel working as expected but in dma mode it's not working.

    I try to workaround the if control in UART_readCancelNoCb function by setting the readSizeRemaning value to 1 and its working after that. And the value stays 1 while reading and canceling again.

    I even tried to set hardware breakpoint to the readSizeRemaning variable address and not any read or write access happened.

    I think there is a bug in the UART_readCancelNoCb driver in dma mode.

    Regards. 

  • Hello Berlam,

    Is it possible for you to send me an application/project file which we can run on our AM64x TI EVM and test this out.

    Please send the project file so that we can just have it and run it on the go.

    If we see that this is a bug, I will raise an internal JIRA for the same.

    While you attach your project, please mention steps to reproduce if its complicated and not the traditional boot flow you are following.

    Apart from this, please also mentioned the problem briefly(A little more in detailed compared to the above explanation) so that this can be conveyed to the dev.

    Regards,

    Vaibhav

  • Hi 

    i changed the uart_echo_dma_am64x-evm_r5fss0-0_nortos_ti-arm-clang example since there was a bug in it. the 92nd line where 60sec limit should be passed, the UART_readCancel function should have been called but it wasnt. my changes were to accomodate that. 

    /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* This example demonstrates the UART RX and TX operation by echoing char
     * that it recieves in blocking, interrupt mode of operation.
     * When user types 'quit', the application ends.
     */
    
    #include <string.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #define APP_UART_BUFSIZE              (200U)
    #define APP_UART_RECEIVE_BUFSIZE      (8U)
    
    uint8_t gUartBuffer[APP_UART_BUFSIZE] __attribute__((aligned(CacheP_CACHELINE_ALIGNMENT)));
    uint8_t gUartReceiveBuffer[APP_UART_RECEIVE_BUFSIZE] __attribute__((aligned(CacheP_CACHELINE_ALIGNMENT)));
    
    uint8_t rx_ok = 0;
    volatile uint32_t gNumBytesRead = 0U, gNumBytesWritten = 0U;
    
    #define APP_UART_ASSERT_ON_FAILURE(transferOK, transaction) \
        do { \
            if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != transaction.status)) \
            { \
                DebugP_assert(FALSE); /* UART TX/RX failed!! */ \
            } \
        } while(0) \
    
    void uart_echo_dma(void *args)
    {
        int32_t          transferOK;
        UART_Transaction trans;
        uint64_t         start_time = 0;
    
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[UART] Echo example DMA mode started ...\r\n");
    
        UART_Transaction_init(&trans);
    
        /* Send entry string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf,"This is uart echo test DMA blocking mode\r\nReceives 8 characters then echo's back. Please input..\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        CacheP_wb((void *)trans.buf, trans.count, CacheP_TYPE_ALL);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        CacheP_wbInv((void *)&gUartReceiveBuffer[0U], APP_UART_RECEIVE_BUFSIZE, CacheP_TYPE_ALL);
        /* Read 8 chars */
        gNumBytesRead = 0U;
        trans.buf   = &gUartReceiveBuffer[0U];
        trans.count = APP_UART_RECEIVE_BUFSIZE;
    
        rx_ok = 0;
        transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &trans);
    
        //get read start time
        start_time = ClockP_getTimeUsec();
        while(rx_ok == 0)
        {
            if((ClockP_getTimeUsec() - start_time)  > 60000000  )
            {
                // wait 60 second and cancel the read
                UART_readCancel(gUartHandle[CONFIG_UART_CONSOLE], &trans);
            }
    
            ClockP_sleep(500000); //sleep 500ms
    
        }
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
    
        /* Echo chars entered */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartReceiveBuffer[0U];
        trans.count = APP_UART_RECEIVE_BUFSIZE;
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        /* Send exit string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf, "\r\nAll tests have passed!!\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        CacheP_wb((void *)trans.buf, trans.count, CacheP_TYPE_ALL);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        DebugP_log("All tests have passed!!\r\n");
    
        Board_driversClose();
        Drivers_close();
    
        return;
    }
    void uart_rx_callback(UART_Handle handle, UART_Transaction *transaction)
    {
    
        rx_ok = 1;
    
    }
    

  • Hello Berlam,

    Thanks for your response.

    Can you check what is the lowest time you can go? 60 seconds is experimental?

    Regards,

    Vaibhav

  • Hello Valbhav

    • 60 second is experimental. My main purpose here is call the read function without blocking the program and if the no data read given time cancel the read. This is working as expected in interrupt and polling mode. But its not working in dma mode.

    Regards 

  • Hello 

    After I made the below changes before calling read cancel it's working in dma mode.

    Setting readSizeRemaining to non zero value 

    gUartConfig[0].object->uartLld_handle->readSizeRemaining =1;

    Regards 

  • Hello Berlam,

    Good to know its working in DMA mode as well.

    Closing the thread for now.

    Regards,

    Vaibhav

  • Hello Valbhav 

    Yes it's seems working as far as I tested it. But I think driver api should be working without my manipulation.

    I made the changes because in driver code there is an if control so I can bypass it. I believe there is a bug there.

    Can u please check why do I need to set that value for function to work.

    Regards. 

  • Yes it's seems working as far as I tested it. But I think driver api should be working without my manipulation.

    I made the changes because in driver code there is an if control so I can bypass it. I believe there is a bug there.

    Can u please check why do I need to set that value for function to work.

    I am checking with the dev on this. Thanks for your patience.