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.

How do I implement a UART readCallback function ?

Other Parts Discussed in Thread: MSP430F5528

Hi,   I am writing uart driver code for an MSP430F5528.  This is with rtos version msp43x_2_16_01_14.

My communication code is in the attached file com.c

In my system an external device will occasionally transmit a packet containing 5 or 9 bytes.  My F5528 needs to receive these packets.

I plan on using the nonblocking callback mode. Once every 10 mS a task called uart_read_fxn() is called.  This task contains

the call to UART_read().  

I know that I need a call back function, and I have the prototype in place, but I have not found any good examples of what  needs to be done in the read callback.

Thank you for your help.

Roy  

5417.com.c

 

  • Hi Roy,

    Your code is correct, the next step depends on what you want your application to do.
    I would recommend that you have a separate task in your application in order to process the data that you're reading. In that case you would post a semaphore from the UART callback function to unblock that task.

    So in the callback you could:
    1. Move the data into a different buffer accessible by the uart data processing task.
    2. Post a semaphore signaling that data has been received

    Best,
    Alexander
  • 4401.com.cHi Alexander,  

    I guess I am not sure how Uart_read() operates when you use it in the callback mode.  The information I gleaned from the forum said that each time I call UART_read(), it will then execute the callback function.  In the callback function I need to place another call to UART_read(), and then read the returned number of bytes from the buffer.   I believe I have done this in readCallBack().  However, I am getting zero bytes read, even though on my logic analyzer I can see a 5 byte packet being sent from my test equipment.

    Please see my attached file com.c

    Roy

  • Hi Roy,

    UART_read() will have a callback function that is executed when all bytes have been received from the UART source. It is not recommended to call UART_read from its own callback as this can potentially lead to stack overflow issues. We recommend posting a semaphore from the callback function and to handle subsequent reads from within your task.

    void readCallback(UART_Handle handle, void *buffer, size_t num)
    {
        Semaphore_post(readSem);
    }
    
    Void testFxn1(UArg a0, UArg a1)
    {
        //UART Initialization here..
    
        for(i = 1; i < 10; i++) {
            readSize = 6;
            UART_read(handle, input , readSize);
            Semaphore_pend(readSem, BIOS_WAIT_FOREVER);
        }
    }

    From the drivers documentation:

    Source:
    software-dl.ti.com/.../_u_a_r_t_8h.html

    Best,

    Alexander

  • Hi Alexander,

    I took your advice and implemented my UART_read() in a task, and a semaphore post from the callback.

    void readCallBack(UART_Handle handle, void *buffer, size_t num )

    {

    /*

    * This callback is executed after the specified number of bytes have been

    * read from UART_read(). Note that this number is always 1 byte.

    */

    Semaphore_post( uart_read_sem );

    } // end of readCallBack() ***************************************************

    void uart_read_fxn( void )

    {

    extern void increment_index( BYTE *index_ptr );

    extern BYTE detect_packet( void );

    extern BYTE bytes_available( void );

    BYTE buffer[LOB];

    int bytes_read;

    BYTE i;

    while( 1 )

    {

    bytes_read = UART_read( uart_handle, &buffer, 1 );

    Semaphore_pend( uart_read_sem, BIOS_WAIT_FOREVER );

    if(bytes_read > 0)

    {

    for(i=0; i<bytes_read; i++)

    {

    // save the data

    uart_read_buffer[ write_index_URB ] = buffer[i];

    write_index_URB++;

    if( write_index_URB >= LOURB)

    {

    write_index_URB = 0;

    }

    }

    }

    if( read_index_URB != write_index_URB )

    {

    // something was read from the UART

    // detect_packet();

    }

    } // end of while( 1 )

    } // end of uart_read_fxn() **************************************************

    If I set a breakpoint after Semaphore_pend(), I get hits on it when a 5 byte packet is sent to the uart.  However, the number of bytes read is always zero.  It knows that there is activity, but it won't give me the received data.

    Can you see anything wrong with my implementation ?

    Thank you for your help.

    Roy

    7485.com.c

  • Hi Roy,

    This is a gap in our documentation for UART_read as it should have the same return as UART_write in callback mode. Ie:

    "In UART_MODE_CALLBACK mode, the return value is always 0".

    This is because in callback mode the UART does not block task execution and as such, the transfer may not be complete when the call returns. So when using callback mode, when the callback function gets called you know you've read the number of bytes set as the readSize and the data is located in the buffer you passed into UART_read.

    So in your code, instead of using your bytes_read variable, which will always be 0 in callback mode, you should change it to something similar to the following:

    BYTE buffer[LOB];
    int readSize = 1;
    BYTE i;
    while( 1 )
    {
    UART_read( uart_handle, &buffer, readSize );
    
    Semaphore_pend( uart_read_sem, BIOS_WAIT_FOREVER );
    
    for(i=0; i<readSize; i++)
    { ... }
    }

    Best,

    Alexander

  • HI Alexander,

    Following your explanation, reception of packets is now working a lot better. Thank you very much for the assistance.

    However, I am seeing about 2 out of 5 packets corrupted. Typically, the first 4 bytes are OK, and then the last byte is corrupted.

    Do you have any ideas on how to troubleshoot this issue ?

    Roy
  • Hi Roy,

    That's strange, are you seeing this behavior if you use blocking mode as well?

    Best,
    Alexander
  • Hi Alexander,

    The blocking mode works flawlessly.  When my test system launches I know that the first packet it sends to me contains 5 bytes.  For 20 launches of my test system, I got the 5 byte packet correctly every time. 

    BYTE buffer[LOB];

    int read_size = 5;

    BYTE i;

     

    while( 1 )

    {

           UART_read( uart_handle, &buffer, read_size );

     

           // Semaphore_pend( uart_read_sem, BIOS_WAIT_FOREVER );

     

           for(i=0; i<read_size; i++)

           {

                  // save the data

                  uart_read_buffer[ write_index_URB ] = buffer[i];

                  write_index_URB++;

                  if( write_index_URB >= LOURB)

                  {

                         write_index_URB = 0;

                  }

           }

    }

    Thanks

    Roy

  • Hi again Roy,

    Apologies for the late reply. I'm still unable to reproduce your issue. Could you run the attached modified uartecho example and let me know if you're able to see corruption on your end? Note this project is for the 5529 launchpad and may require a change in the board file to align the UART pins to your specific board.

    7875.uartecho.zip

    Best,

    Alexander

  • Hi Alexander,

    I have gotten the UART_read() function working very well in callback mode. I did this setting the readsize equal to the size of my packet. Also, I discovered that my test system is sending me some spurious bytes. So some of the problems I was having may be attributable to that.

    Thank you for the help. At this point in time, I feel that my understanding of the callback mode is sufficient to enable me to move forward.

    Roy