Electrical – External Interrupt delayed to in STM31F103C8

cinterruptsmicrocontrollerstm32f103c8t6

I have to write a C program to toggle an LED using an external interrupt on STM32F103(72MHz System Clock). I have initialized EXTI3 on the Falling edge and the ISR Handler toggles an led at high frequency input on external interrupt sensing pin there are delay between sensing and execution of ISR (Approximately 2.6uSec, almost 188 system clock pulse). Where does this delay come from?

I am Attaching my code blow, I have verify my micro-controller clock by writing timer 1 PWM for specific frequency (witch is calculated by the clock frequency 72MHz).

Here Is my code:

#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
    }
}

Best Answer

When an interrupt occurs, ISR has to be executed by the controller. However in between the occurence of interrupt and starting of ISR execution, following things are typically done by the controller:

  1. Finish the execution of whatever instruction it was executing at the time of occurrence of the interrupt.

  2. Context saving ( pushing all regs and the address of next instruction to be executed, to stack )

  3. Jump to the interrupt vector table and resolve the address of ISR. i.e., where the corresponding ISR is sitting ?

Finally the ISR will start executing. These factors make up the delay, what we call interrupt latency. And in your case it is 2.6 us.