This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

sprintf()/_printfi() potential problem?

Other Parts Discussed in Thread: MSP430F5438

I'm writing a bit of code for the MSP430F5438 that's trying to validate a string.  I have my function validate_comms_msg(), which calls sprintf() to generate a string with a checksum that I then compare with the checksum included in the message to validate the message.  Fairly straight forward.

My problem is returning from my validate_comms_msg() function.  Somehow, when I return from my function, my program counter is going to the wrong place.

I've been pouring through the disassembly of my code for the past 4 hours, because I couldn't believe that this was happening.  I've finally almost tracked down WHERE it's happening, but I still don't understand why.

validate_comms_msg() calls, towards the end of the function, sprintf().  

 

C Code: 

char calcChecksum[2];

sprintf(calcChecksum, "%X", CalcUARTChecksum(Message, Length));

 

Assembly:

0x07F32:   411C 0006           MOV.W   0x0006(SP),R12

0x07F36:   411D 000A           MOV.W   0x000a(SP),R13

0x07F3A:   13B0 8F54           CALLA   #CalcUARTChecksum

0x07F3E:   40B1 99C8 0000      MOV.W   #0x99c8,0x0000(SP)

0x07F44:   4C81 0002           MOV.W   R12,0x0002(SP)

0x07F48:   01CC                MOVA    SP,R12

0x07F4A:   503C 0010           ADD.W   #0x0010,R12

0x07F4E:   13B0 9694           CALLA   #sprintf

 

 

This isn't the only time that it calls it, and in the previous instances, it appears to work fine.  However, for whatever reason, and I'm still not sure what that is, in this case, it doesn't quite work right.

Towards the end of sprintf(), somehow there's a call that is overwriting the location on the stack that contains my return address.  Until this call, my return address is 0x007660, which is correct.  However, when this assembly is called, my return address is changed to 0x007600, which is the wrong location, putting me almost at the beginning of my main().

 

 

0x096BC:   13B0 744C           CALLA   #_printfi

0x096C0:   411F 0006           MOV.W   0x0006(SP),R15

0x096C4:   43CF 0000           CLR.B   0x0000(R15)                              <- Problem happening here

0x096C8:   5231                ADD.W   #8,SP

0x096CA:   0110                RETA

 

 

As far as I can tell, something is happening to the stack during the call to _printfi that puts the address of the return address onto the stack at SP+6, which then is loaded into R15, and cleared via the CLR.B instruction.  However, I have no clue WHY this is happening, nor what to do about it.

What's the best way to figure out why this is happening?  And specifically why it's happening this time, but not (as far as I can see) any other time?  Is there any good way to wade through the _printf() disassembly?  Or has anyone experienced this before, and have a fix for it?  Is there another string handling routine I can use instead of sprintf?  I'm just calling the version included in stdio.h, which is the version that's included in the CCS include directory.

For references, I'm using CCS 4.2.3.00004 with the MSP430F5438.  I'll be happy to provide any other information, or snippets of code, memory dumps or any other information that might be needed to help figure out what's going on here.

Thanks,

Ian

  • Make sure you #include <stdio.h> .  If that isn't the issue, check out http://processors.wiki.ti.com/index.php/Tips_for_using_printf .

    Thanks and regards,

    -George 

  • I've made sure to include <stdio.h>.  Calling printf() isn't the problem - the disassembly is there.  It works fine in most cases.  It just happens that in this one case, it seems to cause problems with my return address on the stack.

    I'll take a look at that page for using printf(), but I'm not sure what even to look for on that page.  I've used sprintf() other times in my code without problems, it just seems to be this one, singular (but important) instance where it's doing something REALLY odd.

  • You can look at the source to the RTS yourself, it is in rtssrc.zip in the compiler's lib directory.

    The write at the end of sprintf is putting the NUL character at the end of the string that got created by _printfi.

    Make sure the buffer you are passing to sprintf is long enough to hold the formatted value plus the NUL character.   In fact... it is not.  Unless your checksum is always one hex digit, 2 chacters will not be enough.  Declare the array calcChecksum to be of at least size (sizeof(unsigned)*CHAR_BIT / 4 + 1), or 5 characters.

    Are you using the --printf_support option?  If so, what is value you are using for this option?

    What version of the compiler (not the CCS version) are you using?

  • Ah, yes, you might be right about the size of the checksum I'm returning.  I'll look into that - the code was ported from another system, and we didn't have any problems with it there, so I didn't think to check that possibility.

    I'm using full printf support.

    As for the compiler version, I'm not sure - where do I find that information?  I'm using the code limited version of CCS, downloaded no more than a month ago, so I suspect I'm probably using the full version, but I'm not entirely sure.