Interrupt Handler and Context Saving

General discussion on mikroPascal PRO for PIC32.
Author
Message
Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Interrupt Handler and Context Saving

#1 Post by Rotary_Ed » 25 Aug 2013 14:35

After some further research, I am starting to get some answers to questions I have
about the PIC32 Pascal Compilers handling of interrupts in the multivector mode. I set up Input Capture modules 1 and 3 for detecting rising edge of pulse inputs to both.

In this example, I set the multivector interrupt ics to ICS_OFF which according to the compiler HELP
should mean no context saving as shown below.
ics Interrupt Context Saving; Interrupt Context Saving can be performed in several ways :
ICS_SOFT - Context saving is carried out by the software.
ICS_SRS - Shadow Register set is use for context saving.
ICS_OFF - No context saving
ICS_AUTO - Compiler chooses whether the ICS_SOFT or ICS_SRS will be used.

and also then I also insert the command "disablecontextsaving" (which also indicates no context is saved).
I had expected those two actions would preclude a return from the Interrupt Handler to the Main loop. However, the code pointer did return to the main loop. How? I wondered. See remark after code listing.

These two actions resulted in the following code listing for IC1 and IC3 input capture modules. Note that there is no prologue or Epilogue code with context saving disabled (which is what one would expect with context saving disabled)

So this is sort of the base line.

Code: Select all

 
 //R30 is a temporary Register used to temporarily hold data
  //R0 is always zero - hardware enforced
  //R2 is used for function return values from Co
  //R23 Saved Temporally - caller must preserve value
  //R24 Temporary - caller does not need to preserve contents
...
...  //Input Capture Modules IHR code listing
_IC3:
;IC1_IC3_Test.mpas, 18 ::                 begin
;IC1_IC3_Test.mpas, 20 ::     PORTBset := 0x00002000;  //Turn on LED
     // Following code sets bit 13 in register PORTBclr to turn on LED
0x9D000020        0x34022000  ORI   R2, R0, 8192 // ORI Logical OR Immediate Rt = Rs | Immed  8192 (... 00100000 00000000) set bit 13 and put in R2
0x9D000024        0x3C1EBF88  LUI   R30, 49032  //LUI Load Upper Immediate Rt = immediate << 16   49032 (...  10111111 10001000)
0x9D000028        0xAFC26058  SW    R2, 24664(R30) // SW Store Word Mem[Rs+offset] = Rt
     // Following code clears IFS0.IC3IF flag using IFS0clr and bit 13 in R0
;IC1_IC3_Test.mpas, 22 ::     IFS0.IC3IF  := 0;  //clears interrupt flag (bit 13) at mem addr BF88xxxx +
0x9D00002C        0x34022000  ORI    R2, R0, 8192   //set bit 13 in R2
0x9D000030        0x3C1EBF88  LUI    R30, 49032  //put mem addr BF88 in R30 and **** to upper region of R30
0x9D000034        0xAFC21034  SW     R2, 4148(R30)//Mem addr offset  1030 points to IFS0clr register and + 4 points to bit four, IFS0.IC1IF
;IC1_IC3_Test.mpas, 24 ::                 end;
L_end_IC3:
0x9D000038        0x42000018  ERET     // Clear EXL bit(Enables Interrupts), restores Program Counter and
                                       //reverts the current shadow set to the previous one
; end of _IC3
_IC1:
;IC1_IC3_Test.mpas, 8 ::                 begin
;IC1_IC3_Test.mpas, 10 ::                 PORTBSet := 0x00002000; //Turn on LED PORTB.RB13
0x9D00003C        0x34022000  ORI        R2, R0, 8192
0x9D000040        0x3C1EBF88  LUI        R30, 49032
0x9D000044        0xAFC26058  SW        R2, 24664(R30)
;IC1_IC3_Test.mpas, 12 ::                 IFS0.IC1IF := 0;  //Clear Flag
0x9D000048        0x34020020  ORI        R2, R0, 32
0x9D00004C        0x3C1EBF88  LUI        R30, 49032
0x9D000050        0xAFC21034  SW        R2, 4148(R30)
;IC1_IC3_Test.mpas, 14 ::                 end;
L_end_IC1:
0x9D000054        0x42000018  ERET      // Clear EXL bit(Enables Interrupts), restores Program Counter and
                                       //reverts the current shadow set to the previous one
