Seeking advice with Interrupts, USARTs.

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

Having some issues switching from ATmega products to Xmega products. I'm beating my head on the desk trying to figure out why I have no data showing up on either side of the USART. This is my code, I am praying to the AVRFreak gods to give me some advice.

Main:

int main (void)
{
	
	
	board_init();								
	sysclk_init();								
	rtc_m_init();								
	pmic_init();								
	delay_init(sysclk_get_cpu_hz());			
	pmic_set_scheduling(PMIC_SCH_ROUND_ROBIN);
	
	cpu_irq_enable();

....

USART Code:

//Using a FIFO buffer on both RX and TX
union wireless_buffer fifo_rx_buffer[WIRELESS_RX_BUFFER_SIZE],fifo_tx_buffer[WIRELESS_TX_BUFFER_SIZE];
fifo_desc_t fifo_rx_wireless, fifo_tx_wireless;

void wireless_m_init(){
	
	switch (fifo_init(&fifo_rx_wireless, fifo_rx_buffer, WIRELESS_RX_BUFFER_SIZE) 
			& fifo_init(&fifo_tx_wireless, fifo_tx_buffer, WIRELESS_TX_BUFFER_SIZE)){
		case FIFO_OK:
			usart_serial_init(WIRELESS_USART_BASE, &WIRELESS_SERIAL_OPTIONS);
			WIRELESS_USART.CTRLA = WIRELESS_IRQ_LEVEL << USART_RXCINTLVL_gp;

		case FIFO_ERROR:

			return NULL;
			break;
	} 
	
} 

void send_wireless_command(char *command){	
	
	uint8_t len = strlen(command);
	
	while (len) {
		
		switch (fifo_push_uint8(&fifo_tx_wireless, *command)){
			case FIFO_OK:
				
len--;
				command++;
				break;
			case FIFO_ERROR_OVERFLOW:
				
break;
		} 
	
	} 
	
	uint8_t status = fifo_push_uint8(&fifo_tx_wireless, '\r');
	// enable transmission ISR
	WIRELESS_USART.CTRLA |= WIRELESS_IRQ_LEVEL << USART_DREINTLVL_gp;
	
}

char *get_wireless_response(){
		
	uint8_t size = fifo_get_used_size(&fifo_rx_wireless);
	char rxBuffer[size];
	
	if(size == 0){
		return NULL;
	} else {
		for (int i=0;i

I've verified that the FIFO buffer is pushed and values can be pulled. In debugging, it "appears" that when breaks are applied to the ISR it does fire, but I am not getting anything transmitted or received. I'm sure it's simple, but I've been in the forest so long that I can't see the trees.

Thank you for your time.

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

:?:
Which xmega is this?

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

WIRELESS_DRE_vect is just a

#define WIRELESS_DRE_vect USARTD0_DRE_vect

MCU is an XMega128A1

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

My first idea is that there is serious issues with the ASF FIFO implementation. Even with simple examples of using the FIFO as a buffer with USART RX/TX I'm getting strange results.

This is the USART example from Atmel Studio, modified with the FIFO example:

*! \brief Main function.
 */
int main(void)
{
	union buffer_element fifo_buffer[FIFO_BUFFER_LENGTH];
	
	fifo_desc_t fifo_desc;	
	
	uint8_t tx_buf[] = "Hello AVR world\n";
	uint8_t tx_length = 16;
	uint8_t received_byte;
	uint8_t i;

	/* Initialize the board.
	 * The board-specific conf_board.h file contains the configuration of
	 * the board initialization.
	 */
	board_init();
	sysclk_init();
	
	fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH);

	// USART options.
	static usart_rs232_options_t USART_SERIAL_OPTIONS = {
		.baudrate = USART_SERIAL_EXAMPLE_BAUDRATE,
		.charlength = USART_SERIAL_CHAR_LENGTH,
		.paritytype = USART_SERIAL_PARITY,
		.stopbits = USART_SERIAL_STOP_BIT
	};

	// Initialize usart driver in RS232 mode
	usart_init_rs232(USART_SERIAL_EXAMPLE, &USART_SERIAL_OPTIONS);

	uint8_t status;
	uint8_t pull_value;
	
	

	// Get and echo a character forever, specific '\r' processing.
	while (true) {
		
		fifo_flush(&fifo_desc);
		// Send "message header"
		for (i=0;i<5;i++){
			status = fifo_push_uint8(&fifo_desc, tx_buf[i]);
			//if(fifo_get_used_size(&fifo_desc) == 0) break;
		}
		
		while(!fifo_is_empty(&fifo_desc)){
			
			status = fifo_pull_uint8(&fifo_desc, &pull_value);
			usart_putchar(USART_SERIAL_EXAMPLE, pull_value);
			
		}		
		
	}
	
}			

This is the results:

ooooooooo.... forever
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, think I've found it. Small omission from ASF documentation. Buffer array need to be passed by reference. I was passing in the start of the array and only filling it the first index. Unfortunately I was hanging onto the ASF documentation and giving it full trust that it was 100%. When you have examples that only show one value being pushed onto the FIFO it will work every time, surprise. Try putting 2 values on and see how much fun it is.

This is how it shows in ASF:


fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH)

This is how it should be:


fifo_init(&fifo_desc, &fifo_buffer, FIFO_BUFFER_LENGTH)

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

I worried about the same problem. Using the "&fifo_buffer" didn´t solve anything.
But I got happy with reading this:
..."Size of the buffer (unit is in number of 'elements'). It must be a 2-power and <= to 128."

So using 128 instead of 127 (first I read <128) was it.

I think it doesn´t matter whether you write the "&" before "fifo_buffer", because fifo_buffer is an array and without writing the [] you specify the address. (I think so..)