Interrupción externa retrasada en STM31F103C8

0

Tengo que escribir un programa en C para alternar un LED usando una interrupción externa en STM32F103 (72MHz System Clock). He inicializado EXTI3 en el flanco descendente y el controlador de ISR alterna un led en la entrada de alta frecuencia en el pin de detección de interrupción externo; hay un retraso entre la detección y la ejecución de ISR (aproximadamente 2.6uSec, casi 188 pulsos de reloj del sistema). ¿De dónde viene este retraso?

Estoy adjuntando mi código, he verificado el reloj de mi microcontrolador al escribir el temporizador 1 PWM para una frecuencia específica (witch se calcula por la frecuencia de reloj de 72MHz).

Aquí está mi código:

#include "stm32f10x.h"


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                //LED PUTPUT
                //JTAG-DP Disabled and SW-DP Disabled PA13, PA14, PA15 PB3 and PB4 Release from JTAG-DP/SW-DP module
                //Reset default Value Reset value: 0x4444 4444(ALL INPUT ARE FLOATING) to 0x00000000 (General purpose output push-pull )
                //01: Output mode, max speed 10 MHz.
                //10: Output mode, max speed 2 MHz.
                //11: Output mode, max speed 50 MHz.
#define LED_INIT()  RCC->APB2ENR |=RCC_APB2ENR_IOPAEN|RCC_APB2ENR_IOPCEN;\
                    RCC->APB2ENR |=RCC_APB2ENR_AFIOEN;\
                    AFIO->MAPR |=AFIO_MAPR_SWJ_CFG_DISABLE;\
                    GPIOA->CRH &=~(GPIO_CRH_CNF13|GPIO_CRH_CNF14);\
                    GPIOA->CRH |=(GPIO_CRH_MODE13|GPIO_CRH_MODE14);\
                    GPIOA->ODR &=~(GPIO_ODR_ODR13|GPIO_ODR_ODR14);\
                    GPIOC->CRH &=~(GPIO_CRH_CNF13);\
                    GPIOC->CRH |=GPIO_CRH_MODE13;\
                    GPIOC->BSRR |=GPIO_BRR_BR13;//Set LED(active Low) BIT PC13 High
                    //GPIOC->ODR |=(1<<13);//PIN PC13 is High

#define LED0_ON()           GPIOC->ODR |=GPIO_ODR_ODR13
#define LED0_OFF()          GPIOC->ODR &=~GPIO_ODR_ODR13
#define LED1_ON()           GPIOA->ODR |=GPIO_ODR_ODR13
#define LED1_OFF()          GPIOA->ODR &=~GPIO_ODR_ODR13
#define LED2_ON()           GPIOA->ODR |=GPIO_ODR_ODR14
#define LED2_OFF()          GPIOA->ODR &=~GPIO_ODR_ODR14
#define LED0_TOGGLE()           GPIOC->ODR ^=GPIO_ODR_ODR13
#define LED1_TOGGLE()           GPIOA->ODR ^=GPIO_ODR_ODR13
#define LED2_TOGGLE()           GPIOA->ODR ^=GPIO_ODR_ODR14

#define DEL 1000

void LED_SWITCH_INIT(void);
void interrupt_enable(void);
void Blink_LED(uint32_t del);
void delay(uint32_t del);

int main(void)
{
    LED_SWITCH_INIT();
    interrupt_enable();
    while(1)
    {
    }
}


