USART read problems

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

Hello, I have the following code:

	while (true) {

		uint16_t data;
		enum status_code status = usart_read_wait(&usart_instance, &data);
		if (status == STATUS_ERR_TIMEOUT)
		{
		}

		if (status == STATUS_OK)
			count += 1;
	}

When from a terminal (CoolTerm) I send a string that contains only a single character, the program reads it successfully. When I send a string with 10 characters (eg '1234567890'), the program reads the first one correctly and on one of the later it gives error STATUS_ERR_OVERFLOW. Why is that happening when I send strings with a lot of characters?

 

In case you need it, my uart initialization is like:

void configure_usart(void)
{
//! [setup_config]
	struct usart_config config_usart;
//! [setup_config]
//! [setup_config_defaults]
	usart_get_config_defaults(&config_usart);
//! [setup_config_defaults]

//! [setup_change_config]
	config_usart.baudrate    = 115200;
	config_usart.mux_setting = USART_RX_1_TX_0_XCK_1;
	config_usart.pinmux_pad0 = PINMUX_PB16C_SERCOM5_PAD0;
	config_usart.pinmux_pad1 = PINMUX_PB17C_SERCOM5_PAD1;
	config_usart.pinmux_pad2 = PINMUX_UNUSED;
	config_usart.pinmux_pad3 = PINMUX_UNUSED;
//! [setup_change_config]

//! [setup_set_config]

	while (usart_init(&usart_instance,
			SERCOM5, &config_usart) != STATUS_OK) {
	}

//! [setup_set_config]

//! [setup_enable]
	usart_enable(&usart_instance);
//! [setup_enable]
}

 

Thank you very much.

This topic has a solution.
Last Edited: Sun. May 6, 2018 - 10:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't check for STATUS_ERR_OVERFLOW in the program so how do you know?

What are you running this in?

/Lars

 

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

I run the program in Atmel Studio in the debugger. I use a breakpoint(action) and it displays me the value on the output window.

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

Sorry. Let me clarify it a little bit more. That is a screenshot of my IDE (the way I display the return value of the usart_read_wait in the output window).

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

I don't know how long it takes to process such a break point but it seems likely this is the problem. So why not  just implement more of what you actually are going to do after reading (collect chars in a buffer maybe) and test that.

/Lars

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

Arg!!! You are totally right Lars!

After adding the following code inside my while statement, I seen that a LED I had, was toggling every 30 chars (even when I was sending 30 at an instant time).

if (status == STATUS_OK) {
	count += 1;
	if ((count %30) == 0)
		port_pin_toggle_output_level(PIN_PA23);
}

The mistake from my side starts due to a wrong example project from Atmel (the USART_QUICK_START_CALLBACK). In their callback routine they use the following:

void usart_read_callback(struct usart_module *const usart_module)
{
	usart_write_buffer_job(&usart_instance, (uint8_t *)rx_buffer, MAX_RX_BUFFER_LENGTH);
}

When you send 10 chars from the terminal (eg 1234567890), you don't see all of them being echoed back. You see something like 1235789. This is probably normal and the corruption probably occurs because it is making a write inside the callback which should actually contain code that runs instantly. But looking at such kind of example it makes you believe that something else is happening (maybe problematic uart) and you don't get all your chars being echoed.

 

I have one last question. When I use the

usart_read_buffer_job(&usart_instance, (uint8_t *)rx_buffer, MAX_RX_BUFFER_LENGTH);

Do you know how I can check if my buffer is partially full after some period of time (timeout)? The callback will not trigger if the buffer is not full. I tried to do the following

int rb = usart_instance.remaining_rx_buffer_length;
if (rb < MAX_RX_BUFFER_LENGTH) {
    toRead = MAX_RX_BUFFER_LENGTH - rb;
    usart_abort_job(&usart_instance, USART_TRANSCEIVER_RX);
    // TODO: read the first 'toRead' bytes from the 'rx_buffer'
}

but I am afraid that calling the usart_abort_job might create me various problems.

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

I gave up on using a buffer > 1 with the usart_read_buffer_job function, it's not practical usually (e.g., if a character is lost). So when I used it was just a 1 char read and then collect that in my own buffer (and wait for end of packet with ok checksum in my case).

/Lars

 

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

Thank you very much for confirming me almost the same problem!

 

I will probably go with your approach (make a custom function that reads one by one bytes and append them on a custom buffer).

 

Have a good day!

 

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

Lajon wrote:
I don't know how long it takes to process such a break point

It does take a significant time!

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...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I skip the demo code completely.  Ring buffers and the ISR inserts the characters.

I then use read functions with a timer based timeout and intercharacter timeout from the buffer.

jeff