This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS470R1B1M FIQ & IRQ problem

Other Parts Discussed in Thread: TMS470R1B1M

Hi everyone.  this is my first post.  I am having issues using the FIQ interrupt and IRQ interrupt in conjunction.  I am using IAR embedded workbench 5.00.  I am looking for a procedure on how to setup the two interrupt types.  The basic scenario is as follows:

I have 4 interrupts on the HET.  Three are based on a rising edge on the high speed input pins and one is based on the timer such that it occurs once every millisecond.  The three edge detections occur every 16.67ms and are offset by 5.55 ms from each other.  I started off having all 4 interrupts serviced by the same IRQ_Handler, however, the 3 edge detections can sometimes occur when the 1ms interrupt is operating.  The 5.55ms interrupts occuring as close to the rising edge as possible is much more important than the 1ms interrupt.  As such, I want the edge detection interrupts to occur even if the 1ms interrupt is processing.  I tried therefore to have all the edge detections serviced by the FIQ interrupt.  The interrupt routine works, however, when it is happening periodically the processor will crash.  When I take away the rising edge input signals that drive the edge interrupts the processor does not crash.  I thought perhaps it was a stack issue with the FIQ, but doubling the stack has no positive effect.  I am not sure what to do.  I have included my cstartup.s code below as well as the initialization statements for the FIQ, IRQ and the interrupt handlers.  Thanks so much for your help.  Another option I am willing to consider is nested IRQ interrupts if someone will help me as I cannot seem to get them right.

CStartup.S

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Part one of the system initialization code,
;; contains low-level
;; initialization.
;;
;; $Revision: 18087 $
;;

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION SVC_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)

;
; The module in this file are included in the libraries, and may be
; replaced by any user-defined modules that define the PUBLIC symbol
; __iar_program_start or a user defined start symbol.
;
; To override the cstartup defined in the library, simply add your
; modified version to the workbench project.

        SECTION .intvec:CODE:NOROOT(2)

        PUBLIC  __vector
        PUBLIC  __iar_program_start
        EXTERN IRQ_Handler
        EXTERN FIQ_Handler

        ARM
__vector:
        ;;
        B   __iar_program_start         ;; Reset
        B   .                           ;; Undefined instructions
        B   .                           ;; Software interrupt (SWI/SVC)
        B   .                           ;; Prefetch abort
        B   .                           ;; Data abort
        B   .                           ;; RESERVED
        B   IRQ_Handler                 ;; IRQ
        B   FIQ_Handler                 ;; FIQ

; --------------------------------------------------
; ?cstartup -- low-level system initialization code.
;
; After a reser execution starts here, the mode is ARM, supervisor
; with interrupts disabled.
;

       SECTION .text:CODE:NOROOT(2)

;        PUBLIC  ?cstartup
        EXTERN  ?main
        REQUIRE __vector

        ARM

__iar_program_start:
?cstartup:

;
; Add initialization needed before setup of stackpointers here.
;

;
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
;
; --------------------
; Mode, correspords to bits 0-5 in CPSR
MODE_BITS DEFINE  0x1F    ; Bit mask for mode bits in CPSR
USR_MODE  DEFINE  0x10    ; User mode
FIQ_MODE  DEFINE  0x11    ; Fast Interrupt Request mode
IRQ_MODE  DEFINE  0x12    ; Interrupt Request mode
SVC_MODE  DEFINE  0x13    ; Supervisor mode
ABT_MODE  DEFINE  0x17    ; Abort mode
UND_MODE  DEFINE  0x1B    ; Undefined Instruction mode
SYS_MODE  DEFINE  0x1F    ; System mode

        MRS     r0, cpsr                ; Original PSR value

        BIC     r0, r0, #MODE_BITS      ; Clear the mode bits
        ORR     r0, r0, #IRQ_MODE       ; Set IRQ mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(IRQ_STACK)     ; End of IRQ_STACK

        BIC     r0 ,r0, #MODE_BITS      ; Clear the mode bits
        ORR     r0 ,r0, #FIQ_MODE       ; Set FIQ mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(FIQ_STACK)     ; End of FIQ_STACK

        BIC     r0, r0, #MODE_BITS      ; Clear the mode bits
        ORR     r0, r0, #SVC_MODE       ; Set SVC mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(SVC_STACK)     ; End of SVC_STACK


#ifdef __ARMVFP__
        ;; Enable the VFP coprocessor.

        MOV     r0, #0x40000000         ; Set EN bit in VFP
        FMXR    fpexc, r0               ; FPEXC, clear others.

;
; Disable underflow exceptions by setting flush to zero mode.
; For full IEEE 754 underflow compliance this code should be removed
; and the appropriate exception handler installed.
;

        MOV     r0, #0x01000000         ; Set FZ bit in VFP
        FMXR    fpscr, r0               ; FPSCR, clear others.
#endif

;
; Add more initialization here
;

; Continue to ?main for more IAR specific system startup
                ldr   r0,=?main
                bx    r0

        END

I then initialize the FIRQPR register when i put my clock into pipelined mode and setup the REQVEC

 PCR = CLKDIV_4;
  
  GCR = 0x00008000;
  PCR |= PENABLE;
 
  //FIRQPR = (1<<CIM_HET1);
  //Enables these interrupts: HET1 (High Priority) HET2 (Low Priority)
  REQMASK = ((1 << CIM_HET1) + (1 << CIM_HET2));       // Enable HET Interrupt Mask

