/* rtxcuart.c - MCF5282 MCF5282EVB uart support */ /* * RTXC Quadros Version 1.0 * Copyright (c) 1999-2003 * Quadros Systems, Inc. * ALL RIGHTS RESERVED * * THE INFORMATION HEREIN IS CONFIDENTIAL AND PROPRIETARY. * UNAUTHORIZED DISCLOSURE OR DISTRIBUTION IS PROHIBITED. */ #include "rtxcapi.h" #include "enable.h" #include "sysinit.h" #include "m52xxevb.h" #include "mcf5xxx.h" #include "mcf5282.h" #include "rtxcuart.h" #include "kthread.h" void mcf5282_uart_init(void) { #if defined(HAS_UART0) || defined(HAS_UART1) || defined(HAS_UART2) /* { */ register uint16 ubgs; #endif /* } HAS_UART0 || HAS_UART1 || HAS_UART2 */ #ifdef HAS_UART0 /* { */ /* * Initialize UART0 for serial communications */ /* * Enable URXD0 and UTXD0 on Port UA */ MCF5282_GPIO_PUAPAR |= MCF5282_GPIO_PUAPAR_PUAPA0 | MCF5282_GPIO_PUAPAR_PUAPA1; /* * Reset Transmitter */ MCF5282_UART0_UCR = MCF5282_UART_UCR_RESET_TX; /* * Reset Receiver */ MCF5282_UART0_UCR = MCF5282_UART_UCR_RESET_RX; /* * Reset Mode Register */ MCF5282_UART0_UCR = MCF5282_UART_UCR_RESET_MR; /* * No parity, 8-bits per character */ MCF5282_UART0_UMR = MCF5282_UART_UMR1_PM_NONE | MCF5282_UART_UMR1_BC_8; /* * No echo or loopback, 1 stop bit */ MCF5282_UART0_UMR = MCF5282_UART_UMR2_CM_NORMAL | MCF5282_UART_UMR2_STOP_BITS_1; /* * Set Rx and Tx baud by timer */ MCF5282_UART0_UCSR = MCF5282_UART_UCSR_RCS_SYS_CLK | MCF5282_UART_UCSR_TCS_SYS_CLK; /* * Unmask RxRdy & TxRdy interrupt */ MCF5282_UART0_UIMR = MCF5282_UART_UIMR_RXRDY | MCF5282_UART_UIMR_TXRDY; /* * Calculate baud settings */ ubgs = (uint16)((SYSTEM_CLOCK * 1000000) / (BAUDRATE0 * 64)); MCF5282_UART0_UBG1 = (uint8)((ubgs & 0xFF00) >> 8); MCF5282_UART0_UBG2 = (uint8) (ubgs & 0x00FF); /* * Enable receiver */ MCF5282_UART0_UCR = MCF5282_UART_UCR_RX_ENABLED; /* Enable UART 0 interrupts to ColdFire core */ if (checkICR(13, UART0_LEVEL, UART0_PRIORITY) ) __asm__("halt"); MCF5282_INTC0_ICR13 = MCF5282_INTC_ICR_IL(UART0_LEVEL) | MCF5282_INTC_ICR_IP(UART0_PRIORITY); /* Set UART 0 Interrupt Mask Register */ MCF5282_INTC0_IMRL &= (unsigned long) ~(MCF5282_INTC_IMRL_INT13 | MCF5282_INTC_IMRL_MASKALL); #endif /* } HAS_UART0 */ } /**************************************************************************/ /* global UART workspace */ #define UART_RX_CHAR (MCF5282_UART0_URB) #define UART_TX_CHAR(c) (MCF5282_UART0_UTB = c) #define UART_ENABLE_TX (MCF5282_UART0_UCR = MCF5282_UART_UCR_TX_ENABLED) #define UART_DISABLE_TX (MCF5282_UART0_UCR = MCF5282_UART_UCR_TX_DISABLED) /* Queue for UART Transmit Data. */ static char acTxBuf[UART_TX_SIZE]; /* Queue for storing transmit data. */ static char* pTxBufInput = &acTxBuf[0]; /* Next free location in queue. */ static char* pTxBufOutput = &acTxBuf[0]; /* Oldest data in queue. */ static unsigned int iTxBufCount = 0; /* Number of characters in queue. */ /* Queue for UART Receive Data. */ static char acRxBuf[UART_RX_SIZE]; /* Queue for storing receive data. */ static char* pRxBufInput = &acRxBuf[0]; /* Next free locaton in queue. */ static char* pRxBufOutput = &acRxBuf[0]; /* Oldest data in queue. */ static unsigned int iRxBufCount = 0; /* Number of characters in queue. */ static __inline__ void rtxcss_uartrxc(void); static __inline__ void rtxcss_uarttxc(void); #ifdef SS_UART_STATS /* { */ unsigned int stat_rxchars = 0; unsigned int stat_txchars = 0; unsigned int stat_rxdropped = 0; unsigned int stat_txdropped = 0; unsigned int stat_rxbufcntmax = 0; unsigned int stat_txbufcntmax = 0; #endif /* } SS_UART_STATS */ #ifdef HAS_UART0 /* { */ void uart0isrc(void); void uart0isrc(void) { unsigned char cause = MCF5282_UART0_UISR; /* * is receiver ready? */ if (cause & MCF5282_UART_UISR_RXRDY) { rtxcss_uartrxc(); } if (cause & MCF5282_UART_UISR_TXRDY) { rtxcss_uarttxc(); } LOWER; } #else void uart0isrc(void) { ; } #endif /* } HAS_UART0 */ static __inline__ void rtxcss_uartrxc(void) { volatile char cData; /* Data read from the receiver. */ cData = UART_RX_CHAR; /* Get data from UART receiver. */ if(iRxBufCount < UART_RX_SIZE) /* Is there room in the rx queue? */ { *pRxBufInput = cData; /* Put the new character in the rx queue. */ pRxBufInput++; /* Move the input pointer. */ if(pRxBufInput >= &acRxBuf[0]+UART_RX_SIZE) /* Wrap ptr if necessary. */ pRxBufInput = &acRxBuf[0]; iRxBufCount++; /* Increment rx queue's char counter. */ #ifdef SS_UART_STATS /* { */ stat_rxchars++; if(iRxBufCount > stat_rxbufcntmax) stat_rxbufcntmax = iRxBufCount; #endif /* } SS_UART_STATS */ IS_ScheduleThread(THREAD4); /* Wake up thread that's expecting data. */ } #ifdef SS_UART_STATS /* { */ else stat_rxdropped++; #endif /* } SS_UART_STATS */ } static __inline__ void rtxcss_uarttxc(void) { if(iTxBufCount != 0) /* Are there any characters in the transmit queue? */ { UART_TX_CHAR(*pTxBufOutput); /* Transmit next char in tx queue. */ pTxBufOutput++; /* Point to next char in tx queue. */ if(pTxBufOutput >= &acTxBuf[0]+UART_TX_SIZE) /* Wrap ptr if necessary. */ pTxBufOutput = &acTxBuf[0]; #ifdef SS_UART_STATS /* { */ stat_txchars++; if(iTxBufCount > stat_txbufcntmax) stat_txbufcntmax = iTxBufCount; #endif /* } SS_UART_STATS */ iTxBufCount--; /* Decrement tx queue's char counter. */ } else /* There are no characters in the transmit queue. */ UART_DISABLE_TX; } char rtxcss_uart_rx(void) { char cData; /* Character read from the receive queue. */ if(iRxBufCount == 0) /* If there's nothing to receive, return NULL. */ return((char)0); /* iRxCount != 0 */ cData = *pRxBufOutput; /* Read a character from the rx queue. */ pRxBufOutput++; if(pRxBufOutput >= &acRxBuf[0]+UART_RX_SIZE) /* Wrap if necessary. */ pRxBufOutput = &acRxBuf[0]; DISABLE; /* Protect access to iRxBufCount. */ iRxBufCount--; /* Decrement count of chars in rx queue. */ ENABLE; return(cData); /* Return received character. */ } int rtxcss_uart_tx(char cData) { int rc=UART_TX_SIZE-iTxBufCount; if(rc>0) /* Is there room in the tx queue? */ { *pTxBufInput = cData; /* Put the new character in the tx queue. */ pTxBufInput++; /* Move the input pointer. */ if(pTxBufInput >= &acTxBuf[0]+UART_TX_SIZE) /* Wrap if necessary. */ pTxBufInput = &acTxBuf[0]; DISABLE; /* Protect access to iTxBufCount. */ iTxBufCount++; /* Increment count of chars in tx queue. */ ENABLE; UART_ENABLE_TX; } #ifdef SS_UART_STATS /* { */ else stat_txdropped++; #endif /* } SS_UART_STATS */ return rc; } /* device=0..2, baudrate=9600, 19200, etc. */ void mcf5282_uart_baudrate_set(int device, int baudrate) { uint16 ubgs = (uint16)((SYSTEM_CLOCK * 1000000) / (baudrate * 32)); /* sanity test for bad device no. -- UART 2 not supported yet */ if (device < 0 || device > 1) return; MCF5282_UART_UBG1(device) = (uint8)((ubgs & 0xFF00) >> 8); MCF5282_UART_UBG2(device) = (uint8) (ubgs & 0x00FF); }