; end of _IC1

I then found generated by the compiler at the end of each interrupts code listing the instruction
"ERET" This instruction appears to do several things
1. It Clears the EXL bit(Which globally Enables Interrupts) in the CP0processor Status Register
2. Restores Program Counter (still not certain when the counter is saved but apparently before going into the IRH code)
3. Reverts the current shadow set to the previous one.

So this command appears to be adequate on its own to ensure return from the interrupt handler code, provided the interrupt condition is removed and the module's interrupt flag is cleared in the IHR. IF the flag is not cleared then it appears that the pointer remains pointing to the IRH and no return occurs.

Another item of interest is that whether or not the Input Capture Module has been interrupted enable, if it is turned on and the interrupt condition is met, then the interrupt flag is set. If the module also has its interrupt enabled, then in addition to turning the flag on, an IRQ (interrupt Request) is sent by the module to the Interrupt Controller.

The interrupt controller then checks various registers such as the Status and Cause registers (for such things as interrupt priority and source) of the CP0processor to
determine whether to instruct the main CPU to service the interrupt request.

I will report on results when I next turn context saving back on and generate code from the same source code.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#2 Post by Rotary_Ed » 25 Aug 2013 14:47

I should have shown my interrupt test code previous to the last message

This is my interrupt Handler code. While the priorities are the same the subpriority is set differently. This way I could either have the context saving Prologue and Epilogue code produced using the ICS_SRS or not have any produced by choosing ICS_OFF.

Code: Select all

procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF} ; //Test1

  var Empty_buf:dword ;

   begin

            PORTBSet := 0x00002000; //Turn on LED PORTB.RB13
            Empty_buf := IC1buf;//Empty buffer to remove cause for Persistent Interrupt
            IFS0.IC1IF := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
                              // and pointer never returns to Main loop
   end;
Procedure IC3(); iv IVT_INPUT_CAPTURE_3; ilevel 6; ics ICS_SRS{ICS_OFF}; //Test 1
   var Empty_buf:dword;

   begin

            PORTBset := 0x00002000;  //Turn on LED
            Empty_buf := IC3buf;//Empty buffer to remove cause for Persistent Interrupt
            IFS0.IC3IF  := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
                              // and pointer never returns to Main loop
   end;
This is the Main Code Loop from which the interrupts occur

Code: Select all

 //Expect LED to turn off as Input Capture interrupts return to main loop
   //Either IC will turn on LED, but PORTBclr should turn it off if the program ever returns from interrupt
   //Interrupts do occur for each IC as pulse input applied to each pin will turn on the LED
   //However, the LED does not blink or go off indicating it never returns to Main loop.
   //The only way I can get the IRH to return to main loop is to disable interrupt of the module (IEC0.ICXIE := 0);
   //Pulse train for each is 66.6 Hz with 2msec pulses at at approx 15% duty cycle

   repeat      //Main Loop
       delay_MS(100);
       //Enable IC modules for interrupt and turn on LED in IRH code
       IEC0.IC1IE := 1; //Enable Interrupt
       IFS0.IC1IF := 0; //clear any surious Flag
      
       IEC0.IC3IE := 1; //Enable Interrupt
       IFS0.IC3IF := 0; //clear any surious Flag

       Delay_MS(100);    //Leave LED on for a time

       //Now if pointer returns from IHR to Main loop then disables further Interrupts
       //This would turn off LED otherwise it stays hung in the IRH with repeated interrupts
       //NOTE: To check this code, IF interrupt flag is not cleared in IRH code, the pointer never returns
       //to this main loop.  Otherwise, if it does return it causes LED to blink
       IEC0.IC1IE := 0; //Disable Interrupt
       Empty_buf  := IC1buf; //clear cause of Persistent Interrupt
       IFS0.IC1IF := 0; // clear flag

       IEC0.IC3IE := 0; //Disable Interrupt
       Empty_buf  := IC3buf; //clear cause of Persistent Interrupt
       IFS0.IC3IF := 0; // clear flag

       PORTBclr := 0x00002000;    // LED Should LED if pointer returns from IHR otherwise
                               //if it does not then the pointer never returns from IHR
       //Repeat loop by Re-Enabling Interrupts
       
   until 1 = 2;
