fdevopen equivalent available?

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have some code that uses printf that I want to port to the EVK1100. I have a working interrupt/dma driven uart driver that I could use by changing all the code to use sprintf and then calling the write to uart routine.

It would be a lot nicer if I could tell printf to use a custom routine for stdout. I noticed that the 8 bit compiler had fdevopen which would allow that.

Does anyone know if there is something I could use for the AVR32 environment? I wonder where stdout actually goes by default??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

The easiest method is to redirect Newlib's USART streams to the appropriate UC3 USART:

#include
#include

...

{
/* Give the used CPU clock frequency to Newlib, so it can work properly. */
set_cpu_hz( configCPU_CLOCK_HZ );

/* Code section present if and only if the debug trace is activated. */
#if configDBG
{
static const gpio_map_t DBG_USART_GPIO_MAP =
{
{ configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION },
{ configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION }
};

/* Initialize the USART used for the debug trace with the configured parameters. */
set_usart_base( ( void * ) configDBG_USART );
gpio_enable_module( DBG_USART_GPIO_MAP,
sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[0] ) );
usart_init( configDBG_USART_BAUDRATE );
}
#endif
}

The most advanced solution is to redefine the following functions with custom versions without the weak attribute:

int __attribute__((weak))
_read (int file,
char * ptr,
int len){
int i;

if ( !do_not_use_oscall_coproc )
return _read_sim(file, ptr, len);

if (file != 0)
return unimplemented_syscall("_read with filedes != 0");

for ( i = 0; i < len; i++ ){
ptr[i] = (char)usart_getc();
}

return len;
}

/**
* Low-level write command.
* When newlib buffer is full or fflush is called, this will output
* data to correct location.
* 1 and 2 is stdout and stderr which goes to usart
* 3 is framebuffer
*/
int __attribute__((weak))
_write (int file,
char * ptr,
int len){
int i;

if ( !do_not_use_oscall_coproc )
return _write_sim(file, ptr, len);

if ( (file != 1)
&& (file != 2) && (file!=3))
return unimplemented_syscall("_write with file != 1 or 2");
/* if(file==3){
for(i = 0 ; i < len; i++){
avr32fb_putchar(ptr[i]);
}
} else */{
for ( i = 0; i < len; i++ ){
usart_putc(ptr[i]);
}
}

return len;
}

++
Ben

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the info!

I found that by default it has line buffering on which makes it hard to generate a prompt :)

I ended up starting with a printf ("\r\n") to force the call for the first time (stdout seems to point to a bunch of zeroes before the first use of printf) and then set it to non-buffered mode:

integer _write (integer file, pchar ptr, integer length)
begin
  FILE *pstdout ;

  pstdout = stdout ;
  pstdout->_flags = (pstdout->_flags and not __SLBF) or __SNBF ;
  serial_write (CONSOLE_UART, ptr, length) ;
  return length ;
end
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To configure standard I/O streams as unbuffered, you can simply:

setbuf(stdin, NULL);
setbuf(stdout, NULL);

It has to be executed once and for all.

++
Ben

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KaiBen wrote:
It has to be executed once and for all.

Thanks. That's what I was hoping I could do I just had no idea how.

Bob

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't understand how you are using the _read and _write routines in conjunction with printf. Could you please post the code linking these two features together? I'm trying to do something similar.