IRQ causing unexpected result?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IRQ causing unexpected result?

Jump to solution
1,671 Views
RW
Contributor I
I'm hoping someone here has some ideas on a problem with our code. We're using an MC68HC11E1CFN2 with external memory.

The following code snippet is in a routine that is called repeatedly in the main loop of my program. The bits in accumulator A are reversed into accumulator B then stored into a variable.

 
            LDAB  #$08        ;Load for loop counter
            STAB  INP1_TMP    ;Move 8 bits
            CLRB
GET_DIP_LP  ROLA              ;Move MSB into carry
            RORB              ;Move carry into MSB
            DEC   INP1_TMP
            BNE   GET_DIP_LP ;If not done

            COMB              ;Complement bits
            ANDB  #$3F        ;Mask off unwanted bits

            STAB  INP1_TMP    ;and save

 

The value in INP1_TMP is what I expect. I don't know how often this code gets executed (don't have a debugger) but I'd say it does what it should thousands of times in a row, but every once in a while the value in INP1_TMP is incorrect.

This routine also gets called in my interrupt handling code.

Any idea what could be going wrong? My only theory is that occasionally in between the ROLA and RORB statements, an interrupt happens (and the code executes again) and when it returns the carry bit is incorrect. That should have been saved correctly on the stack though.


It looks like if I don't call this routine in the interrupt handling code everything works fine. I'd still like to know what's going wrong though.


Thanks,

Ryan

Labels (1)
0 Kudos
Reply
1 Solution
786 Views
tonyp
Senior Contributor II
You access INP1_TMP at three different points.  Isn't that enough of a reason, when the same routine gets called from the ISR, also?  Isn't it possible that INP1_TMP gets changed (from the ISR invocation of the same routine) while in the middle of executing the non-ISR routine?
Message Edited by tonyp on 2009-11-20 11:56 PM

View solution in original post

0 Kudos
Reply
5 Replies
786 Views
tonyp
Senior Contributor II
You mean to say you've never heard of the SEI and CLI instructions and what they're good for? (Also, TPA and TAP to restore the pre-SEI condition.)
Message Edited by tonyp on 2009-11-20 11:46 PM
0 Kudos
Reply
786 Views
RW
Contributor I

SEI and CLI are used to disable and re-enable interrupts aren't there?

 

I don't see why I should have to disable interrupts during that block of code.

0 Kudos
Reply
786 Views
tonyp
Senior Contributor II

It's usually possible to find ISR-friendly solutions that do not require interrupts to be disabled.  For example, you don't have to use a variable for counter.  Instead you can do this:

 

 

                    LDAB      #$80
GET_DIP_LP          ROLA                     
                    RORB                     
                    BCC       GET_DIP_LP     

                    COMB                     
                    ANDB      #$3F    
                    STAB      INP1_TMP

 Register B is initially loaded with Bit7 ($80) which, as it gets shifted to the right, it will eventually (after exactly 8 shifts) end up in the CCR[C].  You can check for this to control your loop.

 

That way you only write the final result into INP1_TMP (once, in one atomic operation).

 

 

0 Kudos
Reply
787 Views
tonyp
Senior Contributor II
You access INP1_TMP at three different points.  Isn't that enough of a reason, when the same routine gets called from the ISR, also?  Isn't it possible that INP1_TMP gets changed (from the ISR invocation of the same routine) while in the middle of executing the non-ISR routine?
Message Edited by tonyp on 2009-11-20 11:56 PM
0 Kudos
Reply
786 Views
RW
Contributor I

Ah, of course.

 

I was only thinking about how the values in the accumulators could get messed up when I should have realized it was INP1_TMP.

 

Thank you for the help.

0 Kudos
Reply