1 /******************************************************************************
3 * Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /****************************************************************************/
36 * @addtogroup uartps_v3_5
39 * This file contains the implementation of the interface functions for XUartPs
40 * driver. Refer to the header file xuartps.h for more detailed information.
43 * MODIFICATION HISTORY:
45 * Ver Who Date Changes
46 * ----- ------ -------- ----------------------------------------------
47 * 1.00 drg/jz 01/13/10 First Release
48 * 2.2 hk 06/23/14 SW reset of RX and TX should be done when changing
49 * baud rate. CR# 804281.
50 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
51 * 3.1 kvn 04/10/15 Modified code for latest RTL changes.
52 * 3.5 NK 09/26/17 Fix the RX Buffer Overflow issue.
55 *****************************************************************************/
57 /***************************** Include Files ********************************/
63 /************************** Constant Definitions ****************************/
65 /* The following constant defines the amount of error that is allowed for
66 * a specified baud rate. This error is the difference between the actual
67 * baud rate that will be generated using the specified clock and the
70 #define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */
72 /**************************** Type Definitions ******************************/
75 /***************** Macros (Inline Functions) Definitions ********************/
78 /************************** Function Prototypes *****************************/
80 static void XUartPs_StubHandler(void *CallBackRef, u32 Event,
83 u32 XUartPs_SendBuffer(XUartPs *InstancePtr);
85 u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
87 /************************** Variable Definitions ****************************/
89 /****************************************************************************/
92 * Initializes a specific XUartPs instance such that it is ready to be used.
93 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
94 * parity by default. The baud rate is set to a default value specified by
95 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
96 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
97 * driver is polled mode.
99 * @param InstancePtr is a pointer to the XUartPs instance.
100 * @param Config is a reference to a structure containing information
101 * about a specific XUartPs driver.
102 * @param EffectiveAddr is the device base address in the virtual memory
103 * address space. The caller is responsible for keeping the address
104 * mapping from EffectiveAddr to the device physical base address
105 * unchanged once this function is invoked. Unexpected errors may
106 * occur if the address mapping changes after this function is
107 * called. If address translation is not used, pass in the physical
112 * - XST_SUCCESS if initialization was successful
113 * - XST_UART_BAUD_ERROR if the baud rate is not possible because
114 * the inputclock frequency is not divisible with an acceptable
119 * The default configuration for the UART after initialization is:
121 * - 19,200 bps or XPAR_DFT_BAUDRATE if defined
125 * - FIFO's are enabled with a receive threshold of 8 bytes
126 * - The RX timeout is enabled with a timeout of 1 (4 char times)
128 * All interrupts are disabled.
130 *****************************************************************************/
131 s32 XUartPs_CfgInitialize(XUartPs *InstancePtr,
132 XUartPs_Config * Config, u32 EffectiveAddr)
138 /* Assert validates the input arguments */
139 Xil_AssertNonvoid(InstancePtr != NULL);
140 Xil_AssertNonvoid(Config != NULL);
142 /* Setup the driver instance using passed in parameters */
143 InstancePtr->Config.BaseAddress = EffectiveAddr;
144 InstancePtr->Config.InputClockHz = Config->InputClockHz;
145 InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected;
147 /* Initialize other instance data to default values */
148 InstancePtr->Handler = XUartPs_StubHandler;
150 InstancePtr->SendBuffer.NextBytePtr = NULL;
151 InstancePtr->SendBuffer.RemainingBytes = 0U;
152 InstancePtr->SendBuffer.RequestedBytes = 0U;
154 InstancePtr->ReceiveBuffer.NextBytePtr = NULL;
155 InstancePtr->ReceiveBuffer.RemainingBytes = 0U;
156 InstancePtr->ReceiveBuffer.RequestedBytes = 0U;
158 /* Initialize the platform data */
159 InstancePtr->Platform = XGetPlatform_Info();
161 InstancePtr->is_rxbs_error = 0U;
163 /* Flag that the driver instance is ready to use */
164 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
167 * Set the default baud rate here, can be changed prior to
168 * starting the device
170 BaudRate = (u32)XUARTPS_DFT_BAUDRATE;
171 Status = XUartPs_SetBaudRate(InstancePtr, BaudRate);
172 if (Status != (s32)XST_SUCCESS) {
173 InstancePtr->IsReady = 0U;
177 * Set up the default data format: 8 bit data, 1 stop bit, no
180 ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
183 /* Mask off what's already there */
184 ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK |
185 (u32)XUARTPS_MR_STOPMODE_MASK |
186 (u32)XUARTPS_MR_PARITY_MASK));
188 /* Set the register value to the desired data format */
189 ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT |
190 (u32)XUARTPS_MR_STOPMODE_1_BIT |
191 (u32)XUARTPS_MR_PARITY_NONE);
193 /* Write the mode register out */
194 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
197 /* Set the RX FIFO trigger at 8 data bytes. */
198 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
199 XUARTPS_RXWM_OFFSET, 0x08U);
201 /* Set the RX timeout to 1, which will be 4 character time */
202 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
203 XUARTPS_RXTOUT_OFFSET, 0x01U);
205 /* Disable all interrupts, polled mode is the default */
206 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
209 Status = XST_SUCCESS;
214 /****************************************************************************/
217 * This functions sends the specified buffer using the device in either
218 * polled or interrupt driven mode. This function is non-blocking, if the device
219 * is busy sending data, it will return and indicate zero bytes were sent.
220 * Otherwise, it fills the TX FIFO as much as it can, and return the number of
223 * In a polled mode, this function will only send as much data as TX FIFO can
224 * buffer. The application may need to call it repeatedly to send the entire
227 * In interrupt mode, this function will start sending the specified buffer,
228 * then the interrupt handler will continue sending data until the entire
229 * buffer has been sent. A callback function, as specified by the application,
230 * will be called to indicate the completion of sending.
232 * @param InstancePtr is a pointer to the XUartPs instance.
233 * @param BufferPtr is pointer to a buffer of data to be sent.
234 * @param NumBytes contains the number of bytes to be sent. A value of
235 * zero will stop a previous send operation that is in progress
236 * in interrupt mode. Any data that was already put into the
237 * transmit FIFO will be sent.
239 * @return The number of bytes actually sent.
243 * The number of bytes is not asserted so that this function may be called with
244 * a value of zero to stop an operation that is already in progress.
247 *****************************************************************************/
248 u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr,
253 /* Asserts validate the input arguments */
254 Xil_AssertNonvoid(InstancePtr != NULL);
255 Xil_AssertNonvoid(BufferPtr != NULL);
256 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
259 * Disable the UART transmit interrupts to allow this call to stop a
260 * previous operation that may be interrupt driven.
262 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
263 (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));
265 /* Setup the buffer parameters */
266 InstancePtr->SendBuffer.RequestedBytes = NumBytes;
267 InstancePtr->SendBuffer.RemainingBytes = NumBytes;
268 InstancePtr->SendBuffer.NextBytePtr = BufferPtr;
271 * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after
272 * filling the TX FIFO.
274 BytesSent = XUartPs_SendBuffer(InstancePtr);
279 /****************************************************************************/
282 * This function attempts to receive a specified number of bytes of data
283 * from the device and store it into the specified buffer. This function works
284 * for both polled or interrupt driven modes. It is non-blocking.
286 * In a polled mode, this function will only receive the data already in the
287 * RX FIFO. The application may need to call it repeatedly to receive the
288 * entire buffer. Polled mode is the default mode of operation for the device.
290 * In interrupt mode, this function will start the receiving, if not the entire
291 * buffer has been received, the interrupt handler will continue receiving data
292 * until the entire buffer has been received. A callback function, as specified
293 * by the application, will be called to indicate the completion of the
294 * receiving or error conditions.
296 * @param InstancePtr is a pointer to the XUartPs instance
297 * @param BufferPtr is pointer to buffer for data to be received into
298 * @param NumBytes is the number of bytes to be received. A value of zero
299 * will stop a previous receive operation that is in progress in
302 * @return The number of bytes received.
306 * The number of bytes is not asserted so that this function may be called
307 * with a value of zero to stop an operation that is already in progress.
309 *****************************************************************************/
310 u32 XUartPs_Recv(XUartPs *InstancePtr,
311 u8 *BufferPtr, u32 NumBytes)
316 /* Assert validates the input arguments */
317 Xil_AssertNonvoid(InstancePtr != NULL);
318 Xil_AssertNonvoid(BufferPtr != NULL);
319 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
322 * Disable all the interrupts.
323 * This stops a previous operation that may be interrupt driven
325 ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
327 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
330 /* Setup the buffer parameters */
331 InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes;
332 InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes;
333 InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr;
335 /* Receive the data from the device */
336 ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr);
338 /* Restore the interrupt state */
339 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET,
342 return ReceivedCount;
345 /****************************************************************************/
348 * This function sends a buffer that has been previously specified by setting
349 * up the instance variables of the instance. This function is an internal
350 * function for the XUartPs driver such that it may be called from a shell
351 * function that sets up the buffer or from an interrupt handler.
353 * This function sends the specified buffer in either polled or interrupt
354 * driven modes. This function is non-blocking.
356 * In a polled mode, this function only sends as much data as the TX FIFO
357 * can buffer. The application may need to call it repeatedly to send the
360 * In interrupt mode, this function starts the sending of the buffer, if not
361 * the entire buffer has been sent, then the interrupt handler continues the
362 * sending until the entire buffer has been sent. A callback function, as
363 * specified by the application, will be called to indicate the completion of
366 * @param InstancePtr is a pointer to the XUartPs instance
368 * @return The number of bytes actually sent
372 *****************************************************************************/
373 u32 XUartPs_SendBuffer(XUartPs *InstancePtr)
379 * If the TX FIFO is full, send nothing.
380 * Otherwise put bytes into the TX FIFO unil it is full, or all of the
381 * data has been put into the FIFO.
383 while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) &&
384 (InstancePtr->SendBuffer.RemainingBytes > SentCount)) {
386 /* Fill the FIFO from the buffer */
387 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
389 ((u32)InstancePtr->SendBuffer.
390 NextBytePtr[SentCount]));
392 /* Increment the send count. */
396 /* Update the buffer to reflect the bytes that were sent from it */
397 InstancePtr->SendBuffer.NextBytePtr += SentCount;
398 InstancePtr->SendBuffer.RemainingBytes -= SentCount;
401 * If interrupts are enabled as indicated by the receive interrupt, then
402 * enable the TX FIFO empty interrupt, so further action can be taken
406 XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
408 if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) ||
409 ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)||
410 ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) {
412 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
414 ImrRegister | (u32)XUARTPS_IXR_TXEMPTY);
420 /****************************************************************************/
423 * This function receives a buffer that has been previously specified by setting
424 * up the instance variables of the instance. This function is an internal
425 * function, and it may be called from a shell function that sets up the buffer
426 * or from an interrupt handler.
428 * This function attempts to receive a specified number of bytes from the
429 * device and store it into the specified buffer. This function works for
430 * either polled or interrupt driven modes. It is non-blocking.
432 * In polled mode, this function only receives as much data as in the RX FIFO.
433 * The application may need to call it repeatedly to receive the entire buffer.
434 * Polled mode is the default mode for the driver.
436 * In interrupt mode, this function starts the receiving, if not the entire
437 * buffer has been received, the interrupt handler will continue until the
438 * entire buffer has been received. A callback function, as specified by the
439 * application, will be called to indicate the completion of the receiving or
442 * @param InstancePtr is a pointer to the XUartPs instance
444 * @return The number of bytes received.
448 *****************************************************************************/
449 u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr)
452 u32 ReceivedCount = 0U;
453 u32 ByteStatusValue, EventData;
457 * Read the Channel Status Register to determine if there is any data in
460 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
464 * Loop until there is no more data in RX FIFO or the specified
465 * number of bytes has been received
467 while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&&
468 (((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0))){
470 if (InstancePtr->is_rxbs_error) {
471 ByteStatusValue = XUartPs_ReadReg(
472 InstancePtr->Config.BaseAddress,
473 XUARTPS_RXBS_OFFSET);
474 if((ByteStatusValue & XUARTPS_RXBS_MASK)!= (u32)0) {
475 EventData = ByteStatusValue;
476 Event = XUARTPS_EVENT_PARE_FRAME_BRKE;
478 * Call the application handler to indicate that there is a receive
479 * error or a break interrupt, if the application cares about the
480 * error it call a function to get the last errors.
482 InstancePtr->Handler(InstancePtr->CallBackRef,
487 InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =
488 XUartPs_ReadReg(InstancePtr->Config.
490 XUARTPS_FIFO_OFFSET);
494 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
497 InstancePtr->is_rxbs_error = 0;
499 * Update the receive buffer to reflect the number of bytes just
502 if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL){
503 InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount;
505 InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;
507 return ReceivedCount;
510 /*****************************************************************************/
513 * Sets the baud rate for the device. Checks the input value for
514 * validity and also verifies that the requested rate can be configured to
515 * within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE.
516 * If the provided rate is not possible, the current setting is unchanged.
518 * @param InstancePtr is a pointer to the XUartPs instance
519 * @param BaudRate to be set
522 * - XST_SUCCESS if everything configured as expected
523 * - XST_UART_BAUD_ERROR if the requested rate is not available
524 * because there was too much error
528 *****************************************************************************/
529 s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate)
531 u32 IterBAUDDIV; /* Iterator for available baud divisor values */
532 u32 BRGR_Value; /* Calculated value for baud rate generator */
533 u32 CalcBaudRate; /* Calculated baud rate */
534 u32 BaudError; /* Diff between calculated and requested baud rate */
535 u32 Best_BRGR = 0U; /* Best value for baud rate generator */
536 u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */
537 u32 Best_Error = 0xFFFFFFFFU;
542 /* Asserts validate the input arguments */
543 Xil_AssertNonvoid(InstancePtr != NULL);
544 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
545 Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE);
546 Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE);
549 * Make sure the baud rate is not impossilby large.
550 * Fastest possible baud rate is Input Clock / 2.
552 if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) {
553 return XST_UART_BAUD_ERROR;
555 /* Check whether the input clock is divided by 8 */
556 ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress,
559 InputClk = InstancePtr->Config.InputClockHz;
560 if(ModeReg & XUARTPS_MR_CLKSEL) {
561 InputClk = InstancePtr->Config.InputClockHz / 8;
565 * Determine the Baud divider. It can be 4to 254.
566 * Loop through all possible combinations
568 for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) {
570 /* Calculate the value for BRGR register */
571 BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1));
573 /* Calculate the baud rate from the BRGR value */
574 CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1));
576 /* Avoid unsigned integer underflow */
577 if (BaudRate > CalcBaudRate) {
578 BaudError = BaudRate - CalcBaudRate;
581 BaudError = CalcBaudRate - BaudRate;
584 /* Find the calculated baud rate closest to requested baud rate. */
585 if (Best_Error > BaudError) {
587 Best_BRGR = BRGR_Value;
588 Best_BAUDDIV = IterBAUDDIV;
589 Best_Error = BaudError;
593 /* Make sure the best error is not too large. */
594 PercentError = (Best_Error * 100) / BaudRate;
595 if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) {
596 return XST_UART_BAUD_ERROR;
599 /* Disable TX and RX to avoid glitches when setting the baud rate. */
600 XUartPs_DisableUart(InstancePtr);
602 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
603 XUARTPS_BAUDGEN_OFFSET, Best_BRGR);
604 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
605 XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV);
607 /* RX and TX SW reset */
608 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET,
609 XUARTPS_CR_TXRST | XUARTPS_CR_RXRST);
612 XUartPs_EnableUart(InstancePtr);
614 InstancePtr->BaudRate = BaudRate;
620 /****************************************************************************/
623 * This function is a stub handler that is the default handler such that if the
624 * application has not set the handler when interrupts are enabled, this
625 * function will be called.
627 * @param CallBackRef is unused by this function.
628 * @param Event is unused by this function.
629 * @param ByteCount is unused by this function.
635 *****************************************************************************/
636 static void XUartPs_StubHandler(void *CallBackRef, u32 Event,
642 /* Assert occurs always since this is a stub and should never be called */
643 Xil_AssertVoidAlways();