CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem with ISR - code inside not being executed

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cypher



Joined: 05 Oct 2007
Posts: 31

View user's profile Send private message

Problem with ISR - code inside not being executed
PostPosted: Wed Aug 05, 2009 6:27 pm     Reply with quote

Hi,
I seem to be having an unusual problem. It seems as though I have an intermittent problem with code being executed inside the #int_RB isr. Intermittently I notice that some of the code does not get executed inside this isr. I know I should make my isr short, but is there a limit of how much code I can put in my ISR?

Here are my ISR routines for the #int_RB and #int_timer0, maybe I'm not declaring them correctly:

Code:

#int_RB                             
void  MCW_isr(void)                     
      {
      disable_interrupts(int_rb);   
      delay_us(100);                 
      state[0] = input(ENABLE);     
     state[1] = input(SELECT_A);   //State A select line
      state[2] = input(SELECT_B);   //State B select line
      state[3] = input(SELECT_C);   //State C select line
     delay_us(100);
     chip_select1 = input(ENABLE);
     status_a1     = input(SELECT_A);
     status_b1     = input(SELECT_B);
     status_c1     = input(SELECT_C);
     delay_us(50);
     chip_select2 = input(ENABLE);
     status_a2     = input(SELECT_A);
     status_b2     = input(SELECT_B);
     status_c2     = input(SELECT_C);

     if((chip_select1 == chip_select2)   &&   (status_a1 == status_a2)   &&   (status_b1 == status_b2)   &&   (status_c1 == status_c2))
     {

            if (chip_select2 == 0 && !(chip_select2 == prev_state)) //To check MCW's, state[0] must be 0 and previous state must've been a 1
            {
               check_MCW();               
             }
           else// if (state[0] == 1 && !(state[0] == prev_state)) //On rising edge, tri-state data bus
            {
               set_tris_e(0xFF);          //Tri-states data bus
            }
            prev_state = chip_select2;        //Stores previous state of ENABLE
            MCW_ISR_flag = 1;
     }

      clear_interrupt(int_rb);      //Clear the RB interrupt
      enable_interrupts(int_rb);    //Enable the RB interrupt

      }

#int_timer0                         
void  seconds_isr(void)                 
      {
      disable_interrupts(int_timer0);
      one_second_timer = 1;         //Set the global variable one_second_timer
      set_timer0(0xE000);           //Reload the timer0 register with this value - you can change the length of time of the clock with this number
      clear_interrupt(int_timer0);  //Clear the timer0 interrupt
      enable_interrupts(int_timer0);//Enable the timer0 interrupt

      }


I notice that sometimes some of the code in some of the sub routines that the ISR calls does not get executed. I know this because I put printf statements before and after glowing some LEDs in the code. The printf statements get executed but I do not see the LEDs glow. This happens intermittently though, 90% of the time it works. What could be causing this intermittent problem?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 6:52 pm     Reply with quote

You don't need to disable/enable INT_RB interrupts inside the isr.
There are no nested interrupts. You don't need to clear the interrupt
flag at the end of the isr, because CCS puts in code (unseen) to do that
anyway. You do have some long delays in the isr. You might want
to read Port B, or at least one pin on Port B, just before you exit the isr.
This would clear the "mismatch" condition that causes an INT_RB interrupt.
Are you trying to debounce something with delays ?

You should explain what your overall project is about, and tell us some
details about the signals on the pins used in the INT_RB isr.

You should post at least the framework of a test program, so that we
can look at your PIC, #fuses, #use delay() etc.

Also post your compiler version.
mskala



Joined: 06 Mar 2007
Posts: 100
Location: Massachusetts, USA

View user's profile Send private message

PostPosted: Wed Aug 05, 2009 8:10 pm     Reply with quote

There is no limit to the amount of code you can have in an ISR. Before I changed my architecture around, I had essentially my whole program in one (everything ran from timer interrupt and had to be in right slices) with just a while (1) {} in the main.
cypher



Joined: 05 Oct 2007
Posts: 31

View user's profile Send private message

PostPosted: Thu Aug 06, 2009 12:38 pm     Reply with quote

Thanks for the reply.

So, I tried removing the disable/enable interrupts inside the INT_RB isr but that didn't make any difference. I also tried adding an input_b(); at the end of the isr with no luck.

So, a brief explanation of what i'm trying to do here:

