libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uart_11xx.c Source File

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 }