Jump to content
43oh

sprintf weirdness on cc3200


Recommended Posts

I have a large sketch in Energia for the CC3200 LaunchXL. Sometimes sprintf does weird things.

For example,this code...

  char buffer[500];
  sprintf(buffer, "%f, %f, %f, %d", 1.0, 2.0, 3.0, 4);
  Serial.println(buffer);
 

sometimes produces this result:

0.000000, 0.000000, 0.000000, 536966100

 

This looks incorrect to me. There seems to be a pretty significant bug in the Energia+CC3200 implementation of sprintf. It seems that the size of global variables or maybe the stack might be an influencing factor, but I really can't figure it out.

 

Any ideas for how to fix this?

 

(Note: cross-posted here: https://e2e.ti.com/support/wireless_connectivity/simplelink_wifi_cc31xx_cc32xx/f/968/t/563841)

Link to post
Share on other sites

I have a large sketch in Energia for the CC3200 LaunchXL. Sometimes sprintf does weird things.

For example,this code...

  char buffer[500];
  sprintf(buffer, "%f, %f, %f, %d", 1.0, 2.0, 3.0, 4);
  Serial.println(buffer);
 

sometimes produces this result:

0.000000, 0.000000, 0.000000, 536966100

 

This looks incorrect to me. There seems to be a pretty significant bug in the Energia+CC3200 implementation of sprintf. It seems that the size of global variables or maybe the stack might be an influencing factor, but I really can't figure it out.

 

Any ideas for how to fix this?

 

(Note: cross-posted here: https://e2e.ti.com/support/wireless_connectivity/simplelink_wifi_cc31xx_cc32xx/f/968/t/563841)

Hello . . .

 

So first thing off. Your buffer is too large. This isn't Windows, or even Linux. This is an embedded device where memory is at a premium. Now, perhaps 500 chars( or bytes ) may not be too much, but still far from necessary. reduce its size to ~100.

 

Second off, you should zero out your buffer before you use it. Use memset() or at initialization assign the value of {0} like so:

char buffer[100] = {0};

Thirdly, don't use sprintf(), use snprintf() if available. It's much safer. However if you're dead set on using sprintf(). Check the return value. You're not checking the return value in your code, so for all intents, and purposes. Your code will fail silently.

 

Lastly, float types can sometimes behave very oddly if you're not careful how they're initialized, or used. Sometimes even just adding an 'f' at the end of a value can help. Post-fixing the type, but that's not strictly speaking, necessary.

Link to post
Share on other sites

Ok, sorry, was a bit busy( multitasking ) so left out some information.

 

So, what I mentioned above may, or may not solve your problem. But it would help mitigate problems. It may very well be that sprintf() is not implemented correctly in Energia. With that in mind, do realize that Energia is based on Arduino's wiring, which also makes heavy use of C++. So it may be prudent that "we" use C++ strings, which can be much safer when used.

 

EDIT:

 

Additionally to what I mentioned above. It may be a good thing if you posted all your code so we can see exactly what you're doing.

Link to post
Share on other sites

Thanks for the reply. I have tried all of the following things:

  • Use smaller buffer - I've tried various sizes. The original "real" code was using a longer string with more numbers, but even this shorter version showed the problem.
  • Initialize to zeros - I think this shouldn't be necessary for sprintf or snprintf, but it didn't help.
  • Use snprintf - Actually, I was using snprintf originally, but I changed back to sprintf to simplify the description of the problem.

 

Using Strings instead of sprintf or snprintf sometimes this produces better results, but sometimes it produces very similar results. Below is an example of the code modified to use Strings. At the moment I can't post all of my code, because it contains proprietary IP and I don't have a version that replicates the results in a clean environment. I'm not sure what causes the problem. I think it might be related to memory (heap or stack space) because I'm using WiFi and SLFS, but I'd expect some sort of error instead of strange results.

 

I guess my next step will be to try optimizing the code to reduce memory usage and see if that helps.

 

Anyway, here's a code snippet that shows what I get if I use String instead of snprintf. Note that this same snippet of code works fine when it is part of a smaller sketch.

 

Code:

  float a = 1.0f;
  float b = 2.0f;
  float c = 3.0f;
  int d = 4;
  Serial.println(a);
  Serial.println(b );
  Serial.println(c );
  Serial.println(d);
  String s = String("______________") + String(a)
      + "______:" + String(b )
      + "______" + String(c )
      + "______" + String(d)
      + "______" + String(a)
      + "______" + String(d)
      + "______\r\n\r\n";
  Serial.println(s);

 

Output:

1.00
2.00
3.00
4
______________0.00______0.00______0.00______4______0.00______4______
Link to post
Share on other sites

I refactored my code to reduce global memory usage significantly, and I'm still getting weird results from snprintf (and sprintf) as well as the String class. Sometimes the numbers it prints are "0" and sometimes they contain garbage values.

 

Even though these code snippets that show the problem exist in the context of other (proprietary) code, I don't see how the other code could cause problems, other then maybe by using too much memory. This system isn't multi-threaded, so I don't think there's any way for other code to modify memory between statements.

Link to post
Share on other sites

I refactored my code to reduce global memory usage significantly, and I'm still getting weird results from snprintf (and sprintf) as well as the String class. Sometimes the numbers it prints are "0" and sometimes they contain garbage values.

 

Even though these code snippets that show the problem exist in the context of other (proprietary) code, I don't see how the other code could cause problems, other then maybe by using too much memory. This system isn't multi-threaded, so I don't think there's any way for other code to modify memory between statements.

Sounds like println() has gone wonky.

 

Can you override the numerical base value ? e.g.

Serial.println(value, 10);

To make sure it prints the values in base 10 format ?

 

EDIT:

 

Actually, the second parameter for the float / double type override is number of digits it seems. So . . . base type is irrelevant. But anyway, you could try using a double instead of a float, but they both look to use identical functions.

Link to post
Share on other sites

One thing I found rather interesting is that there is a difference between print.cpp for the MSP430, versus the CC3200 processor cores. print.cpp for the cc3200 is 52 lines longer. I honestly have no idea of the differences between these two processors where the serial interface is concerned but this line count differences bothers me for two reasons. At least off the top of my head.

 

  1. print.cpp in my mind should not contain any hardware specific implementation, That should be done in some sort of hardware abstraction library.
  2. It should just be standard number to string manipulation, so why the difference period ?

EDIT:

https://github.com/energia/Energia/blob/master/hardware/msp430/cores/msp430/Print.cpp

 

versus

 

https://github.com/energia/Energia/blob/master/hardware/cc3200/cores/cc3200/Print.cpp

Link to post
Share on other sites

Running diff between the two versions of print.cpp outputs a ton of differences. Nearly 500 lines.

 

EDIT:

 

Ah, my text editor messed up on the first pastebin, so the second one is closer to real. I did modify the MSP430 file a little to remove a couple of linefeeds in the beginning of the file. So the comment "header", and includes didn't throw off the whole diff process.

 

http://pastebin.com/Rw1e3yW6

 

http://pastebin.com/ss8TcHpp

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...