I have 1 single EN line which I hooked up to PIN_B4 and depending on the rising or falling edge of this line, I read a state bus (PIN_B5-B7) and decide what command was received and hence what operation to perform. In my case I am having this intermittent problem with the microscale() subroutine. In the microscale subroutine, I can either go microscale_high, microscale_low or microscale_off. The intermittent problem occurs when I go from high to off. I notice that all the statements inside the else if statement take place except:

heater_status = 0; I know this because I output heater_status and it is 1
And within DC_heaters_off(), I notice the LED does not turn off and some SWs do not turn off, however, the HOFF1 and HOFF2 printf take place. Hence why I say these statements don't get executed.

This is the intermittent problem i'm having. Now I realize that 90% of the time it works, so I don't think (and i've checked) that there are other places in my code where I do heater_status = 1 or turn on the LED again, otherwise I would see the problem happen every single time right?

Here are some sections of my code below that are related to the issue, please let me know if you see something or have a clue to what is happening. I will try using the debugger and see where all it goes in code once I issue the OFF command just to make sure it isn't re-writing the heater_status flag somewhere and turning the LED on again.

Code:

#include    <18F6722.h>
#device     ADC=10
#include    <stdio.h>
#include    <math.h>
#include    <ctype.h>
#include    <stdlib.h>


/* ---  C Compiler Settings --- */
#use    delay(clock=8000000, internal)
#use    rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8, force_sw, invert)
#use    standard_io(A)              /* Thermistor */
#use    standard_io(B)              /* SW-PIN */
#use    standard_io(C)              /* RS232C */
#use    standard_io(D)              /* Heater */
#use    standard_io(E)              /* HW-PIN */
#use    standard_io(F)              /* Thermistor */
#use    standard_io(G)              /* LED and Temp */

#fuses NOBROWNOUT,FCMEN,IESO,PUT,INTRC_IO,NODEBUG,NOWDT,NOLVP
#ID 0x4D4C,0x342D,0x6552,0x3176
#bit RST = 0x0FD0.4
#bit WDT = 0x0FD0.3
#bit POR = 0x0FD0.1                 //Power-on-Reset flag
#bit BOR = 0x0FD0.0

void main(void)
{

   clear_interrupt(int_timer0);    //Clear the Timer0 interrupt
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);   //Set-up the timer0, internal clock, 256 divide
      set_timer0(0xE000);           //Put this value in the timer0 register to get about 1 second
      enable_interrupts(int_timer0);//Enable timer0 interrupt
      enable_interrupts(GLOBAL);    //Enable all interupts

   while (1)
         {
            if(one_second_timer)
               {
                  read_reg_sr();
               }
         }
}

#int_timer0                         //This is the ISR for the one-second timer
void  seconds_isr(void)                 //Just set a global variable to get out of the ISR incase the MCW_ISR is called
      {
      disable_interrupts(int_timer0);
      one_second_timer = 1;         
      set_timer0(0xE000);           
      clear_interrupt(int_timer0);  //Clear the timer0 interrupt
      enable_interrupts(int_timer0);//Enable the timer0 interrupt
  //    enable_interrupts(global);    //Enable all interrupts
      }

#int_RB                             //This is the ISR for MCW reads and writes
void  MCW_isr(void)                     //You can stay in this ISR longer, regulation won't suffer
      {
      disable_interrupts(int_rb);   
      delay_us(100);                 //This is a switch debounce delay
      state[0] = input(ENABLE);     //Enable pin on DC - don't branch if interrupt is not enable
     state[1] = input(SELECT_A);   //State A select line
      state[2] = input(SELECT_B);   //State B select line
      state[3] = input(SELECT_C);   //State C select line
     delay_us(100);
     chip_select1 = input(ENABLE);
     status_a1     = input(SELECT_A);
     status_b1     = input(SELECT_B);
     status_c1     = input(SELECT_C);
     delay_us(50);
     chip_select2 = input(ENABLE);
     status_a2     = input(SELECT_A);
     status_b2     = input(SELECT_B);
     status_c2     = input(SELECT_C);

     if((chip_select1 == chip_select2)   &&   (status_a1 == status_a2)   &&   (status_b1 == status_b2)   &&   (status_c1 == status_c2))
     {

            if (chip_select2 == 0 && !(chip_select2 == prev_state)) //To check MCW's, state[0] must be 0 and previous state must've been a 1
            {
               check_MCW();               //Calls the check_MCW function to determine state
             }
           else// if (state[0] == 1 && !(state[0] == prev_state)) //On rising edge, tri-state data bus
            {
               set_tris_e(0xFF);          //Tri-states data bus
            }
            prev_state = chip_select2;        //Stores previous state of ENABLE
            MCW_ISR_flag = 1;
     }

        clear_interrupt(int_rb);      //Clear the RB interrupt
        enable_interrupts(int_rb);    //Enable the RB interrupt
      }