When this code was used with the baseline case mentioned in previous post, pulse input to either module would cause the LED to turn on and if the interrupt flag was cleared in the IHR, the code returned to the main loop and caused the LED to blink as the interrupts were first enabled then disabled.

IF I failed to clear either modules interrupt flag, then the code pointer would not return to the main loop and the LED would not blink.

So in summary, if the LED blink that mean return to main loop and if failed to blink that mean the pointer was not returning to the Main loop.

If anyone sees a flaw in this arrangement to determine whether code returns - please let me know!!

I attempted simpler code such as just having the LED turned of in the main code with delays so I could visually see the blink, but decided that was unreliable as it might blink faster than my eyes could detect or the delays would be interrupted by the interrupt so would not help.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#3 Post by Rotary_Ed » 25 Aug 2013 15:11

Ok, here I turn on the context saving to see what code the compiler generates

The settings of interrupt handlers is shown with the ICS_SRS active.

procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF} ; //Test2
Procedure IC3(); iv IVT_INPUT_CAPTURE_3; ilevel 6; ics ICS_SRS{ICS_OFF}; //Test 2

This code then was compiled and the listing was
NOTE: Memory locations can be found in Section 3 of PIC32MX795L512H data sheets
as well as Tables 4-xxx for various PORTS and Perhiperhals

Code: Select all

With ics ICS_SRS, you can clearly see the Prologue and Epilogue generated by the listing
Here data is exchanged between the code and the Coprocessor through the MFCO and
MFT0 instructions.  Both ICs respond to pulse input by turning on the LED
However, there is still no indication the interrupts return to the Main loop
   //Input Capture IC3 Code Listing of its Interrupt Handler
...
...
...
_IC3:
;IC1_IC3_Test.mpas, 18 ::                 begin   //Begin of IC3 interrupt Handler code
                         //Interrupt Prologue
0x9D000000        0x415DE800  RDPGPR   SP, SP    //RDPGPR Read GPR from Previous Shadow Set
                                             //Rt = SGPR[SRSCtlPSS, Rd]  PSS<3:0> bits(SRSCtl<9:6>)
0x9D000004        0x27BDFFF8  ADDIU  SP, SP, -8  //Create Stack space of 8 bytes (2 words)
0x9D000008        0x401E7000  MFC0   R30, 14, 0 //Move EPC value from CoProcessor to R30
0x9D00000C        0xAFBE0004  SW     R30, 4(SP) //Store Value (EPC Pointer) to 
                                             //offset (4) in base (Stack -SP)
                                             //  Push Contents of R30 (EPC pointer) onto stack position 4
0x9D000010        0x401E6000  MFC0   R30, 12, 0  //Move Status Register Content to R30
0x9D000014        0xAFBE0000  SW     R30, 0(SP)  //Push Status Register Content to stack position 0
0x9D000018        0x7C1E7844  INS    R30, R0, 1, 15 //Insert bit field of zeros to clear R30, then
                                                //at postion 1 of R30 for the next 15 bits
0x9D00001C        0x341E1800  ORI    R30, R0, 6144  //OR immediate the bits (... 00011000 00000000)
                                                  // R30 or Requested intercept priority 6 (..110..) into R30
0x9D000020        0x409E6000  MTC0   R30, 12, 0  //Move contents of R30 back to IPL field of Status
                                                //Register in the CoProcessor
                                                
                                         //NOTE.  Apparently if the IPL priority code being sent to IPL of
                                         //status register is not HIGHER than that currently in tha IPL field
                                         //then no interrupt will occur - yet it appears we have already
                                         //had an interrupt to get to this point  puzzled???
                                                         
   //The next set of instructions are related to turning on PORTB.RB13 - bit 13 so LED will turn on

;IC1_IC3_Test.mpas, 20 ::        PORTBset := 0x00002000;  //Turn on LED  code
0x9D000024        0x34022000  ORI   R2, R0, 8192 //OR Immediate contents of R2 (Function Return Register)
                                           //with bits (... 00100000 00000000)-bit 13  PORTB is set -for LED
