2
\$\begingroup\$

I am using STM32VL discovery board(STM32f100rb6).. I wrote following code for NVIC:

void Interrupt_Init(void)
{
    __enable_irq();
    /*Core Base(NVIC)*/

    //set priority to 0
    //NVIC->IP[6] &= ~((uint32_t)0xff00);

    //Activate Interrupts
    NVIC->ISER[0] |= BIT6;

    //Enable Pending BIT for Interrupt 6
    NVIC->ISPR[0] |= BIT6;
    lcd_writechar('1');
} 

and

int main(void)
{
Interrupt_Init();
    while (1)
    {

    }
}
void EXTI0_IRQHandler(void)
{
    //NVIC->ICPR[0] |= BIT6;

    lcd_writechar('2');
}

as you see under Interrupt_Init() I user NVIC->ISPR[0] |= BIT6; phrase to soft-enable exti0-IRQ. so void EXTI0_IRQHandler(void) subroutine must executed and I got '2' on LCD. but as NVIC->ISPR[0] |= BIT6; execute next line(lcd_writechar('1');) never runs.. but when I commented (NVIC->ISPR[0] |= BIT6;) I got '1' on LCD... whats going on??

Update:

I look further into "startup_stm32f10x_md_vl.s" file in my project as startup file:

.section  .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b  Infinite_Loop
  .size  Default_Handler, .-Default_Handler

and:

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  .word  WWDG_IRQHandler
  .word  PVD_IRQHandler
  .word  TAMPER_IRQHandler
  .word  RTC_IRQHandler
  .word  FLASH_IRQHandler
  .word  RCC_IRQHandler
  .word  EXTI0_IRQHandler
...

and:

.weak  EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler

It seems that "EXTI0_IRQHandler" always equal to "Default_Handler" in my projects so it cause infinite loop as we define above.

I think this part:

void EXTI0_IRQHandler(void)
{
  NVIC->ICPR[0] |= BIT6;

  lcd_writechar('2');
}

never influences the "EXTI0_IRQHandler" definition. why?

Update:

Is there any way to jump to EXTI0_IRQHandler without implementing anything in peripheral?? Like asm("B 0x58")? my purpose is to be sure from core configurations then work on peripheral configurations ?

Update:

I nearly found problem but needs help to fix it.. after many examination and using debug features I found this piece of code is faulty:

    void EXTI0_IRQHandler()
    {
      lcd_writechar('2');
      LED_ON();
      NVIC->ICPR[0] |= BIT6;
    }

in detail lcd_writechar('2'); cause to issue because inside function I am using delay() function.This is that piece of code involving delay by SycTick feature:

/*Enable SysTick*/
  //Processor clock (AHB)
  SysTick->CTRL |= BIT2;
  //Counting down to zero to asserts the SysTick exception request.
  SysTick->CTRL |= BIT1;
  SysTick->LOAD = 8000 - 1;
void SysTick_Handler(void)
{
  SysTick_Tick++;
  //lcd_writechar('7');
  SCB->ICSR |= BIT25;
}
void delay(int ms)
{
  SysTick_Tick = 0;
  //Enable Systick Counter
  SysTick->CTRL |= BIT0;
  while (SysTick_Tick < ms) {}
  //Disable Systick Counter
  SysTick->CTRL &= ~BIT0;
  SCB->ICSR |= BIT25;
  return;
}

as you see I am trying to clear pending bit of SysTick by SCB->ICSR |= BIT25; but clearly after running of delay() function from inside of EXTI0_IRQHandler() everything hangs..

\$\endgroup\$
4
\$\begingroup\$

When you enter the interrupt routine, you need to clear the interrupt source flag. If you do not clear the flag, when you exit the interrupt routine it will just re-enter the routine. This way you will always be stuck in EXTI0_IRQHandler.

\$\endgroup\$
  • \$\begingroup\$ thank for your answer but how?? may you explain more by example related o this project?? \$\endgroup\$ – peyman khalili Jun 7 '17 at 16:49
  • \$\begingroup\$ I use void EXTI0_IRQHandler(void) { NVIC->ICPR[0] |= BIT6; lcd_writechar('2'); } for clearing the interrupt source flag but lcd_writechar('2') never runs and everything is the same. \$\endgroup\$ – peyman khalili Jun 8 '17 at 6:54
  • \$\begingroup\$ I am thinking it will always stuck in SysTick_Handler(), please read last update. \$\endgroup\$ – peyman khalili Jun 13 '17 at 5:51
3
\$\begingroup\$

The NVIC->ICPR only removes the pending bit in the NVIC.
But, if the IRQ signal to the NVIC is still active (the EXTI PR register), the pending bit clear in the NVIC will have no effect.

Instead, you have to clear the interrupt request source, EXTI->PR = EXTI_PR_PR6 in the ISR. Otherwise you will be tail-chaining this interrupt routine until a higher priority one arrives.

The definitions you find in startup.s are weak, you override these when you write the actual function.

Using NVIC->ISPR[0] |= BIT6 you generate a software interrupt request. It is cleared when entering the ISR.

General tip, when debugging missing interrupt routines, set a breakpoint here:

.section  .text.Default_Handler,"ax",%progbits
Default_Handler:
 Infinite_Loop:
  b  Infinite_Loop  <-------- breakpoint
  .size  Default_Handler, .-Default_Handler
\$\endgroup\$
  • \$\begingroup\$ @peymankhalili there are two ways to run the isr by software. Call the function. Or set the pending bit. \$\endgroup\$ – Jeroen3 Jun 8 '17 at 19:43
  • \$\begingroup\$ Yes, I did it( set pending bit) by NVIC->ISPR[0] |= BIT6, so void EXTI0_IRQHandler(void) function supposed to run.. but not happening...because we did not get '1' on LCD as lcd_writechar('1'); admit it. \$\endgroup\$ – peyman khalili Jun 9 '17 at 6:02
  • \$\begingroup\$ @peymankhalili Are you by any change triggering the RCC_IRQHandler? \$\endgroup\$ – Jeroen3 Jun 9 '17 at 6:25
  • \$\begingroup\$ no, I want to triggering EXTI0_IRQHandler. I think you want to mention to asm("B 0x58"), It is address of EXTI0_IRQHandler. \$\endgroup\$ – peyman khalili Jun 9 '17 at 7:36
  • \$\begingroup\$ @peymankhalili The NVIC is offset from the vector table by the exceptions. Maybe bit6 is not the IRQ you think it is. Also, you can't branch without link and expect to return. Search for the Procedure Call Standard. \$\endgroup\$ – Jeroen3 Jun 9 '17 at 8:48
1
\$\begingroup\$

Finally, I found the mistake. Priority is the problem.

Use NVIC_SetPriority(EXTI0_IRQn, 1); to set SysTick to a higher priority level than EXTI0_IRQn. Then everything goes OK.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.