¿Cómo distinguir entre una lectura y una escritura en un USART BufferEventHandler de Harmony?

1

Me gustaría usar el controlador Harmony USART en un PIC32MX695F512H usando interrupciones y con soporte de búfer. Después de establecer la configuración adecuada en el Configurador de Armonía MPLAB, el sistema ha generado el ISR para mí ( 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);
}

Ya que este es un archivo generado, asumo que no debo editarlo. Pero si este es el ISR, ¿cómo puedo asegurarme de que mi código se ejecutará en una interrupción de RX? Quiero recibir los datos recibidos en una función que debo editar.

Tal como lo entiendo, para eso es el controlador de eventos del búfer. Así que puedo hacer lo siguiente (este código está muy simplificado):

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);

Mis preguntas son:

  1. ¿Es esta realmente la forma correcta de asegurarse de que se llame a APP_BufferEventHandler en una interrupción de RX?
  2. ¿Cómo puedo distinguir entre un evento RX y un evento TX en el controlador de eventos, si el evento es uno de COMPLETE , ERROR y ABORT ?
pregunta Keelan

2 respuestas

2

Usted prácticamente tiene correcto el modelo deseado. Para responder a sus preguntas:

  1. Sí, excepto que es probable que desee pasar un parámetro context cuando devuelva la llamada a la rutina del manejador de llamadas. Así es como puedes ayudar a identificar la fuente de las cosas y cómo manejarlas. (Por ejemplo, si envía dos "tareas de mensajes" diferentes e independientes a USART1 para que se transmitan, el parámetro de contexto es cómo sabe qué remitente específico estaba usando el recurso, para que pueda actuar en consecuencia).

Mirando su modelo de abstracción a continuación, usaría el parámetro context para indicar a qué cliente se está haciendo referencia en el controlador de eventos, ya que varios clientes pueden compartir el mismo hardware USART.

  • Con una combinación del parámetro context mencionado anteriormente, así como una máquina de estado bien definida que ejecuta cada una de sus máquinas de estado cliente de USART. Desafortunadamente, las cosas se complican rápidamente en Harmony.
  • A continuación se muestra uno de sus Controladores de eventos de búfer en su ejemplo de controlador USART. Puede ver que confirman tanto el parámetro de contexto como el lugar en el que la máquina de estado de sus tareas USART son para manejar el evento y mover la máquina de estado a lo largo.

    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;
        }
    }
    

    Es difícil (en mi opinión) justificar la complejidad de hacer funcionar a Harmony para cualquier cosa que no sea un gigantesco gigante multitarea. Sin embargo, si tiene muchos objetos que comparten muchos recursos, puede que valga la pena armar la armonía.

        
    respondido por el justing
    0

    En mi opinión, sí es necesario agregar código en el __ISR. Por ejemplo:

    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);
        }
    }
    
        
    respondido por el Chris van der Gaag

    Lea otras preguntas en las etiquetas