@ -35,6 +35,32 @@
# include "serial.h"
# ifdef CONFIG_DEBUG_SERIAL
uint16_t cached_lsr [ 256 ] ;
uint16_t cached_rbr [ 256 ] ;
size_t cache_count ;
/* The LSR is read-to-clear on some parts, so we have to make sure status
* bits aren ' t inadvertently lost when doing various tests .
*/
static uint16_t uart_lsr_save ;
static uint16_t uart_lsr_read ( void )
{
uint16_t lsr = * pUART_LSR ;
uart_lsr_save | = ( lsr & ( OE | PE | FE | BI ) ) ;
return lsr | uart_lsr_save ;
}
/* Just do the clear for everyone since it can't hurt. */
static void uart_lsr_clear ( void )
{
uart_lsr_save = 0 ;
* pUART_LSR | = - 1 ;
}
# else
static inline uint16_t uart_lsr_read ( void ) { return * pUART_LSR ; }
static inline void uart_lsr_clear ( void ) { * pUART_LSR = - 1 ; }
# endif
/* Symbol for our assembly to call. */
void serial_set_baud ( uint32_t baud )
{
@ -61,6 +87,12 @@ int serial_init(void)
{
serial_initialize ( ) ;
serial_setbrg ( ) ;
uart_lsr_clear ( ) ;
# ifdef CONFIG_DEBUG_SERIAL
cache_count = 0 ;
memset ( cached_lsr , 0x00 , sizeof ( cached_lsr ) ) ;
memset ( cached_rbr , 0x00 , sizeof ( cached_rbr ) ) ;
# endif
return 0 ;
}
@ -73,7 +105,7 @@ void serial_putc(const char c)
WATCHDOG_RESET ( ) ;
/* wait for the hardware fifo to clear up */
while ( ! ( * pUART_LSR & THRE ) )
while ( ! ( uart_lsr_read ( ) & THRE ) )
continue ;
/* queue the character for transmission */
@ -83,38 +115,54 @@ void serial_putc(const char c)
WATCHDOG_RESET ( ) ;
/* wait for the byte to be shifted over the line */
while ( ! ( * pUART_LSR & TEMT ) )
while ( ! ( uart_lsr_read ( ) & TEMT ) )
continue ;
}
int serial_tstc ( void )
{
WATCHDOG_RESET ( ) ;
return ( * pUART_LSR & DR ) ? 1 : 0 ;
return ( uart_lsr_read ( ) & DR ) ? 1 : 0 ;
}
int serial_getc ( void )
{
uint16_t uart_lsr_val , uart_ rbr_val ;
uint16_t uart_rbr_val ;
/* wait for data ! */
while ( ! serial_tstc ( ) )
continue ;
/* clear the status and grab the new byte */
uart_lsr_val = * pUART_LSR ;
/* grab the new byte */
uart_rbr_val = * pUART_RBR ;
# ifdef CONFIG_DEBUG_SERIAL
/* grab & clear the LSR */
uint16_t uart_lsr_val = uart_lsr_read ( ) ;
cached_lsr [ cache_count ] = uart_lsr_val ;
cached_rbr [ cache_count ] = uart_rbr_val ;
cache_count = ( cache_count + 1 ) % ARRAY_SIZE ( cached_lsr ) ;
if ( uart_lsr_val & ( OE | PE | FE | BI ) ) {
/* Some parts are read-to-clear while others are
* write - to - clear . Just do the write for everyone
* since it cant hurt ( other than code size ) .
*/
* pUART_LSR = ( OE | PE | FE | BI ) ;
uint16_t dll , dlh ;
printf ( " \n [SERIAL ERROR] \n " ) ;
ACCESS_LATCH ( ) ;
dll = * pUART_DLL ;
dlh = * pUART_DLH ;
ACCESS_PORT_IER ( ) ;
printf ( " \t DLL=0x%x DLH=0x%x \n " , dll , dlh ) ;
do {
- - cache_count ;
printf ( " \t %3i: RBR=0x%02x LSR=0x%02x \n " , cache_count ,
cached_rbr [ cache_count ] , cached_lsr [ cache_count ] ) ;
} while ( cache_count > 0 ) ;
return - 1 ;
}
# endif
uart_lsr_clear ( ) ;
return uart_rbr_val & 0xFF ;
return uart_rbr_val ;
}
void serial_puts ( const char * s )