Interrupts Handling

Discussion in 'Embedded Systems and Microcontrollers' started by TCOP, Nov 17, 2012.

  1. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    Hi guys, my issue is this.
    I am using 16F1847 and want to use a tmr0 interrupt to check an I2C RTC and display a message in LCD.
    My problem is that some routines are shared between code and ISR. So when my main loop is calling an I2C routine for doing something else and a TMR0 is triggered, everything is screwed. I am searching of a delicant way to overcome this.
    I am thinking of creating a software int by utilizing an unused hardware int. So instead of calling the I2C procedure from my code, I would just trigger the unused int and then it would call the I2C procedure. This way I2C would be only be called from inside ISR and there would be no chance that an other int could pause the routine.
    How does this sounds? Do I have any other alternative when there are shared procedures between main code and ISRs?
     
  2. MrChips

    Moderator

    Oct 2, 2009
    12,447
    3,363
    Turn off interrupts while doing I2C in the main program.
     
  3. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    Tried that but it does not work. I turn off ints at the start of I2c and turn them on again at the end. This works well until I2C is called from inside ISR. Then this is what happens:
    Firstly Ints are disabled (they were already disabled since an int is active). Code is executed properly until i get at the end of the I2C procedure.
    Then ints are enabled again and allow other ints to be triggered before I have properly returned to my ISR routine.
     
  4. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    anyone out there?
     
  5. MrChips

    Moderator

    Oct 2, 2009
    12,447
    3,363
    1) Don't disable and enable interrupts inside of the I2C routine. Do this in the main calling program.

    2) Don't call I2C routine in the ISR. Instead, set a flag and then do I2C in the main program.
     
  6. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    Damn!... You are right!
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    You are learning (the hard way) why it is recommended not to call *any* routines from an ISR.

    A very workable way around this is to have the ISR set a global variable or flag that something needs to be done. Then your main loop can test this flag and take appropriate action when it is both required and safe to do.
     
  8. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    Since I have a DOS Asm backround, I was thinking to treat this issue the way I would have treated if it was a DOS TSR program (terminate and stay resident). I was about to start doing what I earlier said but then I realized that if it had to be so complicated, then I was probably doing something the wrong way :)
     
  9. MrChips

    Moderator

    Oct 2, 2009
    12,447
    3,363
    The general rule is you do as little as possible in the ISR. You want to get in, set a flag, and get out as quickly as possible.
     
  10. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    This only depends on the latency you can tolerate.

    I2C can work down to DC. So if there is a problem, you are not backing registers properly.

    If you use the I2C in your regular program execution flow, and then it is also called from the ISR, there is a flaw in the logic. You need to prevent reentrancy.

    You also may run out of stack, since there are only 8 levels on some 16Fs. It depends but I2C can require a lot of stack (Not to say, I wrote a small I2C handler for 16F5x, in C, only about 150 words).

    What is the fastest stepping that you need? For what purpose? If that's 1mS or the like, you can execute 1000 program words (at 4MHz).

    Normally you do not really need to care about additional code in the ISR. It does not execute faster or slower or differently than any other code.

    If you want to re-enable interrupts very fast, then you'd temporarily disable a branch that goes deeper and needs more cycles.

    Also if you have to move serial data very fast, it can be better just to poll the flag. Considering, most of the time you won't be moving this serial data.
     
  11. TCOP

    Thread Starter Member

    Apr 27, 2011
    89
    0
    Yeap. That's why I was thinking of an Interrupt to call the I2C. This way, the I2C procedure could only be called if the Int was triggered and the main code would just set the appropriate PIR1 flag to trigger it. Any way. Having just a Flag and poll against it in my main loop is much easier. Thanks a lot.

    Mine is exactly 102 words :) pure asm
     
    Last edited: Nov 17, 2012
Loading...