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

is it "forgetting" the interrupt enable bit??? :o

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



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

is it "forgetting" the interrupt enable bit??? :o
PostPosted: Mon Apr 11, 2011 5:37 pm     Reply with quote

Hi There,

I got a small program running on a 16f883 pic. it's supposed to respond to incoming rs232 data. However, I've realized that there is a seemingly random "sometimes" factor in my app and that sometimes my #int_rda wouldn't kick-in.... Shocked is it considered saf(er) to re-enable the interrupts in every iteration?
I don't see how my code would hang itself anywhere...
I pasted my code below - i have utilized the buffer code from the sisr.c example.
Clues, hints & opinions appreciated!

Code:

 #include <16F883.h>
#device adc=16
#include <string.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(clock=20000000)
#define MCU2_RX PIN_C7
#define MCU2_TX PIN_C6

#USE RS232(baud=9600,parity=N,xmit=MCU2_TX,rcv=MCU2_RX,bits=8,stream=MCU2, ERRORS)


#define ADDR 0x03
#define BUFFER_SIZE 32
#define bkbhit (next_in!=next_out)

typedef struct{
   int16 phase,
        width,
         intens;
   int8 mode,
        Hwver,
        FWver,
        temp;
        
}IRStruct;   

IRStruct LEDdata[2];
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char datagram[9]={0};
char elcnt=0;

void ProcessData(int8 *data, IRStruct *Param);
BYTE bgetc(void);



void main()
{
  enable_interrupts (int_RDA); // enable the rs232 interrupts
  enable_interrupts (GLOBAL);
 
  memset(&LEDdata,      0   sizeof LEDdata);
 
  char cin=0;
  char recv_dat[9]={0};
  int8 incnt=0;
 
 
  while (true){
    
   while(bkbhit){
      
     cin=bgetc();
    
     if (cin == 0x86 || incnt!=0) {
       
       recv_dat[incnt++]=cin;
      
        if (incnt>=9) {
          
          memcpy(datagram,recv_dat,9);
         
          ProcessData(datagram, &LEDdata);
         
          memset(recv_dat,0x00,sizeof(recv_dat));
         
          incnt=0;
         
        }
       
      }
               
    }
   
    if (bit_test (RS232_ERRORS, 2) && !input (MCU2_RX)) {
            
      // if FERR bit set and pin C7 low, reset to start bootloader mode  !
      reset_cpu ();
         
    }       
  }// [MAIN LOOP]
}
//------------------------------------------------------------------------------

BYTE bgetc()
{
   BYTE c;

   while(!bkbhit) ;
   
   c=buffer[next_out];
   
   next_out=(next_out+1) % BUFFER_SIZE;
   
   return(c);
}
//------------------------------------------------------------------------------

void ProcessData(int8 *data, IRStruct *Param)
{
   int8 i=0;
   
   int8 snd[9] = {0};
   
   int8 cmd = data[2];
   
   int8 header = data[0];
   
   int8 address = data[1];

   int8 cksum=data[1]+data[3]+data[4]+data[5]+data[6]+data[7];
   
   // check validity of data (header, address & cksum)
    if (header==0x86 &&
       address == ADDR &&
       cksum==data[8]) {
         
       switch (cmd) {
         
        //assembling response.
           
      }
      
       snd[8] = snd[1] + snd[3] + snd[4] + snd[5] + snd[6] + snd[7];
       // wait a short while before sending the response.
       //delay_ms(5);
      
       if (cmd != 0x09 || cmd !=0x11) {
         
           for(i=0;i<9;i++) {
             
            fputc(snd[i],MCU2);
           
          }
         
         }
        
       }
      
     memset(data,0x00,sizeof(data));
}
//------------------------------------------------------------------------------

#int_rda
void serial_isr() {
   
   int t;

   buffer[next_in]=getc();
   
   t=next_in;
   
   next_in=(next_in+1) % BUFFER_SIZE;
   
   if(next_in==next_out)
   
     next_in=t;           // Buffer full !!
}



Thanks,
roN
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Mon Apr 11, 2011 5:45 pm     Reply with quote

As a note on the side:

After I moved
Code:
  enable_interrupts (int_RDA); // enable the rs232 interrupts
  enable_interrupts (GLOBAL);

inside the while(true), it seems to be working all the time... that's doesn't seem to be right to me...
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 1:52 am     Reply with quote

This is always true
Code:

if (cmd != 0x09 || cmd !=0x11)

cmd cannot be 0x09 and 0x011 at the same time so at least one of these conditions will allways be true Smile

What are the symptoms of it not working?
How do you know?
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 5:31 am     Reply with quote

Hi,

I haven't studied your code in detail, but I have a couple of comments:

1. You should not need to 'enable interrupts' multiple times. Do it once just before your While (True) loop, and that should be sufficient. It may not matter, but you enable interrupts before your initialize a bunch of variables.

2. You define a stream as 'MCU2', but then don't use the stream designator in your INT_RDA ISR. Change 'getc' to 'fgetc(MCU2)'

