+ Reply to Thread
Results 1 to 17 of 17
  1. #1
    Join Date
    Apr 2010
    Location
    Walnut Creek, CA
    Posts
    17

    Unhappy PIC18 interrupt handler, where to save W etc?

    I'm trying to make a simple interrupt handler for the PIC18F8722 timer0. I'm using PICBASIC PRO, MPLAB, the Explorer 18 board, PICKIT 3 and MPASM.

    I'm confused about the assembler interrupt handler for the PIC18F8722. Where is W saved? I see code snippets but not the whole thing and apparently W is saved in different locations for the different PIC micros? And what about the bank(ing)? I can't seem to find answers in the PIC BASIC PRO Manual or in M-chip docs or elsewhere but probably I'm not looking in the proper docs or just not understanding what I'm reading!


    Hi, we are pleased to see that you are using our forum.

    We'd like you to become a member of our community. Membership is FREE, please REGISTER and view our forums without these annoying reminders!

    Once registered you may post on the forums, download from the file areas and use the WIKI without interruption.






    So the beginning of the interrupt code is (for example, from http://www.phanderson.com/PIC/16C84/...rrupt_1.html):
    MOVWF W_SAVE ; save W
    SWAPF STATUS, W ; save STATUS
    MOVWF STATUS_SAVE

    So, for the PIC18F8722, where is W_SAVE located and what to do about the bank(ing)?

    Thanks in advance!

  2. #2
    Join Date
    May 2007
    Posts
    582

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    One nice thing about 18F's is that you don't have to save W, BSR and STATUS when using High Priority Interrupts.
    The hardware does it for you whenever an interrupt occurs by saving the values to "Shadow" registers.

    At the end of the ISR just ...
     RETFIE FAST ; return from interrupt, restore shadows
    and they all get restored.
    A plain RETFIE does not.

    When using Low Priority interrupts you do need to save them.
    But they can be anywhere in RAM, just use MOVFF to save/restore them.
    DT

  4. #4

    Default

    This is helpful as well http://ww1.microchip.com/downloads/e...Doc/39500a.pdf

    You can use the fast return with auto restore for low pri ints too, but not if you have high pri & low pri interrupts enabled at the same time. The high pri interrupt can corrupt shadow values saved during the low pri interrupt.
    Last edited by Bruce; - 15th May 2010 at 22:10.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    Quote Originally Posted by Bruce View Post
    You can use the fast return with auto restore for low pri ints too, but not if you have high pri & low pri interrupts enabled at the same time. The high pri interrupt can corrupt shadow values saved during the low pri interrupt.
    That is so true ...

    But so far, I haven't found a possible reason for anyone to have Low Priority interrupts, without High Priority.
    Consequently, DT_INTS crashes if you try to only use LP ints, mainly because I haven't seen the need.

    Is there a reason anyone can think of for using only Low Priority Interrupts?
    Enquiring minds want to know.
    DT

  6. #6

    Default

    Is there a reason anyone can come up with for using only Low Priority Interrupts?
    I use low priority exclusivley unless I have more than 1 interrupt, and one 'or more' needs priority over the lower priority interrupt task.

    If you only have 1 interrupt enabled, I can't see why making it high priority VS low priority would be of any benefit!

    Consequently, DT_INTS crashes if you try to only use LP ints
    Yikes. I haven't used DT_INTs much with 18F types, but that's good to know. What causes that to happen?
    Last edited by Bruce; - 16th May 2010 at 03:50.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    I use low priority exclusivley unless I have more than 1 interrupt, and one 'or more' needs priority over the lower priority interrupt task.
    Ok,
    But since all the 18F's default to High Priority on power-up.
    You have to first Enable Low Priorities by setting IPEN ...

    RCON.7 = 1 ; enable interrupt priorities

    And clear the corresponding priority bit for the interrupt you're using ...

    IPR1.5 = 0 ; set RCIF to low priority

    And always remember to use GIEL INTCON.6 instead of GIEH INTCON.7

    Then, does that give you anything that the default High priority doesn't?
    Other than more statements to write.

    Well, DT_INTS doesn't really crash, it just won't compile with only LP ints because it's looking for something that isn't there. And I never saw a reason to try to change it.

    Perhaps it's just a way of thinking and I could make DT_INTS allow LP_INTS only.
    But if there's a valid reason, I will definitely do it.

    Q: Is there a reason anyone can think of for using only Low Priority Interrupts?
    DT

  8. #8
    Join Date
    Apr 2010
    Location
    Walnut Creek, CA
    Posts
    17

    Smile Thanks Guys!

    So far I had only thought of one interrupt to use for my project, and I figured I would set it at low priority since there seemed to be no reason to use high-priority when using only one interrupt. Then if later on I discovered that another interrupt was needed, I supposed it might be a higher priority and would then use high priority for it. So, yes, I may need only one interrupt and didn't know of a reason to set it at high priority.

    Interestingly, I think, my PICBASIC PRO manual states in section 9.3 "In any case, you must restore these registers at the end of your assembler interrupt handler. If the 14-bit core PIC MCU has 2K or less of code space, or it is an PIC18 device, the registers are not saved. Your interrupt handler must save and restore any used registers." However, the on-line PICBASIC PRO manual doesn't have such a statement and I hadn't read that section of the on-line manual until this morning. I don't see anything about high or low priority interrupts in the manuals. I suppose MEL can't be expected to put "everything about everything" in their manual but interrupts are a particularly important topic, I think.

    I wasn't planning on using the DT_INTS, figuring that my project is so simple that DT_INTS wouldn't be required. In retrospect, I probably should use DT_INTS but I need to get my code running right away (yesterday, of course) and our Procurement Department takes a couple of weeks or more to purchase anything and I don't want to spend my own $. BTW, I am a firm believer in macros but have always made my own macros.

    So, in conclusion:
    1. Use the high priority interrupts if possible.
    2. For high priority interrupts, use RETFIE FAST ; return from interrupt, restore shadows.
    3. If I have to use low-priority interrupts, I have to save the registers and they can be saved anywhere, using MOVFF to restore them. Also have to use "RCON.7 = 1 ; enable interrupt priorities. And clear the corresponding priority bit for the interrupt you're using ...IPR1.5 = 0 ; set RCIF to low priority. And always remember to use GIEL INTCON.6 instead of GIEH INTCON.7"

    This all seems overly complex with all sorts of special rules, but I guess it comes with the high-capability of the beast. I come from the days of (even before) the DEC PDP8 and PDP9, and am overwhelmed with this complexity.

    I just now discovered a very useful thread from 2006 with Darrel's info about interrupts. Not sure why I didn't see this earlier: http://www.picbasic.co.uk/forum/showthread.php?t=3251

    Now to get back to my home "industrial controller" project with the dsPIC33F and the MPLAB GNU C compiler. That's beginning to seem simpler than using PICBASIC PRO. ;-)

    Thanks again for all the very useful info!

  9. #9

    Default

    Hi Darrel,

    With RCON,IPEN = 0 it's in compatibility mode. I.E. no priority levels on any interrupts, and it's just as easy as say setting up & using interrupts on a 16F part.

    There's no GIEH, GIEL, or any priority high/low bit settings to worry about. So, it's actually a bit easier than setting up & using high & low priority interrupts.

    Here's an example;
    Code:
        list p=18f452
        include "p18f452.inc"
     
        CONFIG OSC=XT,OSCS=OFF,WDT=OFF,WDTPS=128,BOR=ON,BORV=45,LVP=OFF
     
        CBLOCK 0x08
          MyVar
        ENDC
     
        ORG    0x000
        BRA    Init
     
        ORG    0x008           ; all ints vector here in compatibility mode
        BRA    TMR_INT         ; and high-pri vectors here when enabled
     
        ORG    0x018           ; low-pri int vector, but only when priority
        BRA    LOW_PRI         ; interrupts are enabled
     
    Init
        CLRF   MyVar           ; clear MyVar
        CLRF   PORTB           ; Clear PORTB
        CLRF   TRISB           ; PORTB all outputs
        MOVLW  0x07
        MOVWF  ADCON1          ; disable A/D
        MOVLW  B'11000111'     ; TMR0 on, 8-bit, prescaler, 1:256
        MOVWF  T0CON
        BCF    RCON,IPEN       ; disable priority interrupts
        BCF    INTCON,TMR0IF
     
        ; since RCON,IPEN=0, we don't need to worry about any priority
        ; bit settings for any interrupt source, and we refer to GIE,PEIE
        ; VS GIEH,GIEL because we're in "compatibility" mode. We don't
        ; have to mess with anything related to high or low priority
        ; interrupts. Compatibility mode is just as easy as interrupts on
        ; 16F parts.
     
        BSF    INTCON,TMR0IE   ; enable Timer0 interrupt
        BSF    INTCON,PEIE     ; peripheral ints enabled
        BSF    INTCON,GIE      ; global enabled
     
    Main
        MOVFF  MyVar,PORTB     ; show count on PORTB LEDs
        BRA    Main
     
    TMR_INT                    ; default int vector for all interrupts
        INCF   MyVar           ; when in compatibility mode
        BCF    INTCON,TMR0IF
        RETFIE FAST
     
    LOW_PRI                    ; never gets here because priority ints
        INCF   MyVar           ; are not enabled when RCON,IPEN = 0
        BCF    INTCON,TMR0IF
        RETFIE FAST
        END
    And you still have the benefit of fast return with auto context restore even with low pri interrupts.

    Maybe I should have said - I use NO priority levels or compatibility mode VS only low priority interrupts. The only time I enable priority levels is when I have more than one interrupt, and one or more needs to interrupt the less important interrupt assigned to the low vector.

    Otherwise it's easier to just use compatibility mode with no priority levels to worry about.

    I know you're already aware of this, but I figured it would be good to post so folks reading this didn't get confused between using priority levels - I.E. high & low VS compatibility mode where there are no priority levels enabled.
    Last edited by Bruce; - 16th May 2010 at 20:15.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  10. #10
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    I'll take that as a NO.

    No reason to have ONLY Low Priority interrupts. (suggested in post #4).
    DT

  11. #11

    Default

    I'll take that as a NO.
    Yep. I don't see any reason to even have priority levels enabled unless you have one interrupt that needs to interrupt another. I should have said NO priority levels VS LOW priority...

    My point was just to let the OP know he didn't need to enable priority interrupts, or use a high pri interrupt just to use the fast return with auto context restore because this;
    One nice thing about 18F's is that you don't have to save W, BSR and STATUS when using High Priority Interrupts.
    Made it sound like he did.
    Last edited by Bruce; - 16th May 2010 at 20:56.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  12. #12
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    I agree, Thanks.

    I just want to make sure I'm not purposely avoiding something that should be in DT_INTS-18. (getting lazy)

    If there were a reason, now would be the time to mention it.
    Since I'm updating it.

    Anyone?
    DT

  13. #13
    Join Date
    Apr 2010
    Location
    Walnut Creek, CA
    Posts
    17

    Smile Thanks again Guys!

    Your responses are very helpful and greatly appreciated. It's pretty incredible to get this quality of help.

  14. #14

    Default

    I can think of a couple scenarios where it might come in handy to use only low priority interrupts.

    A. If you need the first few code locations for initialization code that would exceed location 0x08, it would be nice to recover this space by forcing all interrupts to vector to 0x18 after initialization.

    B. If you need just a few more words code space, this would free up room between the high/low vectors. GOTO somewhere at 0x00 with GOTO or BRA at 0x08 leaves several words of code space unused between the reset vector & low pri vector.

    For B of course you could just make everything high priority, bump it up to 0x08, but you still have a few words not used from reset to 0x08.

    So I guess in some extreme cases it might be nice to have the option.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  15. #15
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    Excellent!

    I knew I was talking to the right guy.

    Reason A. is a perfectly "Valid" need to have only Low Priority Interrupts.
    Albeit, an infrequent need.

    I will now attempt to add it to the update.

    Way to go Bruce!
    DT

  16. #16
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,935

    Default

    All the back and forth with bruce, I forgot to say ...

    ImAnEE,

    I'm glad it helps, interrupts can be very confusing.
    I've tried to reduce the confusion with DT_INTS, but am still working on it.
    If you're short on time, it's probably the Quickest way though.

    Fortunately for me, there's more and more people answering DT_INTS questions around here.
    So dive in, helps not far away.

    Best regards,
    DT

  17. #17
    Join Date
    Jun 2010
    Posts
    3

    Default

    Quote Originally Posted by ImAnEE View Post
    I'm trying to make a simple interrupt handler for the PIC18F8722 timer0. I'm using PICBASIC PRO, MPLAB, the Explorer 18 board, PICKIT 3 and MPASM.

    I'm confused about the assembler interrupt handler for the PIC18F8722. Where is W saved? I see code snippets but not the whole thing and apparently W is saved in different locations for the different PIC micros? And what about the bank(ing)? I can't seem to find answers in the PIC BASIC PRO Manual or in M-chip docs or elsewhere but probably I'm not looking in the proper docs or just not understanding what I'm reading!

    So the beginning of the interrupt code is (for example, from http://www.phanderson.com/PIC/16C84/...rrupt_1.html):
    MOVWF W_SAVE ; save W
    SWAPF STATUS, W ; save STATUS
    MOVWF STATUS_SAVE

    So, for the PIC18F8722, where is W_SAVE located and what to do about the bank(ing)?

    Thanks in advance!
    I think you should have the swift code so that the banking will surely not interrupt.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts