1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

Starting to fix AVR32 UARt code:

- Check for error return values and return errors when they happen
- Return error value when invalid parameters are passed
- uart.setup(): return the actual baud rate set.
This commit is contained in:
Martin Guy 2011-04-25 16:32:00 +02:00
parent c0119c0908
commit dfcde5bb47
3 changed files with 88 additions and 9 deletions

View File

@ -348,27 +348,42 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
opts.baudrate = baud;
// Set stopbits
if( stopbits == PLATFORM_UART_STOPBITS_1 )
switch (stopbits) {
case PLATFORM_UART_STOPBITS_1:
opts.stopbits = USART_1_STOPBIT;
else if( stopbits == PLATFORM_UART_STOPBITS_1_5 )
break;
case PLATFORM_UART_STOPBITS_1_5:
opts.stopbits = USART_1_5_STOPBITS;
else
break;
case PLATFORM_UART_STOPBITS_2:
opts.stopbits = USART_2_STOPBITS;
break;
default:
return 0;
}
// Set parity
if( parity == PLATFORM_UART_PARITY_EVEN )
switch (parity) {
case PLATFORM_UART_PARITY_EVEN:
opts.paritytype = USART_EVEN_PARITY;
else if( parity == PLATFORM_UART_PARITY_ODD )
break;
case PLATFORM_UART_PARITY_ODD:
opts.paritytype = USART_ODD_PARITY;
else
break;
case PLATFORM_UART_PARITY_NONE:
opts.paritytype = USART_NO_PARITY;
break;
default:
return 0;
}
// Set actual interface
gpio_enable_module(uart_pins + id * 2, 2 );
usart_init_rs232( pusart, &opts, REQ_PBA_FREQ );
if ( usart_init_rs232( pusart, &opts, REQ_PBA_FREQ ) != USART_SUCCESS )
return 0;
// [TODO] Return actual baud here
return baud;
// Return actual baud here
return usart_get_async_baudrate(pusart, REQ_PBA_FREQ);
}
void platform_s_uart_send( unsigned id, u8 data )

View File

@ -111,6 +111,60 @@ static int usart_set_async_baudrate(volatile avr32_usart_t *usart, unsigned int
}
/*! \brief Return the actual baud rate set into the USART
*
* Baud rate calculation:
* \f$ Baudrate = \frac{SelectedClock}{Over \times (CD + \frac{FP}{8})} \f$, \e Over being 16 or 8.
*
* \param usart Base address of the USART instance.
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval baudrate The closest integer to the actual baud rate
* \retval 0 UART clock is off or there was some error on our part
*/
unsigned int usart_get_async_baudrate(volatile avr32_usart_t *usart, unsigned long pba_hz)
{
unsigned int clock; // Master clock frequency
unsigned int over; // divisor of 8 or 16
unsigned int cd; // clock divider (0-65535)
unsigned int fp; // fractional part of clock divider (0-7)
unsigned int divisor; // What the master clock is divided by to get
// the final baud rate
// Find
switch ((usart->mr & AVR32_USART_MR_USCLKS_MASK) >> AVR32_USART_MR_USCLKS_OFFSET)
{
case AVR32_USART_MR_USCLKS_MCK:
clock = pba_hz;
break;
case AVR32_USART_MR_USCLKS_MCK_DIV:
// I can't figure out where the divider is defined. The datasheet
// section 26.7.1 says it is "product dependent, but generally set to 8".
// Fortunately, the code above always selects MCK.
case AVR32_USART_MR_USCLKS_SCK:
// If we have an external clock, we don't know its frequency here.
default:
return 0;
}
over = usart->mr & AVR32_USART_MR_OVER_MASK;
cd = (usart->brgr & AVR32_USART_BRGR_CD_MASK) >> AVR32_USART_BRGR_CD_OFFSET;
fp = (usart->brgr & AVR32_USART_BRGR_FP_MASK) >> AVR32_USART_BRGR_FP_OFFSET;
// if CD==0, no baud rate is generated.
// if CD==1, the clock divider and fractional part are bypassed.
if (cd == 0) return 0;
if (cd == 1) fp = 0;
// Rewriting "divisor = 8 * (2 - over) * (cd + fp/8)" for integer math:
divisor = (2 - over) * (8 * cd + fp);
// Round to the integer that is closest to the actual result
return (clock + divisor/2) / divisor;
}
/*! \brief Calculates a clock divider (\e CD) for the USART synchronous master
* modes to generate a baud rate as close as possible to the baud rate
* set point.

View File

@ -230,6 +230,16 @@ extern void usart_reset(volatile avr32_usart_t *usart);
*/
extern int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Returns the actual baud rate set into the USART in async mode
*
* \param usart Base address of the USART instance.
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval baudrate The nearest integer to the actual baud rate
* \retval 0 No baudrate is being generated or some error
*/
extern unsigned int usart_get_async_baudrate(volatile avr32_usart_t *usart, unsigned long pba_hz);
/*! \brief Sets up the USART to use the standard RS232 protocol in TX-only mode.
*
* Compared to \ref usart_init_rs232, this function allows very high baud rates