0x9D000028        0x3C1EBF88  LUI   R30, 49032   // LUI Load Upper Immediate Rt = immediate << 16
                                             //Bits (... 10111111 10001000 ) shift left 16 bits =
                                             //3213361152 = BF88 00 00 Address loaded in R30  =>
                                             //Internal Peripherals virtual Memory Map
                                             //Starting at BF88_#
0x9D00002C        0xAFC26058  SW    R2, 24664(R30)//Store R2 value at mem location of R30(10111111 10001000..) +
                                             // offset of  24664(...  01100000 01011000)   =
                                             // 10111111 10001000 01100000 01011000 = BF 88 60 58 => 6050 =
                                             //PORTclr memory Register at bit 13 (LED)
                                             //location which then has bit 13 set - to turn on LED
                                                        
//The next set of instructions are related to clearing the interrupt Flag

;IC1_IC3_Test.mpas, 22 ::          IFS0.IC3IF  := 0;  //clears interrupt flag
0x9D000030        0x34022000  ORI      R2, R0, 8192   // Bits (... 00100000 00000000 )  Set bit 13 in R2
                                                         //(Just a coinicident that this
                                                         // is bit 13 same as the LED bit in PORTB)
0x9D000034        0x3C1EBF88  LUI      R30, 49032    // Load Base Address for Peripheral address BF880000 into R30
0x9D000038        0xAFC21034  SW       R2, 4148(R30)  // Point to R30 (base) + Offset 4148 = 0x1034 = BF881030 =
                                                         //IFS0 + 4 = the IFS0clr register bit 13  which clears IFS0.IC3IF
;IC1_IC3_Test.mpas, 24 ::             end;   // End of IC3 Interrupt Handler code
//Now the code reverts back to the register values and Pointer location that it saved at the beginning

             // Epilogue for IC3  - Return to Main code
L_end_IC3:
0x9D00003C        0x8FBE0004  LW       R30, 4(SP)   //LW Load Word Rt = Mem[Rs+offset]  pop EPC pointer off stack
                                                    // and load into R30
0x9D000040        0x409E7000  MTC0     R30, 14, 0  //Move Saved EPC pointer back to CoProcessor EPC register
0x9D000044        0x8FBE0000  LW       R30, 0(SP)    // Pop Saved Status Register Contents  off Stack into R30
0x9D000048        0x409E6000  MTC0     R30, 12, 0  //Update Status Register contents in CoProcessor
0x9D00004C        0x27BD0008  ADDIU    SP, SP, 8  //Clear stack
0x9D000050        0x41DDE800  WRPGPR   SP, SP  //WRPGPR Write to GPR in Previous Shadow Set SGPR[SRSCtlPSS, Rd] = Rt
0x9D000054        0x42000018  ERET     // Clear EXL bit(Enables Interrupts), restores Program Counter and 
                                       //reverts the current shadow set to the previous one

; end of _IC3

//The code and commments are similar (almost identical except for the clearing of IFS0.IC1)
// for IC1 input Capture module and are therefore not shown
So here we have the prologue and epilogue code generated for the interrupt handler code with ICS_SRS and Contextsaving not disabled.

So with all of these registers saved, there should be no problem with the pointer returning to the main loop and causing the LED to blink as the first example did.

However, the pointer apparently does not return to the main loop. At least, the LED never blinks which it did in the first example (with no context saving and ICS_OFF) so apparently the pointer never returns to the Main loop.

So now I am left completely mystified - is there a flaw in my approach to determining when the pointer returns to the main loop (the blinking LED) and is it actually returning? IF is returning why is the LED not blinking as it did in the first test example?

Any help in pointing out flaws in my thinking process, understanding or code would be GREATLY appreciated.

Thanks
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#4 Post by Rotary_Ed » 25 Aug 2013 15:46

I decided to compare side by side in this example. I turn context saving off for IC3 and left it on for IC1. So I set up the two IRH procedures as follows:
procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF}; //Test2
Procedure IC3(); iv IVT_INPUT_CAPTURE_3; ilevel 6; ics {ICS_SRS} ICS_OFF; //Test 2

