Forum: µC & Digital Electronics STM32F1xx EXTI problem to trigger interrupt by SWIER

Author: Gernot (Guest)
Posted on:

Rate this post
0 useful
not useful

i have the following problem to solve:
an interrupt should be triggered when the frame-signal of a 
SPI-interface changes from 0 to 1. If, at the time of enabling this 
interrupt, the frame-signal is already high, the interrupt should be 
triggered by software instead of the rising edge.
I am using int-structures representing the register-bits of EXTI and 
other peripherals mapped to the according places within the 
bit-banding-area of the micro. These are name XXXbbbits. I am also using 
bit-structures which are representing the structures of their according 
registers to manipulate two or more bits at a time. Those are called 
XXXbits and are mapped to the registers original locations.
My SPI acts as a Slave.
I tried the following:
  #define TDXSPIClearFrameInt()            EXTIbbbits.PR.PR4=EXTI_PR_INT_CLR
  #define TDXSPIDisableFrameInt()          EXTIbbbits.IMR.MR4=EXTI_IMR_INT_DIS
  #define TDXSPIEnableFrameInt()          EXTIbbbits.IMR.MR4=EXTI_IMR_INT_EN
  #define TDXSPIClearPendingFrameInt()    NVIC_ClearPendingIRQ(EXTI4_IRQn)
  #define TDXSPISelectRisingFrameInt()    EXTIbbbits.RTSR.TR4=EXTI_RTSR_RE_EN
  #define TDXSPIUnselectRisingFrameInt()  EXTIbbbits.RTSR.TR4=EXTI_RTSR_RE_DIS
  #define TDXSPISelectFallingFrameInt()    EXTIbbbits.FTSR.TR4=EXTI_FTSR_FE_EN
  #define TDXSPIUnselectFallingFrameInt()  EXTIbbbits.FTSR.TR4=EXTI_FTSR_FE_DIS
  #define TDXSPICondRqFrameInt(cond)      EXTIbbbits.SWIER.SWIER4=cond?EXTI_SWIER_INT_RQ:~EXTI_SWIER_INT_RQ
  #define TDXSPIRequestFrameInt()          EXTIbbbits.SWIER.SWIER4=EXTI_SWIER_INT_RQ

  #define EXTI_IMR_INT_DIS         0u
  #define EXTI_IMR_INT_EN          1u
  #define EXTI_EMR_EVT_DIS         0u
  #define EXTI_EMR_EVT_EN          1u
  #define EXTI_RTSR_RE_DIS         0u
  #define EXTI_RTSR_RE_EN          1u
  #define EXTI_FTSR_FE_DIS         0u
  #define EXTI_FTSR_FE_EN          1u
  #define EXTI_SWIER_INT_RQ        1u
  #define EXTI_PR_INT_CLR          1u

void TDXSPISetTimeOut(enum eTDXSPITimeOutIntSources Source)
  // Set time-out-value, enable interrupt for retrigger
  // timer is not startet in case of RX or TX since we don't know when the TDX starts transmission
  // timer is started after reception of the first unit
  // timer-interrupt only used for checking FRAME-idle-time
  // FRAME-interrupt is used to start timer in case of TX and FRAME supervision
  // time-out occured when UIF-flag is set
  TDXSPIDisableFrameInt();                              // disable FRAME-interrrupts
  TDXSPIUnselectRisingFrameInt();                        // not sensitive to any edge
  TDXSPIDisableTimerInt();                              // disable timer-interruptss
  TDXSPIStopTimer();                                    // stop timer
    case TDXSPITimeOutIntSource_SPIRX:                  // initialize timer to supervise time-out during reception
      <some initialization>

    case TDXSPITimeOutIntSource_SPITX:                  // initialize timer to supervise time-out during transmission
      <some other initialization>
    case TDXSPITimeOutIntSource_RDY:                    // initialize timer to supervise maximum response-time to RDY
      <some other initialization>
    case TDXSPITimeOutIntSource_FRAME:                  // initialize timer to supervise minimum idle-time of FRAME-signal
      TDXSPIDEnableTimerInt();                          // enable timer-INTs
      TDXSPISelectRisingFrameInt();                      // Rising edge interrupt only
      TDXSPIClearFrameInt();                            // clear pending INTs
      if(TDXSPIFrameIsIdle())                            // request Int manually if FRAME is already idle
      TDXSPIEnableFrameInt();                            // enable FRAME-INTs

Unfortunately, no interrupt is issued by software. The interrupt is 
triggered only by hardware when the next positive edge occurs. But this 
is one telegram to late.
If I exchange the last two commands, it runs ok:
      TDXSPIEnableFrameInt();                            // enable FRAME-INTs
      if(TDXSPIFrameIsIdle())                            // request Int manually if FRAME is already idle

But, I ran into a race-condition when FRAME has its positive edge while 
the TDXSPIEnableFrameInt() is executed. In this case, the interrupt is 
triggered twice, first by hardware, than again by the if-clause. This 
should not happen.
I have no Idea, why the pending-bit is not set, when I use the first 
example. The only way I found, was to disable the intrerrupts either 
globally or in the NVIC, which I dislike both.

Has anybody a better idea or an explanation, why the first example 
doesn't work?

Thanks in advance


Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]

Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.