cancel
Showing results for 
Search instead for 
Did you mean: 

Retarget printf() on GCC / IDEaliST?

ccowdery9
Associate III
Posted on October 16, 2009 at 08:52

Retarget printf() on GCC / IDEaliST?

12 REPLIES 12
ccowdery9
Associate III
Posted on May 17, 2011 at 12:55

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.

ccowdery9
Associate III
Posted on May 17, 2011 at 12:55

That doesn't work for me for some reason.... :(

Chris.

relaxe
Associate II
Posted on May 17, 2011 at 12:55

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;

}

jaroslaw2
Associate II
Posted on May 17, 2011 at 12:55

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.

ccowdery9
Associate III
Posted on May 17, 2011 at 12:55

OK, sorted (with thanks to Spencer for some helpful clues).

The redirection required is _write_r(). This is my implementation

Code:

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.

pramod
Associate II
Posted on May 17, 2011 at 12:55

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,

Pramod

Quote:

Quote:

Quote:

slawcus
Associate II
Posted on May 17, 2011 at 12:55

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-Options

ccowdery9
Associate III
Posted on May 17, 2011 at 12:55

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.

pramod
Associate II
Posted on May 17, 2011 at 12:55

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