Un par de definiciones en primer lugar:
En el Cortex-M de programación manual, una Excepción es cualquier cosa que se rompe el normal flujo del programa, e invoca el controlador de la tabla de vectores, y las Interrupciones son un subconjunto de las Excepciones, procedentes de los periféricos fuera del núcleo ARM. Porque SysTick se implementa en el Cortex-M de core, se considera una excepción, pero no una interrupción.
Las excepciones tienen un Número de Excepción, empezando desde 0. Las interrupciones tienen un Número de IRQ, empezando desde 0. Porque todas las Interrupciones son Excepciones, todos tienen un Número de Excepción, que es de 16 años mayor que el Número de IRQ. Las Excepciones que no son las Interrupciones (incluyendo SysTick) han Excepción de los Números en el rango 0-15, más pequeño que la Excepción de los Números de las Interrupciones. Algo confusamente, Excepciones que no son las Interrupciones tienen los Números de IRQ demasiado, que por extensión caen en el rango de -16 a -1. SysTick ha Excepción de la Número 15 y Número de IRQ -1.
Estoy usando un STM32F303 MCU y me he dado cuenta de que la SysTick se puede configurar para provocar una excepción, que parece se menciona muy a menudo en varias Guías de Usuario. De esta manera, se tendrá un nivel de prioridad más alto de Interrupciones regulares.
Todas las excepciones, salvo Reset, NMI, y Hardfault han configurable prioridades. Es sólo configurado de forma diferente para las interrupciones y otras excepciones. Ver el CMSIS aplicación como un claro ejemplo:
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)(IRQn) < 0)
{
SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
Usted puede llamar a NVIC_SetPriority
o manipular SCB->SHP
directamente para dar SysTick una prioridad más baja que cualquier otra interrupción.
SysTick ha hecho un predeterminado nivel de prioridad que es superior a la de cualquier interrupción, pero eso es sólo porque en reset, todas las prioridades se establecen en 0, y en caso de empate, el menor número de IRQ gana, en este caso, SysTick con -1.
Por otro lado, parece ser posible establecer Systick como una interrupción en el NVIC así. Tiene su propia solicitud de interrupción número y parece que se puede establecer en estado pendiente. Debido a que el NVIC las interrupciones tienen un nivel de prioridad, también podemos configurarlo de esta manera.
Sólo interrumpe son configurables a través del NVIC registros, y SysTick no es una interrupción. NVIC registros no tienen lugar para los negativos de los números de IRQ, en máscaras de bits o en otros lugares.
SysTick de hecho puede ser ajustado a un estado pendiente, pero eso se hace a través de la SCB->ICSR
, no en NVIC.
Tenga en cuenta que NVIC_SetPriority()
y NVIC_GetPriority()
son la única NVIC_ funciones en CMSIS que lidiar con los negativos de los números de IRQ correctamente. Otras funciones como NVIC_SetPendingIRQ()
o NVIC_EnableIRQ()
acaba de aceptar negativas de los números de IRQ felizmente, hacer algo arrastrando los pies en ellos que se traduce en una GRAN desplazamiento desde el NVIC registros, y garabatear lejana dirección de memoria, posiblemente causando una hardfault, u otro comportamiento extraño. HAL_NVIC_ funciones de algunos de comprobación de límites cuando se habilita USE_FULL_ASSERT
en sus cabeceras, pero de lo contrario simplemente dejar que los parámetros no válidos a través de la CMSIS NVIC funciones.
EDITAR
Hay un truco para encontrar todos los lugares donde se llama a una función con un parámetro negativo. Poner esto en un encabezado común:
#define NVIC_EnableIRQ(x) ((void)sizeof(char[x]))
Es un error en tiempo de compilación cuando esta construcción se invoca con un número negativo. Repita esto para cada NVIC función , excepto NVIC_SetPriority()
y NVIC_GetPriority()
.