/************************************************************************* ** ** Broadcom Corp. Confidential ** Copyright 1999, 2000 Broadcom Corp. All Rights Reserved. ** ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE ** AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR ** EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. ** ** File: serial.h ** Description: polled uart io ** Created: Jeff Fisher ** REVISION: ** ****************************************************************************/ #include "serial.h" #include "burt.h" #ifdef NEXUS_UCOS_II extern BREG_Handle GetREG(); extern BCHP_Handle GetCHP(); extern BINT_Handle GetINT(); #else #include "gist.h" #endif #include "bkni_print.h" //#define POLLED_SERIAL_IO urt_t urt; BURT_Handle urt_handle; BURT_ChannelHandle urt_channel; /* use IRQ0 ua interrupt for reading RX */ static void uart_callback_func(void *context, int param) { #ifndef POLLED_SERIAL_IO unsigned long sizeRemaining, maxRead; uint32_t bytesRead; BERR_Code errCode; BURT_RxError error; if (BURT_IsRxDataAvailable_Isr(urt_channel) == false) { return; } bos_acquire_mutex(&urt.lock, -1); if (urt.rxWrite >= urt.rxRead) { sizeRemaining = urt.rxBufferSize - urt.rxWrite + urt.rxRead -1; } else { sizeRemaining = urt.rxRead - urt.rxWrite; } maxRead = (urt.rxWrite<= urt.rxRead)?sizeRemaining:(urt.rxBufferSize - urt.rxWrite); if (maxRead) { errCode = BURT_Read_Isr(urt_channel, urt.pRxFifo + urt.rxWrite, maxRead, &bytesRead, &error); if (error != BURT_RxError_eNoError) { switch (error) { case BURT_RxError_eReceiverOverRun: BKNI_Printf("=== receiver overrun\n"); break; case BURT_RxError_eReceiverFrameError: BKNI_Printf("=== receiver frame error\n"); break; case BURT_RxError_eReceiverParityError: BKNI_Printf("=== receiver parity error\n"); break; default: break; } } sizeRemaining -= bytesRead; urt.rxWrite += bytesRead; if (urt.rxWrite >= urt.rxBufferSize) { urt.rxWrite = 0; } } bos_release_mutex(&urt.lock); /* re-enable interrupt. */ BURT_EnableRxInt(urt_channel, true); BURT_EnableTxInt(urt_channel, true); #endif } /***********************************************************************/ /* serial_start(UartChannel *uart)*/ /* start or stop interrupt based UART */ /***********************************************************************/ void serial_start(volatile UartChannel *uart, bool start) { uart->sdw_lsr = 0; #ifndef POLLED_SERIAL_IO BURT_EnableRxInt(urt_channel, start ? true : false); BURT_EnableTxInt(urt_channel, start ? true : false); /* don't print out anything when using this function */ if (!start) { uint32_t bytesRead; BERR_Code errCode; BURT_RxError error; while (BURT_IsRxDataAvailable(urt_channel)) { errCode = BURT_Read(urt_channel, urt.pRxFifo + urt.rxWrite, 1, &bytesRead, &error); } } bos_acquire_mutex(&urt.lock, -1); urt.rxRead = urt.rxWrite = 0; bos_release_mutex(&urt.lock); #endif } /***********************************************************************/ /* serial_init(UartChannel *uart,unsigned int baud)*/ /***********************************************************************/ void serial_init(volatile UartChannel *uart, unsigned int baud) { #if (BCHP_CHIP==7550) || (BCHP_CHIP==7552) #ifdef POLLED_SERIAL_IO uart->sdw_lsr = 0; #else BURT_ChannelSettings channelSettings; uint32_t tval; /* do one read to prevent annoying interrupt at startup when serial dongle is disconnected */ tval = uart->sdw_rbr_thr_dll & 0xFF; urt.rxBufferSize = 256; urt.rxRead = urt.rxWrite = 0; urt.pRxFifo = BKNI_Malloc(urt.rxBufferSize); bos_create_mutex(&urt.lock); BURT_Open(&urt_handle, GetCHP(), GetREG(), GetINT(), NULL); BURT_GetChannelDefaultSettings(urt_handle, 0, &channelSettings); channelSettings.intMode = false; channelSettings.rxIntMode = true; channelSettings.baud = baud; channelSettings.bits = BURT_DataBits_eDataBits8; channelSettings.parity = BURT_Parity_eNone; BURT_OpenChannel(urt_handle, &urt_channel, 0, &channelSettings); BURT_RegisterCallback(urt_channel, uart_callback_func); #endif #else /*---------------------------------------------------------------------*/ /* Dissable channel's receiver and transmitter. */ /*---------------------------------------------------------------------*/ uart->control = 0; // uart->control &= ~(TXEN|RXEN); /*---------------------------------------------------------------------*/ /* disable interrupts on this channel . */ /*---------------------------------------------------------------------*/ uart->rxstat = 0; uart->txstat = 0; /*-----------------------------------------------------------------*/ /* set character size and parity control bit (8,none only) */ /*-----------------------------------------------------------------*/ uart->control = BITM8; baud = ((XTALFREQ / baud) /16); uart->baudh = (unsigned char)((baud >> 8) & 0xFF); uart->baudl = (unsigned char)(baud & 0xFF); /*---------------------------------------------------------------------*/ /* Finally, re-enable the transmitter and receiver. */ /*---------------------------------------------------------------------*/ uart->control |= (TXEN|RXEN); #endif } /***********************************************************************/ /* serial_getc(UartChannel *uart, int block)*/ /***********************************************************************/ #define RXRDA 0x01 #define RXOVFERR 0x02 #define RXPARERR 0x04 #define RXFRAMERR 0x08 #define RXBIERR 0x10 /* BI error */ #define RXFIFOERR 0x80 /* Rx FIFO error */ int serial_getc(volatile UartChannel *uart, bool block) { #if (BCHP_CHIP==7550) || (BCHP_CHIP==7552) #ifdef POLLED_SERIAL_IO int blen = 1; unsigned int status; char tval; while (blen > 0) { status = uart->sdw_lsr; if(status & (RXOVFERR | RXPARERR | RXFRAMERR | RXBIERR | RXFIFOERR)) { /* Just read the bad character to clear the bit. */ tval = uart->sdw_rbr_thr_dll & 0xFF; } else if(status & RXRDA) { tval = uart->sdw_rbr_thr_dll & 0xFF; blen--; } else { /* block if required */ if (!block) { return 0; } } } return tval; #else char tval; while (1) { if (urt.rxWrite == urt.rxRead) { // no data yet. if (!block) { #ifdef CONFIG_GP return -1; #else return 0; #endif } else { continue; } } else { tval = urt.pRxFifo[urt.rxRead]; bos_acquire_mutex(&urt.lock, -1); urt.rxRead++; if (urt.rxRead >= urt.rxBufferSize) { urt.rxRead = 0; } bos_release_mutex(&urt.lock); return tval; } } #endif #else if (!block) { if (!(uart->rxstat & RXDATARDY)) { return 0; } } while (!(uart->rxstat & RXDATARDY)) ; return (unsigned char)uart->rxdata; #endif } /***********************************************************************/ /* serial_putc(UartChannel *uart, unsigned int c)*/ /***********************************************************************/ static inline void serial_do_putc(volatile UartChannel *uart, int c) { #if (BCHP_CHIP==7550) || (BCHP_CHIP==7552) if(uart->sdw_scr == 0){ while(0 == (uart->sdw_lsr & THRE)) { #ifndef POLLED_SERIAL_IO if (!bos_in_interrupt()) BKNI_Sleep(1); #endif } uart->sdw_scr = 32; } uart->sdw_scr--; uart->sdw_rbr_thr_dll = (unsigned char)c; #else while (!(uart->txstat & TXDREGEMT)) ; uart->txdata = (unsigned char)c; #endif } /***********************************************************************/ /* serial_putc(UartChannel *uart, unsigned int c)*/ /***********************************************************************/ void serial_putc(volatile UartChannel *uart, int c) { serial_do_putc(uart,c); }