/********************************************************************************* * Embedded Studio 2007 * * File: ES_UART.c * Desc: PC16550 UART Driver Functions * **********************************************************************************/ //Includes #include "ES_UART.h" /********************************************************************************************* * Function: UART_Open * * Desc: This function opens the UART port to use in FIFO Polling mode * * Params: int ch - channel number (1 or 2) * ConfigStruct *pConfig - pointer to the port Configuration * FpgaUartCtrlStruct *pUart - pointer to the UART control block * * Returns: bool - true if the port opens successfully, false otherwise * * Notes: * *********************************************************************************************/ bool UART_Open(int ch, FpgaUartCtrlStruct *pUart, UartConfigStruct *pConfig) { if(ch == 0) //FPGA UART 1 { pUart->RBR = pFPGA1_UART_RBR; pUart->THR = pFPGA1_UART_THR; pUart->DLL = pFPGA1_UART_DLL; pUart->DLM = pFPGA1_UART_DLM; pUart->IER = pFPGA1_UART_IER; pUart->IIR = pFPGA1_UART_IIR; pUart->FCR = pFPGA1_UART_FCR; pUart->LCR = pFPGA1_UART_LCR; pUart->MCR = pFPGA1_UART_MCR; pUart->LSR = pFPGA1_UART_LSR; pUart->MSR = pFPGA1_UART_MSR; pUart->SCR = pFPGA1_UART_SR; } else if(ch == 1) //FPGA UART 2 { pUart->RBR = pFPGA2_UART_RBR; pUart->THR = pFPGA2_UART_THR; pUart->DLL = pFPGA2_UART_DLL; pUart->DLM = pFPGA2_UART_DLM; pUart->IER = pFPGA2_UART_IER; pUart->IIR = pFPGA2_UART_IIR; pUart->FCR = pFPGA2_UART_FCR; pUart->LCR = pFPGA2_UART_LCR; pUart->MCR = pFPGA2_UART_MCR; pUart->LSR = pFPGA2_UART_LSR; pUart->MSR = pFPGA2_UART_MSR; pUart->SCR = pFPGA2_UART_SR; } else { return false; } //set up configuration pUart->IER->ALL = 0; //disable interrupts //sticky if(pConfig->Sticky) { pUart->LCR->BIT.SP = 1; pUart->LCR->BIT.PEN = 1; } else { //parity if(pConfig->Parity == ODD) { pUart->LCR->BIT.PEN = 1; pUart->LCR->BIT.EPS = 0; } else if(pConfig->Parity == EVEN) { pUart->LCR->BIT.PEN = 1; pUart->LCR->BIT.EPS = 1; } else { pUart->LCR->BIT.PEN = 0; } } //data bits pUart->LCR->BIT.WLS = pConfig->DataBits; //stop bits pUart->LCR->BIT.STB = pConfig->StopBits; //break bit pUart->LCR->BIT.SB = 0; //baud rate //divisor = Fin / (Baudrate * 16) pUart->LCR->BIT.DLAB = 1; //enable baud rate setting *pUart->DLL = FPGA_UART_BAUD_RATE_DIVISOR(pConfig->BaudRate) & 0xFF; *pUart->DLM = (FPGA_UART_BAUD_RATE_DIVISOR(pConfig->BaudRate) & 0xFF00) >> 8; pUart->LCR->BIT.DLAB = 0; //disable baud rate setting //modem control register pUart->MCR->ALL = 0; //FIFO control register pUart->FCR->BIT.FIFOE = 1; //enable FIFO pUart->FCR->BIT.RCVR_FIFOR = 1; //reset receiver fifo pUart->FCR->BIT.XMIT_FIFOR = 1; //reset transmitter fifo pUart->FCR->BIT.DMA_MS = 1; //enable DMA pUart->FCR->BIT.RCVRT = pConfig->RxFifoLevel; //receiver FIFO trigger level //enable Rx and Line Status interrupts pUart->IER->BIT.ERBFI = 1; pUart->IER->BIT.ELSI = 1; return true; } /********************************************************************************************* * Function: UART_Read * * Desc: This function reads data from the FPGA UART up to the number of bytes required or till * the end of the bytes available. * * Params: FpgaUartCtrlStruct *pUart * int *pBuffer - the location to store data * int nBytes - number of byte to be read * int mark - mark of a packet * * Returns: int - the number of bytes read from the port. -1 means error had ocurred * * Notes: * *********************************************************************************************/ int UART_Read(FpgaUartCtrlStruct *pUart, int *pBuffer, int nBytes, int mark) { int temp; int nByteRead = 0; int *pDest; Uart16550LSRUnion lsr; bool markSearch; //flag to indicate the period of mark searching //get a complete packet when FIFO receives all bytes of triggered level if (pUart->IIR->BIT.IP == 0) { switch (pUart->IIR->BIT.IIB2) { case IIR_RX_LINE_ERR: //error occurred //flush the fifo if error occurred, //but don't use the flush command, instead, read out the bytes one by one until the end while (true) { lsr.ALL = pUart->LSR->ALL; //reading the LSR resets the IIR if(lsr.BIT.DR == 0) { break; } else { temp = *pUart->RBR; } } nByteRead = -1; //discard any data break; case IIR_RX_DATA_READY: //data ready do { //LSR updates with each word, it shall be read for each word lsr.ALL = pUart->LSR->ALL; if (lsr.BIT.DR == 0) { break; //exit if there is no more word in the FIFO } else { //get valid data if (mark != 0) { //mark is valid, so we need to look for the mark if (nByteRead == 0) { //look for the mark byte temp = *pUart->RBR & 0xFF; if (temp == mark) { //we found the mark pDest = pBuffer; *pDest++ = temp; nByteRead++; markSearch = false; } else { markSearch = true; } } else { //mark has been found, so save the next word *pDest++ = (*pUart->RBR & 0xFF); nByteRead++; } } else { //mark is null, so don't look for the mark markSearch = false; *pDest++ = (*pUart->RBR & 0xFF); nByteRead++; } } }while (markSearch || (--nBytes > 0)); //during the period of mark search, don't decrement the byte count, but use the markSearch flag break; default: break; } } return nByteRead; } /********************************************************************************************* * Function: UART_Write * * Desc: This function writes a series of bytes to UART * * Params: FpgaUartCtrlStruct *pUart * int *pBuffer - the location of data source * int nBytes - number of byte to be written * * Returns: int - the number of bytes written successfully * * Notes: * *********************************************************************************************/ int FPGA_UART_Write(FpgaUartCtrlStruct *pUart, int *pBuffer, int nBytes) { int nByteWritten = 0; int *pDest = pBuffer; int i; //wait for the currect transmission to complete while (pUart->LSR->BIT.THRE == 0); //send the packet one byte by one byte for(i = 0; i < nBytes; i++) { *pUart->THR = *pDest++; nByteWritten++; DSP_Delay(1); //there must be some time delay between writes for FPGA UART to work properly } return nByteWritten; } /********************************************************************************************* * Function: UART_Close * * Desc: This function disables the UART port * * Params: FpgaUartCtrlStruct *pUart - the port to be closed * * Returns: bool - true if it closes successfully * * Notes: * *********************************************************************************************/ bool FPGA_UART_Close(FpgaUartCtrlStruct *pUart) { //disable FIFO pUart->FCR->BIT.FIFOE = 0; //disable Rx and Line Status interrupts pUart->IER->BIT.ERBFI = 0; pUart->IER->BIT.ELSI = 0; return true; }