I've the following snippet of code which I'm compiling on my IAR workbench.
// global declaration
float fval = 3.14f;
uint8_t uartTxBuffer [100];
void function(void)
{
memset(uartTxBuffer,'\0',sizeof(uartTxBuffer);
sprintf(uartTxBuffer,"\n\r Value is %f",fval);
UartWrite(uart, uartTxBuffer,strlen(uartTxBuffer));
}
The output is
Value is %f // and not 3.14
Can someone explain me what is the issue in my code?
Is it the Uartwrite function or am I making some mistake in using the C language?
I've tried the same code using printf on Keil MDK and it outputs the correct value on the serial terminal. So is this an IDE issue?
Can someone guide me here?
After a brief research this came up
https://www.iar.com/support/tech-notes/general/problems-with-printf-floating-point-f-on-arm/
The problem seems to be the byte alignment of the Stack Pointer.
Set a breakpoint on the sprintf() call and check the value of the stack pointer in the debugger.
Most of the answers I found are related to FreeRTOS ( which I don't know if you are using it):
sprintf breaking under new FreeRTOS
sprintf %f corrupts stack
sprintf in FreeRTOS
A common solution is to resort to
a third party library called printf-stdarg.c that provides a tiny print/sprintf/printf implementation for use in cases where the libraries that come with the compiler are just too big for small embedded use
I hope this might help
Related
I'm porting a code base to a new build environment and am running into this issue at link-time.
Error: L6915E: Library reports error: Heap was used, but no heap region was defined
The target is a 32-bit Arm Cortex R5. Not using malloc or free anywhere in the code base. In the past during a similar build environment port I had gotten past this issue by using microlib. No such luck this time though.
EDIT: Turns out I could have resolved the issue just by using microlib at compile-time. I thought I tried that when I had asked the question, but actually didn't.
Resolved the issue by re-targeting fputc and re-defining __stdout and __stdin.
The ARM C library implementation of fputc() seems to have been using malloc(), so after retargeting fputc to use my UART driver, there were no heap-accessing functions in my code.
struct __FILE { int handle; /* Add whatever you need here */};
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
}
I'm programming on a STM32F437. I'm using SafeRTOS. The compiler is GCC.
In one task I'm using snprintf() to prepare a string with values.
The problem is that the snprintf() fails to handle floating point numbers. It just ends the resulting string (with '\0') when it reaches any %f or %g in the formatting string.
But, and this is strange. The snprintf() in the task works with no problem if I add a dummy call to snprintf() in main() before starting the RTOS.
The dummy call:
char dummy[20];
snprintf(dummy, sizeof(dummy), "%g", 3.14159);
I found a similar solution here
But no answer why it works.
Any ideas what is going on?
The printf library in some small implementations does not include floating point support. Perhaps the dummy call is somehow causing a more complete (and larger) library to be used?
The dummy call may be optimized away by compiler. As you are printing only constant. Try to look in disassembly or try to compile it with -O0 flag set.
Float support in general tends to be large, especially on platforms without hardware FPU available where all computing operation have to be done by calls to the library. So many standard libraries just omit it unless you explicitly specify that you want it enabled.
I'm trying out some old code frome the book "Black art of 3d game programming". I know it is outdated but I started reading it and it's kind of fun and interesting. I downloaded the OpenWatcom C Compiler and made a new DOS Project in order to get this old code even compiled. I already compiled on piece of code where Videomode int13h is set and then I was able to draw pixels to the screen. But this was done with a C function called _setvideomode(). In the following example the videomode is set via the _int86 function which makes the interrupt call and the prototype should be in bios.h, but OpenWatcom says: No prototype found for function _int86. I am stuck now and don't know what to do ;) Here is the code:
void setGraphxMode(int mode){
union REGS inregs,outregs;
inregs.h.ah = 0;
inregs.h.al = (unsigned char)mode;
_int86(0x10,&inregs,&outregs);
}
int main(){
return 0;
}
Would appreciate any advise on this and yes I know: Graphics are done via DirectX or OpenGL these days. This is just for learning purpose! Thank you :)
Under OpenWatcom the call you are looking for is int386 I believe:
int386(0x10, &inregs, &outregs);
I am not getting answers on the AVR Freaks forum and wonder if someone here could help me.
The answer might lie in this SO question, but I am not sure why it would be necessary.
Basically, I have my fist ever Atmel project (AVR studio 6, UC3 processor). The code compiles and links and I can load it to the Atmel board and step through in the debugger.
However, when I try to step over (or run until a breakpoint on the line after) a (valid) call to sprintf(), malloc() or memcpy() (there may be more, which I have not yet discovered), the IDE never returns to the next line of my code, just seeming to hang, or run forever.
[Note] Compiler optimization is off
Do I need to set some linker options (e.g link static (which I tried & it didn't help)? Or build with some library?
What confuses me is that the code compilers and links - what is being linked when I call these standard functions? If I need something else I would expect a compiler or linker error, but get none - so why won't my code run?
Sorry for such a stupid n00nb question, but it is my first micro-controller project.
I discovered that the CPU on my board is an Engineering Sample and not supported by Atmel Studio without a new io.h file.
I sort of figured that out from this question: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=106652
Sorry to have troubled you.
what is being linked when I call these standard functions?
The AVR-libc, the implementation of the C standard library ported to the AVR platform.
so why won't my code run?
Compiler errors and runtime errors are not even related. Both of these lines are valid C and they compile, however, on most systems, I'd expect them to dump core:
int x = 1 / 0;
*(int *)0 = 41;
So it might be either:
a bug in the standard library (very unlikely), or
a bug in the online debugger (very unlikely), or
maybe you just expect something that is not supposed to happen?
Instead of trying to step over, what happens if you set a breakpoint at next line after the line you want to step over?
Also, does the operation change if you turn off compiler optimization?
I seem to be having a problem with a macro that I have defined in a C program.
I compile this software and run it sucessfully with the MIPS compiler.
It builds OK but throws the error "Segmentation fault" at runtime when using icc.
I compiled both of these on 64 bit architectures (MIPS on SGI, with -64 flag and icc on an intel platform).
Is there some magic switch I need to use to make this work correctly on both system? I turned on warnings for the intel compiler, and EVERY one of the places in my program where a macro is invoked throws a warning. Usually something along the lines of mismatched types on the macro's parameters (int to char *) or some such thing.
Here is the offending macro
#define DEBUG_ENTER(name) {tdepth++;
if(tnames[tdepth] == NULL) tnames[tdepth] = memalign(8, sizeof(char)*MAXLEN);
strcopy(tnames[tdepth],name);
FU_DEBUG("Entering \n");}
This basically is used for debugging - printing to a log file with a set number of tabs in based on how many function calls there are. (tdepth = tab depth)
I did some checking around in man pages. it seems like memalign is only supported on IRIX. This may be my problem. I am going to track it down.
This might have to do with the system's "endianness." Looking here it seems that MIPS has switchable endianness. I'm not sure if you are using the correct endianness already, but if you aren't, you will DEFINATELY have problems.
This might be a byte order issue. MIPS can be big endian but intel is little endian.
It sounds like the array tnames is an array of int. If you're assigning pointers to it, it should be an array of a pointer type - in this case probably char * is appropriate.
(Also, strcopy() isn't a standard function - are you sure you don't mean strcpy()?)