Strange Pic Timer1 Interrupt problem

Discussion in 'Embedded Systems and Microcontrollers' started by spinnaker, Feb 23, 2012.

  1. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    I have the following interrupt routine for Timer1

    Code ( (Unknown Language)):
    1.  
    2. #pragma interruptlow InterruptServiceLow
    3. void InterruptServiceLow(void)
    4. {
    5.     static int x = 0;  
    6.    
    7.     // Check for Timer1 Overflow Interrupt
    8.     if  (PIR1bits.TMR1IF)
    9.     {        
    10.        
    11.         LATBbits.LATB3 =~ LATBbits.LATB3;
    12.         TMR1H = 255;             // preload for timer1 MSB register
    13.         TMR1L = 195;             // preload for timer1 LSB register
    14.         PIR1bits.TMR1IF = 0;     // clear flag        
    15.     }
    16.  
    17. }
    18.  
    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.
     
  2. be80be

    Senior Member

    Jul 5, 2008
    431
    57
    There are a lot more setting on these chips
    You probable need to make sure there set right
     
  3. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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.
     
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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
    Code ( (Unknown Language)):
    1. static void interrupt
    2. isr(void)   // Here is interrupt function - the name is
    3.     // unimportant.
    4. {
    5.  if(TMR1IF)
    6.   {// Was this a timer overflow?
    7.       TMR1IF=0;//Clear interrupt flag, ready for next
    8.    TMR1H=0x80;
    9. //If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
    10.      timer_tick=1;
    11.   }//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
     
  5. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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.
     
  6. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,903
    2,155
    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?
     
  7. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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.
     
  8. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    Have you tried under view in MPLAB (toolbar) show disassembly listing
     
  9. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988

    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):

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

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

    AAC Fanatic!

    Aug 27, 2009
    2,903
    2,155
    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.
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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...
     
  12. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988

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

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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.
     
  14. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
  15. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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:
     
  16. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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.
     
  17. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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.
     
  18. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    988
    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
     
Loading...