+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Interrupts in Proton and PIC issues

  1. #1
    Licensed User breed's Avatar
    Join Date
    Apr 2011
    Location
    Delta, Colorado
    Posts
    12

    Default Interrupts in Proton and PIC issues

    This issue keeps coming up on the forum and for good reason. Interrupts are very complicated and little things can cause very bad things to happen. Many of which are very difficult if not almost impossible to figure out. I have over 20 years experience in assembler for PIC and am just now working with Proton. My experience lets me "see" things that most wouldn't and how Proton may or may not deal with the issues. Since I need to have a post or two to be able to stay on the forum I figured I'd pass on my knowledge of the issue. Sorry if this is long.

    Okay, for starters the first thing to do when dealing with hardware interrupt routines is to always have a set of variables that only the interrupt routines use. I normally have general use variables for passing data between routines, counters in routines, etc (dta, tmp, cnt). I always define a new set of these variables and add an I in front of them (idta, itmp, icnt) to indicate that they are for the interrupt routines only. This, obviously, works well. The real problem turns up when passing data between the interrupt routines and the main program. Obviously we have to be able to do this otherwise the interrupts typically wouldn't do us much good.

    First lets talk about passing byte sized variables. Typically there are no problems with this. For example, I have a hardware serial input buffer that grabs characters from the port and stuffs them into a "ring" buffer (I use an array in Proton). I have the buffer and 2 pointers. The input pointer (ipnt) is read and written to by the interrupt routine and the output pointer (opnt) is read and written to by the main program loop. I'll post my Proton modified code for it if anyone is interested. The thing is, when a character comes in the input pointer (ipnt) is incremented (written to by the interrupt routine) and the character saved in the buffer. The main program loop then looks at the ipnt and if its larger than the opnt then it knows there is a character(s) available in the buffer. It reads it (them) out and increments the opnt until it equals the ipnt (all characters handled). Obviously there are rollover issues that are dealt with but that’s not important here. With this arrangement there are no collision or corruption issues.

    The really big problem comes in when you have to pass a word sized variable (as I often do) between the main program and interrupt routine. This comes from the fact that it actually takes at least 4 PIC instructions to deal with a word sized variable. For example- dtaw=idtaw would be coded as
    movf idtaw,w low byte
    movwf dtaw low byte
    movf idtawh,w high byte
    movwf dtawh high byte
    The problem is that an interrupt can come in anywhere between these steps. So, say we get the first byte transferred and get an interrupt. Now we have different data in idtaw. Now when we return from the interrupt the high byte gets written with the wrong data. This can have very bad effects (say the data was 1ff and new data is 200- this could result in dtaw having a value of 2ff). This goes both ways (to and from interrupt routines).

    The only way to deal with this is to turn off interrupts when doing a word (or larger variable- a far worse situation) data transfer while in the main program loop. I wondered if Proton dealt with this issue and looked at the generated code (nope). You would think that just putting in a command of gie=0 before a transfer would work. Not so!!! I ran across this issue years ago in a document but can't find it now. This is where it gets really complicated. The command gie=0 is a single assembler command but it is possible for an interrupt to get flagged and set during the clearing of gie. This may not be an issue for all PICs but it was for some I've worked with. So what happens- you clear the interrupts but an interrupt is logged part way through the instruction (they take 4 clock cycles complete). Now the instruction is completed but the interrupt is set so the interrupt is handled and the return from the interrupt sets gie back to on. In the Microchip documentation they said the only way to deal with this issue is to clear gie, check and make sure it is clear, and re-clear it if it isn't before continuing on. In proton this would be
    While gie=1
    Gie=0
    Wend

    Yes, although the probability of this happening is remote it can happen and cause serious intermittent problems.

    Another place where disabling interrupts is important is when writing to the PIC internal eeprom. If you don't disable the interrupts a write to the eeprom can fail. This comes from the fact that you have to set up the data and address to be written, enable the write, then write a pattern (55,AA) to the control register for the write to take place. If an interrupt happens during the process of writing the pattern the data will not be written to the eeprom. There are two ways to deal with this- read the data written back and if it is not correct re-write it (probably a good idea in general- I do it) or make sure interrupts are off before writing to the eeprom. I was hoping that maybe Proton dealt with this for eeprom writes but looking at the generated code it doesn't. I understand it though, trying to cover all possibilities for interrupts would be an almost impossible task (not to mention those who are getting away with their code that seems to work and putting in turning off interrupts messing things up ticking them off).

    Hi, its great to see you visiting our forum. Why not try Proton Compiler for FREE?

    Download the FREE version of Proton Compiler, Its called Amicus18 and its available from HERE

    Already using proton Compiler??? Get rid of these pesky messages... get LICENSED USER STATUS




    The point here is you have to turn off interrupts when transferring word+ sized variables and eeprom writes and a simple gie=0 won't do. You must call (gosub) an interrupt disable routine before doing any of these things.
    Gieoff: while gie=1
    Gie=0
    wend
    return

    Hope this information is of some use to those trying to use interrupts.


  2. If you're a Licensed user of PROTON DEVELOPMENT SUITE, apply for Licensed User Status to remove these pesky messages
     and get access to additional forum areas, Beta test downloads and more!

  3. #2
    Super Moderator fanie's Avatar
    Join Date
    Oct 2005
    Location
    Crime riddled ZA
    Posts
    8,019


    Default Re: Interrupts in Proton and PIC issues

    Hello Breed,

    Interrups work very easy ! You have to figger out they work, what they affect and then it's really very easy.
    Keep in mind an interrupt is like polling a bit without the pic using code to poll it, iow it's like a peripheral doing something in the background while the pic actively does something else.

    There may be times when you don't want an interrupt to occur, like in the interrupt handling routine, and perhaps when you write to a display etc or it will appear sticky and jumpy, but it depends on the priority of the interrupt. To prevent an interrupt you just disable it temporary then enable afterwards. Most of these no-no's are a line or three and you still catch the interrupt.

    When you write the interrupt routine, the best is always to keep the int routine as short as possible. Something that worked well for me a few times was to set a value or bits in a variable or inc the variable value so you won't lose an occurrence, then exit and handle the set bits in the variable instead of trying to handle the condition in the int routine.

    Sometimes you have to design the hardware to assist the code so an interrupt ie on a pin will have a bit of a delay so the code will see it every time, ie a cap that will delay the input condition instead of relying in the software to see it.

    I always say one has to work out - in the mind - or what's left of it - exactly how something works then you can begin to design the hardware and software to jointly become functional in what you want to achieve.

    Most apps doesn't even need interrupts if you're just a bit clever with the software's layout.
    Fanie
    FAZE
    73 de ZS6FAZ
    http://fanie.cambs.net
    Stick to pic

  4. #3
    Super Moderator wastrix's Avatar
    Join Date
    May 2008
    Location
    Sydney, Australia
    Posts
    2,555


    Default Re: Interrupts in Proton and PIC issues

    Thanks for writing that, I have put it on the wiki here: http://www.protonbasic.co.uk/content...and-PIC-issues
    "If you have an important point to make, don't try to be subtle or clever. Use a pile driver."
    - Winston Churchill
    If you want to contact me, please email me, don't PM me.

  5. #4
    Licensed User barak's Avatar
    Join Date
    Apr 2008
    Location
    Minnesota USA
    Posts
    360


    Default Re: Interrupts in Proton and PIC issues

    very usefull - thanks

  6. #5
    Super Moderator John Drew's Avatar
    Join Date
    Feb 2002
    Location
    Millicent, South Australia
    Posts
    911


    Default Re: Interrupts in Proton and PIC issues

    Well written Breed.
    John

  7. #6
    Licensed User roger's Avatar
    Join Date
    Dec 2002
    Location
    Sproughton, Suffolk
    Posts
    372


    Default Re: Interrupts in Proton and PIC issues

    Quote Originally Posted by breed View Post

    So what happens- you clear the interrupts but an interrupt is logged part way through the instruction (they take 4 clock cycles complete). Now the instruction is completed but the interrupt is set so the interrupt is handled and the return from the interrupt sets gie back to on. In the Microchip documentation they said the only way to deal with this issue is to clear gie, check and make sure it is clear, and re-clear it if it isn't before continuing on. In proton this would be
    While gie=1
    Gie=0
    Wend

    Yes, although the probability of this happening is remote it can happen and cause serious intermittent problems.

    The point here is you have to turn off interrupts when transferring word+ sized variables and eeprom writes and a simple gie=0 won't do. You must call (gosub) an interrupt disable routine before doing.
    I know the problem you describe was a significant issue with the earlier mid range pics, I don't know whether it still exists in 18F pics today, or whether the issue has been dealt with in the pic architecture. I havn't seen it mentioned in recent technical manuals, maybe I should read more. Still better safe than sorry.

    I would be interested in your Proton "ring' buffer code, if you can post or PM. I am currently working on a project where any of 32 switches can generate an interrupt, and had been trying to convert some C code to do a similar thing.

    Thanks

    roger

  8. #7
    Licensed User W4GNS's Avatar
    Join Date
    Nov 2009
    Location
    Virginia, USA
    Posts
    105


    Default Re: Interrupts in Proton and PIC issues

    Thanks for your time to write that Breed, It's a welcome change to the forum
    Gary
    W4GNS dit dit
    Email: spam@uce.gov
    Tel: BR549

  9. #8
    Licensed User breed's Avatar
    Join Date
    Apr 2011
    Location
    Delta, Colorado
    Posts
    12


    Default Re: Interrupts in Proton and PIC issues

    Thank you all for your input on my post. As was said by fanie- you have to think like the pic when working with interrupts, which is what I have always done with my assembler but now its more difficult without digging into the generated code to see exactly how the compiler handles things. Making the jump to Proton kind of got me thinking about some of the issues with interrupts and how I may need to deal with them with Proton. That got me to going “hmmm” and digging around the forum on the issue of interrupts. I saw a lot of posts on the subject and realized that these little issues I had to deal with in the assembler world might be things that weren’t so obvious. So I made the post hoping that some may find the information useful.

    I am posting my snippet of code for the serial buffer here. It’s the Protonized version of how I’ve always done it in assembler. I apologize if this is not the proper way to do this or I mess up the posting of the code. This is the first and only forum I am on so I still have lots to learn about the correct way to do things. Hope folks find it useful. Many of you will probably notice my lack of efficient Proton coding which comes from my thinking in assembler all these years and this was (is) my first Proton project. That will improve with time as I get more comfortable with how the compiler handles things (learning what I can get away with).

    Code:
    ;Example of handeling interrupts in basic and a serial port receive buffer.
    
    On_Hardware_Interrupt intstrt               ;goto intstrt if interrupt
    
        ;inpterupt routine variables
        Dim itmp As Byte                            ;temp use
        Dim icnt As Byte
        
        ;rs232 rec buffer variables
        Symbol blmt=10                               ;set buffer size to 10 (0-9)
        Dim rbuf[blmt] As Byte                      ;set up receive buffer
        Dim ipnt As Byte                            ;chr input pointer
        Dim opnt As Byte                            ;chr output pointer    
    
        ;system controls
        Symbol gie=INTCON.7                             ;interupt enable
        Symbol tmr1if=PIR1.0                            ;timer 1 rollover flag
        Symbol rcif=PIR1.5                              ;receive buffer full flag
        Symbol txif=PIR1.4                              ;transmit buffer empty flag
        Symbol rcie=PIE1.5                              ;rs232 rec int enable
        Symbol spen=RCSTA.7                             ;serial port enable
        Symbol cren=RCSTA.4                             ;async rec enable
        Symbol ferr=RCSTA.2                             ;framing error flag
        Symbol oerr=RCSTA.1                             ;overrun error flag
    
    
        
    ;*******************************************************************************
    ;                           interupt routines
    ;*******************************************************************************
            GoTo init                               ;get around the interrupr handler
    
    High_Int_Sub_Start
    
    intstrt:
            Context Save                            ;this is a small price to pay for being
                                                    ;sure that Proton system variables aren't
                                                    ;messed up by Proton funtions in the
                                                    ;interrupt loop. This example doesn't
                                                    ;really use higher level commands but
                                                    ;there are other higher level things in
                                                    ;the actual program that do.
                                                    
    
    intchk: If rcif=1 Then recin                    ;serial input interrupt
            If tmr1if=1 Then tmrcnt                 ;timer1 rollover interrupt
            GoTo intend
            
            ;Test interrupt timer/counter- sets updf for main to see new data in icnt. 
            ;I used this as an initial test of how Proton would handle interrupts (keep in
            ;mind the program this is from is my very first project with proton).
    tmrcnt: Inc icnt
            updf=1
            tmr1if=0
            GoTo intchk        
            
            
            ;recin- gets characters from async port and saves it in ring buffer so they can
            ;be processed in the main program loop when time allows. If the buffer overflows
            ;the last character is discarded. If there is an internal overrun error the port
            ;is reset and the character is discarded. If there is a framing error the
            ;chr is also discarded.
    recin:  itmp=RCREG                                      ;get chr
            If oerr=1 Then                                  ;if overrun error
                cren=0                                      ;reset port
                cren=1
                GoTo rcend                                  ;discard chr
            End If
            If ferr=1 Then rcend                            ;if framing error discard chr
            Inc ipnt                                        ;select next pos in buffer
            If ipnt=blmt Then Clear ipnt                    ;if rollover reset to start 
            If ipnt=opnt Then                               ;if buffer is full
                Dec ipnt                                    ;reduce ipnt by 1
                If ipnt=255 Then ipnt=blmt-1
                GoTo rcend                                  ;discard chr
            End If
            rbuf[ipnt]= itmp                                ;put chr in buffer
    rcend:  GoTo intchk                                     ;make sure no more interrupts
                                                            ;to process
    
    
    intend: Context Restore
    
    High_Int_Sub_End
    
    
    init:           ;basic initialization here
    
    ;******************************************************************************
    ;           Main program loop
    ;******************************************************************************
    
    timdly: If tmr1if=1 Then GoTo process  ;this is how I actually have my time reference
            ;now and don't use the interrupt timer function (its commented out in the code).
            ;I left it in the above routine to show how I process multiple interrupts.
            
            ;dataio- gets data from the rs232 buffur and processes it.
            ;commands
            ;O- turns unit on (takes out of standby)
            ;F- turns unit off (puts into standby)
            ;R- reset current alarms (does not affect maint alarms)
            ;D- send units data
            
    dataio: If ipnt=opnt Then timdly                 ;exit if no chr in buffer
            Inc opnt                                 ;select next chr
            If opnt=blmt Then Clear opnt             ;rollover adjust
            dta=rbuf[opnt]                           ;get chr
            If dta="O" Then swtm.0=1                 ;set run switch if on rec
            If dta="F" Then swtm.1=1                 ;set stop switch if off rec
            If dta="R" Then swtm.2=1                 ;set reset switch if reset rec
            If dta="D" Then GoSub sndsys             ;send system data
    ;!!! for testing
            ;GoSub chrout                             ;echo character
            ;If dta=13 Then
            ;    dta=10
            ;    GoSub chrout                       ;I have since found that hserout works
            ;EndIf                                  ;well and I didn't need my chrout sub.
            GoTo timdly
    
    process: ;timed (.25sec) system data processing, controls, displays, etc.
            tmr1if=0
            ;
            ;
            ;
            GoTo timdly
    My program is doing what!!??

  10. #9
    Super Moderator John Drew's Avatar
    Join Date
    Feb 2002
    Location
    Millicent, South Australia
    Posts
    911


    Default Re: Interrupts in Proton and PIC issues

    Welcome to the Forum, Breed. You'll find a lot of helpful people here.

    With your permission, I'll put your code as an article on the Wiki (or you can do it yourself), it's a bit easier to find helpful stuff there rather than search among a heap of threads.

    Many of us struggle with interrupts but, as you know, once 'conquered' they make things much more efficient. Our king of interrupts is Tim, so if we can attract his attention he may make a comment on your code.

    Your background shows by the way you comment your code, you're going to be a valuable resource for us and hopefully the reverse will also be true.
    Cheers
    John
    VK5DJ

  11. #10
    Licensed User Gorgus's Avatar
    Join Date
    Aug 2008
    Location
    Eskilstuna, Sweden
    Posts
    1


    Default Re: Interrupts in Proton and PIC issues

    Thanks, this information will surely come in handy.

+ Reply to Thread
Page 1 of 2 12 LastLast

Similar Threads

  1. More USB issues...
    By wastrix in forum Proton Plus Compiler v3
    Replies: 10
    Last Post: 5th May 2011, 12:09
  2. Do proton commands temporarily disable interrupts?
    By Willi Grundmann in forum Proton Plus Compiler v3
    Replies: 15
    Last Post: 17th May 2009, 06:34
  3. Interrupts issues and solutions
    By nhadzid in forum Proton Plus Compiler v3
    Replies: 1
    Last Post: 9th November 2005, 19:23

Members who have read this thread since 2nd May 2012, 19:41 : 7

Actions :  (Set Date)  (Clear Date)

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