1

I would like to use the Harmony USART driver on a PIC32MX695F512H using interrupts and with buffer support. After setting the appropriate settings in the MPLAB Harmony Configurator, the system has generated the ISR for me (system_interrupt.c):

void __ISR(_UART_2_VECTOR, ipl1AUTO) _IntHandlerDrvUsartInstance0(void) {
    DRV_USART_TasksTransmit(sysObj.drvUsart0);
    DRV_USART_TasksReceive(sysObj.drvUsart0);
    DRV_USART_TasksError(sysObj.drvUsart0);
}

Since this is a generated file, I assume I'm not supposed to edit it. But if this is the ISR, how can I make sure my code will be executed on an RX interrupt. I want to receive the received data in a function that I am supposed to edit.

As I understand it, that is what the buffer event handler is for. So I can do the following (this code is highly simplified):

void APP_BufferEventHandler(DRV_USART_BUFFER_EVENT bufferEvent,
        DRV_USART_BUFFER_HANDLE bufferHandle, uintptr_t context) {
    switch (bufferEvent) {
        case DRV_USART_BUFFER_EVENT_COMPLETE:
            // @todo
            break;
        case DRV_USART_BUFFER_EVENT_ERROR:
            appData.state = APP_ERROR;
            break;
        case DRV_USART_BUFFER_EVENT_ABORT:
            appData.state = APP_ERROR;
            break;
    }
}

//... in APP_Tasks somewhere:

    appData.usartHandle = DRV_USART_Open(DRV_USART_INDEX_0,
            DRV_IO_INTENT_READWRITE | DRV_IO_INTENT_NONBLOCKING);
    DRV_USART_BufferEventHandlerSet(appData.usartHandle,
            APP_BufferEventHandler, 0);

My questions are:

  1. Is this actually the right way to make sure APP_BufferEventHandler is called on an RX interrupt?
  2. How can I distinguish between an RX and a TX event in the event handler, if the event is one of COMPLETE, ERROR and ABORT?

2 Answers2

2

You pretty much have their intended model correct. To address your questions:

  1. Yes, except you probably want to pass along a context parameter when you call the call back handler set routine. This is how you can help identify the source of things and how to handle it. (For example, if you send two different, independent "message tasks" to USART1 to be transmitted out, the context parameter is how you know which specific sender it was using the resource, so you can act accordingly).

Looking at their abstraction model below, you would use the context parameter to tell which client is being referenced to in the event handler, since multiple clients can share the same USART hardware.

abs model

  1. With a mix of the above mentioned context parameter, as well as a well defined state machine running each of your USARTs client state machines. Unfortunately, things get complicated fast in Harmony.

Below is one of their Buffer Event Handlers in their USART driver example. You can see that they confirm both the context paramter, as well as where their USART tasks state machine are to handle the event and move the state machine along.

C:\microchip\harmony\v1_06_02\apps\driver\usart\usart_loopback\firmware

void APP_BufferEventHandlerUsart1(DRV_USART_BUFFER_EVENT buffEvent,
                            DRV_USART_BUFFER_HANDLE hBufferEvent,
                            uintptr_t context )
{
    switch(buffEvent)
    {   
        /* Buffer event is completed successfully */
        case DRV_USART_BUFFER_EVENT_COMPLETE:
        {
            if((context == 1) &&(appData.usart1State == APP_STATE_USART1_WAIT_FOR_TX_COMPLETION))
            {
                    appData.usart1State = APP_STATE_USART1_WAIT_TO_RX_BACK_DATA;
            }
            else if((context == 1) &&(appData.usart1State == APP_STATE_USART1_WAIT_TO_RX_BACK_DATA))
            {
                    gDataRxedAtUsart1 = true;
                    appData.state = APP_STATE_VERIFY_LOOPBACK_DATA;
            }
        }
        break;
        /* Buffer event has some error */
        case DRV_USART_BUFFER_EVENT_ERROR:
            break;
       default:
            break;
    }
}

It is hard (in my opinion) to justify the complexity of getting Harmony running for anything short of a huge multitasking behemoth. However, if you have many objects sharing many resources, Harmony may be worth toughing it out.

justing
  • 1,743
  • 13
  • 21
0

To my opinion you actually do need to add code in the __ISR. For example:

void __ISR(_UART_1_VECTOR, ipl1AUTO) _IntHandlerDrvUsartInstance0(void) {
    DRV_USART_TasksTransmit(sysObj.drvUsart0);
    DRV_USART_TasksReceive(sysObj.drvUsart0);
    DRV_USART_TasksError(sysObj.drvUsart0);

    //o_LED_ld3 = ~o_LED_ld3; 
    while (!DRV_USART_ReceiverBufferIsEmpty(appData.UsartHandle))
    {
        // read received byte
        appData.rx_byte = DRV_USART_ReadByte(appData.UsartHandle); 
        //UART_Write_Char(appData.rx_byte);
    }
}
  • 1
    The ISR is in a generated file (as I wrote in the question), so I don't think this is a good idea. The changes would be overridden when regenerating the file. –  Aug 16 '16 at 14:40
  • 1
    Half of the tutorials you would find about MPLAB Harmony will make you writing on generated files (interrupts, init, etc...), so I don't think this is a good argument. And if you need to generate those files again, the IDE will point at each change you made and let you decide to keep the change or to replace by the newly generated version. – Edesign Aug 16 '16 at 16:31