Strange Pic Timer1 Interrupt problem

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
I have the following interrupt routine for Timer1

Rich (BB code):
#pragma interruptlow InterruptServiceLow
void InterruptServiceLow(void)
{
    static int x = 0;   
    
    // Check for Timer1 Overflow Interrupt
    if  (PIR1bits.TMR1IF)
    {        
        
        LATBbits.LATB3 =~ LATBbits.LATB3;
        TMR1H = 255;             // preload for timer1 MSB register
        TMR1L = 195;             // preload for timer1 LSB register
        PIR1bits.TMR1IF = 0;     // clear flag        
    }

}
The ISR simply toggles a latch.

Notice the static int x = 0; line.

If I remove it the ISR no longer gets called. I can even move it outside the function and the ISR gets called. I just can't remove it.

In addition I have another variable declared globally.

char weekdays[7][4] = {"Sun", "Mon", "Tue", "Wed","Thr","Fri","Sat"};

that is also unused.

If I remove it the ISR no longer gets called. Very strange.

At first I though it was a bad chip. I had a 18F27J53 but I also have a 18F26J53 and it does the same thing.

It is almost like I need X amount of memory allocated for the ISR to work.


And I have a second issue with code not running in a release compile these chips but I will post in a separate thread.
 

be80be

Joined Jul 5, 2008
1,930
There are a lot more setting on these chips
Due to the number of peripheral
interrupt sources, there are three Peripheral Interrupt
Request (Flag) registers (PIR1, PIR2, PIR3).
Note 1: Interrupt flag bits are set when an interrupt
condition occurs, regardless of the state of
its corresponding enable bit or the Global
Interrupt Enable bit, GIE (INTCON<7>).
2: User software should ensure the
appropriate interrupt flag bits are cleared
prior to enabling an interrupt and after
servicing that interrupt
You probable need to make sure there set right
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
There are a lot more setting on these chips



You probable need to make sure there set right
Yes I am aware of that. I just did not include them.

The settings don't explain why simply removing a variable declaration causes the ISR not to be called.
 

t06afre