3. Break the problem up into parts to determine if you have a 'reception issue' or a 'processing issue'. That is, start by getting rid of all the code not related to receiving the incoming serial data, and verify that you can receive the intended data 100% of the time before moving on to the data processing.

John
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 10:10 am     Reply with quote

Wayne_ wrote:
This is always true
Code:

if (cmd != 0x09 || cmd !=0x11)

cmd cannot be 0x09 and 0x011 at the same time so at least one of these conditions will allways be true Smile

What are the symptoms of it not working?
How do you know?

Hoops, I guess that better be a && than a || - thanks for the hint!
The symptoms are that this code all of a sudden stopped responding to any kind of queries and a reset would resolve the problem. The queries were still coming yes, I could monitor this on my debugging terminal as well as on the scope i have connected to Rx and Tx.
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 10:16 am     Reply with quote

ezflyr wrote:
Hi,

I haven't studied your code in detail, but I have a couple of comments:

1. You should not need to 'enable interrupts' multiple times. Do it once just before your While (True) loop, and that should be sufficient. It may not matter, but you enable interrupts before your initialize a bunch of variables.

2. You define a stream as 'MCU2', but then don't use the stream designator in your INT_RDA ISR. Change 'getc' to 'fgetc(MCU2)'

3. Break the problem up into parts to determine if you have a 'reception issue' or a 'processing issue'. That is, start by getting rid of all the code not related to receiving the incoming serial data, and verify that you can receive the intended data 100% of the time before moving on to the data processing.

John

Alright
#1 yes I know that once only should be enough.... how come it matters when i enable the interrupts? :o However, moved it to the top of my main now....
#2 -getc()
+fgetc(MCU2)
- I however think this has nothing to sdo with my problem as the interrupt didn't even trigger anymore...
#3 Yep, I agree.... will keep digging further today...

Thanks for your hints!
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 2:34 pm     Reply with quote

I would move your variable declarations in front of the function calls.
Standard C, requires variables to always be declared at the top of a routine.
Later C allows them to also be declared at the start of a code block.
Neither allow them to be declared 'mid code'.
Only later languages like C++ do.
CCS, does not complain if variables are declared 'in code', _but_ I have seen a lot of odd behaviour appear when they are....

Best Wishes
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 3:02 pm     Reply with quote

Ttelmah wrote:
I would move your variable declarations in front of the function calls.
Standard C, requires variables to always be declared at the top of a routine.
Later C allows them to also be declared at the start of a code block.
Neither allow them to be declared 'mid code'.
Only later languages like C++ do.
CCS, does not complain if variables are declared 'in code', _but_ I have seen a lot of odd behaviour appear when they are....

Best Wishes

HI Ttelmah, yeah in fact, I have seen some weird behaviours too that "all of a sudden" disappeared just by moving the variable declarations to the top. Also I have resolved my problem, the problem actually was that I wasn't careful enough on how I handled a double pointer in my ProcessData function. CCS isn't just not complaining about variable declarations, it also doesn't make a difference between * and **. It sure requires you/us to be careful! Esp when you're used to errors and warnings from GNU compilers and such.
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 3:17 pm     Reply with quote

Hi Cerr,

Your experience is somewhat 'classic' in software debugging, that is problems in one area of the program appear as problems in another area. That is why I encouraged you to divide up the problem into one of data reception, and data processing.

Why don't you post a copy of your revised code so that anyone reading this thread will have the opportunity to learn what you did?

Thanks,

John
cerr



Joined: 10 Feb 2011
Posts: 241
Location: Vancouver, BC

View user's profile Send private message

PostPosted: Tue Apr 12, 2011 3:19 pm     Reply with quote

ezflyr wrote:
Hi Cerr,

Your experience is somewhat 'classic' in software debugging, that is problems in one area of the program appear as problems in another area. That is why I encouraged you to divide up the problem into one of data reception, and data processing.

Why don't you post a copy of your revised code so that anyone reading this thread will have the opportunity to learn what you did?

Thanks,

John


Yep, I sure can do:
Code:

#include <16F883.h>
#include <stdlib.h>


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(clock=20000000)
#define MCU2_RX PIN_C7
#define MCU2_TX PIN_C6

#USE RS232(baud=9600,parity=N,xmit=MCU2_TX,rcv=MCU2_RX,bits=8,stream=MCU2, ERRORS)


#define ADDR 0x03
#define BUFFER_SIZE 32
#define bkbhit (next_in!=next_out)

typedef struct{
   int16 phase,
        width,
         intens,
         brightness;
   int8 mode,
        Hwver,
        FWver,
        temp;
        
}IRStruct;   

IRStruct LEDdata[2];
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char datagram[9]={0};
char elcnt=0;

void ProcessData(int8 *data, IRStruct *Param);
BYTE bgetc(void);



