Worrying Weirdness

Moderator: Benj

jethronull
Posts: 30
Joined: Tue Dec 04, 2012 4:03 am
Has thanked: 1 time
Contact:

Worrying Weirdness

Postby jethronull » Thu Apr 18, 2013 8:27 pm

I got past all the RS232 weirdness and my project has grown greatly without issue. I took Ben's advice and stripped as much code as I can out of the RS232 interrupts. That worked well. Much time past without issue but today I found a new gremlin, or maybe it's the same old one. With some very minor changes (just tidying up unused variables) my RS232 output started to be corrupt. After looking at all the sensible thing I started to put back the variables. I found one string variable whose presence dictates whether the code works or not. With it, it works, without, it doesn't. This variable is not being used anywhere. It is just declared[20] and set to "". It does not matter if I change the name but it stops working if it is too big [200] or too small [2]. I can also change it to a ULONG and it still works but smaller vars do not. Obviously this is something to do with the stack or space it consumes but I still have about 25% free ram, lots of rom and about half the heap left. I am not assuming this is RS232 related this time. I have a routine that converts ASCII encoded hex to an int to be transmitted via SendRS232Char and that routine seems to be where things go wrong (the output top 4 bits are varied, though not correct, but the bottom 4 bits are stuck stuck at 8. I suspect this routine because it creates a byte from two ascii hex chars). The routine has worked just fine for weeks. Having something flaky like this happening without having a solid cause and effect worries me for the reliability of my code. I'd really like to get to the bottom of it. Oh, and the code compiles fine, just the usual
Serious Warning: Possible sw stack corruption, function 'delay_us' called by more than one asynchronous thread (main/Task, interrupt, interrupt low)
which I don't know how to avoid.

Due to IP concerns I cannot attach the whole program anymore, but here is the routine that I suspect falls over with and without the var:

Code: Select all

MX_UINT8 FCM_Hex2Int(MX_CHAR* PFCL_HEX2_INT_STR)
{
   //Local variable definitions
   MX_UINT8 FCL_LENGTH;
   MX_UINT8 FCL_COUNT = (0x0);
   MX_UINT8 FCL_INT_VALUE = (0x0);
   MX_UINT8 FCL_INT_CONVERSION = (0x0);
   MX_UINT8 FCL_INT_VAR = (0x0);
   MX_UINT8 FCL_INDEX = (0x0);


   #define FC_SZ_HEX2_INT_STR 20
   MX_UINT8 FCL_HEX2_INT_STR[FC_SZ_HEX2_INT_STR];
   FCI_CONCATENATE(PFCL_HEX2_INT_STR,FC_SZ_HEX2_INT_STR,"",0,FCL_HEX2_INT_STR,FC_SZ_HEX2_INT_STR);
   MX_UINT8 FCR_RETVAL;

   //String Manipulation
   //Calculation:
   //  .length = Length$ (.hex2_int_str)
   FCL_LENGTH = FCI_GETLENGTH(FCL_HEX2_INT_STR, FC_SZ_HEX2_INT_STR);

   //Calculation
   //Calculation:
   //  .count = 0
   //  .int_value = 0
   //  .int_conversion = 0
   FCL_COUNT = 0;
   FCL_INT_VALUE = 0;
   FCL_INT_CONVERSION = 0;

   //Loop
   //Loop: While .count < .length
   while (1)
   {

      //Calculation
      //Calculation:
      //  .int_var = (.length - .count) - 1
      FCL_INT_VAR = (FCL_LENGTH - FCL_COUNT) - 1;

      //Calculation
      //Calculation:
      //  .index = (.length - .count) - 1
      //  .int_var = .hex2_int_str[.index]
      FCL_INDEX = (FCL_LENGTH - FCL_COUNT) - 1;
      FCL_INT_VAR = FCL_HEX2_INT_STR[FCL_INDEX];

      //Decision
      //Decision: .int_var > 64?
      if (FCL_INT_VAR > 64)
      {

         //Calculation
         //Calculation:
         //  .int_var = .int_var - 55
         FCL_INT_VAR = FCL_INT_VAR - 55;

      } else {

         //Calculation
         //Calculation:
         //  .int_var = .int_var - 48
         FCL_INT_VAR = FCL_INT_VAR - 48;

      }

      //Calculation
      //Calculation:
      //  .int_value = .int_var << .count * 4
      //  .int_conversion = .int_conversion + .int_value
      FCL_INT_VALUE = FCL_INT_VAR << FCL_COUNT * 4;
      FCL_INT_CONVERSION = FCL_INT_CONVERSION + FCL_INT_VALUE;

      //Calculation
      //Calculation:
      //  .count = .count + 1
      FCL_COUNT = FCL_COUNT + 1;


      if ((FCL_COUNT < FCL_LENGTH) == 0) break;
   }

   //Calculation
   //Calculation:
   //  .Return = .int_conversion
   FCR_RETVAL = FCL_INT_CONVERSION;

   return (FCR_RETVAL);
   //Local variable definitions
   #undef FC_SZ_HEX2_INT_STR

}



