/** * * Sets the options for the specified driver instance. The options are * implemented as bit masks such that multiple options may be enabled or * disabled simultaneously. * * The GetOptions function may be called to retrieve the currently enabled * options. The result is ORed in the desired new settings to be enabled and * ANDed with the inverse to clear the settings to be disabled. The resulting * value is then used as the options for the SetOption function call. * * @param InstancePtr is a pointer to the XUartNs550 instance. * @param Options contains the options to be set which are bit masks * contained in the file xuartns550.h and named XUN_OPTION_*. * * @return * - XST_SUCCESS if the options were set successfully. * - XST_UART_CONFIG_ERROR if the options could not be set because * the hardware does not support FIFOs * * @note None. * *****************************************************************************/ int XUartNs550_SetOptions(XUartNs550 *InstancePtr, u16 Options) { u32 Index; u32 Register; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Loop thru the options table to map the logical options to the * physical options in the registers of the UART */ for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) { /* * If the FIFO control register is being read, this is a * special case that requires special register processing */ if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) { Register = ReadFcrRegister(InstancePtr->BaseAddress); } else { /* * Read the register which contains option so that the * register can be changed without destoying any other * bits of the register */ Register = XUartNs550_ReadReg(InstancePtr->BaseAddress, OptionsTable[Index].RegisterOffset); } /* * If the option is set in the input, then set the * corresponding bit in the specified register, otherwise * clear the bit in the register */ if (Options & OptionsTable[Index].Option) { Register |= OptionsTable[Index].Mask; } else { Register &= ~OptionsTable[Index].Mask; } /* * Write the new value to the register to set the option */ XUartNs550_WriteReg(InstancePtr->BaseAddress, OptionsTable[Index].RegisterOffset, Register); } /* To be done, add error checks for enabling/resetting FIFOs */ return XST_SUCCESS; }
/** * * This functions reads the FIFO control register. It's primary purpose is to * isolate the special processing for reading this register. It is necessary * to write to the line control register, then read the FIFO control register, * and then restore the line control register. * * @param BaseAddress contains the base address of the registers in the * device. * * @return The contents of the FIFO control register. * * @note None. * *****************************************************************************/ static u32 ReadFcrRegister(u32 BaseAddress) { u32 LcrRegister; u32 FcrRegister; u32 IerRegister; /* * Enter a critical section here by disabling Uart interrupts. We do * not want to receive an interrupt while we have the FCR latched since * the interrupt handler may want to read the IIR */ IerRegister = XUartNs550_ReadReg(BaseAddress, XUN_IER_OFFSET); XUartNs550_WriteReg(BaseAddress, XUN_IER_OFFSET, 0); /* * Get the line control register contents and set the divisor latch * access bit so the FIFO control register can be read, this can't * be done with a true 16550, but is a feature in the Xilinx device */ LcrRegister = XUartNs550_GetLineControlReg(BaseAddress); XUartNs550_SetLineControlReg(BaseAddress, LcrRegister | XUN_LCR_DLAB); /* * Read the FIFO control register so it can be returned */ FcrRegister = XUartNs550_ReadReg(BaseAddress, XUN_FCR_OFFSET); /* * Restore the line control register to it's original contents such * that the DLAB bit is no longer set and return the register */ XUartNs550_SetLineControlReg(BaseAddress, LcrRegister); /* * Exit the critical section by restoring the IER */ XUartNs550_WriteReg(BaseAddress, XUN_IER_OFFSET, IerRegister); return FcrRegister; }
/** * * This function gets the modem status from the specified UART. The modem * status indicates any changes of the modem signals. This function allows * the modem status to be read in a polled mode. The modem status is updated * whenever it is read such that reading it twice may not yield the same * results. * * @param InstancePtr is a pointer to the XUartNs550 instance . * * @return The modem status which are bit masks that are contained in * the file xuartns550.h and named XUN_MODEM_*. * * @note * * The bit masks used for the modem status are the exact bits of the modem * status register with no abstraction. * *****************************************************************************/ u8 XUartNs550_GetModemStatus(XUartNs550 *InstancePtr) { u32 ModemStatusRegister; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); /* * Read the modem status register to return */ ModemStatusRegister = XUartNs550_ReadReg(InstancePtr->BaseAddress, XUN_MSR_OFFSET); return (u8) ModemStatusRegister; }
/** * * Gets the options for the specified driver instance. The options are * implemented as bit masks such that multiple options may be enabled or * disabled simulataneously. * * @param InstancePtr is a pointer to the XUartNs550 instance. * * @return The current options for the UART. The optionss are bit masks * that are contained in the file xuartns550.h and * named XUN_OPTION_*. * * @note None. * *****************************************************************************/ u16 XUartNs550_GetOptions(XUartNs550 *InstancePtr) { u16 Options = 0; u32 Register; u32 Index; /* * Assert validates the input arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Loop thru the options table to map the physical options in the * registers of the UART to the logical options to be returned */ for (Index = 0; Index < XUN_NUM_OPTIONS; Index++) { /* * If the FIFO control register is being read, the make sure to * setup the line control register so it can be read */ if (OptionsTable[Index].RegisterOffset == XUN_FCR_OFFSET) { Register = ReadFcrRegister(InstancePtr->BaseAddress); } else { Register = XUartNs550_ReadReg(InstancePtr->BaseAddress, OptionsTable[Index].RegisterOffset); } /* * If the bit in the register which correlates to the option * is set, then set the corresponding bit in the options, * ignoring any bits which are zero since the options variable * is initialized to zero */ if (Register & OptionsTable[Index].Mask) { Options |= OptionsTable[Index].Option; } } return Options; }
int hello_rotary(void) { unsigned int data; int pulses=0, dir=0; /*** XUartNs550_SetBaud(UART_BASEADDR, UART_CLOCK, UART_BAUDRATE); XUartNs550_mSetLineControlReg(UART_BASEADDR, XUN_LCR_8_DATA_BITS); ***/ xil_printf("\n\r********************************************************"); xil_printf("\n\r********************************************************"); xil_printf("\n\r** KC705 - Rotary Switch Test **"); xil_printf("\n\r********************************************************"); xil_printf("\n\r********************************************************\r\n"); xil_printf("Watch the ROTARY pulses count:\r\n"); xil_printf("press any key to exit the test\r\n"); XUartNs550_ReadReg(STDIN_BASEADDRESS, XUN_RBR_OFFSET); //set GPIO input mode XGpio_mSetDataReg(XPAR_ROTARY_GPIO_BASEADDR, 4, 0xffffffff); while(1) { ///////////////////////////////////// // STATE 1: Get the direction pulse //xil_printf(" \r\nState1 \r\n"); do { // get hold of a pulse that tells one of below // bits[1:0] = 01 Left rotation // bits[1:0] = 10 Right rotation // bit 2 = 1 button press data = XGpio_mGetDataReg(XPAR_ROTARY_GPIO_BASEADDR, 0); if(data & 0x1) { dir = DIR_LEFT; break; } if(data & 0x2) { dir = DIR_RIGHT; break; } if( XUartNs550_IsReceiveData(STDIN_BASEADDRESS) ) goto rotary_exit; } while( (data& 0x3) == 0); ////////////////////////////////////////////// // STATE 2: Get the pulses from both switches //xil_printf(" State2 \r\n"); do { data = XGpio_mGetDataReg(XPAR_ROTARY_GPIO_BASEADDR, 0); if( XUartNs550_IsReceiveData(STDIN_BASEADDRESS) ) goto rotary_exit; } while( (data& 0x3) != 0x3); ///////////////////////////////////////////////////// // STATE 3: Get the pulses from both switches to NULL //xil_printf(" State3 \r\n"); do { data = XGpio_mGetDataReg(XPAR_ROTARY_GPIO_BASEADDR, 0); if( XUartNs550_IsReceiveData(STDIN_BASEADDRESS) ) goto rotary_exit; } while( (data& 0x3) != 0); // PRESS ANY KEY TO EXIT if( XUartNs550_IsReceiveData(STDIN_BASEADDRESS) ) goto rotary_exit; // RESULT TO USER pulses += dir; xil_printf("%s-%d [Exit: press anykey]\r\n", (dir==DIR_RIGHT) ? "Anti-Clockwise" : " Clockwise", abs(pulses) ); } rotary_exit: XUartNs550_ReadReg(STDIN_BASEADDRESS, XUN_RBR_OFFSET); return 0; }
/** * * This functions 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 statistics are cleared at the end of the test. The time for this test * to execute is proportional to the baud rate that has been set prior to * calling this function. * * @param InstancePtr is a pointer to the XUartNs550 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. * ******************************************************************************/ int XUartNs550_SelfTest(XUartNs550 *InstancePtr) { int Status = XST_SUCCESS; u32 McrRegister; u32 LsrRegister; u32 IerRegister; u32 Index; /* * Assert validates the input arguments */ XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Setup for polling by disabling all interrupts in the interrupt enable * register */ IerRegister = XUartNs550_ReadReg(InstancePtr->BaseAddress, XUN_IER_OFFSET); XUartNs550_WriteReg(InstancePtr->BaseAddress, XUN_IER_OFFSET, 0); /* * Setup for loopback by enabling the loopback in the modem control * register */ McrRegister = XUartNs550_ReadReg(InstancePtr->BaseAddress, XUN_MCR_OFFSET); XUartNs550_WriteReg(InstancePtr->BaseAddress, XUN_MCR_OFFSET, McrRegister | XUN_MCR_LOOP); /* * Send a number of bytes and receive them, one at a time so this * test will work for 450 and 550 */ for (Index = 0; Index < XUN_TOTAL_BYTES; Index++) { /* * Send out the byte and if it was not sent then the failure * will be caught in the compare at the end */ XUartNs550_Send(InstancePtr, &TestString[Index], 1); /* * Wait til the byte is received such that it should be waiting * in the receiver. This can hang if the HW is broken */ do { LsrRegister = XUartNs550_GetLineStatusReg(InstancePtr->BaseAddress); } while ((LsrRegister & XUN_LSR_DATA_READY) == 0); /* * Receive the byte that should have been received because of * the loopback, if it wasn't received then it will be caught * in the compare at the end */ XUartNs550_Recv(InstancePtr, &ReturnString[Index], 1); } /* * Clear the stats since they are corrupted by the test */ XUartNs550_ClearStats(InstancePtr); /* * Compare the bytes received to the bytes sent to verify the exact data * was received */ for (Index = 0; Index < XUN_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 */ XUartNs550_WriteReg(InstancePtr->BaseAddress, XUN_IER_OFFSET, IerRegister); XUartNs550_WriteReg(InstancePtr->BaseAddress, XUN_MCR_OFFSET, McrRegister); return Status; }