void main()
{
  char cin=0;
  char recv_dat[9]={0};
  int8 incnt=0;
  int ch=0;
 
  memset(&LEDdata,      0   sizeof LEDdata);
  enable_interrupts (int_RDA); // enable the rs232 interrupts
  enable_interrupts (GLOBAL);
  srand(0xffff);
  // loading some random data into structure
  LEDdata[0].FWver = 0x01;
  LEDdata[0].HWver= 0x01;
  LEDdata[0].temp = 0xaa;
  LEDdata[0].mode = 0xbb;
  LEDdata[0].brightness = 0x5678;
  LEDdata[1].brightness = 0x1234;
 
  while (true){    
   ch^=1;
   
   LEDdata[ch].brightness = rand();
   
   while(bkbhit){
      
     cin=bgetc();
    
     if (cin == 0x86 || incnt!=0) {
       
       recv_dat[incnt++]=cin;
      
        if (incnt>=9) {
 
          memcpy(datagram,recv_dat,9);
         
          ProcessData(datagram, LEDdata);
         
          memset(recv_dat,0x00,sizeof(recv_dat));
         
          incnt=0;
         
        }
       
      }
               
    }
   
/*    if (bit_test (RS232_ERRORS, 2) && !input (MCU2_RX)) {
            
      // if FERR bit set and pin C7 low, reset to start bootloader mode  !
      reset_cpu ();
         
    }        */
  }// [MAIN LOOP]
}
//------------------------------------------------------------------------------

BYTE bgetc()
{
   BYTE c;

   while(!bkbhit) ;
   
   c=buffer[next_out];
   
   next_out=(next_out+1) % BUFFER_SIZE;
   
   return(c);
}
//------------------------------------------------------------------------------

void ProcessData(int8 *data, IRStruct *Param)
{
   int8 i=0;
   
   int8 snd[9] = {0};
   
   int8 cmd = data[2];
   
   int8 header = data[0];
   
   int8 address = data[1];

   int8 cksum=data[1]+data[3]+data[4]+data[5]+data[6]+data[7];
   
   // check validity of data (header, address & cksum)
    if (header==0x86 &&
       address == ADDR &&
       cksum==data[8]) {
         
       switch (cmd) {
         
        case 0x07:
       
            //Pulse status query

            if (data[6] == 0 || data[6] == 1)   {
              snd[0] = 0x86;
              snd[1] = 0x03;
              snd[2] = cmd;
              snd[3] = data[6];
              snd[4] = Param[data[6]].width;
              snd[5] = ( Param[data[6]].width >>8 );
              snd[6] = Param[data[6]].phase;
              snd[7] = ( Param[data[6]].phase >>8 );
            }
           
            break;
           
        case 0x09:
       
            //Pulse status setup
           
            if (data[3] == 0 || data[3] == 1)   {
              
              Param[data[3]].phase = data[7] | ((int16)data[8] <<8);
               
              Param[data[3]].width = data[4] | ((int16)data[5] <<8);
             
            }
           
            break;
           
        case 0x11:
       
            //IR intensity setup
           
            if (data[4] == 0 || data[4] == 1)
              Param[data[4]].intens = data[5] | ((int16)data[6]<<8);
           
            break;
           
        case 0x13:
       
            //IR intensity query
           
            if (data[6] == 0 || data[6] == 1)   {
              snd[0] = 0x86;
              snd[1] = 0x03;
              snd[2] = cmd;
              snd[3] = 0x66;
              snd[4] = data[6];
              snd[5] = Param[data[6]].intens;
              snd[6] = ( Param[data[6]].intens >>8 );
              snd[7] = 0x01;
            }
           
            break;
           
        case 0x15:
       
            //Board status query
            snd[0] = 0x86;
            snd[1] = 0x03;
            snd[2] = cmd;
            snd[3] = 0x66;
            snd[4] = Param[0].temp;
            snd[5] = Param[0].Fwver;
            snd[6] = Param[0].Hwver;
            snd[7] = Param[0].mode;
           
            break;
           
        case 0x17:
       
            //Bright/Dark query
           
            if (data[6] == 0 || data[6] == 1)   {
              snd[0] = 0x86;
              snd[1] = 0x03;
              snd[2] = cmd;
              snd[3] = 0x00;
              snd[4] = data[6];
              snd[5] = 0x66;
              snd[6] = Param[data[6]].brightness;
              snd[7] = ( Param[data[6]].brightness>>8 );
            }
           
            break;
           
        default:
           
      }
      
       snd[8] = snd[1] + snd[3] + snd[4] + snd[5] + snd[6] + snd[7];
       // wait a short while before sending the response.
       //delay_ms(5);
      
       if (cmd != 0x09 && cmd !=0x11) {
         
           for(i=0;i<9;i++) {
             
            fputc(snd[i],MCU2);
           
          }
         
         }
        
       }
}
//------------------------------------------------------------------------------

#int_rda
void serial_isr() {
   
   int t;

   buffer[next_in]=fgetc(MCU2);
   
   t=next_in;
   
   next_in=(next_in+1) % BUFFER_SIZE;
   
   if(next_in==next_out)
   
     next_in=t;           // Buffer full !!
}

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