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 support@ccsinfo.com

Multiple Interrupt Help

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



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

Multiple Interrupt Help
PostPosted: Thu Dec 29, 2005 12:34 pm     Reply with quote

Please excuse the minimal effort on my part to understand my problem. I've finally deduced that my problem is being caused by multiple interrupts and I've wasted alot of time getting to this point so I'm going to impose on the kindness of the experts for, what I hope is, a quick solutuon/explanation.

(I found one relevant post by RJ but didn't understand it.)

18LF4620 @ 20MHz & 3.3v
3.236

Interrupts are:

Code:
//setup counter for firmware RTC
   int_count = INTS_PER_SECOND;
   set_rtcc(0);
   setup_counters (RTCC_INTERNAL, (RTCC_DIV_256 | RTCC_8_BIT));
   enable_interrupts (INT_RTCC);      //(RTCC_ZERO);

   //software PWM for LEDs timer
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   enable_interrupt(INT_TIMER1);

   enable_interrupts(int_rda);
   enable_interrupts(GLOBAL);

/*******************************
       Software PWM ISR
*******************************/
#int_timer1
void tick_interrupt(void) {

   static int8 loop = LOOPCNT;
   static int8 pulse;

   if(--loop == 0) {
      loop = LOOPCNT;
      pulse = width;
   }

   if(pulse) {
      output_low(ENABLE);
      pulse--;
   } else {
      output_high(ENABLE);
   }

   SET_TIMER1(0xFFFFFF00);     //preload timer to prevent blinking
}




Their usage is: (in order of importance)

Timer_1 for a software PWM to control brightness on LEDs (using PCM's code.. I think) Any fishiness here will cause varying brightness.

RDA serial radio.

A software RTC/Timer for flashing a heartbeat LED and house keeping.


My problem is that when I shorten up the pulse I think I'm blowing the stack. Code continues to run but serial receives don't work.

My question is how do I prevent interference between interrupts?

Thanks guys,

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 1:03 pm     Reply with quote

Quote:
My problem is that when I shorten up the pulse I think I'm
blowing the stack. Code continues to run but serial receives don't work.

1. Use the #priority statement to put INT_RDA first.

2. Put the ERRORS directive in your #use rs232 statement.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 1:18 pm     Reply with quote

Quote:
Code:
SET_TIMER1(0xFFFFFF00);     //preload timer to prevent blinking
Timer1 is 16 bits, you are loading it with a 32 bit value.

Why don't you use the inbuilt PWM hardware? It will be more precise and better adjustable with much less software overhead.
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 1:52 pm     Reply with quote

ckielstra wrote:
Timer1 is 16 bits, you are loading it with a 32 bit value.


Ouch. Thanks. I missed that one!

ckielstra wrote:
Why don't you use the inbuilt PWM hardware?


I hadn't planned on using PWM for controlling LEDs so hardware isn't set up for it. I was hoping the software version would work....


PCM,

I had "errors" in my RS232 setup. I tried the #priority option and that didn't help.

When I comment out the OUTPUT_HIGH and OUTPUT_LOW lines in the ISR, problems are greatly reduced. Time consumed there is the problem?

Also, another manifestation of the problem is bad ADC readings. I have a TC1047 for internal temp readings. When I start reducing the width the ADC starts spitting out bad readings....

Thanks, I'll continue to try things as I think of them.

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 2:14 pm     Reply with quote

Quote:
When I comment out the OUTPUT_HIGH and OUTPUT_LOW lines in the ISR, problems are greatly reduced. Time consumed there is the problem?

I didn't look closely at your code before. I did now, and I can see
that you're doing long delays inside your isr. Interrupts are disabled
while an isr is executing. If you have a long enough delay in the isr,
you'll start missing incoming RS-232 characters.
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 6:25 pm     Reply with quote

I've tried moving the output_hi/lo commands outside the ISR and it isn't functional. The LEDs flicker.

I don't think the problem is necessarily missing incoming RS232 comms. I've found a couple of lines of code that seem to be the most to blame. If I comment them out and use a work around I don't have the problems I originally had. (really all the workaround is, is preventing the offending functions from executing each time through the main loop, and only allowing them to run every other second or so...)

Even with the workaround code the ICD locks up. This is leading me to believe I'm screwing up the stack, etc.

I'm new to the ICD so I don't know if there is a way to keep track of everything up to the point where it blows up. I've tried stepping through to the armageddon point but that hasn't been successful.

Any other ideas would be greatly appreciated.

Thanks,

John



PS Here is the suspect code:
Code:


#define NUM_OF_CABLES  15

int8 fetch_chip_pwr(int1 chip, int8 cable) {

   int8 i;
   int8 j;
   int8 pins_powered = 0;

   if(cable > NUM_OF_CABLES) {     //return 0 for non-existent cable
      return(0);
   }

   if(chip == 1) {
      for(j = 0; j < 2; j++) {
         for(i = 0; i < 8; i++) {
            //correction for array indexing
            if(bit_test(LED_out[cable - 1][j], i)) pins_powered++;
         }
      }
   }

   if(chip == 2) {
      for(j = 0; j < 2; j++) {
         for(i = 0; i < 8; i++) {
            //correction for array indexing
            if(bit_test(LED_out[cable - 1][j + 2], i)) pins_powered++;
         }
      }
   }

   return(pins_powered);
}


int16 fetch_system_pwr(void) {

   int8 i;
   int8 j;
   int16 total_pins_powered = 0;

   for(i = 1; i <= NUM_OF_CABLES; i++) {
      for(j = 1; j < 3; j++) {
         total_pins_powered = total_pins_powered + (int16)fetch_chip_pwr(j, i);
      }
   }

   return(total_pins_powered);
}
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Dec 29, 2005 8:45 pm     Reply with quote

Quote:
I didn't look closely at your code before. I did now, and I can see
that you're doing long delays inside your isr. Interrupts are disabled
while an isr is executing. If you have a long enough delay in the isr,
you'll start missing incoming RS-232 characters.


Was the original posted code modified because I don't see any unreasonably long delays.

Quote:
Any other ideas would be greatly appreciated.


I cannot comment on the behaviour of the ICD you are using however, from the information you have given, there is another likely cause of problem. You have not listed all your interrupt handler code but I speculate you are using a function inside one of the other interrupt handlers that you are also using outside the handler. When this situation occurs the compiler inserts disable and reenable sequences in the code outside the handler. If there are long delays in these procedures then interrupt handling becomes erratic and interrupts might be missed. The compiler warns you that it is doing this. I suspect the root cause it outside the code segments you have listed.

Also in your listed priorities, the PWM is not the highest priority interrupt handling functio required for your application. This is because persistence, both the LED and the human eye, mean it would be impossible to differentiate the incremental delay of processing a serial rx interrupt.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!


Last edited by asmallri on Thu Dec 29, 2005 9:26 pm; edited 1 time in total
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Thu Dec 29, 2005 9:11 pm     Reply with quote

Andrew,

Thanks for the input. The interrupt (rda) being disabled outside the handler starts to sound more like the symptom. Essentially, everything works except for the serial interrupt. As for the function inside and outside the ISR it doesn't look as though that's happening (most of my code is cut and paste from the CCS pros :-)

I finally gave up and, luckily, I had an open CCP/PWM pin available and tried the hardware option (thanks ckielstra). And it looks as though that maybe the solution to all my problems. However, I'd really like to understand what I was doing to myself so I could learn something from the past three days that have gone down the crapper.

Thanks to all,

John
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Dec 30, 2005 10:04 am     Reply with quote

Quote:
However, I'd really like to understand what I was doing to myself so I could learn something from the past three days that have gone down the crapper.
From the little program code you have given us it is not possible to tell where you went wrong.

Interrupts have some side effects that even advanced programmers have problems with, for example what Asmallri already pointed out is that the CCS compiler sometimes disables interrupts (calling the strcpy, memcpy and read_eeprom functions are examples of this).

An important thing to notice is that your software PWM routine was taking an awfull lot of processing power. You were triggering this interrupt every 256 instruction cycles. On a PIC18 processor the overhead for an interrupt is about 75 instruction cycles, add to this the overhead of your interrupt function and you get a total of almost 100 instruction cycles for every PWM interrupt. This means your processor was 40% of it's time busy controlling the LED.....

It is possible to use a software PWM when the hardware PWM pins are not available, but the implementation chosen here was not optimal for your project. This software PWM was most likely designed for use with an 8 bit timer, hence your SET_TIMER1(0xFF00) at the end of the ISR. With the 16-bit timer available in your project I would have chosen another approach where you don't use a 'pulse' variable but instead vary the time between interrupts by manipulating the Timer1 counter. This way it should be possible to reduce the number of Timer1 interrupts by at least a factor 10.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 30, 2005 4:02 pm     Reply with quote

Quote:
Was the original posted code modified because I don't see any unreasonably long delays

You are correct. I screwed up.
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Fri Dec 30, 2005 8:59 pm     Reply with quote

ckielstra,

Thanks for the additional info. I understand your more efficient use of the timer for a software PWM, I will keep that in my bag of tricks. Luckily, as I said before, I modified the board to use the available CCP/PWM pin and it works great. The ICD even works now, probably a pretty good indication I'm not totally destroying registers, pointers, and the like?

I still do have one odd manifestation. When I run particular piece of code the ADC will start to wander from a previous stable report. I won't post a bunch of code (yet) but, is there some place where I could start to look for the problem?

Thanks,

John
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Fri Dec 30, 2005 9:10 pm     Reply with quote

Well.... as always I had a momentary lapse in ignorance after the last post and thought to try this:

Code:
         setup_ccp2(CCP_OFF);
         check_analog();
         setup_ccp2(CCP_PWM);


And that cleaned up everything, and it isn't even noticable in the LEDs.

Thanks again to all,

John
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