Handling comms timeouts with AVR32UC3B0512

Started by Andrew May 24, 2012
Hi,

I need to be able to handle comms timeouts with my project. I have read the relevant sections in the data sheet, but found information lacking.

I have modified the following function to initialise timeouts:

int usart_init_rs232(volatile struct avr32_usart_t * usart, struct usart_options_t * opt, long cpu_hz)
{
int retval;

/* Reset the usart and shutdown RX and TX */
usart_reset(usart);

/* Control input values */
if (opt == 0) /* Null pointer */
return USART_INVALID_INPUT;
if (opt->charlength < 5 || opt->charlength > 9)
return USART_INVALID_INPUT;
if (opt->paritytype > 7)
return USART_INVALID_INPUT;
if (opt->stopbits > 2+255)
return USART_INVALID_INPUT;
if (opt->channelmode > 3)
return USART_INVALID_INPUT;

if ((retval = usart_set_baudrate(usart, opt->baudrate, cpu_hz)) != \
USART_SUCCESS)
return retval;

if (opt->charlength == 9) {
/* Charlength set to 9 bits; MODE9 dominates CHRL */
usart->mr |= (1< } else {
/* CHRL gives the charlength( - 5) when USART_MODE9=0 */
usart->mr | ((opt->charlength-5) << AVR32_USART_MR_CHRL_OFFSET);
}

usart->mr |= (opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET) |
(opt->paritytype << AVR32_USART_MR_PAR_OFFSET);

if (opt->stopbits > 2)
{
/* Set two stop bits */
usart->mr |= (2 << AVR32_USART_MR_NBSTOP_OFFSET);
/* And a timeguard period gives the rest */
usart->ttgr = (opt->stopbits-2);
}
else
/* Insert 1, 1.5 or 2 stop bits */
usart->mr |= (opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET);

/* Setup complete; enable communication */
/* Enable input and output */
usart->cr |= (1< (1<
// Setup timeout values
usart->rtor = 0x1FFFF;
// enable timeouts
usart->cr |= (1<
return USART_SUCCESS;
}

I have modified usart_read_char() to handle timeouts:

int usart_read_char(volatile struct avr32_usart_t * usart, int * c)
{
/* Check for errors; Frame, parity and overrun In RS485 mode a parity
error would mean that we received an address char */
if (usart->csr &
((1 << AVR32_USART_CSR_OVRE_OFFSET) |
(1 << AVR32_USART_CSR_FRAME_OFFSET) |
(1 << AVR32_USART_CSR_PARE_OFFSET))) {

return USART_RX_ERROR;
}

else if (usart->csr & (1 << AVR32_USART_CSR_TIMEOUT)) {
usart->cr |= (1< usart->cr |= (1< return USART_RX_ERROR;
}
/* No error; if we really did receive a char, read it and return SUCCESS */
else if ((usart->csr & (1< *c = (unsigned short)usart->rhr;
usart->cr |= (1<
return USART_SUCCESS;
} else {
return USART_RX_EMPTY;
}
} /* usart_read */

When a timeout occurs it is detected, but the usart then appears to crash. I can spy on the comms between the micorcontroller, and the device it is communicating with, and I can see that the micro is sending the right command, and the other device is returning the correct information, but the usart only generates comms erros so I'm not able to read any valid data.

Can someone please give me a few pointers on how to handle comms timeouts with AVR32, and how to reset the usart so that it doesn't return spurious chars on subsequent reads.

Thanks in advance

Andrew

hi,
when you receive a byte you must read the io register UCSRA where you found error flags, reading UCSRA reset errors.
on the other hand, if you connect 2 mcu via a RS232 channel with less than 10m cable you mast not have problems.
normally I use interrupts to send and receive data with UART, I define a Txd & Rxd structures, Then Rxd & Txd variables, a pointer for each (pRxd, pTxd) and a counter for each (RxCnt, TxCnt).
example :
   struct hRxd
   {
         int a, b, c ;
         char f[20] ;
        ...
   };
   struct hRxd Rxd ;   
   char * pRxd = &Rxd ;
   char RxCnt = 0 ;
in the RXC interrupt service routine stock the data :
   char s ;

   s =  UCSRA ;// hear you test error flags
   *(pRxd  + RxCnt) = UDR ; 
   if (++RxCnt >= sizeof(Rxd)
   {
      RxCnt = 0 ; 
      // Data received actions 
   }

enjoy 

________________________________
From: Andrew
To: a...
Sent: Friday, May 25, 2012 2:12 AM
Subject: [AVR club] Handling comms timeouts with AVR32UC3B0512


 
Hi,

I need to be able to handle comms timeouts with my project. I have read the relevant sections in the data sheet, but found information lacking.

I have modified the following function to initialise timeouts:

int usart_init_rs232(volatile struct avr32_usart_t * usart, struct usart_options_t * opt, long cpu_hz)
{
int retval;

/* Reset the usart and shutdown RX and TX */
usart_reset(usart);

/* Control input values */
if (opt == 0) /* Null pointer */
return USART_INVALID_INPUT;
if (opt->charlength < 5 || opt->charlength > 9)
return USART_INVALID_INPUT;
if (opt->paritytype > 7)
return USART_INVALID_INPUT;
if (opt->stopbits > 2+255)
return USART_INVALID_INPUT;
if (opt->channelmode > 3)
return USART_INVALID_INPUT;

if ((retval = usart_set_baudrate(usart, opt->baudrate, cpu_hz)) != \
USART_SUCCESS)
return retval;

if (opt->charlength == 9) {
/* Charlength set to 9 bits; MODE9 dominates CHRL */
usart->mr |= (1< } else {
/* CHRL gives the charlength( - 5) when USART_MODE9=0 */
usart->mr |=
((opt->charlength-5) << AVR32_USART_MR_CHRL_OFFSET);
}

usart->mr |= (opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET) |
(opt->paritytype << AVR32_USART_MR_PAR_OFFSET);

if (opt->stopbits > 2)
{
/* Set two stop bits */
usart->mr |= (2 << AVR32_USART_MR_NBSTOP_OFFSET);
/* And a timeguard period gives the rest */
usart->ttgr = (opt->stopbits-2);
}
else
/* Insert 1, 1.5 or 2 stop bits */
usart->mr |= (opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET);

/* Setup complete; enable communication */
/* Enable input and output */
usart->cr |= (1< (1<
// Setup timeout values
usart->rtor = 0x1FFFF;
// enable timeouts
usart->cr |= (1<
return USART_SUCCESS;
}

I have modified usart_read_char() to handle timeouts:

int usart_read_char(volatile struct avr32_usart_t * usart, int * c)
{
/* Check for errors; Frame, parity and overrun In RS485 mode a parity
error would mean that we received an address char */
if (usart->csr &
((1 << AVR32_USART_CSR_OVRE_OFFSET) |
(1 << AVR32_USART_CSR_FRAME_OFFSET) |
(1 << AVR32_USART_CSR_PARE_OFFSET))) {

return USART_RX_ERROR;
}

else if (usart->csr & (1 << AVR32_USART_CSR_TIMEOUT)) {
usart->cr |= (1< usart->cr |= (1< return USART_RX_ERROR;
}
/* No error; if we really did receive a char, read it and return SUCCESS */
else if ((usart->csr & (1< *c = (unsigned short)usart->rhr;
usart->cr |= (1<
return USART_SUCCESS;
} else {
return USART_RX_EMPTY;
}
} /* usart_read */

When a timeout occurs it is detected, but the usart then appears to crash. I can spy on the comms between the micorcontroller, and the device it is communicating with, and I can see that the micro is sending the right command, and the other device is returning the correct information, but the usart only generates comms erros so I'm not able to read any valid data.

Can someone please give me a few pointers on how to handle comms timeouts with AVR32, and how to reset the usart so that it doesn't return spurious chars on subsequent reads.

Thanks in advance

Andrew