¿Cómo verificar si la interrupción periférica específica está habilitada en NVIC?

Estoy usando una placa Discovery STM32F4 con la biblioteca de periféricos estándar (SPL) de ST. Tengo una situación con un búfer circular: la interrupción del temporizador sondea botones y llena un búfer circular cada milisegundo si se presiona un botón, con un índice de ese botón. El bucle principal luego lo saca del búfer circular y ejecuta el comando apropiado. Ambas acciones requieren varios pasos (comprobar y cambiar los índices a un búfer circular, ...).

Cuando esto sucede en el bucle principal, la interrupción del temporizador debe desactivarse durante ese breve tiempo (para que los índices no se arruinen), pero no quiero desactivar todas las interrupciones solo por eso. Además, es preferible que aún se atienda una interrupción si ocurrió mientras estaba deshabilitada.

Traté de hacer esto deshabilitando la interrupción del temporizador para ese temporizador específico (TIM6 en mi caso) en el NVIC (pero lo dejé habilitado en el propio temporizador). Pero luego descubrí que no hay forma de verificar si las interrupciones se deshabilitaron en primer lugar, antes de deshabilitarlas (no puedo habilitar las interrupciones nuevamente si no se habilitaron antes, ya que puede estropear las cosas).

Entonces mis preguntas son:

  • ¿Cómo verifico si una interrupción periférica específica está habilitada en el NVIC? (Solo hay funciones EnableIRQy DisableIRQ.)

    Intenté verificar el valor en

    NVIC->ICER[((uint32_t)(IRQn) >> 5)];

    y

    NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5];

    pero salen 0 aunque la interrupción esté habilitada.

  • ¿Se seguirá sirviendo la interrupción (si ocurrió cuando estaba deshabilitada solo en el lado de NVIC) cuando se habilite nuevamente?

De acuerdo con el manual de referencia, leer NVIC->ISER debería proporcionarle el estado actual de activación/desactivación. ¿Estás seguro de que estás viendo el correcto?

Respuestas (1)

Respuesta rápida:

Yo usaría el siguiente (feo) código:

if (NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] &
   (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F))
{
    // It's enabled!
}

Explicación:

Los NVIC_ISERxregistros son de doble propósito. Si escribe a 1en un bit específico, habilitará la interrupción. Si lee un bit específico, le dirá si la interrupción está habilitada:

ingrese la descripción de la imagen aquí

Está utilizando SPL y, por lo tanto, está manejando la asignación de fuentes de interrupción a registros ISER y ubicaciones de bits.

En el core_cm4.harchivo, versión 3.00, esta es la NVIC_EnableIRQ()función:

__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
    /*  NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));  enable interrupt */
    NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */
}

Es interesante que comentaron la primera línea (que era idéntica a la misma función en core_cm3.h) y la dejaron ahí; Supongo que fue una corrección de errores y se olvidaron de eliminar el código incorrecto. Me perdí por todos los encasillamientos, pero espero que sean necesarios.

Mi respuesta anterior sigue el modelo de esta NVIC_EnableIRQ()función.


En cuanto al comportamiento del sistema, lo siguiente se toma del documento PM0056 de ST (que es para M3, no para M4, pero el comportamiento es similar):

Si se habilita una interrupción pendiente, el NVIC activa la interrupción en función de su prioridad. Si una interrupción no está habilitada, afirmar su señal de interrupción cambia el estado de interrupción a pendiente, pero el NVIC nunca activa la interrupción, independientemente de su prioridad.

Si se establece el indicador "pendiente", la interrupción se atenderá tan pronto como vuelva a habilitar la interrupción.

Gracias, parece que no leí bien el registro. Miré la función enableIRQ y pensé que solo la parte anterior = sería suficiente. Me confundí un poco. Probé su solución y funciona, devuelve 0 si está deshabilitado y 8388608 si está habilitado para TIM7 (temporizador aleatorio seleccionado para la prueba).
@ Terraviper-5 ¡Me alegro de que haya funcionado! Ese valor representa que se establece bit23. Si usa la declaración "if" como la escribí, no necesitará realizar un seguimiento del valor del registro ni cambiar nada si decide cambiar los temporizadores. ¡Buena suerte!