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.
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.
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.