STM32: la interrupción de UART se está activando sin que se establezca ningún indicador

3

Estoy utilizando el módulo UART4 de un STM32F105. Estoy usando la interrupción RXNE ("RX Buffer Not Empty") para capturar los datos a medida que ingresan. Funciona como se esperaba.

Cuando la interrupción RXNE está habilitada, también habilita la interrupción de saturación (ORE). Esto también parece funcionar como se esperaba.

El indicador de estado ORE se asigna como USART_FLAG_ORE . El indicador de interrupción correspondiente es USART_IT_ORE . Si la interrupción de RXNE está habilitada, cuando se establece el bit de bandera, también se debe establecer el bit de TI. Copiado del Manual del usuario :

Estoy manejando la interrupción así:

void usartISR(void)
{
    // Did we receive data?
    if(USART_GetITStatus(UART4, USART_IT_RXNE) == SET)
    {
        // Add it to the active buffer
    }

    // Did the receiver overrun?
    else if(USART_GetITStatus(UART4, USART_IT_ORE) == SET)
    {
        // Clean up and clear the Overrun condition
    }

    // No other triggers have been enabled
    else
    {
        ErrorHandler(ERR_BAD_INTERRUPT);
    }
}

El problema ocurre si el indicador ORE ya está establecido cuando habilito la interrupción:

{
    // The USART_FLAG_ORE bit is already set

    // The following command causes an immediate vector to the ISR:
    USART_IT_Config(UART4, USART_IT_RXNE, ENABLE);
}

Los vectores de código para el ISR, pero el indicador USART_IT_ORE no parece establecerse. El ISR salta alegremente hasta el final y llama al controlador de errores. Si miro los registros USART_CR, ninguno de los otros eventos de interrupción están habilitados. Si omito el controlador de errores, el código se envía repetidamente al ISR, aunque no se hayan configurado indicadores de TI.

¿Por qué se activa el ISR sin que se establezca la marca USART_IT_ORE ? ¿Me estoy perdiendo algo obvio?

    
pregunta bitsmack

2 respuestas

6

Habiendo pasado por las definiciones en stm32f10x_usart.h y Get_ITStatus() en la fuente, es evidente que no hay 'banderas de interrupción' reales de UART. Sólo hay banderas de estado en el registro de estado. Como sabe, cuando ocurre un evento, se establece el bit de bandera correspondiente, ya sea que las interrupciones estén habilitadas o no. Si la interrupción asociada está habilitada, entonces la MCU salta al ISR relevante, donde se puede manejar el evento.

LaimagendearribamuestraquesilainterrupciónRXNEestáhabilitadayelindicadorOREestáactivado,seactivaunainterrupción,comodebeser.Ensucódigo,intentóobtenerelestadodel'indicadordeinterrupción'conGet_ITStatus().Sinembargo,loúnicoqueGet_ITStatus()hacees:compruebesielindicadordeestadoasociadoesSET&&silainterrupciónasociadaestáhabilitada.

Ahora,sabemosquelaprimeracondiciónesverdadera,yaqueustedESTABLECElamarcayhaverificadoqueefectivamenteestáestablecida.Lasegundacondicióntambiéndebesercierta:silainterrupciónqueseverificófueRXNEIE(yaquelahabilitó).Peroelbitdehabilitacióndeinterrupciónrealqueseestáverificando,cuandoUSART_IT_OREsepasaaGet_ITStatus(),esEIE(Errordeinterrupciónhabilitada).Porlotanto,comonohabilitóestainterrupción,Get_ITStatus()siempredevolveráRESET(0)paraunerrordesaturación.

Sinembargo,

Get_ITStatus()noescompletamenteincorrecto.EldiagramaanteriormuestraquecuandoseestablecenORE,EIEyDMAR,segeneraráunainterrupción.Deacuerdoconelmanualenelenlacequeproporcionó:

Este fragmento de código proporciona confirmación adicional. Así que parece que los autores de la biblioteca solo codificaron para esta segunda posibilidad (aunque no correctamente ya que DMAR no está marcado). Su solución temporal verifica el indicador de estado directamente, lo que está bien siempre y cuando no configure el EIE con RXNEIE, ya que no sabría qué fuente generó el Error de saturación.

    
respondido por el TisteAndii
0

He encontrado una solución. Esto no responde directamente a la pregunta, pero esperamos que sirva de ayuda hasta que alguien responda mejor :)

Resulta que a pesar de que USART_IT_ORE no se configura, USART_FLAG_ORE bit sí . Si modifico el ISR para verificar el bit de marca (usando USART_GetFlagStatus(USART_FLAG_ORE) ) en lugar del bit de TI ( USART_GetITStatus(USART_IT_ORE) ), entonces el ISR se comporta muy bien.

Curiosamente, tanto USART_FLAG_ORE como USART_IT_ORE se borran con la misma secuencia de eventos. Se limpian juntos. Así que no tuve que cambiar más mi código ...

    
respondido por el bitsmack

Lea otras preguntas en las etiquetas