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 /****************************************************************************/
37 * This file contains the implementation of the interface functions for XUartPs
38 * driver. Refer to the header file xuartps.h for more detailed information.
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ------ -------- ----------------------------------------------
45 * 1.00 drg/jz 01/13/10 First Release
46 * 2.2 hk 06/23/14 SW reset of RX and TX should be done when changing
47 * baud rate. CR# 804281.
48 * 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
51 *****************************************************************************/
53 /***************************** Include Files ********************************/
59 /************************** Constant Definitions ****************************/
61 /* The following constant defines the amount of error that is allowed for
62 * a specified baud rate. This error is the difference between the actual
63 * baud rate that will be generated using the specified clock and the
66 #define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */
68 /**************************** Type Definitions ******************************/
71 /***************** Macros (Inline Functions) Definitions ********************/
74 /************************** Function Prototypes *****************************/
76 static void XUartPs_StubHandler(void *CallBackRef, u32 Event,
79 u32 XUartPs_SendBuffer(XUartPs *InstancePtr);
81 u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
83 /************************** Variable Definitions ****************************/
85 /****************************************************************************/
88 * Initializes a specific XUartPs instance such that it is ready to be used.
89 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
90 * parity by default. The baud rate is set to a default value specified by
91 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
92 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
93 * driver is polled mode.
95 * @param InstancePtr is a pointer to the XUartPs instance.
96 * @param Config is a reference to a structure containing information
97 * about a specific XUartPs driver.
98 * @param EffectiveAddr is the device base address in the virtual memory
99 * address space. The caller is responsible for keeping the address
100 * mapping from EffectiveAddr to the device physical base address
101 * unchanged once this function is invoked. Unexpected errors may
102 * occur if the address mapping changes after this function is
103 * called. If address translation is not used, pass in the physical
108 * - XST_SUCCESS if initialization was successful
109 * - XST_UART_BAUD_ERROR if the baud rate is not possible because
110 * the inputclock frequency is not divisible with an acceptable
115 * The default configuration for the UART after initialization is:
117 * - 19,200 bps or XPAR_DFT_BAUDRATE if defined
121 * - FIFO's are enabled with a receive threshold of 8 bytes
122 * - The RX timeout is enabled with a timeout of 1 (4 char times)
124 * All interrupts are disabled.
126 *****************************************************************************/
127 s32 XUartPs_CfgInitialize(XUartPs *InstancePtr,
128 XUartPs_Config * Config, u32 EffectiveAddr)
135 * Assert validates the input arguments
137 Xil_AssertNonvoid(InstancePtr != NULL);
138 Xil_AssertNonvoid(Config != NULL);
141 * 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;
148 * Initialize other instance data to default values
150 InstancePtr->Handler = XUartPs_StubHandler;
152 InstancePtr->SendBuffer.NextBytePtr = NULL;
153 InstancePtr->SendBuffer.RemainingBytes = 0U;
154 InstancePtr->SendBuffer.RequestedBytes = 0U;
156 InstancePtr->ReceiveBuffer.NextBytePtr = NULL;
157 InstancePtr->ReceiveBuffer.RemainingBytes = 0U;
158 InstancePtr->ReceiveBuffer.RequestedBytes = 0U;
161 * Flag that the driver instance is ready to use
163 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
166 * Set the default baud rate here, can be changed prior to
167 * starting the device
169 BaudRate = (u32)XUARTPS_DFT_BAUDRATE;
170 Status = XUartPs_SetBaudRate(InstancePtr, BaudRate);
171 if (Status != (s32)XST_SUCCESS) {
172 InstancePtr->IsReady = 0U;
176 * Set up the default data format: 8 bit data, 1 stop bit, no
179 ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
183 * Mask off what's already there
185 ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK |
186 (u32)XUARTPS_MR_STOPMODE_MASK |
187 (u32)XUARTPS_MR_PARITY_MASK));
190 * Set the register value to the desired data format
192 ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT |
193 (u32)XUARTPS_MR_STOPMODE_1_BIT |
194 (u32)XUARTPS_MR_PARITY_NONE);
197 * Write the mode register out
199 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
203 * Set the RX FIFO trigger at 8 data bytes.
205 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
206 XUARTPS_RXWM_OFFSET, 0x08U);
209 * Set the RX timeout to 1, which will be 4 character time
211 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
212 XUARTPS_RXTOUT_OFFSET, 0x01U);
215 * Disable all interrupts, polled mode is the default
217 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
220 Status = XST_SUCCESS;
225 /****************************************************************************/
228 * This functions sends the specified buffer using the device in either
229 * polled or interrupt driven mode. This function is non-blocking, if the device
230 * is busy sending data, it will return and indicate zero bytes were sent.
231 * Otherwise, it fills the TX FIFO as much as it can, and return the number of
234 * In a polled mode, this function will only send as much data as TX FIFO can
235 * buffer. The application may need to call it repeatedly to send the entire
238 * In interrupt mode, this function will start sending the specified buffer,
239 * then the interrupt handler will continue sending data until the entire
240 * buffer has been sent. A callback function, as specified by the application,
241 * will be called to indicate the completion of sending.
243 * @param InstancePtr is a pointer to the XUartPs instance.
244 * @param BufferPtr is pointer to a buffer of data to be sent.
245 * @param NumBytes contains the number of bytes to be sent. A value of
246 * zero will stop a previous send operation that is in progress
247 * in interrupt mode. Any data that was already put into the
248 * transmit FIFO will be sent.
250 * @return The number of bytes actually sent.
254 * The number of bytes is not asserted so that this function may be called with
255 * a value of zero to stop an operation that is already in progress.
258 *****************************************************************************/
259 u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr,
265 * Asserts validate the input arguments
267 Xil_AssertNonvoid(InstancePtr != NULL);
268 Xil_AssertNonvoid(BufferPtr != NULL);
269 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
272 * Disable the UART transmit interrupts to allow this call to stop a
273 * previous operation that may be interrupt driven.
275 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
276 (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));
279 * Setup the buffer parameters
281 InstancePtr->SendBuffer.RequestedBytes = NumBytes;
282 InstancePtr->SendBuffer.RemainingBytes = NumBytes;
283 InstancePtr->SendBuffer.NextBytePtr = BufferPtr;
286 * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after
287 * filling the TX FIFO.
289 BytesSent = XUartPs_SendBuffer(InstancePtr);
294 /****************************************************************************/
297 * This function attempts to receive a specified number of bytes of data
298 * from the device and store it into the specified buffer. This function works
299 * for both polled or interrupt driven modes. It is non-blocking.
301 * In a polled mode, this function will only receive the data already in the
302 * RX FIFO. The application may need to call it repeatedly to receive the
303 * entire buffer. Polled mode is the default mode of operation for the device.
305 * In interrupt mode, this function will start the receiving, if not the entire
306 * buffer has been received, the interrupt handler will continue receiving data
307 * until the entire buffer has been received. A callback function, as specified
308 * by the application, will be called to indicate the completion of the
309 * receiving or error conditions.
311 * @param InstancePtr is a pointer to the XUartPs instance
312 * @param BufferPtr is pointer to buffer for data to be received into
313 * @param NumBytes is the number of bytes to be received. A value of zero
314 * will stop a previous receive operation that is in progress in
317 * @return The number of bytes received.
321 * The number of bytes is not asserted so that this function may be called
322 * with a value of zero to stop an operation that is already in progress.
324 *****************************************************************************/
325 u32 XUartPs_Recv(XUartPs *InstancePtr,
326 u8 *BufferPtr, u32 NumBytes)
332 * Assert validates the input arguments
334 Xil_AssertNonvoid(InstancePtr != NULL);
335 Xil_AssertNonvoid(BufferPtr != NULL);
336 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
339 * Disable all the interrupts.
340 * This stops a previous operation that may be interrupt driven
342 ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
344 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
348 * Setup the buffer parameters
350 InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes;
351 InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes;
352 InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr;
355 * Receive the data from the device
357 ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr);
360 * Restore the interrupt state
362 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET,
365 return ReceivedCount;
368 /****************************************************************************/
371 * This function sends a buffer that has been previously specified by setting
372 * up the instance variables of the instance. This function is an internal
373 * function for the XUartPs driver such that it may be called from a shell
374 * function that sets up the buffer or from an interrupt handler.
376 * This function sends the specified buffer in either polled or interrupt
377 * driven modes. This function is non-blocking.
379 * In a polled mode, this function only sends as much data as the TX FIFO
380 * can buffer. The application may need to call it repeatedly to send the
383 * In interrupt mode, this function starts the sending of the buffer, if not
384 * the entire buffer has been sent, then the interrupt handler continues the
385 * sending until the entire buffer has been sent. A callback function, as
386 * specified by the application, will be called to indicate the completion of
389 * @param InstancePtr is a pointer to the XUartPs instance
391 * @return The number of bytes actually sent
395 *****************************************************************************/
396 u32 XUartPs_SendBuffer(XUartPs *InstancePtr)
402 * If the TX FIFO is full, send nothing.
403 * Otherwise put bytes into the TX FIFO unil it is full, or all of the
404 * data has been put into the FIFO.
406 while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) &&
407 (InstancePtr->SendBuffer.RemainingBytes > SentCount)) {
410 * Fill the FIFO from the buffer
412 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
414 ((u32)InstancePtr->SendBuffer.
415 NextBytePtr[SentCount]));
418 * Increment the send count.
424 * Update the buffer to reflect the bytes that were sent from it
426 InstancePtr->SendBuffer.NextBytePtr += SentCount;
427 InstancePtr->SendBuffer.RemainingBytes -= SentCount;
430 * If interrupts are enabled as indicated by the receive interrupt, then
431 * enable the TX FIFO empty interrupt, so further action can be taken
435 XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
437 if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) ||
438 ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)||
439 ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) {
441 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
443 ImrRegister | (u32)XUARTPS_IXR_TXEMPTY);
449 /****************************************************************************/
452 * This function receives a buffer that has been previously specified by setting
453 * up the instance variables of the instance. This function is an internal
454 * function, and it may be called from a shell function that sets up the buffer
455 * or from an interrupt handler.
457 * This function attempts to receive a specified number of bytes from the
458 * device and store it into the specified buffer. This function works for
459 * either polled or interrupt driven modes. It is non-blocking.
461 * In polled mode, this function only receives as much data as in the RX FIFO.
462 * The application may need to call it repeatedly to receive the entire buffer.
463 * Polled mode is the default mode for the driver.
465 * In interrupt mode, this function starts the receiving, if not the entire
466 * buffer has been received, the interrupt handler will continue until the
467 * entire buffer has been received. A callback function, as specified by the
468 * application, will be called to indicate the completion of the receiving or
471 * @param InstancePtr is a pointer to the XUartPs instance
473 * @return The number of bytes received.
477 *****************************************************************************/
478 u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr)
481 u32 ReceivedCount = 0U;
484 * Read the Channel Status Register to determine if there is any data in
487 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
491 * Loop until there is no more data in RX FIFO or the specified
492 * number of bytes has been received
494 while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&&
495 (((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0))){
497 InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =
498 XUartPs_ReadReg(InstancePtr->Config.
500 XUARTPS_FIFO_OFFSET);
504 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
509 * Update the receive buffer to reflect the number of bytes just
512 if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL){
513 InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount;
515 InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;
517 return ReceivedCount;
520 /*****************************************************************************/
523 * Sets the baud rate for the device. Checks the input value for
524 * validity and also verifies that the requested rate can be configured to
525 * within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE.
526 * If the provided rate is not possible, the current setting is unchanged.
528 * @param InstancePtr is a pointer to the XUartPs instance
529 * @param BaudRate to be set
532 * - XST_SUCCESS if everything configured as expected
533 * - XST_UART_BAUD_ERROR if the requested rate is not available
534 * because there was too much error
538 *****************************************************************************/
539 s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate)
541 u32 IterBAUDDIV; /* Iterator for available baud divisor values */
542 u32 BRGR_Value; /* Calculated value for baud rate generator */
543 u32 CalcBaudRate; /* Calculated baud rate */
544 u32 BaudError; /* Diff between calculated and requested baud rate */
545 u32 Best_BRGR = 0U; /* Best value for baud rate generator */
546 u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */
547 u32 Best_Error = 0xFFFFFFFFU;
553 * Asserts validate the input arguments
555 Xil_AssertNonvoid(InstancePtr != NULL);
556 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
557 Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE);
558 Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE);
561 * Make sure the baud rate is not impossilby large.
562 * Fastest possible baud rate is Input Clock / 2.
564 if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) {
565 return XST_UART_BAUD_ERROR;
568 * Check whether the input clock is divided by 8
570 ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress,
573 InputClk = InstancePtr->Config.InputClockHz;
574 if(ModeReg & XUARTPS_MR_CLKSEL) {
575 InputClk = InstancePtr->Config.InputClockHz / 8;
579 * Determine the Baud divider. It can be 4to 254.
580 * Loop through all possible combinations
582 for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) {
585 * Calculate the value for BRGR register
587 BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1));
590 * Calculate the baud rate from the BRGR value
592 CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1));
595 * Avoid unsigned integer underflow
597 if (BaudRate > CalcBaudRate) {
598 BaudError = BaudRate - CalcBaudRate;
601 BaudError = CalcBaudRate - BaudRate;
605 * Find the calculated baud rate closest to requested baud rate.
607 if (Best_Error > BaudError) {
609 Best_BRGR = BRGR_Value;
610 Best_BAUDDIV = IterBAUDDIV;
611 Best_Error = BaudError;
616 * Make sure the best error is not too large.
618 PercentError = (Best_Error * 100) / BaudRate;
619 if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) {
620 return XST_UART_BAUD_ERROR;
624 * Disable TX and RX to avoid glitches when setting the baud rate.
626 XUartPs_DisableUart(InstancePtr);
628 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
629 XUARTPS_BAUDGEN_OFFSET, Best_BRGR);
630 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
631 XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV);
636 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET,
637 XUARTPS_CR_TXRST | XUARTPS_CR_RXRST);
642 XUartPs_EnableUart(InstancePtr);
644 InstancePtr->BaudRate = BaudRate;
650 /****************************************************************************/
653 * This function is a stub handler that is the default handler such that if the
654 * application has not set the handler when interrupts are enabled, this
655 * function will be called.
657 * @param CallBackRef is unused by this function.
658 * @param Event is unused by this function.
659 * @param ByteCount is unused by this function.
665 *****************************************************************************/
666 static void XUartPs_StubHandler(void *CallBackRef, u32 Event,
669 (void *) CallBackRef;
673 * Assert occurs always since this is a stub and should never be called
675 Xil_AssertVoidAlways();