3

* UPDATE *

Here is what I found. Whenever I had that function in there it wouldn't actually make the code lock up. It would actually make the read RTC I²C function very slow to execute, but the code would still run properly, but I had to wait a really long time to get past every time I read the RTC.

So there is an alarm interrupt for the RTC and this was triggering other I²C interactions inside the ISR, so it looks like it was trying to do two I²C communications at the same time, therefore slowing down the process. I removed the functions in the ISR and it's working now. I will keep investigating.


I am having this problem when programming an STM32F103 microcontroller using IAR 5.40. I have this function that if I try to printf a local variable it causes the code to freeze at another point way before it even gets to that function in question.

What could possibly be causing this?

This is the function:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string

  printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!

  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

I tried this as well and this does not cause the lock I experienced:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10);
  printf("index = 2\n");


  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

There is no optimization enabled whatsoever and the code gets stuck when trying to read a byte out of my I²C RTC, but as soon as I remove this printf("index = %s\n", bTmpSms); or use this one instead printf("index = 2\n"); then everything is happy. Any ideas?

The bSmsIndex will never be more than 30 actually and even then the lock up happens wayyyy before this function gets called.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jramirez
  • 8,537
  • 7
  • 33
  • 46

7 Answers7

2

char bTmpSms[3] only has space for "99". If your bSmsIndex is 100 or greater, you will be trying to write to memory that doesn't belong to you.


Edit after the update

I don't have a reference to itoa on my local machine, but I found this one ( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ ). According to that reference, the destination array MUST BE LONG ENOUGH FOR ANY POSSIBLE VALUE. Check your documentation: your specific itoa might be different.

Or use sprintf, snprintf, or some function described by the Standard.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • Correct, but it's not the write that's causing the issue (as the second code works). It's the printf reading the string that kills things. However, the write could cause a problem at some point too, so definately an issue too – The Archetypal Paul Oct 12 '10 at 18:39
  • @Paul - but who knows what the errant write might be trashing? – Michael Burr Oct 12 '10 at 18:43
  • 1
    As far as I'm concerned, writing to memory that doesn't belong to you, could make your program transfer money from your bank account to mine :-) – pmg Oct 12 '10 at 18:48
1

Some ideas:

If itoa() is not properly NUL-terminating the string, then the call to printf may result in the machine looking for the NUL forever.

pmg has a very good point.

Also, consider what type the first argument to itoa() is. If it's signed and you're passing in an unsigned integer, then you may be getting an unexpected minus sign in bTmpSms. Try using sprintf() instead.

Matt K
  • 13,370
  • 2
  • 32
  • 51
1

The change in code is moving the rest of your code around in memory. My guess is that some other part of the code, not listed here, is bashing some random location; in the first case that location contains something critical, in the second case it does not.

These are the worst kinds of problems to track down*. Good luck.

*Maybe not the worst - it could be worse if it were a race condition between multiple threads that only manifested itself once a week. Still not my favorite kind of bug.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

It seems that if I don't initialize the variable bTmpSms to something the problem occurs.

I also realized that it is not the printf that is the problem. It is the itoa function. It got me to check that even though I didn't think that was the problem, when I commented the itoa function then the whole code worked.

So I ended up doing this:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[4] = "aaa";    // I still need to find out why this is !!!

  itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string

  printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!

  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

This is the itoa function I got:

char itoa(int value, char* result, int base)
{
  // Check that the base if valid
  if (base < 2 || base > 36) {
      *result = '\0';
      return 0;
  }

  char* ptr = result, *ptr1 = result, tmp_char;
  int tmp_value;

  do
  {
    tmp_value = value;
    value /= base;
    *ptr++ = "zyxwvutsr

qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; } while (value);

  // Apply negative sign
  if (tmp_value < 0)
      *ptr++ = '-';
  *ptr-- = '\0';
  while(ptr1 < ptr)
  {
    tmp_char = *ptr;
    *ptr--= *ptr1;
    *ptr1++ = tmp_char;
  }
  return 1;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jramirez
  • 8,537
  • 7
  • 33
  • 46
  • See my answer. I don't think you fixed the problem, I think you masked it. It will come back to bite you later on. – Mark Ransom Oct 12 '10 at 21:21
  • I agree with you. thats why I said I will check this function later. but at least I know where the problem is for the most part. – jramirez Oct 12 '10 at 21:28
  • I hope I'm not misunderstanding you - it sounded like the problem manifests even before the `atoi` function is called, so the bug can't be there either. You don't *really* know where the problem is. – Mark Ransom Oct 12 '10 at 21:34
  • the problem only appears when the atoi function is in there. and no it does not get there. when the function is commented out the code runs correctly so that gives some ideas where the problemis , also I am going to use sprintf( bTmpSms, "%d", bSmsIndex ) which seems to be working. again is embedded programming so it will take me a little while to step through the code find where the problem really is I will update any progress – jramirez Oct 12 '10 at 21:46
0

What's the value of bSmsIndex?

If more than 99 it will be three digits when converted to a string. When zero terminated, it will be four characters, but you've allocated only three to bTmpSms so the null may get overwritten and the printf will try to print whatever is after bTmpSms until the next null. That could access anything, really.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
0

What's the value of bSmsIndex you're trying to print?

If it's greater than 99 then you're overrunning the bTmpSms array.

If that doesn't help, then use IAR's pretty good debugger - I'd drop into the assembly window at the point where printf() is being called and single step until things went into the weeds. That'll probably make clear what the problem is.

Or as a quick-n-dirty troubleshoot, try sizing the array to something large (maybe 8) and see what happens.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

Try to disassemble this area with index = 2 vs. index = %s.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
old_timer
  • 69,149
  • 8
  • 89
  • 168