3

I'm trying to print an integer into a string with snprintf for display on an OLED display from an ARM micro. However, when I use %d or %u the micro locks up and stops executing. Using %x or %c works fine, but the output isn't much use.

What could cause this behaviour? Unfortunately I don't have access to a JTAG device to debug. I'm using arm-none-eabi-gcc to compile and it's all running on a maple mini.

UPDATE

Passing values < 10 seems to make it work.

aliask
  • 133
  • 7
  • Are you pushing an `int` onto the stack? `%d` is larger than `%c`, so if you push a `char` then it will work with `%c` but crash with `%d`. Try specifying `(int)yourvariable` instead of `yourvariable` when calling `snprintf`. – ta.speot.is Oct 08 '11 at 10:20
  • 2
    @todda.speot.is: Incorrect. When passed to `printf`, `%d` and `%c` both specify the same type: `int`. – Dietrich Epp Oct 08 '11 at 10:21
  • Please show us the code using snprintf. – Roland Illig Oct 08 '11 at 11:02
  • Sure: `int sweeplo = 2412; char Menutext[21] = {0}; snprintf(Menutext, sizeof(Menutext), "Start: %X MHz", sweeplo);` – aliask Oct 08 '11 at 11:04
  • Sounds like the problem might be that division support isn't properly enabled (does division work elsewhere in your program?) – user786653 Oct 08 '11 at 12:42
  • I threw a divide in ("%d", sweeplo/1206) to test this theory, and it _kind of_ worked. The string was displayed correctly (output 2), but the micro crashed very shortly after (hard to tell exactly where it crashes with no JTAG). – aliask Oct 08 '11 at 13:07
  • The comments/answers focusing on division are probably on the right track. I suspect your compiler/linker are calling/linking the incorrect code for integer division. – R.. GitHub STOP HELPING ICE Oct 08 '11 at 13:29
  • @aliask: Are you sure that actually results in a division in the generated code? Check the disassembly for that code part and the relevant part of `snprintf` that does the division (which would be `stdio-common/_iota.c` in recent glibc versions IIRC). – user786653 Oct 08 '11 at 17:29

4 Answers4

2

This actually turned out to be a stack size issue with the RTOS that I was using. I guess the added complexity of the snprintf call was pushing it over the limit and crashing.

Thanks to all who took a crack at answering this!

aliask
  • 133
  • 7
1

Passing values < 10 seems to make it work.

This sounds to me as if you have a missing/non-working divide routine. printf/sprintf usually prints decimal numbers by successively dividing them by 10. For numbers less than 10 the division is not necessary and that's probably why it doesn't work.

To check, make a function which divides two variables (dividing by a constant is usually optimized into multiplication by the compiler). E.g.:

int t()
{
  volatile int a, b; // use volatile to prevent compiler optimizations
  a = 123;
  b = 10;
  return a/b;
};

Also, check your build log for link warnings.

Igor Skochinsky
  • 22,978
  • 1
  • 62
  • 101
0

It can't be a type error since %x and %u both specify the same types. So it has to be a problem in snprintf itself. The only major difference between the two is that %u has to divide integers and compute the remainder, whereas %x can get by with shifts and masks.

It is possible that your C library was compiled for a different variety of ARM processor than you are using, and perhaps it is using an illegal instruction to compute a quotient or remainder.

Make sure you are compiling your library for Cortex M3. E.g.,

gcc -mcpu=cortex-m3 ...
Dietrich Epp
  • 182,361
  • 34
  • 307
  • 387
  • -mcpu is already set as cortex-m3, and I agree about the type issue. I guessed there was some issue with snprintf but am surprised that something so basic isn't working properly on a common architecture like ARM. Surely I'm doing **something** wrong :P – aliask Oct 08 '11 at 10:50
0

Do you have a prototype in scope ? snprintf() is a varargs function, and calling a varargs may involve some trickery to get the arguments at the place where the function expects them.

Also: always use the proper types when calling a varargs function. (the one after the '%' is the type that snprintf() expects to find somewhere, 'somewhere' may even depend on the type. Anything goes...) in your case : "%X" expects an unsigned int. Give it to her, either by casting the parameter in the function call, or by using "unsigned int sweeplow;" when defining it. Negative frequencies or counts make no sense anyway.

wildplasser
  • 38,231
  • 6
  • 56
  • 94