embedded - valor - Detectar de forma segura, si la función se llama desde un ISR?
velocidad en funcion de la posicion (4)
Después de algunas discusiones y más búsquedas, encontré el registro correcto: Registro de estado de programa de interrupción: El IPSR contiene el número de tipo de excepción de la rutina de servicio de interrupción (ISR) actual. Ver el resumen de registro en la Tabla 626 para sus atributos.
Si no se llama a una función desde un isr, el valor del registro es IPSR == 0
Estoy desarrollando software para un controlador de micras ARM Cortex M3 (NXP LPC1769). En este momento estoy buscando un mecanismo para detectar si mi función se llama dentro de un ISR. Supongo que tengo que comprobar un registro. Basado en esta información me gustaría llamar funciones difíciles.
Ya verifiqué el manual de referencia, si hay un registro que contiene la información necesaria.
Por ejemplo, traté de detectar si me llamaban desde un ISR (utilicé SysTick-ISR) en base al registro "Registro de bits activo de interrupción" (IABR). Este registro debe ser! = 0 si un ISR está activo. Pero el valor era 0x00000000. Esto implica que no hay interrupción activa. Además de esta prueba, verifiqué el registro de NVIC y SC en el manual de referencia en busca de un registro que contenga la bandera necesaria pero no encontré ninguno.
¿Alguien sabe un registro / mecanismo adecuado para mi problema?
El método más simple es pasar el contexto como un parámetro a la función. También es plataforma independiente.
typedef enum _context {
normal_context = 0,
isr_context = 1
} context;
Llamada a la función desde ISR:
func(param1, param2, isr_context);
Llame a la función desde el código normal:
func(param1, param2, normal_context);
Si el código ISR no está bajo su control y solo está pasando un puntero a función, entonces use dos funciones de envoltorio diferentes. Uno que pasa isr_context y otro que pasa normal_context como un parámetro a la función.
La mejor manera es probablemente hacer dos funciones diferentes: una que se llama desde el ISR y otra que se llama desde el resto del programa.
Si esa no es una opción, entonces podría determinar la persona que llama con el estándar C puro, no se necesitan registros:
inline void my_func (const char* caller);
static void isr (void)
{
my_func(__func__);
}
inline void my_func (const char* caller)
{
if(strcmp(caller, "isr")==0)
{
// was called from isr
}
else
{
// called from elsewhere
}
}
Si le da nombres inteligentes a sus ISR, el código anterior será lo suficientemente rápido para ejecutarse desde un isr.
Debe probar el campo VECTACTIVE del registro de estados de control de interrupciones .
Yo uso lo siguiente:
//! Test if in interrupt mode
inline bool isInterrupt()
{
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0 ;
}
SCM y SCB_ICSR_VECTACTIVE_Msk están definidos en el CMSIS (core_cm3.h), que imagino que se incluiría indirectamente en el encabezado específico de su parte (lpc17xx.h o similar, supongo). Estoy usando C ++, incluido stdbool.h en C te dará un tipo de bool, o cambiará a un int o typedef tuyo.
Entonces se usa así por ejemplo:
void somefunction( char ch )
{
if( isInterrupt() )
{
// Do not block if ISR
send( ch, NO_WAIT ) ;
}
else
{
send( ch, TIMEOUT ) ;
}
}
Si se requiere una solución que no asuma ningún conocimiento de la arquitectura, considere lo siguiente:
volatile int interrupt_nest_count = 0 ;
#define ENTER_ISR() interrupt_nest_count++
#define EXIT_ISR() interrupt_nest_count--
#define IN_ISR() (interrupt_nest_count != 0)
void isrA()
{
ENTER_ISR() ;
somefunction( ''a'' ) ;
EXIT_ISR() ;
}
void isrB()
{
ENTER_ISR() ;
somefunction( ''b'' ) ;
EXIT_ISR() ;
}
void somefunction( char ch )
{
if( IN_ISR() )
{
// Do not block if ISR
send( ch, NO_WAIT ) ;
}
else
{
send( ch, TIMEOUT ) ;
}
}
Sin embargo, la pregunta se refiere a la detección segura del contexto de interrupción, y esto se basa en las macros de entrada / salida que se agregan a todos los ISR.