Any ideas?

TIA
Jon/JethroNull

User avatar
JonnyW
Posts: 1230
Joined: Fri Oct 29, 2010 9:13 am
Location: Matrix Multimedia Ltd
Has thanked: 64 times
Been thanked: 306 times
Contact:

Re: Worrying Weirdness

Postby JonnyW » Thu Apr 18, 2013 11:32 pm

Hello. Without seeing your program it is difficult to diagnose.

Best guess, there is an array, probably a string, immediately before your 'padding' variable in memory. Something in the program is overwriting the end of this variable by more than 2 bytes. This causes other data to be corrupt which causes the strange behaviour.

At any point, if you set the padding variable to an initial value does its value change? If so, what to - does that give any clues as to what is overwriting it?

I can not see any problems off-hand with your posted routine that would cause a corruption of memory.

Jonny

jethronull
Posts: 30
Joined: Tue Dec 04, 2012 4:03 am
Has thanked: 1 time
Contact:

Re: Worrying Weirdness

Postby jethronull » Fri Apr 19, 2013 8:13 am

Jonny,

You got it! I found a string variable that was set to only 2 bytes long and which was actually used just prior to passing data to the routine I sent you. I just set it to 20 chars long and the problem went away (I could delete the padding variable). But I am curious as to how it overran:

Code: Select all

Byte_To_Send = Mid$ (Packet_To_Send_Str, .loop,2)
Val_To_Send = Hex2Int (Byte_To_Send)
.loop = .loop + 2


The lengthened string was Byte_To_Send. As far as I can see it could only ever get two bytes. It's not a problem anymore, I have room to set it to 20 (or whatever it really needs), I'm just curious as to why it could overrun.

But thanks a lot. I feel much better :)
Jon/JethroNull

kersing
Valued Contributor
Valued Contributor
Posts: 1873
Joined: Wed Aug 27, 2008 10:31 pm
Location: Netherlands
Has thanked: 530 times
Been thanked: 1040 times
Contact:

Re: Worrying Weirdness

Postby kersing » Fri Apr 19, 2013 9:42 am

jethronull wrote:The lengthened string was Byte_To_Send. As far as I can see it could only ever get two bytes. It's not a problem anymore, I have room to set it to 20 (or whatever it really needs), I'm just curious as to why it could overrun.


In C a string is terminated with a zero byte (0x00). If you want a string to contain N bytes you need to allocate N+1 bytes. In your case that means you need to allocate 2+1= 3 bytes.
“Integrity is doing the right thing, even when no one is watching.”

― C.S. Lewis

jethronull
Posts: 30
Joined: Tue Dec 04, 2012 4:03 am
Has thanked: 1 time
Contact:

Re: Worrying Weirdness

Postby jethronull » Fri Apr 19, 2013 4:07 pm

Thanks Kersing. That is probably it, though I had assumed Flowcode took care of that. It seems to in other instances. Anyway, I'll give all my strings at least one extra byte to be on the safe side. Thanks!
Jon/JethroNull

User avatar
Benj
Matrix Staff
Posts: 14151
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4330 times
Been thanked: 4080 times
Contact:

Re: Worrying Weirdness

Postby Benj » Fri Apr 19, 2013 4:30 pm

Your right the null termination does help as a sanity check but Flowcode shouldn't need this to do it's job when a string is filled with data as when a string is passed as a function the length of the string is also passed. We end the string by reaching a 0 null data byte or the end of the string.

So it sounds like there is a bug in the hex2int function. I will have a look and see if it is easily fixable. Do you know if the problem exists in simulation or on hardware or both? Not much I can do about the simulation.

jethronull
Posts: 30
Joined: Tue Dec 04, 2012 4:03 am
Has thanked: 1 time
Contact:

Re: Worrying Weirdness

Postby jethronull » Fri Apr 19, 2013 7:22 pm

Hi Ben,

My project is so wrapped up in external data sources, interfaces and so on it is not easy to simulate anymore, even with VNet (if you added a means to feed serial data in and out of the simulation from the PC serial port so that the simulation can talk to real world devices - that would be simply fantastic!). But I tried a quick experiment just isolating the hex2int function. I could not reproduce the error, but then I am far from sure that it was taking all factors into account. If necessary I can send you the whole fcf but I can't post it on the forum for IPR reasons. Just give me a direct email address. Hey, while you are looking at my hex2int routine could you give me a critique on it? I suspect there is a simpler way of doing this.

Thanks for all you guys excellent help, as always.

Jon
Jon/JethroNull

jethronull
Posts: 30
Joined: Tue Dec 04, 2012 4:03 am
Has thanked: 1 time
Contact:

Re: Worrying Weirdness

Postby jethronull » Wed Apr 24, 2013 12:54 am

Ben,

Any luck finding a bug in my hex2int function?

Jon
Jon/JethroNull