libuav original
Dependents: UAVCAN UAVCAN_Subscriber
uart_11xx.c
00001 /* 00002 * @brief LPC11xx UART chip driver 00003 * 00004 * @note 00005 * Copyright(C) NXP Semiconductors, 2012 00006 * All rights reserved. 00007 * 00008 * @par 00009 * Software that is described herein is for illustrative purposes only 00010 * which provides customers with programming information regarding the 00011 * LPC products. This software is supplied "AS IS" without any warranties of 00012 * any kind, and NXP Semiconductors and its licensor disclaim any and 00013 * all warranties, express or implied, including all implied warranties of 00014 * merchantability, fitness for a particular purpose and non-infringement of 00015 * intellectual property rights. NXP Semiconductors assumes no responsibility 00016 * or liability for the use of the software, conveys no license or rights under any 00017 * patent, copyright, mask work right, or any other intellectual property rights in 00018 * or to any products. NXP Semiconductors reserves the right to make changes 00019 * in the software without notification. NXP Semiconductors also makes no 00020 * representation or warranty that such application will be suitable for the 00021 * specified use without further testing or modification. 00022 * 00023 * @par 00024 * Permission to use, copy, modify, and distribute this software and its 00025 * documentation is hereby granted, under NXP Semiconductors' and its 00026 * licensor's relevant copyrights in the software, without fee, provided that it 00027 * is used in conjunction with NXP Semiconductors microcontrollers. This 00028 * copyright, permission, and disclaimer notice must appear in all copies of 00029 * this code. 00030 */ 00031 00032 #include "chip.h" 00033 00034 #if __GNUC__ 00035 # pragma GCC diagnostic ignored "-Wsign-conversion" 00036 # pragma GCC diagnostic ignored "-Wconversion" 00037 # pragma GCC diagnostic ignored "-Wmissing-declarations" 00038 # pragma GCC diagnostic ignored "-Wunused-parameter" 00039 #endif 00040 00041 /***************************************************************************** 00042 * Private types/enumerations/variables 00043 ****************************************************************************/ 00044 00045 /***************************************************************************** 00046 * Public types/enumerations/variables 00047 ****************************************************************************/ 00048 00049 /***************************************************************************** 00050 * Private functions 00051 ****************************************************************************/ 00052 00053 /***************************************************************************** 00054 * Public functions 00055 ****************************************************************************/ 00056 00057 /* Initializes the pUART peripheral */ 00058 void Chip_UART_Init(LPC_USART_T *pUART) 00059 { 00060 Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0 ); 00061 Chip_Clock_SetUARTClockDiv(1); 00062 00063 /* Enable FIFOs by default, reset them */ 00064 Chip_UART_SetupFIFOS(pUART, (UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS)); 00065 00066 /* Default 8N1, with DLAB disabled */ 00067 Chip_UART_ConfigData(pUART, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS)); 00068 00069 /* Disable fractional divider */ 00070 pUART->FDR = 0x10; 00071 } 00072 00073 /* De-initializes the pUART peripheral */ 00074 void Chip_UART_DeInit(LPC_USART_T *pUART) 00075 { 00076 Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_UART0 ); 00077 } 00078 00079 /* Transmit a byte array through the UART peripheral (non-blocking) */ 00080 int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes) 00081 { 00082 int sent = 0; 00083 uint8_t *p8 = (uint8_t *) data; 00084 00085 /* Send until the transmit FIFO is full or out of bytes */ 00086 while ((sent < numBytes) && 00087 ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0)) { 00088 Chip_UART_SendByte(pUART, *p8); 00089 p8++; 00090 sent++; 00091 } 00092 00093 return sent; 00094 } 00095 00096 /* Transmit a byte array through the UART peripheral (blocking) */ 00097 int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes) 00098 { 00099 int pass, sent = 0; 00100 uint8_t *p8 = (uint8_t *) data; 00101 00102 while (numBytes > 0) { 00103 pass = Chip_UART_Send(pUART, p8, numBytes); 00104 numBytes -= pass; 00105 sent += pass; 00106 p8 += pass; 00107 } 00108 00109 return sent; 00110 } 00111 00112 /* Read data through the UART peripheral (non-blocking) */ 00113 int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes) 00114 { 00115 int readBytes = 0; 00116 uint8_t *p8 = (uint8_t *) data; 00117 00118 /* Send until the transmit FIFO is full or out of bytes */ 00119 while ((readBytes < numBytes) && 00120 ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) != 0)) { 00121 *p8 = Chip_UART_ReadByte(pUART); 00122 p8++; 00123 readBytes++; 00124 } 00125 00126 return readBytes; 00127 } 00128 00129 /* Read data through the UART peripheral (blocking) */ 00130 int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes) 00131 { 00132 int pass, readBytes = 0; 00133 uint8_t *p8 = (uint8_t *) data; 00134 00135 while (readBytes < numBytes) { 00136 pass = Chip_UART_Read(pUART, p8, numBytes); 00137 numBytes -= pass; 00138 readBytes += pass; 00139 p8 += pass; 00140 } 00141 00142 return readBytes; 00143 } 00144 00145 /* Determines and sets best dividers to get a target bit rate */ 00146 uint32_t Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate) 00147 { 00148 uint32_t div, divh, divl, clkin; 00149 00150 /* Determine UART clock in rate without FDR */ 00151 clkin = Chip_Clock_GetMainClockRate(); 00152 div = clkin / (baudrate * 16); 00153 00154 /* High and low halves of the divider */ 00155 divh = div / 256; 00156 divl = div - (divh * 256); 00157 00158 Chip_UART_EnableDivisorAccess(pUART); 00159 Chip_UART_SetDivisorLatches(pUART, divl, divh); 00160 Chip_UART_DisableDivisorAccess(pUART); 00161 00162 /* Fractional FDR alreadt setup for 1 in UART init */ 00163 00164 return clkin / div; 00165 } 00166 00167 /* UART receive-only interrupt handler for ring buffers */ 00168 void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB) 00169 { 00170 /* New data will be ignored if data not popped in time */ 00171 while (Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) { 00172 uint8_t ch = Chip_UART_ReadByte(pUART); 00173 RingBuffer_Insert(pRB, &ch); 00174 } 00175 } 00176 00177 /* UART transmit-only interrupt handler for ring buffers */ 00178 void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB) 00179 { 00180 uint8_t ch; 00181 00182 /* Fill FIFO until full or until TX ring buffer is empty */ 00183 while ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0 && 00184 RingBuffer_Pop(pRB, &ch)) { 00185 Chip_UART_SendByte(pUART, ch); 00186 } 00187 } 00188 00189 /* Populate a transmit ring buffer and start UART transmit */ 00190 uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes) 00191 { 00192 uint32_t ret; 00193 uint8_t *p8 = (uint8_t *) data; 00194 00195 /* Don't let UART transmit ring buffer change in the UART IRQ handler */ 00196 Chip_UART_IntDisable(pUART, UART_IER_THREINT); 00197 00198 /* Move as much data as possible into transmit ring buffer */ 00199 ret = RingBuffer_InsertMult(pRB, p8, bytes); 00200 Chip_UART_TXIntHandlerRB(pUART, pRB); 00201 00202 /* Add additional data to transmit ring buffer if possible */ 00203 ret += RingBuffer_InsertMult(pRB, (p8 + ret), (bytes - ret)); 00204 00205 /* Enable UART transmit interrupt */ 00206 Chip_UART_IntEnable(pUART, UART_IER_THREINT); 00207 00208 return ret; 00209 } 00210 00211 /* Copy data from a receive ring buffer */ 00212 int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes) 00213 { 00214 (void) pUART; 00215 00216 return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes); 00217 } 00218 00219 /* UART receive/transmit interrupt handler for ring buffers */ 00220 void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB) 00221 { 00222 /* Handle transmit interrupt if enabled */ 00223 if (pUART->IER & UART_IER_THREINT) { 00224 Chip_UART_TXIntHandlerRB(pUART, pTXRB); 00225 00226 /* Disable transmit interrupt if the ring buffer is empty */ 00227 if (RingBuffer_IsEmpty(pTXRB)) { 00228 Chip_UART_IntDisable(pUART, UART_IER_THREINT); 00229 } 00230 } 00231 00232 /* Handle receive interrupt */ 00233 Chip_UART_RXIntHandlerRB(pUART, pRXRB); 00234 } 00235 00236 /* Determines and sets best dividers to get a target baud rate */ 00237 uint32_t Chip_UART_SetBaudFDR(LPC_USART_T *pUART, uint32_t baudrate) 00238 00239 { 00240 uint32_t uClk = 0; 00241 uint32_t dval = 0; 00242 uint32_t mval = 0; 00243 uint32_t dl = 0; 00244 uint32_t rate16 = 16 * baudrate; 00245 uint32_t actualRate = 0; 00246 00247 /* Get Clock rate */ 00248 uClk = Chip_Clock_GetMainClockRate(); 00249 00250 /* The fractional is calculated as (PCLK % (16 * Baudrate)) / (16 * Baudrate) 00251 * Let's make it to be the ratio DivVal / MulVal 00252 */ 00253 dval = uClk % rate16; 00254 00255 /* The PCLK / (16 * Baudrate) is fractional 00256 * => dval = pclk % rate16 00257 * mval = rate16; 00258 * now mormalize the ratio 00259 * dval / mval = 1 / new_mval 00260 * new_mval = mval / dval 00261 * new_dval = 1 00262 */ 00263 if (dval > 0) { 00264 mval = rate16 / dval; 00265 dval = 1; 00266 00267 /* In case mval still bigger then 4 bits 00268 * no adjustment require 00269 */ 00270 if (mval > 12) { 00271 dval = 0; 00272 } 00273 } 00274 dval &= 0xf; 00275 mval &= 0xf; 00276 dl = uClk / (rate16 + rate16 *dval / mval); 00277 00278 /* Update UART registers */ 00279 Chip_UART_EnableDivisorAccess(pUART); 00280 Chip_UART_SetDivisorLatches(pUART, UART_LOAD_DLL(dl), UART_LOAD_DLM(dl)); 00281 Chip_UART_DisableDivisorAccess(pUART); 00282 00283 /* Set best fractional divider */ 00284 pUART->FDR = (UART_FDR_MULVAL(mval) | UART_FDR_DIVADDVAL(dval)); 00285 00286 /* Return actual baud rate */ 00287 actualRate = uClk / (16 * dl + 16 * dl * dval / mval); 00288 return actualRate; 00289 }
Generated on Tue Jul 12 2022 17:17:35 by 1.7.2