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

SW UART and faulty loop variable

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



Joined: 10 Feb 2004
Posts: 7

View user's profile Send private message

SW UART and faulty loop variable
PostPosted: Thu Apr 01, 2004 7:08 pm     Reply with quote

Ok, I have a stumper here. I have a SW UART that isn't behaving properly. I send over 50 bytes, which it reads into an array and then does a CRC check. The first byte determines whether or not there is more data coming. When I only send one byte, everything is fine. It takes the data in and writes it out to EEPROM as I want it to. When I send two bytes seems like it is working fine until I look at the data. It just writes the first packet out to memory. I thought the UART was faulty because when I looked at the RAM in MPLAB I could see the array wasn't being updated, but on further inspection, my loop variable to read in the array from the serial port refuses to initialize. When it comes through the loop again it starts at 50 and that messes everything up. Can anyone tell me what is going on? The offending part starts at 0x1d. Everything else seems to work great.

Code:

//-------------------------------------------------------------------
void SW_Uart()
{
   long SW_crc=0x0000;
   //long SW_crc_chk=0x0000;
   char SW_char,SW_count;
   int CRC_loop,crc1,crc2;
   char CRC_test=0;
   
   SW_char=SWgetch();
   
   switch (SW_char)
   {
      case 0x00:  //Init message
      {
         SWputchar(0x15);  //Send NAK
         break;
      }
      case 0x0e:  //Download request
      {
         if (rindex==0)
         {
            SWputchar(0x15);  //If there are no waveforms in device, return NAK
            break;
         }
         else
         {
            SW_index=1;
            do
            {
               do
               {
                  SW_crc=0x0000;
                  SW_read_eeprom(SW_index);
                  if (SW_index==rindex)
                     SW_Message[0]=(0x03);
                  else SW_Message[0]=(0x02);
                  SW_Message[1]=(SW_index);
                  SW_Message[2]=(0x2C);
                  SW_Message[3]=(0x00);
                  for (CRC_loop=4; CRC_loop<48; CRC_loop++)
                     SW_crc+=(long)(SW_message[CRC_loop]);
                  SW_message[48]=(SW_crc & 0xFF);
                  SW_message[49]=(SW_crc>>8);
                  for (i=0; i<50; i++)
                     SWputchar(SW_message[i]);
                  SW_char=SWgetch();   //Receive handshake
               }
               while (SW_char!=0x06);  //repeat sending until you receive ACK
               SW_index++;
            }
            while (SW_index<=rindex);
            break;
         }
      }
      case 0x1d:
      {
         SW_count=0;
         SWputchar(0x06);  //send ACK
         do
         {
            j=0;
            for (j=0; j<50; j++)
            {
               SW_message[j]=SWgetch();
            }
            SW_crc=0x0000;
            for (CRC_loop=4; CRC_loop<48; CRC_loop++)
               SW_crc+=(long) (SW_message[CRC_loop]);
            crc1=SW_crc & 0xFF;
            crc2=SW_crc>>8;
            if ((crc1==SW_message[48]) && (crc2==SW_message[49]))
            {
               CRC_test=1;
               start=(44*(long)SW_message[1])+2;
               for (i=0; i<20; i++)
                  write_ext_eeprom(start+i,SW_message[i+4]);
               start=start+20;
               for (i=0; i<24; i++)
                  write_ext_eeprom(start+i,SW_message[i+24]);
               SW_count++;
               write_ext_eeprom(1,SW_count);
               rindex=SW_count;
               SWputchar(0x06);  //send ACK
               delay_ms(10);
            }
            else
            {
               CRC_test=0;
               delay_ms(10);
               SWputchar(0x15);  //Send NAK
               delay_ms(10);
            }
           
           
         }
         while ((SW_message[0]==0x02) || (CRC_test==0));
         
         break;
      }
   }
   
}
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Thu Apr 01, 2004 7:45 pm     Reply with quote

Two short questions:
1. I can't find the definition for your loop variable j. Is it a global variable? Maybe it's being changed in an ISR or something?
2. Is watchdog enabled in your code? If so is it being kicked properly?
jonpaul



Joined: 10 Feb 2004
Posts: 7

View user's profile Send private message

PostPosted: Thu Apr 01, 2004 7:52 pm     Reply with quote

Good point. j is a global variable, declared at the same time as i actually.

Code:
static int i,j,temp,fixtemp;                    //temporary variables for loops, etc.