I then initialize the High End Timer (HET)
__no_init volatile HETPROGRAM0_UN e_HETPROGRAM0_UN @ 0x00800000;

void MemCopy32(unsigned long *dst, unsigned long *src, int bytes);

void HET_init()
{
 
  HETGCR = CLK_MASTER;
  /* %0000000000000001000000000000000;
  bit 24 - Power Down - set to 1 will stop clocks of HET
  bit 16 - used to synchronize multiple HETs.  For single HET must be
           set to 1.
  bit 8 - 64 bit access - set to 0 so 32 bit access of HET.
  bit 2 - debug status flag - set when in test mode and a breakpoint is reached
  bit 1 - Ignore suspend - set to zero so stops at software breakpoints - in
          debug mode.
  bit 0 - on/off.  Only set to 1 to activate timer.
  */ 
 
 
  MemCopy32((unsigned long *)&e_HETPROGRAM0_UN, (unsigned long *)HET_INIT0_PST,
           sizeof(HET_INIT0_PST));  
  /*
  PLACE THIS ITEM IN MAIN CODE:
  HETGCR |= 1;      //Turns on HET 
  Read HETFLG to see which interrupt fired.
 
  */

  HETPFR = 0x204;    //Prescale factors - must be set!
  //20 time slots - set LR to 4 (010) and HR to 4 (000100) which is 5 slots
  //LR & HR are multiplied for HET time slots 4*5 = 20
 
 
  HETDCLR = 0xffffffff;                         // Clear HET output latches
  HETDIR = 0xFFFFFFF8;
  //HETDIR = 0x0000003F;    //SETS OUTPUTS AND INPUTS
  //Pins 3,4,5 are outputs - SCRGATECTRL0,1,2
  //Pins 0,1,2 are inputs - PhaseCrossDetection0,1,2
 
 
  Interrupt_Init();
   
}

void MemCopy32(unsigned long *dst, unsigned long *src, int bytes)
{
  for (int i = 0; i < (bytes + 3) / 4; i++)
    *dst++ = *src++;
}

Then here is the interrupt vectors and the subroutines called by them.  All of these are located in the main.cpp file.

void HET1_irq_handler();
void HET2_irq_handler();

//------------------------------------------------------------------------------
// TMS470R1B1M Standard Interrupt Handler
//------------------------------------------------------------------------------

extern "C" __irq __arm void IRQ_Handler(void)

  switch ((0xff & IRQIVEC)-1)
  {
    //Checks HET group 2 - low priority
  case CIM_HET2 :
     HET2_irq_handler();
     break;
  }
}

//------------------------------------------------------------------------------
// TMS470R1B1M Standard Interrupt Handler
//------------------------------------------------------------------------------

extern "C" __fiq __arm void FIQ_Handler(void)

  switch ((0xff & FIQIVEC)-1)
  {
   //Checks HET group 1 - high priority
   case CIM_HET1 :
     HET1_irq_handler();
     break;
  }
}

 

//------------------------------------------------------------------------------
// HET Priority 1 Interrupt Handler
//------------------------------------------------------------------------------
void HET1_irq_handler()
{
  HSI_Status = HETFLG & 0x700;

  switch ((0xff & HETOFF1)-1)   //This also resets the HET interrupt flag
  {
  //Interrupts for phase crossings
  case 8:
    HET_Phase_A();
    break;
  case 9:
    HET_Phase_B();
    break;
  case 10:
    HET_Phase_C();
    break;
  }
}

//------------------------------------------------------------------------------
// HET Priority 2 Interrupt Handler
//------------------------------------------------------------------------------
void HET2_irq_handler()
{
  switch ((0xff & HETOFF2)-1)   //This also resets the HET interrupt flag
  {
  case 0:             // Instruction 0
    //1 MS interrupt
    HET1_1ms_INT();
    break;
  //Interrupt if no crossings detected
  case 11:
    HET_No_3_Phase();
    break;
  }
}

The symptoms are intermittent.  Sometime the chip will reset after a second, sometimes 4 or 5 seconds, sometimes a little longer, but it never resets when the edge crossings are not occuring.  Thanks for your help.

  • Hello,

    Can you view the contents of the system module exception status register and the global status register when the reset occurs? This will give an indication of what is causing the system reset.

    Regards,

    Sunil

  • Hi Jonathan,

        You may have your problem resolved already.


        Here are my thoughts:

        The interrupts are working intermittently may due to the HET  priority level for those HET interrupt sources/instructions are not being setup correctly. Try to add the following:

      . . .

      //Set the priority level of these interrupts group: CIM_HET1 (High Priority) CIM_HET2 (Low Priority)

    HETPRY = (0x1 << 8) + (0x1 << 9) + (0x1 << 10) ;        //<--Add this: HET interrupt from instruction 8, 9 and 10 are priority 1, and the rest are priority 2.

      . . .

    Note: After the uC power-on reset, the HETPRY is 0x00000000 by default.


    Best Regards,

    Soo


  • I ended up resolving the problem using the WCAP timer command to simply capture when the rising edge crossings occur and then servicing them after the 1ms interrupt is finished.  That is really what i needed was the exact time the interrupt occured.  Thanks though.