/* * uart.c * * Created on: Nov 10, 2014 * Author: ucart */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "uart.h" #include <xuartps.h> #include <xstatus.h> // Global PS's XUartPs* _Uart0PS; XUartPs* _Uart1PS; static INTC Intc; //This is copied from xuart driver /***************************************************/ #define XUARTPS_MAX_BAUD_ERROR_RATE 3 /* max % error allowed */ int XUartPs_SetBaudRate_ours(XUartPs *InstancePtr, u32 BaudRate) { u8 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 = 0; /* Best value for baud rate generator */ u8 Best_BAUDDIV = 0; /* Best value for baud divisor */ u32 Best_Error = 0xFFFFFFFF; 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 <= XUARTPS_MAX_RATE); Xil_AssertNonvoid(BaudRate >= 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); /* * Enable device */ XUartPs_EnableUart(InstancePtr); InstancePtr->BaudRate = BaudRate; return XST_SUCCESS; } /***************************************************/ /************************************************/ /************** Main UART Interface *************/ XUartPs* uart_init(XUartPs* uartps_ptr, u16 deviceID, int baudRate) { XUartPs_Config* config = XUartPs_LookupConfig(deviceID); //Configure XUartPs instance int Status = XUartPs_CfgInitialize(uartps_ptr, config, config->BaseAddress); if (Status != XST_SUCCESS){ return NULL; } //Set Baudrate for BT //XUartPs_SetBaudRate(uartps_ptr, baudRate); XUartPs_SetBaudRate_ours(uartps_ptr, baudRate); return uartps_ptr; } void uart_clearFIFOs(XUartPs* uartps_ptr) { //Get UART0 Control Register and clear the TX and RX Fifos int* uart_ctrl_reg = (int*) uartps_ptr->Config.BaseAddress; *uart_ctrl_reg |= 0x00000003; // clear TX & RX } void uart_sendByte(XUartPs* uartps_ptr, char data) { XUartPs_SendByte(uartps_ptr->Config.BaseAddress, data); } void uart_sendStr(XUartPs* uartps_ptr, char* str) { uart_sendBytes(uartps_ptr, str, strlen(str)); } void uart_sendBytes(XUartPs* uartps_ptr, char* data, int numBytes) { while (uart_isSending(uartps_ptr)) ; int done = 0; while (done < numBytes) { done += XUartPs_Send(uartps_ptr, (unsigned char*) (&data[done]), numBytes - done); } } int uart_isSending(XUartPs* uartps_ptr) { return XUartPs_IsSending(uartps_ptr); } int uart_hasData(XUartPs* uartps_ptr) { return XUartPs_IsReceiveData(uartps_ptr->Config.BaseAddress); } void uart_recvBytes(XUartPs* uartps_ptr, char* buffer, int numBytes) { int received = 0; while (received < numBytes) { received += XUartPs_Recv(uartps_ptr, (unsigned char*) &buffer[received], (numBytes - received)); } } char uart_recvByte(XUartPs* uartps_ptr) { return XUartPs_RecvByte(uartps_ptr->Config.BaseAddress); //char buffer[1]; //XUartPs_Recv(uartps_ptr, (unsigned char*) &buffer[0], 1); // return buffer[0]; } /*****************************************************************************/ /** * * This function sets up the interrupt system so interrupts can occur for the * Uart. This function is application-specific. * * @param IntcInstancePtr is a pointer to the instance of the INTC. * @param UartInstancePtr contains a pointer to the instance of the UART * driver which is going to be connected to the interrupt * controller. * @param UartIntrId is the interrupt Id and is typically * XPAR_<UARTPS_instance>_INTR value from xparameters.h. * * @return XST_SUCCESS if successful, otherwise XST_FAILURE. * * @note None. * ****************************************************************************/ int SetupInterruptSystem(XUartPs *UartInstancePtr, u16 UartIntrId, Xil_ExceptionHandler handler) { int Status; XScuGic_Config *IntcConfig; /* Config for interrupt controller */ /* Initialize the interrupt controller driver */ IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == IntcConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(&Intc, IntcConfig, IntcConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect the interrupt controller interrupt handler to the * hardware interrupt handling logic in the processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, &Intc); /* * Connect a device driver handler that will be called when an * interrupt for the device occurs, the device driver handler * performs the specific interrupt processing for the device */ Status = XScuGic_Connect(&Intc, UartIntrId, handler, (void *) UartInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* Enable the interrupt for the device */ XScuGic_Enable(&Intc, UartIntrId); /* Enable interrupts */ Xil_ExceptionEnable(); return XST_SUCCESS; } /************************************************/ /************************************************/ /************************************************/ /********** UART 0 convenience methods **********/ XUartPs* uart0_init(u16 deviceID, int baudRate){ if (_Uart0PS) { free(_Uart0PS); } _Uart0PS = malloc(sizeof(XUartPs)); return uart_init(_Uart0PS, deviceID, baudRate); } // Initializes the interrupt system for UART 0 int uart0_int_init(u16 UartIntrId, Xil_ExceptionHandler handler) { return SetupInterruptSystem(_Uart0PS, UartIntrId, handler); } void uart0_clearFIFOs(){ uart_clearFIFOs(_Uart0PS); } void uart0_sendByte(u8 data){ uart_sendByte(_Uart0PS, data); } void uart0_sendStr(char* str) { uart_sendStr(_Uart0PS, str); } void uart0_sendMetaData(metadata_t md) { uart0_sendByte(md.begin_char); uart0_sendByte(md.msg_type & 0x00ff); uart0_sendByte((md.msg_type >> 8) & 0x00ff); uart0_sendByte(md.msg_id & 0x00ff); uart0_sendByte((md.msg_id >> 8) & 0x00ff); uart0_sendByte(md.data_len & 0x00ff); uart0_sendByte((md.data_len >> 8) & 0x00ff); } void uart0_sendBytes(char* data, int numBytes){ uart_sendBytes(_Uart0PS, data, numBytes); } int uart0_isSending(){ return uart_isSending(_Uart0PS); } int uart0_hasData(){ return uart_hasData(_Uart0PS); } void uart0_recvBytes(char* buffer, int numBytes) { uart_recvBytes(_Uart0PS, buffer, numBytes); } char uart0_recvByte() { return uart_recvByte(_Uart0PS); } /************************************************/ /************************************************/ /************************************************/ /********** UART 1 convenience methods **********/ XUartPs* uart1_init(u16 deviceID, int baudRate){ if (_Uart1PS) { free(_Uart1PS); } _Uart1PS = malloc(sizeof(XUartPs)); return uart_init(_Uart1PS, deviceID, baudRate); } void uart1_clearFIFOs(){ uart_clearFIFOs(_Uart1PS); } void uart1_sendByte(char data){ uart_sendByte(_Uart1PS, data); } void uart1_sendStr(char* str) { uart_sendStr(_Uart1PS, str); } void uart1_sendBytes(char* data, int numBytes){ uart_sendBytes(_Uart1PS, data, numBytes); } int uart1_isSending(){ return uart_isSending(_Uart1PS); } int uart1_hasData(){ return uart_hasData(_Uart1PS); } void uart1_recvBytes(char* buffer, int numBytes) { uart_recvBytes(_Uart1PS, buffer, numBytes); } char uart1_recvByte() { return uart_recvByte(_Uart1PS); } /************************************************/