The test for a return of the pointer to the main loop would be a blinking LED

Code: Select all

_IC3:
// using Procedure IC3(); iv IVT_INPUT_CAPTURE_3; ilevel 6; ics {ICS_SRS} ICS_OFF; //Test 2
 // With ICS_OFF, The IC3 code has no prologue/epilogue, but does result in a return to Main loop - LED blinks


;IC1_IC3_Test.mpas, 19 :: 		begin
;IC1_IC3_Test.mpas, 20 :: 		PORTBSet := 0x00002000; //Turn on LED PORTB.RB13
0x9D000020	0x34022000  ORI	R2, R0, 8192
0x9D000024	0x3C1EBF88  LUI	R30, 49032
0x9D000028	0xAFC26058  SW	R2, 24664(R30)
;IC1_IC3_Test.mpas, 22 :: 		IFS0.IC3IF  := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
0x9D00002C	0x34022000  ORI	R2, R0, 8192
0x9D000030	0x3C1EBF88  LUI	R30, 49032
0x9D000034	0xAFC21034  SW	R2, 4148(R30)
;IC1_IC3_Test.mpas, 25 :: 		end;
L_end_IC3:
0x9D000038	0x42000018  ERET	
; end of _IC3


_IC1:

 //Using procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF}; //Test2
 // with ICS_SRS, a Prologue and Epilogue is generated, however, the code does not return to Main Loop
 // The LED does not blink

;IC1_IC3_Test.mpas, 9 :: 		begin
0x9D00003C	0x415DE800  RDPGPR	SP, SP
0x9D000040	0x27BDFFF8  ADDIU	SP, SP, -8
0x9D000044	0x401E7000  MFC0	R30, 14, 0
0x9D000048	0xAFBE0004  SW	R30, 4(SP)
0x9D00004C	0x401E6000  MFC0	R30, 12, 0
0x9D000050	0xAFBE0000  SW	R30, 0(SP)
0x9D000054	0x7C1E7844  INS	R30, R0, 1, 15
0x9D000058	0x341E1800  ORI	R30, R0, 6144
0x9D00005C	0x409E6000  MTC0	R30, 12, 0
;IC1_IC3_Test.mpas, 10 :: 		PORTBSet := 0x00002000; //Turn on LED PORTB.RB13
0x9D000060	0x34022000  ORI	R2, R0, 8192
0x9D000064	0x3C1EBF88  LUI	R30, 49032
0x9D000068	0xAFC26058  SW	R2, 24664(R30)
;IC1_IC3_Test.mpas, 12 :: 		IFS0.IC1IF := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
0x9D00006C	0x34020020  ORI	R2, R0, 32
0x9D000070	0x3C1EBF88  LUI	R30, 49032
0x9D000074	0xAFC21034  SW	R2, 4148(R30)
;IC1_IC3_Test.mpas, 15 :: 		end;
L_end_IC1:
0x9D000078	0x8FBE0004  LW	R30, 4(SP)
0x9D00007C	0x409E7000  MTC0	R30, 14, 0
0x9D000080	0x8FBE0000  LW	R30, 0(SP)
0x9D000084	0x409E6000  MTC0	R30, 12, 0
0x9D000088	0x27BD0008  ADDIU	SP, SP, 8
0x9D00008C	0x41DDE800  WRPGPR	SP, SP
0x9D000090	0x42000018  ERET	
; end of _IC1
So there in a side by side example with one IC module IC1) IRH having context saving enable and one (IC3) not having context saving enabled. The IC3 (with no context saving) returns to the main loop, however, IC1 with prologue and Epilogue does not appear to return.

Just the opposite results of what I would have expected. So I am more confused than usual. :?
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#5 Post by Rotary_Ed » 25 Aug 2013 16:19

Further experimenting in order to understand the entire Interrupt process with the PIC32, I found something else interesting.

My original order of the LED instruction in the IRH was

Code: Select all

procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF}; //Test2

  var Empty_buf:dword ;

   begin
             PORTBSet := 0x00002000; //Turn on LED PORTB.RB13
            Empty_buf := IC1buf;//Empty buffer to remove cause for Persistent Interrupt
            IFS0.IC1IF := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
                              // and pointer never returns to Main loop
               end;