Joined May 11, 2009
5,936
Hi Spinnaker. Is your timer1 in free running mode? Writing to the timer1l inside the ISR. May cause some jitter. Maybe it is better to use the compare mode. You count up to a pre defined number. Then the timer reach this number an interrupt may be generated. And the timer will be set to zero.
I just finished a PIC LCD clock my self. Using a watch crystal time device. And Hi-Tech C.
Here is my ISR
Rich (BB code):
static void interrupt
isr(void)   // Here is interrupt function - the name is
    // unimportant.
{
 if(TMR1IF) 
  {// Was this a timer overflow?
      TMR1IF=0;//Clear interrupt flag, ready for next
   TMR1H=0x80;
//If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
     timer_tick=1;
  }//we are done here
Here I write to TMR1H inside the ISR. But that is OK as long the TMR1L register has not rolled over from 255 to 0. And hence changed the TMR1H register content
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
Hi Spinnaker. Is your timer1 in free running mode? Writing to the timer1l inside the ISR. May cause some jitter. Maybe it is better to use the compare mode. You count up to a pre defined number. Then the timer reach this number an interrupt may be generated. And the timer will be set to zero.
I just finished a PIC LCD clock my self. Using a watch crystal time device. And Hi-Tech C.
Here is my ISR
Rich (BB code):
static void interrupt
isr(void)   // Here is interrupt function - the name is
    // unimportant.
{
 if(TMR1IF) 
  {// Was this a timer overflow?
      TMR1IF=0;//Clear interrupt flag, ready for next
   TMR1H=0x80;
//If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
     timer_tick=1;
  }//we are done here
Here I write to TMR1H inside the ISR. But that is OK as long the TMR1L register has not rolled over from 255 to 0. And hence changed the TMR1H register content
I am not worried about jitter. Eventually the timer will be driven by an external XTAL anyway.

I just need to know why a simple removal of an unused variable declaration would cause the ISR to no longer be called.
 

nsaspook

Joined Aug 27, 2009
6,286
When you read the code off the chip after it's programmed before and after the variable removal is the asm code generated for the ISR the same? What programmer are you using?
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
When you read the code off the chip after it's programmed before and after the variable removal is the asm code generated for the ISR the same? What programmer are you using?
I am using c18 compiler in MPLab. I took a look at the build options and don't see how to produce assembler. It produces hex files just fine but no assembler.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
Have you tried under view in MPLAB (toolbar) show disassembly listing

Duh that's right. Forgot about that. :) I was looking for an asm file. :)

Anyway here is the asm in the interrupt routine that is produced with the variable defined (remember the ISR is being called with the variable defined):

Rich (BB code):
---  E:\Data\MPLAB\USART-Timer1-Problem\interrupts.c  --------------------------------------------
1:                 #include <P18F27J53.h>
2:                 
3:                 
4:                 void InterruptServiceLow(void);
5:                 
6:                 
7:                 // Low priority interrupt vector
8:                 #pragma code InterruptVectorLow = 0x18
9:                 void InterruptVectorLow (void)
10:                {
11:                  _asm
12:                    goto InterruptServiceLow //jump to interrupt routine
 00018    EFB7     GOTO 0x56e
 0001A    F002     NOP
13:                  _endasm
14:                }
 0001C    0012     RETURN 0
15:                
16:                /** D E C L A R A T I O N S *******************************************/
17:                #pragma code    // declare executable instructions
18:                
19:                
20:                static int x = 0;
21:                long i;   
22:                
23:                #pragma interruptlow InterruptServiceLow
24:                void InterruptServiceLow(void)
 0056E    CFD8     MOVFF 0xfd8, 0xfe4
 00570    FFE4     NOP
 00572    CFE0     MOVFF 0xfe0, 0xfe4
 00574    FFE4     NOP
 00576    6EE4     MOVWF 0xfe4, ACCESS
 00578    CFDA     MOVFF 0xfda, 0xfe4
 0057A    FFE4     NOP
 0057C    CFE2     MOVFF 0xfe2, 0xfda
 0057E    FFDA     NOP
 00580    52E6     MOVF 0xfe6, F, ACCESS
25:                {
26:                
27:                    
28:                    // Check for Timer1 Overflow Interrupt
29:                    if  (PIR1bits.TMR1IF)
 00582    A09E     BTFSS 0xf9e, 0, ACCESS
 00584    D005     BRA 0x590
30:                    {        
31:                        
32:                        LATBbits.LATB3 =~ LATBbits.LATB3;
 00586    768A     BTG 0xf8a, 0x3, ACCESS
33:                        TMR1H = 255;             // preload for timer1 MSB register
 00588    68CF     SETF 0xfcf, ACCESS
34:                        TMR1L = 195;             // preload for timer1 LSB register
 0058A    0EC3     MOVLW 0xc3
 0058C    6ECE     MOVWF 0xfce, ACCESS
35:                        PIR1bits.TMR1IF = 0;     // clear flag        
 0058E    909E     BCF 0xf9e, 0, ACCESS
36:                    }
37:                
38:                }
 00590    52E5     MOVF 0xfe5, F, ACCESS
 00592    CFE5     MOVFF 0xfe5, 0xfda
 00594    FFDA     NOP
 00596    50E5     MOVF 0xfe5, W, ACCESS
 00598    CFE5     MOVFF 0xfe5, 0xfe0
 0059A    FFE0     NOP
 0059C    CFE5     MOVFF 0xfe5, 0xfd8
 0059E    FFD8     NOP
 005A0    0010     RETFIE 0

Here is the code with the variable removed (this is where the ISR is not being called):
Rich (BB code):
:                 #include <P18F27J53.h>
2:                 
3:                 
4:                 void InterruptServiceLow(void);
5:                 
6:                 
7:                 // Low priority interrupt vector
8:                 #pragma code InterruptVectorLow = 0x18
9:                 void InterruptVectorLow (void)
10:                {
11:                  _asm
12:                    goto InterruptServiceLow //jump to interrupt routine
 00018    EFAA     GOTO 0x554
 0001A    F002     NOP
13:                  _endasm
14:                }
 0001C    0012     RETURN 0
15:                
16:                /** D E C L A R A T I O N S *******************************************/
17:                #pragma code    // declare executable instructions
18:                
19:                
20:                
21:                
22:                #pragma interruptlow InterruptServiceLow
23:                void InterruptServiceLow(void)
 00554    CFD8     MOVFF 0xfd8, 0xfe4
 00556    FFE4     NOP
 00558    CFE0     MOVFF 0xfe0, 0xfe4
 0055A    FFE4     NOP
 0055C    6EE4     MOVWF 0xfe4, ACCESS
 0055E    CFDA     MOVFF 0xfda, 0xfe4
 00560    FFE4     NOP
 00562    CFE2     MOVFF 0xfe2, 0xfda
 00564    FFDA     NOP
 00566    52E6     MOVF 0xfe6, F, ACCESS
24:                {
25:                
26:                    
27:                    // Check for Timer1 Overflow Interrupt
28:                    if  (PIR1bits.TMR1IF)
 00568    A09E     BTFSS 0xf9e, 0, ACCESS
 0056A    D005     BRA 0x576
29:                    {        
30:                        
31:                        LATBbits.LATB3 =~ LATBbits.LATB3;
 0056C    768A     BTG 0xf8a, 0x3, ACCESS
32:                        TMR1H = 255;             // preload for timer1 MSB register
 0056E    68CF     SETF 0xfcf, ACCESS
33:                        TMR1L = 195;             // preload for timer1 LSB register
 00570    0EC3     MOVLW 0xc3
 00572    6ECE     MOVWF 0xfce, ACCESS
34:                        PIR1bits.TMR1IF = 0;     // clear flag        
 00574    909E     BCF 0xf9e, 0, ACCESS
35:                    }
36:                
37:                }
 00576    52E5     MOVF 0xfe5, F, ACCESS
 00578    CFE5     MOVFF 0xfe5, 0xfda
 0057A    FFDA     NOP
 0057C    50E5     MOVF 0xfe5, W, ACCESS
 0057E    CFE5     MOVFF 0xfe5, 0xfe0
 00580    FFE0     NOP
 00582    CFE5     MOVFF 0xfe5, 0xfd8
 00584    FFD8     NOP
 00586    0010     RETFIE 0
 

nsaspook

Joined Aug 27, 2009
6,286
Nothing wrong on the compiler side.
My guess about your problem points to programmer hardware not flashing the chip correctly. The weird problems you have seem like program memory corruption on the chip when it's running.
 

ErnieM

Joined Apr 24, 2011
7,996
As long as you don't have code protection set your programmer should be able to do a code verify. If that passes then that is not the problem.

Also, non-enables interrupt sources may or may not set their interrupt flags but if the sources are not enabled those flags have no effect and never fire an interrupt. The worst thing that can happen is you don't reset the flag to an enabled source: when you do your return that interrupt fires again and again and again...
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
Nothing wrong on the compiler side.
My guess about your problem points to programmer hardware not flashing the chip correctly. The weird problems you have seem like program memory corruption on the chip when it's running.

The program does verify correctly after programming.

Though I have seen posts to avoid these chips. There is a pdf somewhere from microchip suggesting a modification to the PicKit 3 for one or both of the chips.
 

ErnieM

Joined Apr 24, 2011
7,996
There is a pdf somewhere from microchip suggesting a modification to the PicKit 3 for one or both of the chips.
I don't believe so, at least I never saw such. I did see a forum post where someone had to add a 470 ohm pull down to get theirs to work, but in a later post they admitted also trying a larger value to see how much pull down was really required.

They discovered no resistor was needed at all.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
I don't believe so, at least I never saw such. I did see a forum post where someone had to add a 470 ohm pull down to get theirs to work, but in a later post they admitted also trying a larger value to see how much pull down was really required.

They discovered no resistor was needed at all.

That was me and I did see the pdf.

http://ww1.microchip.com/downloads/en/DeviceDoc/ETN32_PICkit_3_Operation_at_Low_Voltage.pdfhttp://ww1.microchip.com/downloads/en/DeviceDochttp://ww1.microchip.com/downloads/en/DeviceDoc/ETN32_PICkit_3_Operation_at_Low_Voltage.pdf
 

t06afre

Joined May 11, 2009
5,936
I do not think your problem is related to PICKIT 3 programmer but rather the programmer Spinaker (ha ha). How good are you at using MPSIM. Take a look at the picture I have made as an example. Here I have made the classic bummer of not setting the GIE flag. So no interrupt will be made. In the ISR I have placed a breakpoint. And also added some watches, and a clock stimulus.
By starting and stopping the program (in the debug menu) I can see that the timer counts. So that part is OK. But the breakpoint is not reached. Ok then something is wrong with the interrupt setup. And ouch that was correct. I did not set the GIE flagg:eek:
 

Attachments

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
I do not think your problem is related to PICKIT 3 programmer but rather the programmer Spinaker (ha ha). How good are you at using MPSIM. Take a look at the picture I have made as an example. Here I have made the classic bummer of not setting the GIE flag. So no interrupt will be made. In the ISR I have placed a breakpoint. And also added some watches, and a clock stimulus.
By starting and stopping the program (in the debug menu) I can see that the timer counts. So that part is OK. But the breakpoint is not reached. Ok then something is wrong with the interrupt setup. And ouch that was correct. I did not set the GIE flagg:eek:
Read my post again. The only change I am making is removing an unused declared variable and it does not run. GIE is being set.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
OK this is very strange. I also have a P18F45k20 and it is doing the exact same thing!

So either it has to be the code (which I can't see how it could be when all I am doing is removing a variable) or maybe a setting in mplab? I have an old project for testing Timer0 for the 18f45k20 that works just fine. I think I will try and convert it to my new Pics and see what I get.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
Finally figured it out. It was this line

IPR1bits.TMR1IP = 1;

should have been

IPR1bits.TMR1IP = 0;

But that still does not explain why defining a variable caused it to work. That is very strange. What threw me is because defining a varible seemed to fix the issue I assumed it could not be the code. I finally decided to take a closer look.
It is actually kind of disturbing that I could get the interrupt to work with the wrong setting.


Also it still does not run in release mode. See this thread:

http://forum.allaboutcircuits.com/showthread.php?t=66552
 
Top