Something went wrong on our end
uart.c 9.10 KiB
/*
* 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);
}
/************************************************/