This would cause the LED to turn on as expected and with the turn off in the main loop cause the LED to blink. However, when I moved the instruction line for PORTBset to a location after clearing the flag as shown below, the LED would no longer turn on.

Code: Select all

procedure IC1(); iv IVT_INPUT_CAPTURE_1; ilevel 6; ics ICS_SRS {ICS_OFF}; //Test2

  var Empty_buf:dword ;

   begin
             
            Empty_buf := IC1buf;//Empty buffer to remove cause for Persistent Interrupt
            IFS0.IC1IF := 0;  //Clear Flag  - if flag is not cleared it forces hang up in IHR
                              // and pointer never returns to Main loop
            PORTBSet := 0x00002000; //Turn on LED PORTB.RB13   NOTE:  If placed here
            //the clearing of the IC1IF flag appears to precludes the code ever turning on the LED
            //in other words, it appears that any code after the flag is cleared does not
            //get executed in the IRH?
   end;
The result of putting the LED turn on code after clearing the flag was surprising - it never turned on. This indicated possibly that no code after clearing the flag in an IRH is executed???? IF that is correct (and it may not be), that is disturbing - as most recommendations on IRH is to clear the flag immediately upon entering the IRH.

Which if this finding is correct, would mean a lot of IRH code would never get executed - so I am sure I must be mistaken in this finding. But, then I don't see why the LED does not get turned on.


Just another thing that puzzles me. :roll:
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

LGR
Posts: 3204
Joined: 23 Sep 2004 20:07

Re: Interrupt Handler and Context Saving

#6 Post by LGR » 27 Aug 2013 19:59

If you look through the forum, I was having some other issues a while ago related to this, with UART interrupts. As I recall, I found a workaround, but never a satisfactory explanation. I think there are some arthropods in there.

I also never got to the bottom of a related issue regarding register allocation. I was trying to put some ASM in an ISR, and every time I did that, it changed the register assignments.
If you know what you're doing, you're not learning anything.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#7 Post by Rotary_Ed » 27 Aug 2013 22:15

Hi LGR,

Well, I have just written a prologue and epilogue in assembly for my interrupt handler code which does return the Program Counter to the main loop (at least for my simple IC1 and IC3 interrupt handler code).

When I set ics to ICS_OFF (and disablecontextsaving for good measure), the interrupt hander (with my prologue and epilogue) does turn on the LED and it does go back to the Main loop as the LED does blinks on and off. Furthermore it does this with either IC1 or IC3 OR with both of the modules being trigger with a pulse train.

I could never get the interrupts to do that when I had both of them on or even one to do that if I permitted context saving by the compiler. Interestingly enough if I disabled all context savings the two simple interrupts would return for this simple case. Both interrupts are at the same priority level (6) and I have the SRS (shadow registers) set for the priority 6 in the project edit - however, I do make the sub-priority of IC1 and IC3 different.

One thing I found in my code was that it was essential to have a "asm di end" command in the code to disable all interrupts before even finishing the prologue code and starting into the Interrupt Handler code. This leads me to believe that possibly one part of the problem might be other interrupts interrupting even before the context registers get saved. But, again, just a theory. You then have to issue an "asm ei end;" command to restore interrupt capability. However, I found that if I do this in my epilogue code before I return to the main loop (which is where I now have the "ei" command), then the program counter never appears to return - again leading me to believe the Program counter got lost :lol:

Now I just got the prologue and epilogue written and working today for this relative simple case. So I have some more experimenting to do before drawing any conclusions.

I found that Chapter 4. Exceptions and Interrupts in the M4K core found in MIPS32® M4K™ Processor Core Software User’s Manual essential to understanding what was happening with the interrupts in the PIC32. Quite different than the old PIC18F I had been using.

I suspect, but don't have any usable evidence, that when multiple interrupts are happening that the Program counter gets messed up. One possibility is if you are processing interrupt handler code and a second interrupt occurs of higher priority, that the system saves the PC again, but this time its pointing at the first interrupt handler and you get caught in an endless loop. So when the higher priority interrupt finishes it indeed returns to the first interrupt handler - but then the program counter back to the main loop has been lost. But, that is just a theory on my part at this point.

