Microchip MPLAB Harmony Programming - What is a Callback

Thread Starter

Marc Sugrue

Joined Jan 19, 2018
167
Good Afternoon All,
I'm doing some embedded programming with Microchip Harmony 3 and for the first time i've come accross a callback whilst trying to read and write to a serial port.

Harmony has placed the following structure in the code but i'm not quite sure of its purpose. Any pointers (excuse the pun) would be appreciated.

Code:
typedef struct
{
    uint8_t *               txBuffer;
    size_t                  txSize;
    size_t                  txProcessedSize;
    UART_CALLBACK           txCallback;
    uintptr_t               txContext;
    bool                    txBusyStatus;

    uint8_t *               rxBuffer;
    size_t                  rxSize;
    size_t                  rxProcessedSize;
    UART_CALLBACK           rxCallback;
    uintptr_t               rxContext;
    bool                    rxBusyStatus;

} UART_OBJECT ;
The read serial interrupt handler also has this code auto generated which from first glance doesn't seem to do any reading of the port so some clarification of how this is to be used would be appreciated.

Code:
static void UART2_RX_InterruptHandler (void)
{
    if(uart2Obj.rxBusyStatus == true)
    {
        while((_U2STA_URXDA_MASK == (U2STA & _U2STA_URXDA_MASK)) && (uart2Obj.rxSize > uart2Obj.rxProcessedSize) )
        {
            uart2Obj.rxBuffer[uart2Obj.rxProcessedSize++] = (uint8_t )(U2RXREG);
        }

        /* Clear UART2 RX Interrupt flag */
        IFS1CLR = _IFS1_U2RXIF_MASK;

        /* Check if the buffer is done */
        if(uart2Obj.rxProcessedSize >= uart2Obj.rxSize)
        {
            uart2Obj.rxBusyStatus = false;

            /* Disable the fault interrupt */
            IEC1CLR = _IEC1_U2EIE_MASK;

            /* Disable the receive interrupt */
            IEC1CLR = _IEC1_U2RXIE_MASK;


            if(uart2Obj.rxCallback != NULL)
            {
                uart2Obj.rxCallback(uart2Obj.rxContext);
            }
        }
    }
    else
    {
        // Nothing to process
        ;
    }
}
Thanks in advance
 
Last edited:
Code:
        while((_U2STA_URXDA_MASK == (U2STA & _U2STA_URXDA_MASK)) && (uart2Obj.rxSize > uart2Obj.rxProcessedSize) )
        {
            uart2Obj.rxBuffer[uart2Obj.rxProcessedSize++] = (uint8_t )(U2RXREG);
        }
These couple lines actually do the reading and store the data in uart2Obj.rxBuffer. The callback gets called after enough data is read to match the count in uart2Obj.rxSize.

Code:
    uint8_t *               rxBuffer;
    size_t                  rxSize;
    size_t                  rxProcessedSize;
    UART_CALLBACK           rxCallback;
    uintptr_t               rxContext;
    bool                    rxBusyStatus;
The way it looks to me... rxBuffer would be your buffer to read in to. rxSize is the byte count you want to read. rxProccessedSize is the count of bytes read so far. rxCallback is what is called after your byte counts (to read, and already read) match. rxContext is a bit fuzzy... maybe something in the read setup function will make that one more clear. rxBusyStatus is if it is still working or not.

I'm going to guess the intent of the callback is for you to set a flag or something to catch in the main loop to show the read has completed.
 

Thread Starter

Marc Sugrue

Joined Jan 19, 2018
167
These couple lines actually do the reading and store the data in uart2Obj.rxBuffer. The callback gets called after enough data is read to match the count in uart2Obj.rxSize.

Code:
    uint8_t *               rxBuffer;
    size_t                  rxSize;
    size_t                  rxProcessedSize;
    UART_CALLBACK           rxCallback;
    uintptr_t               rxContext;
    bool                    rxBusyStatus;
The way it looks to me... rxBuffer would be your buffer to read in to. rxSize is the byte count you want to read. rxProccessedSize is the count of bytes read so far. rxCallback is what is called after your byte counts (to read, and already read) match. rxContext is a bit fuzzy... maybe something in the read setup function will make that one more clear. rxBusyStatus is if it is still working or not.

I'm going to guess the intent of the callback is for you to set a flag or something to catch in the main loop to show the read has completed.
Thanks you so much for your input, that makes a bit more sense - not quite Harmony with me yet but its close to clicking, the issue for me was uart2Obj is just an instance of the data structure object so couldn't see its purpose. From your explanation it makes more sense. They also provide a seperate function UART2_Read which seems to write to this structure which i originally mistook as a read of the uart but actually it looks to be more of a configuration of the buffers and enabling of the read interrupt. Is that how you see it?

Code:
bool UART2_Read(void* buffer, const size_t size )
{
    bool status = false;
    uint8_t* lBuffer = (uint8_t* )buffer;

    if(lBuffer != NULL)
    {
        /* Check if receive request is in progress */
        if(uart2Obj.rxBusyStatus == false)
        {
            /* Clear errors before submitting the request.
             * ErrorGet clears errors internally. */
            UART2_ErrorGet();

            uart2Obj.rxBuffer = lBuffer;
            uart2Obj.rxSize = size;
            uart2Obj.rxProcessedSize = 0;
            uart2Obj.rxBusyStatus = true;
            status = true;

            /* Enable UART2_FAULT Interrupt */
            IEC1SET = _IEC1_U2EIE_MASK;

            /* Enable UART2_RX Interrupt */
            IEC1SET = _IEC1_U2RXIE_MASK;
        }
    }

    return status;
}
 
@Marc Sugrue I hope you figured this out by now. Unfortunately when I saw your last response I was in a rush and didn't notice the question asked. My apologies, but I'm thinking you were on the right track. UART2_Read() does look to be the setup routine. Interesting how it's done, but depending on what you actually need to have happen while reading it may need some tweaking. Good luck
 
Top