I'm pretty certain the WDT is disabled. But I don't recall actually directing that to happen except when I finally program the chip. The curious thing is that j won't reinitialize in the loop, but i does it fine. Twice actually, even when j fails. Oh and there is no ISR for the SW UART. It waits for a keyboard hit and then launches the code I pasted. And after the variable fails it exits the loop as it should and goes back to waiting for a key board hit. I'll just quote it for you:

Code:
#use RS232(BAUD = 9600, XMIT = PIN_D6, RCV = PIN_D7, PARITY = N, BITS = 8)

void SWputchar(char input)
{
   putchar(input);
}

char SWgetch()
{
   return (getch());
}

char SWkbhit()
{
   return (kbhit());
}

#use RS232(BAUD = 115200, XMIT = PIN_C6, RCV = PIN_C7, PARITY = N, BITS = 8)


And then later....

Code:
else if (current_state==12)
      {
        while (next_state==12)
         {
            if (SWkbhit())
               SW_Uart();
         }
        }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 01, 2004 9:26 pm     Reply with quote

Look at the symbol table in the .SYM file. Find the memory
address used by the j variable. Carefully examine the
other symbols to see if they also use this address.
They shouldn't, because it's a global variable, but it's
worth checking.

Also look at the variable that has an address just prior
to the one used by j. Is it an array ?
Is it possible that somewhere in your code, you're
over-running the end of the array and clobbering j ?

Or perhaps the variable just before j is a char, and
you're treating it as a word, somewhere in your code,
and thus over-writing j ?

------------------------

If nothing else works, get rid of the switch-case and
change it to a chain of if-elseif statements. This may
potentially solve the problem. (Based on historical
memory of weird problems with switch-case being
solved this way, in posts that I've seen on this board).

Also, what PIC are you using and what's your version of
the compiler ?
jonpaul



Joined: 10 Feb 2004
Posts: 7

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 4:28 pm     Reply with quote

I looked in the SYM file and j seems to be the only one at that address. The variable just before j is i, which is also a loop variable. And it seems to be fine.

From the sym file
    0D0 flash_id
    0D1 i
    0D2 j
    0D3 temp
    0D4 fixtemp


They are all chars. I'm currently using a pic16f77 with compiler version 3.118. I'm going to try changing to if statements this afternoon and see if that will fix things.....
jonpaul



Joined: 10 Feb 2004
Posts: 7

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 4:54 pm     Reply with quote

No joy. Sad Even with if else statements the j loop variable still won't initialize. Even changing it to i doesn't change the problem. The same behavior is exhibited. I just don't understand why it has this stuck at behavior. I can't even force it to 0 by explictly assigning it before the loop starts. Is it a bank problem? Except i initializes properly twice in succession in the same loop....... Man this is annoying.
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 5:07 pm     Reply with quote

Instead of a static global try a local variable for j (and i if you need to) and see if it works.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 5:11 pm     Reply with quote

I saw this happen once, a long time ago with vs. 2.xxx of the compiler.
An interrupt routine was re-using a memory location that was used
as a loop counter. I found it by studying the symbol table.

I wonder, can you absolutely guarantee that the problem is
due to 'j' not being initialized ? Or is this an assumption, based
on the symptoms ? Can you put a printf() statement in the loop,
or break on it with a debugger ?
jonpaul



Joined: 10 Feb 2004
Posts: 7

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 5:57 pm     Reply with quote

I am sure it is 'j' not being initialized. I'm running this on an MPLAB ICE 2000 debugger plugged into my target board. When I break right after the loop, 'j' is at 51, a value it should never attain. Of course that doesn't explain why the 0 value in the array does get updated when the 'j' value is 50 the second time it goes through the loop. But it seems from what I observe that it executes the statement within the loop once and then exits because 'j' isn't less than 50.

I've changed the variable to a local variable and that seems to fix the problem. I can read the packet out of the eeprom after transmitting and it is correct. Also I can send packets with a faulty CRC and it correctly flags it and lets me resend. It also works if I forcibly initialize 'j' after the loop finishes, but not if I do it before. Though it seems that my problem is fixed, I don't have a whole lot of confidence. I still don't know why it wasn't working and I am afraid it will rear its ugly head again.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 6:19 pm     Reply with quote

If possible, you should try it without the ICE. Program the PIC
with your original switch-case code, and see if the problem occurs
when it runs in stand-alone mode. This will tell you if the ICE
is causing the problem.
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Apr 02, 2004 8:10 pm     Reply with quote

Also, when you had defined j as static, did you look into the .LST file? Did it make sense?
I've had bad experience with CCS and static variables before.
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