void  check_MCW(void)               //Function to select the state function based on select lines
      {
      state[1] = input(SELECT_A);   //State A select line
      state[2] = input(SELECT_B);   //State B select line
      state[3] = input(SELECT_C);   //State C select line
      if (state[1] == 0 && state[2] == 0 && state[3] == 0)  //State 0b000
         {
            read_therm();           //Calls temperature READ function
         }
      if (state[1] == 1 && state[2] == 0 && state[3] == 0)  //State 0b001
         {
            read_temp();            //Calls Setpoint READ function
         }
      if (state[1] == 0 && state[2] == 1 && state[3] == 0)  //State 0b010
         {
            write_temp();           //Calls Setpoint WRITE function
         }
      if (state[1] == 1 && state[2] == 1 && state[3] == 0)  //State 0b011
         {
            reset();                //Calls RESET function
         }
      if (state[1] == 0 && state[2] == 0 && state[3] == 1)  //State 0b100
         {
            microscale();           //Calls Microscale function
         }
      if (state[1] == 1 && state[2] == 0 && state[3] == 1)  //State 0b101
         {
            PC_codes();         //Calls Additional features function
         }
      if (state[1] == 0 && state[2] == 1 && state[3] == 1)  //State 0b110
         {
            test_mode();            //Calls Test Mode function
         }
      if (state[1] == 1 && state[2] == 1 && state[3] == 1)  //State 0b111
         {
            run();                  //Calls RUN function
         }
      check_state_flag = 1;
      }

void  read_reg_sr(void)             //This is the subroutine called by the WHILE loop before, every second
      {
      output_low(LED1);             //Set blue LED on to enter subroutine
      count_time();                 //Count the present elapsed time
      read_thermistors();           //Read the current thermistor values
      FAULTS(flag);                      //Check if there is a thermistor FAULT
     printf("Reg = %d\r",regulation_enable);
      if ((dead_therms <3) && (regulation_enable == 1))   //If at least one therm is working and regualtion is true, then regulate
         {
       printf("*\r");
         regulation();              //Calls the regulation function
         }
     
      if(temp_therm1 != prev_temp1 || temp_therm2 != prev_temp2 || temp_therm3 != prev_temp3)   //If therms have changed since their previous values, then call report_therms
         {
         report_temp();             //Calls the report_therm function
         }
      if (save_error_codes)
         {
         error_word = make32(error_codes[4],error_codes[3],error_codes[2],error_codes[1]);
         write_ee_32(error_codes_ee_address,error_word);
         write_ee_32(error_codes_ee_address + 4,error_word);
         }
      one_second_timer = 0;         //Resets the global variable to call this fuction (set by ISR)
      ten_minute_timer = 0;
 //   restart_wdt();                //Reset the WDT counter
      print_MCW_status();
      output_high(LED1);            //Turn OFF blue LED
      }

void  microscale(void)
      {
      int microscale_input = 0;     //Set-up temp variable
      microscale_input = input_e(); //Read input from data bus
      if (microscale_input == microscale_high && microscale_byte_1 == 1)   //If keycode is met and high-temp pattern recognized, keep going
         {
         current_temp = set_temp_high; //Set current_temp to set_temp_high
         current_temp_comp = set_temp_high_comp;
         regulation_enable = 1;
         operating_mode = 0xFE;
//       write_ee_8(previous_state_address,0xFE);
         microscale_high_flag = 1;
         }
      else if (microscale_input == microscale_low && microscale_byte_1 == 1)  //If keycode is met and low-temp pattern recognized, keep going
         {
         current_temp = set_temp_low;  //Set current_temp to set_temp_low
         current_temp_comp = set_temp_low_comp;
         regulation_enable = 1;
         operating_mode = 0xB8;
       write_ee_8(previous_state_address,0xB8);
         microscale_low_flag = 1;
         }
      else if (microscale_input == microscale_off && microscale_byte_1 == 1)  //If keycode is met and off pattern recognized, keep going
         {
         current_temp = 0;
       heater_status = 0;
         DC_heaters_off();
         regulation_enable = 0;
         operating_mode = 0x23;
       write_ee_8(previous_state_address,0x23);
         microscale_off_flag = 1;
       printf("Done\r");
         }
      else                          //If second word is wrong code
         {
         microscale_byte_1 = 0;     //Reset first keycode bit
         }
      if (microscale_input == write_pattern_1 && microscale_byte_1 == 0)   //Compare first word to keycode
         {
         reset_regs();              //Reset all intermediate MCW flags
         microscale_byte_1 = 1;     //Set keycode successful bit
         microscale_keycode_flag = 1;
         }
      }

