printf_P(PSTR("test\n\r") gives rubbish when not u

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

Hi,

A printf_P(PSTR("test\n\r") give rubbish output:

Part of the code:

//#include
#include
#include
#include "i2c.h"
#include "uart.h"

int main()
{
uart_init();
fdevopen(uart_putchar,uart_getchar);
printf_P(PSTR("test\n\r"));

gives rubbish on my securecrt terminal (rs232 terminal - better than hyperterminal).

It also gives 5 warnings:
../Main.c:18: warning: implicit declaration of function `printf_P'
../Main.c:19: warning: implicit declaration of function `scanf'
../Main.c:55: warning: implicit declaration of function `printf'
../Main.c:77: warning: implicit declaration of function `fdevopen'
../uart.c:143: warning: implicit declaration of function `defined'

Now if I add the stdio.h to the code it works. Now with only 3 warnings:
../Main.c:77: warning: passing arg 1 of `fdevopen' from incompatible pointer type
../Main.c:77: warning: passing arg 2 of `fdevopen' from incompatible pointer type
../uart.c:143: warning: implicit declaration of function `defined'

So what is going on here? I do not get it. Why does it compile without stdio.h and what does the implicit declaration mean? So I'm still have a few warnings. What do these warnings mean?

Any idea's?

Nick

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

Quote:
what does the implicit declaration mean?

It means that it could not find the declaration of the function (since the declaration is contained in the stdio.h file).

Quote:
../Main.c:77: warning: passing arg 1 of `fdevopen' from incompatible pointer type
../Main.c:77: warning: passing arg 2 of `fdevopen' from incompatible pointer type

The fdevopen function is expecting certain parameter types being passed in. Obviously your definition of uart_putchar and uart_getchar are different from what the function wants.

Regards,
Steve A.

The Board helps those that help themselves.

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

yeah let us see your uart_putchar and uart_getchar

i use

uint8_t uart_tx(uint8_t uart_tx) {
	while(!(UCSRA & _BV(UDRE)));
	UDR = uart_tx;
	return 0;
}

uint8_t uart_rx(void) {
	while(!(UCSRA & _BV(RXC)));
	return UDR;                   
}

FILE * stdio_dev;
	stdio_dev = fdevopen(uart_tx, uart_rx);

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

Allright,

Since the uart software (from Jesper Hansen) is public domain I include it here.
I've changed it a bit for an Atmega 644. Also the h file is changed a bit (for use with a 18.432 MHz xtal and for correct baud rate selection)

/*

**
** Copyright (C) 2006 Jesper Hansen
**
**
** Simple uart functionality
**
** File uart.c
**
*************************************************************************
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*************************************************************************/

/** \file uart.c
Simple uart functionality
*/

#include
#include
#include
#include "uart.h"

#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || \
defined(__AVR_ATmega32__) || defined(__AVR_ATmega8515__) || \
defined(__AVR_ATmega8535__) || defined(__AVR_ATmega323__)
//
// Single USART devices
//
#define ATMEGA_USART
#define UART0_UBRR_HIGH UBRRH
#define UART0_UBRR_LOW UBRRL
#define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
#define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE

#elif defined(__AVR_ATmega644__)

#define ATMEGA_USART0
#define UART0_UBRR_HIGH UBRR0H
#define UART0_UBRR_LOW UBRR0L
#define UART0_RECEIVE_INTERRUPT SIG_USART_RECV
#define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0

#elif defined(__AVR_ATmega162__) || \
defined(__AVR_ATmega64__) || \
defined(__AVR_ATmega128__)
//
// Dual USART devices
//
#define ATMEGA_USART0
#define UART0_UBRR_HIGH UBRR0H
#define UART0_UBRR_LOW UBRR0L
#define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV
#define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROL2 UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0

#define ATMEGA_USART1
#define UART1_UBRR_HIGH UBRR1H
#define UART1_UBRR_LOW UBRR1L
#define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV
#define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_CONTROL2 UCSR1C
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1

#else
//
// unsupported type
//
#error "Processor type not supported in uart.c !"
#endif

//
// size of receive ring buffer
//
#define BUFFER_SIZE 16 //!< Size of receive ringbuffer

uint8_t uart_ring[BUFFER_SIZE]; //!< Receive ringbuffer data space
volatile uint8_t ring_in; //!< Receive ringbuffer input index
volatile uint8_t ring_out; //!< Receive ringbuffer output index

/*
uint8_t bytes_in_ring(void)
{
if (ring_in > ring_out)
return (ring_in - ring_out);
else if (ring_out > ring_in)
return (BUFFER_SIZE - (ring_out - ring_in));
else
return 0;
}
*/

/** UART Receive Complete Interrupt Function.
*/
SIGNAL(UART0_RECEIVE_INTERRUPT)
{
uart_ring[ring_in] = UART0_DATA;
ring_in = (ring_in + 1) % BUFFER_SIZE;
}

/** Init UART.
Setup I/O ports and interrups for the serial link
*/
void uart_init(void)
{
ring_in = 0;
ring_out = 0;

// set default baud rate
:oops: UART0_UBRR_HIGH = UART_BAUD_SELECT >> 8;
UART0_UBRR_LOW = UART_BAUD_SELECT;

#if defined (ATMEGA_USART)
// enable receive, transmit and ensable receive interrupts
UART0_CONTROL = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
// set default format, asynch, n,8,1
#ifdef URSEL
UCSRC = (1<<URSEL)|(3<<UCSZ0);
#else
UCSRC = (3<<UCSZ0);
#endif

#elif defined (ATMEGA_USART0 )
// enable receive, transmit and ensable receive interrupts
UART0_CONTROL = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
// set default format, asynch, n,8,1
/* #ifdef URSEL0
UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
#else
UCSR0C = (3<<UCSZ00);
#endif
*/
#endif

// enable interrupts
sei();
}

/** Set Communications Speed.
\param speed Communications speed to set

Deze routine is blijkbaar niet nodig!!!

void uart_setspeeed(uint16_t speed)
{
uint16_t temp = (uint16_t) ((uint32_t) F_CPU / (((uint32_t) speed * 16L) - 1));

// set baud rate
UART0_UBRR_HIGH = temp >> 8;
UART0_UBRR_LOW = temp;
}

*/

/** Receive a character.
Get a character from the communications line.
Will block if no character is available.
\return Received character
*/
int uart_getchar(void)
{
int c;
while( ring_in == ring_out); // block waiting

c = uart_ring[ring_out];
ring_out = (ring_out + 1) % BUFFER_SIZE;

return c;
}

/** Check for available data.
Check if any character is ready in the receive buffer
\return Non-zero if character is available
*/
uint8_t uart_haschar(void)
{
return (ring_in != ring_out);
}

/** Send a character.
Transmit a character on the communications line.
\param data Character to send
\return Copy of transmitted character.
*/
int uart_putchar(char data)
{
#if defined (ATMEGA_USART)
while ( !(UART0_STATUS & (1<<UDRE)) ); // wait for free space in buffer
#else
while ( !(UART0_STATUS & (1<<UDRE0)) ); // wait for free space in buffer
#endif
UART0_DATA = data; // send byte
return data;
}

****************************************************************************************************************************************************************************************

The compiler gives a warning (../uart.c:141: warning: implicit declaration of function `defined') at this line: :oops: UART0_UBRR_HIGH = UART_BAUD_SELECT >> 8;

Here is the uart.h file:

/** \file uart.h
Simple uart functionality
*/

#ifndef __UART_H__
#define __UART_H__

#include

// requires the constant F_CPU to be set to the frequency of the CPU crystal
#if !defined F_CPU
#error Constant F_CPU not set !
#endif

//
// UART Default Baud rate calculation
//
#define UART_BAUD_RATE 115200
// #define U2X 0 // not using u2x
// u2x0 for atmega644
#define USING_U2X0 (F_CPU < 2000000ul && defined(U2X0))
#define BAUD_DIV (USING_U2X0? 8: 16)

#define UART_BAUD_SELECT (((F_CPU + (UART_BAUD_RATE) * (BAUD_DIV / 2)) / ((UART_BAUD_RATE) * BAUD_DIV) - 1))

/** Check for available data.
Check if any character is ready in the receive buffer
\return Non-zero if character is available
*/
uint8_t uart_haschar( void );

/** Init UART.
Setup I/O ports and interrups for the serial link
*/
void uart_init( void );

/** Set Communications Speed.
\param speed Communications speed to set
*/
void uart_setspeed( uint16_t speed );

/** Receive a character.
Get a character from the communications line.
Will block if no character is available.
\return Received character
*/
int uart_getchar( void );

/** Send a character.
Transmit a character on the communications line.
\param data Character to send
\return Copy of transmitted character.
*/
int uart_putchar( char data );

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/** Receive a character.
Get a character from the communications line.
Will block if no character is available.
\return Received character
*/
int uart_getchar(void)
{
int c;
while( ring_in == ring_out); // block waiting

c = uart_ring[ring_out];
ring_out = (ring_out + 1) % BUFFER_SIZE;

return c;
}
/** Send a character.
Transmit a character on the communications line.
\param data Character to send
\return Copy of transmitted character.
*/
int uart_putchar(char data)
{
#if defined (ATMEGA_USART)
while ( !(UART0_STATUS & (1<<UDRE)) ); // wait for free space in buffer
#else
while ( !(UART0_STATUS & (1<<UDRE0)) ); // wait for free space in buffer
#endif
UART0_DATA = data; // send byte
return data;
} 

These functions are the problem.

They were written to interface with an out-of-date version of avr-libc. Since avr-libc version 1.4, the argument list required of stream driver functions has changed.

See the avr-libc manual for details -- if you read the whole section of the manual, it should be clear what you need to change in these functions to make them compatible with the new API.

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

> They were written to interface with an out-of-date version of avr-libc.

I'd say they haven't been written with stdio in mind at all. stdio requires
that upon success, the function returns 0, but these return the character
being passed in (perhaps even with a pointless sign-extension applied,
iff the "char" type is a signed one).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Lfmorrison,

I've been reading through the different files and it is still not clear to me. Please enlighten me.

Thanks

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

Please start over with avr-libc's example code then.

http://www.nongnu.org/avr-libc/u...

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

The specific paragraphs in the manual dealing with the issue in question are at the following link:
(Paragraphs 1, 2, 3, and 4)

http://www.nongnu.org/avr-libc/u...

There is also now a replacement for fdev_open which doesn't make use of malloc():

http://www.nongnu.org/avr-libc/u...