2009-10-15 11:52 PM
Retarget printf() on GCC / IDEaliST?
2011-05-17 03:55 AM
Hi,
I would like to retarget printf() to the uart. I have checked out the application note & example, and they don't work. I have tried defining the following three functions: int __io_putchar(int ch) int fputc(int ch, FILE *f) int _write(int file,char *ptr,int len) and none of them are called when I execute a printf() My dev tools are Anglia IDEaliST, which uses GCC. Any pointers gratefully received. Thanks, Chris.2011-05-17 03:55 AM
That doesn't work for me for some reason.... :(
Chris.2011-05-17 03:55 AM
Below is code found inside the FWLib examples. It works fine for printf() with me. I have no clue about scanf tho...
//////////////////////////////////////////////////////////////////// // Redirect fputc to the serial port, so printf() outputs to USART1. #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ /////////////////////////////////////////////////////////////////// /******************************************************************************* * Function Name : PUTCHAR_PROTOTYPE * Description : Retargets the C library printf function to the USART. * Input : None * Output : None * Return : None *******************************************************************************/ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART1, (u8) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; }2011-05-17 03:55 AM
This example works fine with RIDE 7. This is because RIDE has it's own printf. They call it small printf.
Did you try to change environment into RIDE 7. I used to work with Anglia but then I moved into RIDE. It is better, in my opinion, and it is free too.2011-05-17 03:55 AM
OK, sorted (with thanks to Spencer for some helpful clues).
The redirection required is _write_r(). This is my implementationCode:
int _write_r(void *reent, int fd, char *ptr, size_t len) { size_t i; for (i=0; i<len; i++) { uart_putc(ptr[i]); } return len; } However, newlib wasn't calling _write_r because malloc was failing. This turned out to be because the stack / heap was insufficient. Under these circumstances, newlib calls exit() which hangs up. So I changed the relevant part of my linker script to:Code:
_STACKSIZE = 8192; _HEAPSIZE = 512; and Bingo, it worked! I also decided to leave in a verbose version of _sbrk_r to give me warning if it hangs up for the same reason in the future:Code:
void exit(int n) { uart_puts(''exit()n''); while(1); } register char *stack_ptr asm (''sp''); caddr_t _sbrk_r(void *reent, size_t incr) { extern char end asm (''end''); // Defined by the linker //extern char end asm (''__heap_start__''); // Defined by the linker static char *heap_end; char *prev_heap_end; if( heap_end == NULL ) heap_end = &end; prev_heap_end = heap_end; if(( heap_end + incr ) > stack_ptr ) { /* Some of the libstdc++-v3 tests rely upon detecting out of memory errors, so do not abort here. */ //write( 1, ''sbrk: Heap and stack collisionn'', 32 ); //abort(); uart_puts(''HALT - heap exhaustedn''); exit(1); //errno = ENOMEM; return (caddr_t) -1; } heap_end += incr; return (caddr_t) prev_heap_end; } I hope this helps somebody else. Chris.2011-05-17 03:55 AM
Hi Chris,
Thanks for your post. Unfortunately, the same does not work for me. I get linker errors like this: ...libc.a uses FPA instructions, whereas Hello.elf does not. I use GCC version 4.4.1. I specify ''-mfpu=vfp'' in compiler options. Is that the reason? But aren't we supposed to use ''-mfpu=vfp'' for Cortex-M3 processors? Which processor do you use? And do you use ''-mfpu=vfp'' option? Regards, PramodQuote:
Quote:
Quote:
2011-05-17 03:55 AM
Option that you use is for floating point units. Something that Cortex-M3 doesn't have.
http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#ARM-Options2011-05-17 03:55 AM
I'm using IDEaliST, and the gcc command is:
main.c -mthumb -march=armv7-m -g -ffunction-sections -fdata-sections -Wall -O2 -Iinc -Iusb/inc -Ifat/inc -Ifat/conf -Ifat/inc/interfaces Chris.2011-05-17 03:55 AM
Hi,
Thanks Chris and slawcus. It seems that Chris is using ARM7, so it works. On the other hand, I am using Cortex-M3. slawcus, do you mean I should not use -mfpu=vfp ? I tried to change it to -mfpu=fpa because that is what the gcc library functions seem to use. After that, there were no errors, but some warnings: interworking not enabled. And the code does not work (no output). Perhaps -mfpu=vfp is the only choice for Cortex-M3. However, the gcc library is built with fpa option, so I can not link to it? If so, how can I get gcc library built for Cortex-M3 (i.e. with fpa option)? Regards, Pramod