/* * * This function sends a buffer that has been previously specified by setting * up the instance variables of the instance. This function is an internal * function for the XUartPs driver such that it may be called from a shell * function that sets up the buffer or from an interrupt handler. * * This function sends the specified buffer in either polled or interrupt * driven modes. This function is non-blocking. * * In a polled mode, this function only sends as much data as the TX FIFO * can buffer. The application may need to call it repeatedly to send the * entire buffer. * * In interrupt mode, this function starts the sending of the buffer, if not * the entire buffer has been sent, then the interrupt handler continues the * sending until the entire buffer has been sent. A callback function, as * specified by the application, will be called to indicate the completion of * sending. * * @param InstancePtr is a pointer to the XUartPs instance * * @return The number of bytes actually sent * * @note None. * *****************************************************************************/ u32 XUartPs_SendBuffer(XUartPs *InstancePtr) { u32 SentCount = 0U; u32 ImrRegister; /* * If the TX FIFO is full, send nothing. * Otherwise put bytes into the TX FIFO unil it is full, or all of the * data has been put into the FIFO. */ while ((!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress)) && (InstancePtr->SendBuffer.RemainingBytes > SentCount)) { /* * Fill the FIFO from the buffer */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_FIFO_OFFSET, ((u32)InstancePtr->SendBuffer. NextBytePtr[SentCount])); /* * Increment the send count. */ SentCount++; } /* * Update the buffer to reflect the bytes that were sent from it */ InstancePtr->SendBuffer.NextBytePtr += SentCount; InstancePtr->SendBuffer.RemainingBytes -= SentCount; /* * If interrupts are enabled as indicated by the receive interrupt, then * enable the TX FIFO empty interrupt, so further action can be taken * for this sending. */ ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_IMR_OFFSET); if (((ImrRegister & XUARTPS_IXR_RXFULL) != (u32)0) || ((ImrRegister & XUARTPS_IXR_RXEMPTY) != (u32)0)|| ((ImrRegister & XUARTPS_IXR_RXOVR) != (u32)0)) { XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, ImrRegister | (u32)XUARTPS_IXR_TXEMPTY); } return SentCount; }
/** * * This function handles the interrupt when data has been sent, the transmit * FIFO is empty (transmitter holding register). * * @param InstancePtr is a pointer to the XUartPs instance * @param IsrStatus is the register value for channel status register * * @return None. * * @note None. * *****************************************************************************/ static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus) { /* * If there are not bytes to be sent from the specified buffer then disable * the transmit interrupt so it will stop interrupting as it interrupts * any time the FIFO is empty */ if (InstancePtr->SendBuffer.RemainingBytes == (u32)0) { XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)); /* Call the application handler to indicate the sending is done */ InstancePtr->Handler(InstancePtr->CallBackRef, XUARTPS_EVENT_SENT_DATA, InstancePtr->SendBuffer.RequestedBytes - InstancePtr->SendBuffer.RemainingBytes); } /* * If TX FIFO is empty, send more. */ else if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) { (void)XUartPs_SendBuffer(InstancePtr); } else { /* Else with dummy entry for MISRA-C Compliance.*/ ; } }
/** * * This functions sends the specified buffer using the device in either * polled or interrupt driven mode. This function is non-blocking, if the device * is busy sending data, it will return and indicate zero bytes were sent. * Otherwise, it fills the TX FIFO as much as it can, and return the number of * bytes sent. * * In a polled mode, this function will only send as much data as TX FIFO can * buffer. The application may need to call it repeatedly to send the entire * buffer. * * In interrupt mode, this function will start sending the specified buffer, * then the interrupt handler will continue sending data until the entire * buffer has been sent. A callback function, as specified by the application, * will be called to indicate the completion of sending. * * @param InstancePtr is a pointer to the XUartPs instance. * @param BufferPtr is pointer to a buffer of data to be sent. * @param NumBytes contains the number of bytes to be sent. A value of * zero will stop a previous send operation that is in progress * in interrupt mode. Any data that was already put into the * transmit FIFO will be sent. * * @return The number of bytes actually sent. * * @note * * The number of bytes is not asserted so that this function may be called with * a value of zero to stop an operation that is already in progress. * <br><br> * *****************************************************************************/ u32 XUartPs_Send(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes) { u32 BytesSent; /* * Asserts validate the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(BufferPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Disable the UART transmit interrupts to allow this call to stop a * previous operation that may be interrupt driven. */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL)); /* * Setup the buffer parameters */ InstancePtr->SendBuffer.RequestedBytes = NumBytes; InstancePtr->SendBuffer.RemainingBytes = NumBytes; InstancePtr->SendBuffer.NextBytePtr = BufferPtr; /* * Transmit interrupts will be enabled in XUartPs_SendBuffer(), after * filling the TX FIFO. */ BytesSent = XUartPs_SendBuffer(InstancePtr); return BytesSent; }
/** * * This function sets the interrupt mask. * * @param InstancePtr is a pointer to the XUartPs instance * @param Mask contains the interrupts to be enabled or disabled. * A '1' enables an interupt, and a '0' disables. * * @return None. * * @note None. * *****************************************************************************/ void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask) { u32 TempMask = Mask; /* Assert validates the input arguments */ Xil_AssertVoid(InstancePtr != NULL); TempMask &= (u32)XUARTPS_IXR_MASK; /* Write the mask to the IER Register */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, TempMask); /* Write the inverse of the Mask to the IDR register */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, (~TempMask)); }
/** * * This function is the interrupt handler for the driver. * It must be connected to an interrupt system by the application such that it * can be called when an interrupt occurs. * * @param InstancePtr contains a pointer to the driver instance * * @return None. * * @note None. * ******************************************************************************/ void XUartPs_InterruptHandler(XUartPs *InstancePtr) { u32 IsrStatus; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read the interrupt ID register to determine which * interrupt is active */ IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_IMR_OFFSET); IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET); /* * Dispatch an appropriate handler. */ if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | (u32)XUARTPS_IXR_RXFULL)) != (u32)0) { /* Received data interrupt */ ReceiveDataHandler(InstancePtr); } if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL)) != (u32)0) { /* Transmit data interrupt */ SendDataHandler(InstancePtr, IsrStatus); } if((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING | (u32)XUARTPS_IXR_PARITY)) != (u32)0) { /* Received Error Status interrupt */ ReceiveErrorHandler(InstancePtr); } if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) { /* Received Timeout interrupt */ ReceiveTimeoutHandler(InstancePtr); } if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) { /* Modem status interrupt */ ModemHandler(InstancePtr); } /* * Clear the interrupt status. */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, IsrStatus); }
/** * * This function attempts to receive a specified number of bytes of data * from the device and store it into the specified buffer. This function works * for both polled or interrupt driven modes. It is non-blocking. * * In a polled mode, this function will only receive the data already in the * RX FIFO. The application may need to call it repeatedly to receive the * entire buffer. Polled mode is the default mode of operation for the device. * * In interrupt mode, this function will start the receiving, if not the entire * buffer has been received, the interrupt handler will continue receiving data * until the entire buffer has been received. A callback function, as specified * by the application, will be called to indicate the completion of the * receiving or error conditions. * * @param InstancePtr is a pointer to the XUartPs instance * @param BufferPtr is pointer to buffer for data to be received into * @param NumBytes is the number of bytes to be received. A value of zero * will stop a previous receive operation that is in progress in * interrupt mode. * * @return The number of bytes received. * * @note * * The number of bytes is not asserted so that this function may be called * with a value of zero to stop an operation that is already in progress. * *****************************************************************************/ u32 XUartPs_Recv(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes) { u32 ReceivedCount; u32 ImrRegister; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(BufferPtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Disable all the interrupts. * This stops a previous operation that may be interrupt driven */ ImrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_IMR_OFFSET); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); /* * Setup the buffer parameters */ InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes; InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes; InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr; /* * Receive the data from the device */ ReceivedCount = XUartPs_ReceiveBuffer(InstancePtr); /* * Restore the interrupt state */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, ImrRegister); return ReceivedCount; }
/** * * This function sends one byte using the device. This function operates in * polled mode and blocks until the data has been put into the TX FIFO register. * * @param BaseAddress contains the base address of the device. * @param Data contains the byte to be sent. * * @return None. * * @note None. * *****************************************************************************/ void XUartPs_SendByte(u32 BaseAddress, u8 Data) { /* * Wait until there is space in TX FIFO */ while (XUartPs_IsTransmitFull(BaseAddress)); /* * Write the byte into the TX FIFO */ XUartPs_WriteReg(BaseAddress, XUARTPS_FIFO_OFFSET, Data); }
/* * See the serial2.h header file. */ xComPortHandle xSerialPortInitMinimal( uint32_t ulWantedBaud, UBaseType_t uxQueueLength ) { BaseType_t xStatus; XUartPs_Config *pxConfig; /* Create the queue used to hold received characters. NOTE THE COMMENTS AT THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPSOE. */ xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) ); configASSERT( xRxQueue ); /* Create the semaphore used to signal the end of a transmission, then take the semaphore so it is in the correct state the first time xSerialSendString() is called. A block time of zero is used when taking the semaphore as it is guaranteed to be available (it was just created). */ xTxCompleteSemaphore = xSemaphoreCreateBinary(); configASSERT( xTxCompleteSemaphore ); xSemaphoreTake( xTxCompleteSemaphore, 0 ); /* Look up the UART configuration then initialise the dirver. */ pxConfig = XUartPs_LookupConfig( XPAR_XUARTPS_0_DEVICE_ID ); /* Initialise the driver. */ xStatus = XUartPs_CfgInitialize( &xUARTInstance, pxConfig, XPAR_PS7_UART_1_BASEADDR ); configASSERT( xStatus == XST_SUCCESS ); ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ /* Misc. parameter configuration. */ XUartPs_SetBaudRate( &xUARTInstance, ulWantedBaud ); XUartPs_SetOperMode( &xUARTInstance, XUARTPS_OPER_MODE_NORMAL ); /* Install the interrupt service routine that is defined within this file. */ xStatus = XScuGic_Connect( &xInterruptController, XPAR_XUARTPS_1_INTR, (Xil_ExceptionHandler) prvUART_Handler, (void *) &xUARTInstance ); configASSERT( xStatus == XST_SUCCESS ); ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */ /* Ensure interrupts start clear. */ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK ); /* Enable the UART interrupt within the GIC. */ XScuGic_Enable( &xInterruptController, XPAR_XUARTPS_1_INTR ); /* Enable the interrupts of interest in the UART. */ XUartPs_SetInterruptMask( &xUARTInstance, XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT | XUARTPS_IXR_TXEMPTY ); /* Set the receive timeout. */ XUartPs_SetRecvTimeout( &xUARTInstance, 8 ); return ( xComPortHandle ) 0; }
/* ---------------------------------------------------------------------------- * * menu() * * ---------------------------------------------------------------------------- * * Presented at system startup. Allows the user to select between three * options by pressing certain keys on the keyboard: * 's' - Audio loopback streaming * 'n' - Tonal noise is generated by an NCO and added to the audio * being captured from the audio codec. * 'f' - The audio + tonal noise is passed to an adaptive LMS noise * cancellation filter which will use the tonal noise estimate * to remove the noise from the audio. * * This menu is shown upon exiting from any of the above options. * ---------------------------------------------------------------------------- */ void menu(){ u8 inp = 0x00; u32 CntrlRegister; /* Turn off all LEDs */ Xil_Out32(LED_BASE, 0); CntrlRegister = XUartPs_ReadReg(UART_BASEADDR, XUARTPS_CR_OFFSET); XUartPs_WriteReg(UART_BASEADDR, XUARTPS_CR_OFFSET, ((CntrlRegister & ~XUARTPS_CR_EN_DIS_MASK) | XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN)); xil_printf("\r\n\r\n"); xil_printf("Embedded LMS Filtering Demo\r\n"); xil_printf("Enter 's' to stream pure audio, 'n' to add tonal noise and 'f' to adaptively filter\r\n"); xil_printf("----------------------------------------\r\n"); // Wait for input from UART via the terminal while (!XUartPs_IsReceiveData(UART_BASEADDR)); inp = XUartPs_ReadReg(UART_BASEADDR, XUARTPS_FIFO_OFFSET); // Select function based on UART input switch(inp){ case 's': xil_printf("STREAMING AUDIO\r\n"); xil_printf("Press 'q' to return to the main menu\r\n"); audio_stream(); break; case 'n': xil_printf("ENTERING NOISE GENERATION OPERATION\r\n"); xil_printf("Select step size via the DIP switches...\r\n\n"); xil_printf("Press 'q' to return to the main menu\r\n"); tonal_noise(); break; case 'f': xil_printf("ENTERING LMS FILTERING OPERATION\r\n"); xil_printf("Press 'q' to return to the main menu\r\n"); lms_filter(); break; default: menu(); break; } // switch } // menu()
/** * * This function does a minimal test on the UART device using the hardware * interface. * * @param UartBaseAddress is the base address of the device * * @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful * * @note None. * **************************************************************************/ int UartPsEchoExample(u32 UartBaseAddress) { int Index; u32 Running; u8 RecvChar; u32 CntrlRegister; CntrlRegister = XUartPs_ReadReg(UartBaseAddress, XUARTPS_CR_OFFSET); /* * Enable TX and RX for the device */ XUartPs_WriteReg(UartBaseAddress, XUARTPS_CR_OFFSET, ((CntrlRegister & ~XUARTPS_CR_EN_DIS_MASK) | XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN)); /* * Initialize the send buffer bytes with a pattern to send and the * the receive buffer bytes to zero */ for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { SendBuffer[Index] = Index + '0'; } /* * Send the entire transmit buffer. */ for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { /* * Wait until there is space in TX FIFO */ while (XUartPs_IsTransmitFull(UartBaseAddress)); /* * Write the byte into the TX FIFO */ XUartPs_WriteReg(UartBaseAddress, XUARTPS_FIFO_OFFSET, SendBuffer[Index]); } Running = TRUE; while (Running) { /* * Wait until there is data */ while (!XUartPs_IsReceiveData(UartBaseAddress)); RecvChar = XUartPs_ReadReg(UartBaseAddress, XUARTPS_FIFO_OFFSET); /* Change the capitalization */ if (('a' <= RecvChar) && ('z' >= RecvChar)) { // Convert the Capital letter to a small. RecvChar = RecvChar - 'a' + 'A'; } else if (('A' <= RecvChar) && ('Z' >= RecvChar)) { // Convert the small letter to a Capital. RecvChar = RecvChar - 'A' + 'a'; } else if (CHAR_ESC == RecvChar) { Running = FALSE; } /* Echo the character back */ XUartPs_WriteReg(UartBaseAddress, XUARTPS_FIFO_OFFSET, RecvChar); } return XST_SUCCESS; }
/** * * This function resets UART * * @param BaseAddress contains the base address of the device. * * @return None * * @note None. * *****************************************************************************/ void XUartPs_ResetHw(u32 BaseAddress) { /* * Disable interrupts */ XUartPs_WriteReg(BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); /* * Disable receive and transmit */ XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS); /* * Software reset of receive and transmit * This clears the FIFO. */ XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); /* * Clear status flags - SW reset wont clear sticky flags. */ XUartPs_WriteReg(BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK); /* * Mode register reset value : All zeroes * Normal mode, even parity, 1 stop bit */ XUartPs_WriteReg(BaseAddress, XUARTPS_MR_OFFSET, XUARTPS_MR_CHMODE_NORM); /* * Rx and TX trigger register reset values */ XUartPs_WriteReg(BaseAddress, XUARTPS_RXWM_OFFSET, XUARTPS_RXWM_RESET_VAL); XUartPs_WriteReg(BaseAddress, XUARTPS_TXWM_OFFSET, XUARTPS_TXWM_RESET_VAL); /* * Rx timeout disabled by default */ XUartPs_WriteReg(BaseAddress, XUARTPS_RXTOUT_OFFSET, XUARTPS_RXTOUT_DISABLE); /* * Baud rate generator and dividor reset values */ XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDGEN_OFFSET, XUARTPS_BAUDGEN_RESET_VAL); XUartPs_WriteReg(BaseAddress, XUARTPS_BAUDDIV_OFFSET, XUARTPS_BAUDDIV_RESET_VAL); /* * Control register reset value - * RX and TX are disable by default */ XUartPs_WriteReg(BaseAddress, XUARTPS_CR_OFFSET, XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS | XUARTPS_CR_STOPBRK); }
void prvUART_Handler( void *pvNotUsed ) { extern unsigned int XUartPs_SendBuffer( XUartPs *InstancePtr ); uint32_t ulActiveInterrupts, ulChannelStatusRegister; BaseType_t xHigherPriorityTaskWoken = pdFALSE; char cChar; configASSERT( pvNotUsed == &xUARTInstance ); /* Remove compile warnings if configASSERT() is not defined. */ ( void ) pvNotUsed; /* Read the interrupt ID register to see which interrupt is active. */ ulActiveInterrupts = XUartPs_ReadReg(XPAR_PS7_UART_1_BASEADDR, XUARTPS_IMR_OFFSET); ulActiveInterrupts &= XUartPs_ReadReg(XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET); /* Are any receive events of interest active? */ if( ( ulActiveInterrupts & serRECEIVE_INTERRUPT_MASK ) != 0 ) { /* Read the Channel Status Register to determine if there is any data in the RX FIFO. */ ulChannelStatusRegister = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_SR_OFFSET ); /* Move data from the Rx FIFO to the Rx queue. NOTE THE COMMENTS AT THE TOP OF THIS FILE ABOUT USING QUEUES FOR THIS PURPSOE. */ while( ( ulChannelStatusRegister & XUARTPS_SR_RXEMPTY ) == 0 ) { cChar = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_FIFO_OFFSET ); /* If writing to the queue unblocks a task, and the unblocked task has a priority above the currently running task (the task that this interrupt interrupted), then xHigherPriorityTaskWoken will be set to pdTRUE inside the xQueueSendFromISR() function. xHigherPriorityTaskWoken is then passed to portYIELD_FROM_ISR() at the end of this interrupt handler to request a context switch so the interrupt returns directly to the (higher priority) unblocked task. */ xQueueSendFromISR( xRxQueue, &cChar, &xHigherPriorityTaskWoken ); ulChannelStatusRegister = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_SR_OFFSET ); } } /* Are any transmit events of interest active? */ if( ( ulActiveInterrupts & serTRANSMIT_IINTERRUPT_MASK ) != 0 ) { if( xUARTInstance.SendBuffer.RemainingBytes == 0 ) { /* Give back the semaphore to indicate that the tranmission is complete. If giving the semaphore unblocks a task, and the unblocked task has a priority above the currently running task (the task that this interrupt interrupted), then xHigherPriorityTaskWoken will be set to pdTRUE inside the xSemaphoreGiveFromISR() function. xHigherPriorityTaskWoken is then passed to portYIELD_FROM_ISR() at the end of this interrupt handler to request a context switch so the interrupt returns directly to the (higher priority) unblocked task. */ xSemaphoreGiveFromISR( xTxCompleteSemaphore, &xHigherPriorityTaskWoken ); /* No more data to transmit. */ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_IDR_OFFSET, XUARTPS_IXR_TXEMPTY ); } else { /* More data to send. */ XUartPs_SendBuffer( &xUARTInstance ); } } /* portYIELD_FROM_ISR() will request a context switch if executing this interrupt handler caused a task to leave the blocked state, and the task that left the blocked state has a higher priority than the currently running task (the task this interrupt interrupted). See the comment above the calls to xSemaphoreGiveFromISR() and xQueueSendFromISR() within this function. */ portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); /* Clear the interrupt status. */ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET, ulActiveInterrupts ); }
/** * * Sets the baud rate for the device. Checks the input value for * validity and also verifies that the requested rate can be configured to * within the maximum error range specified by XUARTPS_MAX_BAUD_ERROR_RATE. * If the provided rate is not possible, the current setting is unchanged. * * @param InstancePtr is a pointer to the XUartPs instance * @param BaudRate to be set * * @return * - XST_SUCCESS if everything configured as expected * - XST_UART_BAUD_ERROR if the requested rate is not available * because there was too much error * * @note None. * *****************************************************************************/ s32 XUartPs_SetBaudRate(XUartPs *InstancePtr, u32 BaudRate) { u32 IterBAUDDIV; /* Iterator for available baud divisor values */ u32 BRGR_Value; /* Calculated value for baud rate generator */ u32 CalcBaudRate; /* Calculated baud rate */ u32 BaudError; /* Diff between calculated and requested baud rate */ u32 Best_BRGR = 0U; /* Best value for baud rate generator */ u8 Best_BAUDDIV = 0U; /* Best value for baud divisor */ u32 Best_Error = 0xFFFFFFFFU; u32 PercentError; u32 ModeReg; u32 InputClk; /* * Asserts validate the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(BaudRate <= (u32)XUARTPS_MAX_RATE); Xil_AssertNonvoid(BaudRate >= (u32)XUARTPS_MIN_RATE); /* * Make sure the baud rate is not impossilby large. * Fastest possible baud rate is Input Clock / 2. */ if ((BaudRate * 2) > InstancePtr->Config.InputClockHz) { return XST_UART_BAUD_ERROR; } /* * Check whether the input clock is divided by 8 */ ModeReg = XUartPs_ReadReg( InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET); InputClk = InstancePtr->Config.InputClockHz; if(ModeReg & XUARTPS_MR_CLKSEL) { InputClk = InstancePtr->Config.InputClockHz / 8; } /* * Determine the Baud divider. It can be 4to 254. * Loop through all possible combinations */ for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++) { /* * Calculate the value for BRGR register */ BRGR_Value = InputClk / (BaudRate * (IterBAUDDIV + 1)); /* * Calculate the baud rate from the BRGR value */ CalcBaudRate = InputClk/ (BRGR_Value * (IterBAUDDIV + 1)); /* * Avoid unsigned integer underflow */ if (BaudRate > CalcBaudRate) { BaudError = BaudRate - CalcBaudRate; } else { BaudError = CalcBaudRate - BaudRate; } /* * Find the calculated baud rate closest to requested baud rate. */ if (Best_Error > BaudError) { Best_BRGR = BRGR_Value; Best_BAUDDIV = IterBAUDDIV; Best_Error = BaudError; } } /* * Make sure the best error is not too large. */ PercentError = (Best_Error * 100) / BaudRate; if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError) { return XST_UART_BAUD_ERROR; } /* * Disable TX and RX to avoid glitches when setting the baud rate. */ XUartPs_DisableUart(InstancePtr); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_BAUDGEN_OFFSET, Best_BRGR); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_BAUDDIV_OFFSET, Best_BAUDDIV); /* * RX and TX SW reset */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET, XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); /* * Enable device */ XUartPs_EnableUart(InstancePtr); InstancePtr->BaudRate = BaudRate; return XST_SUCCESS; }
/** * * Initializes a specific XUartPs instance such that it is ready to be used. * The data format of the device is setup for 8 data bits, 1 stop bit, and no * parity by default. The baud rate is set to a default value specified by * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The * receive FIFO threshold is set for 8 bytes. The default operating mode of the * driver is polled mode. * * @param InstancePtr is a pointer to the XUartPs instance. * @param Config is a reference to a structure containing information * about a specific XUartPs driver. * @param EffectiveAddr is the device base address in the virtual memory * address space. The caller is responsible for keeping the address * mapping from EffectiveAddr to the device physical base address * unchanged once this function is invoked. Unexpected errors may * occur if the address mapping changes after this function is * called. If address translation is not used, pass in the physical * address instead. * * @return * * - XST_SUCCESS if initialization was successful * - XST_UART_BAUD_ERROR if the baud rate is not possible because * the inputclock frequency is not divisible with an acceptable * amount of error * * @note * * The default configuration for the UART after initialization is: * * - 19,200 bps or XPAR_DFT_BAUDRATE if defined * - 8 data bits * - 1 stop bit * - no parity * - FIFO's are enabled with a receive threshold of 8 bytes * - The RX timeout is enabled with a timeout of 1 (4 char times) * * All interrupts are disabled. * *****************************************************************************/ s32 XUartPs_CfgInitialize(XUartPs *InstancePtr, XUartPs_Config * Config, u32 EffectiveAddr) { s32 Status; u32 ModeRegister; u32 BaudRate; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Config != NULL); /* * Setup the driver instance using passed in parameters */ InstancePtr->Config.BaseAddress = EffectiveAddr; InstancePtr->Config.InputClockHz = Config->InputClockHz; InstancePtr->Config.ModemPinsConnected = Config->ModemPinsConnected; /* * Initialize other instance data to default values */ InstancePtr->Handler = XUartPs_StubHandler; InstancePtr->SendBuffer.NextBytePtr = NULL; InstancePtr->SendBuffer.RemainingBytes = 0U; InstancePtr->SendBuffer.RequestedBytes = 0U; InstancePtr->ReceiveBuffer.NextBytePtr = NULL; InstancePtr->ReceiveBuffer.RemainingBytes = 0U; InstancePtr->ReceiveBuffer.RequestedBytes = 0U; /* * Flag that the driver instance is ready to use */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; /* * Set the default baud rate here, can be changed prior to * starting the device */ BaudRate = (u32)XUARTPS_DFT_BAUDRATE; Status = XUartPs_SetBaudRate(InstancePtr, BaudRate); if (Status != (s32)XST_SUCCESS) { InstancePtr->IsReady = 0U; } else { /* * Set up the default data format: 8 bit data, 1 stop bit, no * parity */ ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET); /* * Mask off what's already there */ ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK | (u32)XUARTPS_MR_STOPMODE_MASK | (u32)XUARTPS_MR_PARITY_MASK)); /* * Set the register value to the desired data format */ ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT | (u32)XUARTPS_MR_STOPMODE_1_BIT | (u32)XUARTPS_MR_PARITY_NONE); /* * Write the mode register out */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, ModeRegister); /* * Set the RX FIFO trigger at 8 data bytes. */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_RXWM_OFFSET, 0x08U); /* * Set the RX timeout to 1, which will be 4 character time */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_RXTOUT_OFFSET, 0x01U); /* * Disable all interrupts, polled mode is the default */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); Status = XST_SUCCESS; } return Status; }
/** * * This function runs a self-test on the driver and hardware device. This self * test performs a local loopback and verifies data can be sent and received. * * The time for this test is proportional to the baud rate that has been set * prior to calling this function. * * The mode and control registers are restored before return. * * @param InstancePtr is a pointer to the XUartPs instance * * @return * - XST_SUCCESS if the test was successful * - XST_UART_TEST_FAIL if the test failed looping back the data * * @note * * This function can hang if the hardware is not functioning properly. * ******************************************************************************/ s32 XUartPs_SelfTest(XUartPs *InstancePtr) { s32 Status = XST_SUCCESS; u32 IntrRegister; u32 ModeRegister; u8 Index; u32 ReceiveDataResult; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Disable all interrupts in the interrupt disable register */ IntrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_IMR_OFFSET); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK); /* * Setup for local loopback */ ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, ((ModeRegister & (u32)(~XUARTPS_MR_CHMODE_MASK)) | (u32)XUARTPS_MR_CHMODE_L_LOOP)); /* * Send a number of bytes and receive them, one at a time. */ for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { /* * Send out the byte and if it was not sent then the failure * will be caught in the comparison at the end */ (void)XUartPs_Send(InstancePtr, &TestString[Index], 1U); /* * Wait until the byte is received. This can hang if the HW * is broken. Watch for the FIFO empty flag to be false. */ ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY; while (ReceiveDataResult == XUARTPS_SR_RXEMPTY ) { ReceiveDataResult = Xil_In32((InstancePtr->Config.BaseAddress) + XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY; } /* * Receive the byte */ (void)XUartPs_Recv(InstancePtr, &ReturnString[Index], 1U); } /* * Compare the bytes received to the bytes sent to verify the exact data * was received */ for (Index = 0U; Index < XUARTPS_TOTAL_BYTES; Index++) { if (TestString[Index] != ReturnString[Index]) { Status = XST_UART_TEST_FAIL; } } /* * Restore the registers which were altered to put into polling and * loopback modes so that this test is not destructive */ XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, IntrRegister); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET, ModeRegister); return Status; }