void LED_SWITCH_INIT(void){
        RCC->APB2ENR |=RCC_APB2ENR_IOPBEN;//Clock Enable For Port B
        RCC->APB2ENR |=RCC_APB2ENR_AFIOEN;
        //LED PUTPUT
        LED_INIT();
        //SWITCH INPUT 176
        AFIO->MAPR =AFIO_MAPR_SWJ_CFG_DISABLE;  //TAG-DP Disabled and SW-DP Disabled

        GPIOB->CRL &=~GPIO_CRL_CNF3;//|GPIO_CRL_CNF4|GPIO_CRL_CNF5|GPIO_CRL_CNF6|GPIO_CRL_CNF7);
        GPIOB->CRL |=GPIO_CRL_CNF3_1;//|GPIO_CRL_CNF4_1|GPIO_CRL_CNF5_1|GPIO_CRL_CNF6_1|GPIO_CRL_CNF7_1);
        GPIOB->ODR |=GPIO_ODR_ODR3;//|GPIO_ODR_ODR4|GPIO_ODR_ODR5|GPIO_ODR_ODR6|GPIO_ODR_ODR7|GPIO_ODR_ODR8|GPIO_ODR_ODR9;//Pullup Enable

        //AFIO->EVCR |=AFIO_EVCR_EVOE|AFIO_EVCR_PORT_0|AFIO_EVCR_PIN_PX3;

        AFIO->EXTICR[0] |=AFIO_EXTICR1_EXTI3_PB;    //Select EXT3 on PORTB for External interrupt3
        //AFIO->EXTICR[1] |=AFIO_EXTICR2_EXTI5_PB;
        EXTI->IMR |=EXTI_IMR_MR3;//|EXTI_IMR_MR19;  // (0)Select PIN PB3/* Interrupt mask register (EXTI_IMR) */
        //EXTI->IMR |=EXTI_IMR_MR5;
        //EXTI->EMR |= EXTI_EMR_MR3;//|EXTI_EMR_MR19; ///* Event mask register (EXTI_EMR) */
        EXTI->RTSR |=EXTI_RTSR_TR3; ////0: Rising trigger disabled (for Event and Interrupt) for input line
        //EXTI->FTSR |=EXTI_FTSR_TR3;   //1: Falling trigger enabled (for Event and Interrupt) for input line.
    /* Falling trigger selection register (EXTI_FTSR) */
        EXTI->FTSR |=EXTI_FTSR_TR3;
        //EXTI->FTSR |=EXTI_FTSR_TR5;
    /* Rising trigger selection register (EXTI_RTSR) */
        //EXTI->RTSR |=EXTI_RTSR_TR5;
    /* Pending register (EXTI_PR) */
        EXTI->PR |=EXTI_PR_PR3; //Clear Interrupt Flag
        //NVIC IRQ See Interrupt Enable faction */
        //EXTI->SWIER |=EXTI_SWIER_SWIER3;
}

void interrupt_enable(void){
    unsigned int priority = 0,Group=0;

    NVIC_SetPriorityGrouping(Group);
    /* bits[7:4] used for Group Priority
       N/A used for Sub-Group Priority */

    priority = NVIC_EncodePriority(Group,0,0);
    /*0= Priority Grouping, 0= Group Priority, 0= Sub-Priority*/

    NVIC_SetPriority(EXTI3_IRQn,priority);//Set new Priority

    //NVIC_SetPriorityGrouping(NVIC_PriorityGroup_1);

    NVIC_EnableIRQ(EXTI3_IRQn);

}

void EXTI3_IRQHandler(void){//
    LED0_TOGGLE();
    if ((EXTI->PR&EXTI_PR_PR3)) {
        EXTI->PR |=EXTI_PR_PR3; //Clear the EXTI line 3 pending bit
    }
}
    
pregunta Harish C jangid

2 respuestas

1

Cuando se produce una interrupción, el controlador debe ejecutar el ISR. Sin embargo, entre la aparición de la interrupción y el inicio de la ejecución de ISR, el controlador realiza las siguientes tareas:

  1. Finalice la ejecución de cualquier instrucción que estuviera ejecutando en el momento en que ocurrió la interrupción.

  2. Ahorro de contexto (para presionar todos los registros y la dirección de la siguiente instrucción a ejecutar)

  3. Salta a la tabla de vectores de interrupción y resuelve la dirección de ISR. es decir, donde está sentado el ISR correspondiente?

Finalmente el ISR comenzará a ejecutarse. Estos factores componen el retraso, lo que llamamos latencia de interrupción. Y en tu caso es 2.6 nosotros.

    
respondido por el MITU RAJ
0

Siempre hay una latencia heredada (retardo) desde el momento en que se activó un desencadenante de evento, en este caso, un pin de MPU es alto o bajo. Sin embargo, no solo existe un retraso en el ciclo del reloj desde el reloj de 4 fases que controla la mayoría de los núcleos de CPU / MPU, sino que cualquier código existente en proceso debe alcanzar un punto seguro donde pueda interrumpirse. Si no definió una ventana de interrupción en su código principal donde las interrupciones están habilitadas para tantos usuarios de EE. UU., Entonces se desactivará si una llamada ISR estaba pendiente o no, entonces el tiempo de reacción a una llamada ISR es desconocido.

Inserto en el bucle de reingreso de cada bloque de código (que podría mantener 'estado' por algún tiempo) una rutina ISR llamada IWIN, que significa ventana de interrupción. Solo permite interrupciones en un punto conocido en el código para 10 uS o menos. Permite ejecutar interrupciones pendientes y luego salir. Si no hay un ISR pendiente, IWIN expira, desactiva las interrupciones y vuelve al código principal.

Recuerde que todos los activadores, ya sea por hardware o software, tienen un estado pendiente antes de que un ISR pueda manejarlos . Debe definir dónde se permiten las interrupciones para evitar comportamientos impredecibles en su programa. Aun así, el código existente debe completarse hasta un punto seguro antes de verificar el estado de ISR.

    
respondido por el Sparky256

Lea otras preguntas en las etiquetas