void  DC_heaters_off(void)          //Function to immediately shut-off heater circuits
      {
     printf("HOFF1\r");
      output_bit(SW1,0);
      output_bit(SW2,0);
      output_bit(SW3,0);
      output_bit(SW4,0);
      output_bit(SW5,0);
      output_bit(SW6,0);
      output_high(LED2);
     printf("HOFF2\r");
      }
cypher



Joined: 05 Oct 2007
Posts: 31

View user's profile Send private message

PostPosted: Thu Aug 06, 2009 12:55 pm     Reply with quote

I was just thinking because this problem happens only intermittently, maybe its to do with timing of some type.

Is there a need for me to do some interrupt priority handling, for example the int_rb gets higher priority than #int_timer0?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 06, 2009 3:18 pm     Reply with quote

Your program has so much code in it that I don't want to look at it.
A test program posted on this board, should be as short as possible.
For example, standard i/o mode is the default mode of the compiler.
You don't have to specify it. Next, you four #bit variables that are
not used. All those lines aren't needed for us to look at your problem.
They just get in the way.

Consider the way we like to work: You post a very short, compilable
test program. We look at it for a few seconds and solve it by inspection,
and type in an answer. That's the ideal way for us. Try to post a short
program and help us to do it that way.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Aug 06, 2009 3:38 pm     Reply with quote

you observe that there is no limit to the amount of code
you can put in an ISR
AND you are correct - in the sense of VOLUME of code

but unless you get a concept of the TIME domain
and the execution profile of your program
you will never make the mess you have work

decide what is the MINIMUM code you need in the isr and go with JUsT that

then use global variables to report out what HAPPENED in the ISR most recently - or use a buffer to report MULTIPLE events and trim the buffer as your MAIN makes use of that data

HINT: BYTE or INT8 vars are the best reporting method since you don't have the issue of a possible half/read - disturbed by INT Update
the rare exceptions are the buffered registers of the TIMERS themselves in 16 bit mode

until you grasp that concept - you should leave INTS alone
as i fear you are exceding the speed of THOUGHT
Ttelmah
Guest







PostPosted: Fri Aug 07, 2009 2:27 am     Reply with quote

Realistically, the most likely cause for code not executing at times, is _hardware_.
The commonest problems, are things like LED's without current limiting resistors, poor supply supression etc., which leads to the chip actually resetting intermittently when certain instructions are exected.
The second, is not understanding your own hardware. So (for instance), what happens if the INT_RB code is called unexpectedly, when the 'signal' you are expecting hasn't been received?. You clear the timer interrupt, but don't read the PORTB register, at the start of the main. INT_RB, is almost certain to have been set during boot (unless the incoming line(s) you are monitoring, are stable before the internal register latches, the interrupt _will_ be set). So, what will happen to the logic of your interrupt, if this happens?.

Now, I see references to heaters. Almost certainly implies reasonable currents involved. How are these switched?. How is the power line supressed?. Are this possibly inductive (any 'coil', _will_ have significant inductance)?. If so, what are you doing to trap inductive spikes?. Does your drive circuit on each heater, and LED, allow the logic line from the processor to reach it's 'high' level?. What capacitances are involved in the drive circuits?.

Best Wishes
cypher



Joined: 05 Oct 2007
Posts: 31

View user's profile Send private message

PostPosted: Fri Aug 07, 2009 7:09 pm     Reply with quote

Thanks for all your help guys. I will keep your pointers in mind for the future.

I have found the problem I was having. It is a logical problem related to interrupts taking place but has nothing to do with timing or hardware problems. Basically what was happening is that when an interrupt happens and I execute a particular command, I was setting a bunch of flags related to that event. And when the ISR would end, the place where the code would resume would re-initialize the flags that I just set in my ISR, overwriting the things I did in my ISR.

So, the intermittent problem only happened when I was at a particular place in my code AND the interrupt took place at that time.
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Fri Aug 07, 2009 10:27 pm     Reply with quote

Welcome to "race" conditions.

Gotta watch that stuff...

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group