printf puzzle

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

I have UART and printf setup "working" on an XMega128A3U with the code below.  I can successfully print text to my terminal, but there are two unexpected results: 1.  The "UART Ready!" text is printed twice, which isn't terrible, but I don't understand why as it is only called once.  2. Instead of printing the integer 13 (or any other number), it prints hundreds of apostrophes (0x60 in hex) for each single call of

printf(" %d ", 13);

Any attempt to use printf for other that text via %u, %i, %f gives similar unexpected results.

 

The test text line in main loop seems to work fine.

printf("test23456789\n\n");

 

Relevant code:

void uart_init()
{
	PORTE.OUTSET = PIN7_bm;
	//set transmit pin as output
	PORTE.DIRSET = PIN7_bm;

	//57600
    USARTE1.BAUDCTRLA = (2158 & 0xff) ;
    USARTE1.BAUDCTRLB = ((-6) << USART_BSCALE_gp) | ((2158 >> 8));

	//Disable interrupts
	USARTE1_CTRLA = 0;
	//8 data bits, no parity and 1 stop bit
	USARTE1_CTRLC = USART_CHSIZE_8BIT_gc;
	//Enable transmit
	USARTE1_CTRLB = USART_TXEN_bm;
	}
	
	
	static int uart_putchar (char c, FILE *stream){
	if (c == '\n')
	uart_putchar('\r', stream);

	// Wait for the transmit buffer to be empty
	while ( !( USARTE1.STATUS & USART_DREIF_bm) );

	// Put our character into the transmit buffer
	USARTE1.DATA = c;
	return 0;
}


//inside main:

//init data out uart on PORTE1
uart_init();

//stdio setup
static FILE mystdout = FDEV_SETUP_STREAM (uart_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = &mystdout;
printf("UART Ready!\n");


//Repeated inside Main loop
	printf(" %d ", 13);
	printf("test23456789\n\n");

 

This topic has a solution.
Last Edited: Wed. Jul 11, 2018 - 03:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't show snippet. Show a real test program that anyone can build and try.

 

Already the fact that the "ready" message appears twice rings alarm bells. Sounds like memory corruption or an interrupt that is enabled but not vectored or something like that.

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

Never mind.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

Last Edited: Wed. Jul 11, 2018 - 02:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian,

 

Have you had sufficient coffee today? Personally I would expect:

printf(" %d ", 13);

to produce

 13

Don't know about you??

 

(it might have used 13 as a memory address if something like %s had been used but %d just means "print this signed number in ASCII")

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

clawson wrote:

Have you had sufficient coffee today?

 

Nope, not nearly enough. I read one thing, saw another, and typed a third.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

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

oops...your uart_putchar is calling itself!

When in the dark remember-the future looks brighter than ever.

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

avrcandies wrote:
oops...your uart_putchar is calling itself!
That is "normal". See:

 

http://nongnu.org/avr-libc/user-...

 

and this in particular:

 

http://nongnu.org/avr-libc/examp...

 

The example implementation of uart_putchar() does this:

/*
 * Send character c down the UART Tx, wait until tx holding register
 * is empty.
 */
int
uart_putchar(char c, FILE *stream)
{

  if (c == '\a')
    {
      fputs("*ring*\n", stderr);
      return 0;
    }

  if (c == '\n')
    uart_putchar('\r', stream);
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;

  return 0;
}

So it recursively calls itself (but only for '\n') to always convert \n into \r\n.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks!!  Your inputs got me unstuck.  Wrote a quick test program that worked perfect using code above.  Went back to the original full code with your comments in mind and confidence that the UART portion was OK and realized I had device set as Xmega 64 vice 128.  Upshot is posted code snippets work, just can't be a knuckle head and set the wrong device.

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

Excellent!

 

And a very useful demonstration of how producing a test case can actually help you to find the problem yourself!

 

Now, please mark the solution - see Tip #5.

 

#DemoSolvesProblem

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jul 12, 2018 - 11:44 AM