In my project code, having two input capture modules interrupting to a pulse train that may be synchronous and not getting hung up is crucial, so I can not really get further along in converting my code from PIC18 to PIC32 until I get this sorted out.

So I am going to try to expand/modify my prologue/epilogue code and see if I can expand its usefulness.

On the other hand, all of this could just be a figment of my imagination or dementia setting in :shock: .

Thanks for your comments
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

LGR
Posts: 3204
Joined: 23 Sep 2004 20:07

Re: Interrupt Handler and Context Saving

#8 Post by LGR » 27 Aug 2013 22:20

Sounds like the same thing I was dealing with. What I did was go to single vector mode. Theoretically, it's a little less efficient, but at least it worked. That way you're sidestepping the context thing.

Even after that, it did some squirrelly things, but they were squirrelly things I could live with.
If you know what you're doing, you're not learning anything.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#9 Post by Rotary_Ed » 27 Aug 2013 23:09

Yes, I agree - that is indeed also my strategy, if I can't find a way to make this multivector mode work in my programs then back to the single vector interrupt and polling.

I have identified at least 11 different steps/processes :shock: that have to occur in the multivector mode and it mainly involves manipulating a number of different register and bit fields in them in the right order.

If I were smart instead of bull-headed I would drop the multivector stuff now, but, alas :( I'll probably plug along a bit longer since I am finally starting to make a small bit of headway.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

jpc
Posts: 1986
Joined: 22 Apr 2005 17:40
Location: France 87

Re: Interrupt Handler and Context Saving

#10 Post by jpc » 28 Aug 2013 11:45

Ed,

unfortunately i am too busy at the moment to look into your specific problems but there must be a simple explanation ( or a specific problem on that family of pic's) i use mutivector interrupts in many projects without problems, no assembly, context saving done by the compiler, some of these applications run with battery backup without problems for many month until now, there are timerinterrupts every 100 uSec so if there was a problem it should have shown by now.
I have some bad feeling about the way you access bit's and flags, i never use the register.bit but allways the constant label for the specific bit from the definitionfile.
as example this :

Code: Select all

procedure irq_usart_init(channel : byte;baudrate : longint;priority : byte);
begin
  memset(@uarts,0,sizeof(uarts));
  //memset(@v_tmr,0,sizeof(v_tmr));
  memset(@hid_channel,0,sizeof(hid_channel));
  this_uart := @uarts[channel];
  with this_uart^ do
  begin
    empty := true;
    full := false;
  end;
  case channel of
   1   :  begin
            Uart1_Init(baudrate);
            ON__U1MODE_bit := 1;
            delay_ms(10);
            While Uart1_data_Ready do Uart1_Read;  // flush Uart Fifo
            U1RXIF_bit := 0;                       // clear flag
            U1IP0_bit := priority.0;
            U1IP1_bit := priority.1;
            U1IP2_bit := priority.2;
            OERR_bit := 0;
            reset_buffer(1);
            set_delimiter(1,#13+#10+#0); // default delimiter crlf
          end;
   2   :  begin
            Uart2_Init(baudrate);
            ON__U2MODE_bit := 1;
            delay_ms(10);
            While Uart2_data_Ready do Uart2_Read;  // flush Uart Fifo
            U2RXIF_bit := 0;                       // clear flag
            U2IP0_bit := priority.0;
            U2IP1_bit := priority.1;
            U2IP2_bit := priority.2;
            OERR_U2STA_bit := 0;
            reset_buffer(2);
            set_delimiter(2,#13+#10+#0); // default delimiter crlf
          end;

  end; // case

end;
from what you tell us here i have the impression you are drifting away from Pascal, you want after all to program in a high level language and the compiler is meant to help you with that, i have full confidence and by principle never use assembly .
Most of my P32 projects i must admit are on the P32MX3/4xx chips.
Au royaume des aveugles, les borgnes sont rois.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#11 Post by Rotary_Ed » 28 Aug 2013 13:05

Hi jpc,

I certainly understand about limited time :D , thanks for you comments suggestions, I always find them useful and informative.

I am certainly in agreement with you that its quite likely the problem is on my end - but, simple interrupt handler procedures that worked fine with the 18F series, just don't seem to give the same response.

I reallllllly don't want to go to assembly - but, I am puzzled as to why with my simple loop, the Program Counter does not seem to return to the main loop using the compiler's tools.

I will look over your code and see if modifications to mine make any difference. I have found some inconsistencies in the definition file as to the way certain bits of registers are defined are defined. But, nothing that would have bearing on my "problem"

The biggest problem is that when I have the two Input Capture modules active at the same time I seem to get no return to the main loop. Its true that the pulses on both would happen almost simulatenously - but, I had hoped that given them different subpriorities would eliminate any contention there.

I have suspected that perhaps my test for whether the program counter returned to the main loop was flawed and that the PC was returning, but for some reason my code was not turning the LED off. But, even after I posted my code on several forums, no one has pointed out any flaw in the concept.

The hope is that the light bulb will come on if I keep playing with it.

Again, greatly appreciate your comments and suggestions.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Handler and Context Saving

#12 Post by janni » 28 Aug 2013 18:08

Rotary_Ed wrote:The biggest problem is that when I have the two Input Capture modules active at the same time I seem to get no return to the main loop.
I've noticed an inconsistency in your otherwise detailed analysis of the produced assembly. You seem to overlook the fact that optimizer removes the statement supposed to empty the ICxbuf buffer. Failing to empty the buffer would indeed make disabling interrupt source necessary.

Declaring Empty_buf volatile should prevent optimizer from removing the statement.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#13 Post by Rotary_Ed » 28 Aug 2013 19:42

Thanks, janni

Embarrassing as all get out :oops: , but you are absolutely correct. Got lost in the forest and forgot about the trees.

That would indeed explain why the IRH would never return the Program Counter, because the persistent cause for the interrupt was never eliminated!

I will try your suggestion - boy, would be nice if that solved the problem - embarrassing, but nice :D .
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#14 Post by Rotary_Ed » 28 Aug 2013 20:02

Sometimes, I think I am just too dumb for this stuff :x ! - other times, I know I am.

I declared the variable "empty_buf" as "volatile" - and guess what? Yep! the program pointer is now returning to the main loop between interrupts. Works in my simple test program, so no doubt it will work in the real project program.

Funny how, I checked out the clearing of the flag in the code listing as well as many other things, but never once even noticed that the empty_buf variable action was no where to be seen in the listing!

Ah, the hours and days spending reading up on the external interrupt process in the MIPS MK4 volumes- all not needed - but, it was interesting and illuminating in any case.

Again, janni, I am indebted to you and others like you, who once again have pulled my head out of the sand.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Re: Interrupt Handler and Context Saving

#15 Post by Rotary_Ed » 28 Aug 2013 20:23

Here you are, the first appearance of the Empty_buf := ICXbuf code in my program listing :oops:

Code: Select all

...
...
;IC1_IC3_Test.mpas, 199 :: 		Empty_buf  := IC1buf; //clear cause of Persistent Interrupt
0x9D000264	0x3C1EBF80  LUI	R30, 49024
0x9D000268	0x8FC22010  LW	R2, 8208(R30)
0x9D00026C	0xAC228000  SW	R2, Offset(_Empty_buf+0)(GP)
;IC1_IC3_Test.mpas, 200 :: 		IFS0.IC1IF := 0; // clear flag
0x9D000270	0x3C1EBF88  LUI	R30, 49032
0x9D000274	0xAFC31034  SW	R3, 4148(R30)
...
...
How could I have missed it for so long - answer, wasn't looking carefully enough.

I had emptied the buffer in my source code as I was aware a full buffer would be the cause of a persistent interrupt if I did not. But, never followed up in the code to ensure that was happening. I really need to get in the habit of checking what the optimizer does to my code.

There should be a warning in the Help list about needing to use volatile on such variables or perhaps every one already knew - but me. :lol:

Now it has me wondering what else in my code may fall prey to this type of problem that I don't even suspect - without you (or someone) noticing that missing element in my code, I probably never would have found it - so what else lurks out there?

Thanks again
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Post Reply

Return to “mikroPascal PRO for PIC32 General”