How to disable/enable interrupts on a stm32f107 ch

2019-07-26 14:40发布

问题:

I have an ARM stm32f107 chip. I'm porting a project from IAR to GCC

IAR provides the following functions to enable and disable interrupts:

#define __disable_interrupt() ...
#define __enable_interrupt() ...

How do I enable / disable interrupt for my chip using GCC?

回答1:

I can't answer for ARM but the same function in Coldfire boils down to setting/clearing the Interrupt Priority Level masking register in the CPU. Setting it to the highest number disables/ignores all but non-maskable, setting it to 0 enables all (YMMV).

Worth noting that it's handy to read-back the value when "disabling" and restore when "enabling" to ensure that stacked interrupts don't break each other:

ipl = DisableInts(); // Remember what the IPL was
<"Risky" code happens here>
EnableInts(ipl); // Restore value

This is useful when twiddling interrupt masks, which may cause spurious interrupts, or doing stuff that shouldn't be interrupted.

Functions come out as:

uint8 DisableInts(void)
{
    return(asm_set_ipl(7));
}

uint8 EnableInts(uint8 ipl)
{
    return(asm_set_ipl(ipl));
}

Both of which map to this asm:

asm_set_ipl:
_asm_set_ipl:
/* Modified for CW7.2! */
    link    A6,#-8
    movem.l D6-D7,(SP)

    move.l  D0,D6           /* save argument                 */

    move.w  SR,D7           /* current sr                    */

    move.l  D7,D0           /* prepare return value          */
    andi.l  #0x0700,D0      /* mask out IPL                  */
    lsr.l   #8,D0           /* IPL                           */

    andi.l  #0x07,D6        /* least significant three bits  */
    lsl.l   #8,D6           /* move over to make mask        */

    andi.l  #0x0000F8FF,D7  /* zero out current IPL          */
    or.l    D6,D7           /* place new IPL in sr           */
    move.w  D7,SR

    movem.l (SP),D6-D7
    //lea     8(SP),SP
    unlk    A6
    rts


回答2:

When developing for the STM32, RM0008 is your best friend. From Section 10.2.4 on page 199:

To generate the interrupt, the interrupt line should be configured and enabled. This is done by programming the two trigger registers with the desired edge detection and by enabling the interrupt request by writing a ‘1’ to the corresponding bit in the interrupt mask register.

So you need to set the appropriate mask bits in the appropriate registers. For external interrupts, that's the EXTI_IMR and EXTI_EMR registers. There are many others.



回答3:

The ARM Documentation says that _enable_irq(); compiles to “CPSIE I” that means Clear All Masks. On the other hand _disable_irq(); compiles to Set Mask.