added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /*
<> 144:ef7eb2e8f9f7 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
<> 144:ef7eb2e8f9f7 3 * All rights reserved.
<> 144:ef7eb2e8f9f7 4 *
<> 144:ef7eb2e8f9f7 5 * Redistribution and use in source and binary forms, with or without modification,
<> 144:ef7eb2e8f9f7 6 * are permitted provided that the following conditions are met:
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * o Redistributions of source code must retain the above copyright notice, this list
<> 144:ef7eb2e8f9f7 9 * of conditions and the following disclaimer.
<> 144:ef7eb2e8f9f7 10 *
<> 144:ef7eb2e8f9f7 11 * o Redistributions in binary form must reproduce the above copyright notice, this
<> 144:ef7eb2e8f9f7 12 * list of conditions and the following disclaimer in the documentation and/or
<> 144:ef7eb2e8f9f7 13 * other materials provided with the distribution.
<> 144:ef7eb2e8f9f7 14 *
<> 144:ef7eb2e8f9f7 15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
<> 144:ef7eb2e8f9f7 16 * contributors may be used to endorse or promote products derived from this
<> 144:ef7eb2e8f9f7 17 * software without specific prior written permission.
<> 144:ef7eb2e8f9f7 18 *
<> 144:ef7eb2e8f9f7 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
<> 144:ef7eb2e8f9f7 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
<> 144:ef7eb2e8f9f7 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
<> 144:ef7eb2e8f9f7 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
<> 144:ef7eb2e8f9f7 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
<> 144:ef7eb2e8f9f7 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
<> 144:ef7eb2e8f9f7 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
<> 144:ef7eb2e8f9f7 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
<> 144:ef7eb2e8f9f7 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
<> 144:ef7eb2e8f9f7 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<> 144:ef7eb2e8f9f7 29 */
<> 144:ef7eb2e8f9f7 30
<> 144:ef7eb2e8f9f7 31 #include "fsl_lpuart.h"
<> 144:ef7eb2e8f9f7 32
<> 144:ef7eb2e8f9f7 33 /*******************************************************************************
<> 144:ef7eb2e8f9f7 34 * Definitions
<> 144:ef7eb2e8f9f7 35 ******************************************************************************/
<> 144:ef7eb2e8f9f7 36 /* LPUART transfer state. */
<> 144:ef7eb2e8f9f7 37 enum _lpuart_transfer_states
<> 144:ef7eb2e8f9f7 38 {
<> 144:ef7eb2e8f9f7 39 kLPUART_TxIdle, /*!< TX idle. */
<> 144:ef7eb2e8f9f7 40 kLPUART_TxBusy, /*!< TX busy. */
<> 144:ef7eb2e8f9f7 41 kLPUART_RxIdle, /*!< RX idle. */
<> 144:ef7eb2e8f9f7 42 kLPUART_RxBusy /*!< RX busy. */
<> 144:ef7eb2e8f9f7 43 };
<> 144:ef7eb2e8f9f7 44
<> 144:ef7eb2e8f9f7 45 /* Typedef for interrupt handler. */
<> 144:ef7eb2e8f9f7 46 typedef void (*lpuart_isr_t)(LPUART_Type *base, lpuart_handle_t *handle);
<> 144:ef7eb2e8f9f7 47
<> 144:ef7eb2e8f9f7 48 /*******************************************************************************
<> 144:ef7eb2e8f9f7 49 * Prototypes
<> 144:ef7eb2e8f9f7 50 ******************************************************************************/
<> 144:ef7eb2e8f9f7 51 /*!
<> 144:ef7eb2e8f9f7 52 * @brief Get the LPUART instance from peripheral base address.
<> 144:ef7eb2e8f9f7 53 *
<> 144:ef7eb2e8f9f7 54 * @param base LPUART peripheral base address.
<> 144:ef7eb2e8f9f7 55 * @return LPUART instance.
<> 144:ef7eb2e8f9f7 56 */
<> 144:ef7eb2e8f9f7 57 uint32_t LPUART_GetInstance(LPUART_Type *base);
<> 144:ef7eb2e8f9f7 58
<> 144:ef7eb2e8f9f7 59 /*!
<> 144:ef7eb2e8f9f7 60 * @brief Get the length of received data in RX ring buffer.
<> 144:ef7eb2e8f9f7 61 *
<> 144:ef7eb2e8f9f7 62 * @userData handle LPUART handle pointer.
<> 144:ef7eb2e8f9f7 63 * @return Length of received data in RX ring buffer.
<> 144:ef7eb2e8f9f7 64 */
<> 144:ef7eb2e8f9f7 65 static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle);
<> 144:ef7eb2e8f9f7 66
<> 144:ef7eb2e8f9f7 67 /*!
<> 144:ef7eb2e8f9f7 68 * @brief Check whether the RX ring buffer is full.
<> 144:ef7eb2e8f9f7 69 *
<> 144:ef7eb2e8f9f7 70 * @userData handle LPUART handle pointer.
<> 144:ef7eb2e8f9f7 71 * @retval true RX ring buffer is full.
<> 144:ef7eb2e8f9f7 72 * @retval false RX ring buffer is not full.
<> 144:ef7eb2e8f9f7 73 */
<> 144:ef7eb2e8f9f7 74 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle);
<> 144:ef7eb2e8f9f7 75
<> 144:ef7eb2e8f9f7 76 /*!
<> 144:ef7eb2e8f9f7 77 * @brief Write to TX register using non-blocking method.
<> 144:ef7eb2e8f9f7 78 *
<> 144:ef7eb2e8f9f7 79 * This function writes data to the TX register directly, upper layer must make
<> 144:ef7eb2e8f9f7 80 * sure the TX register is empty or TX FIFO has empty room before calling this function.
<> 144:ef7eb2e8f9f7 81 *
<> 144:ef7eb2e8f9f7 82 * @note This function does not check whether all the data has been sent out to bus,
<> 144:ef7eb2e8f9f7 83 * so before disable TX, check kLPUART_TransmissionCompleteFlag to ensure the TX is
<> 144:ef7eb2e8f9f7 84 * finished.
<> 144:ef7eb2e8f9f7 85 *
<> 144:ef7eb2e8f9f7 86 * @param base LPUART peripheral base address.
<> 144:ef7eb2e8f9f7 87 * @param data Start addresss of the data to write.
<> 144:ef7eb2e8f9f7 88 * @param length Size of the buffer to be sent.
<> 144:ef7eb2e8f9f7 89 */
<> 144:ef7eb2e8f9f7 90 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
<> 144:ef7eb2e8f9f7 91
<> 144:ef7eb2e8f9f7 92 /*!
<> 144:ef7eb2e8f9f7 93 * @brief Read RX register using non-blocking method.
<> 144:ef7eb2e8f9f7 94 *
<> 144:ef7eb2e8f9f7 95 * This function reads data from the TX register directly, upper layer must make
<> 144:ef7eb2e8f9f7 96 * sure the RX register is full or TX FIFO has data before calling this function.
<> 144:ef7eb2e8f9f7 97 *
<> 144:ef7eb2e8f9f7 98 * @param base LPUART peripheral base address.
<> 144:ef7eb2e8f9f7 99 * @param data Start addresss of the buffer to store the received data.
<> 144:ef7eb2e8f9f7 100 * @param length Size of the buffer.
<> 144:ef7eb2e8f9f7 101 */
<> 144:ef7eb2e8f9f7 102 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length);
<> 144:ef7eb2e8f9f7 103
<> 144:ef7eb2e8f9f7 104 /*******************************************************************************
<> 144:ef7eb2e8f9f7 105 * Variables
<> 144:ef7eb2e8f9f7 106 ******************************************************************************/
<> 144:ef7eb2e8f9f7 107 /* Array of LPUART handle. */
<> 144:ef7eb2e8f9f7 108 static lpuart_handle_t *s_lpuartHandle[FSL_FEATURE_SOC_LPUART_COUNT];
<> 144:ef7eb2e8f9f7 109 /* Array of LPUART peripheral base address. */
<> 144:ef7eb2e8f9f7 110 static LPUART_Type *const s_lpuartBases[] = LPUART_BASE_PTRS;
<> 144:ef7eb2e8f9f7 111 /* Array of LPUART IRQ number. */
<> 144:ef7eb2e8f9f7 112 static const IRQn_Type s_lpuartIRQ[] = LPUART_RX_TX_IRQS;
<> 144:ef7eb2e8f9f7 113 /* Array of LPUART clock name. */
<> 144:ef7eb2e8f9f7 114 static const clock_ip_name_t s_lpuartClock[] = LPUART_CLOCKS;
<> 144:ef7eb2e8f9f7 115 /* LPUART ISR for transactional APIs. */
<> 144:ef7eb2e8f9f7 116 static lpuart_isr_t s_lpuartIsr;
<> 144:ef7eb2e8f9f7 117
<> 144:ef7eb2e8f9f7 118 /*******************************************************************************
<> 144:ef7eb2e8f9f7 119 * Code
<> 144:ef7eb2e8f9f7 120 ******************************************************************************/
<> 144:ef7eb2e8f9f7 121 uint32_t LPUART_GetInstance(LPUART_Type *base)
<> 144:ef7eb2e8f9f7 122 {
<> 144:ef7eb2e8f9f7 123 uint32_t instance;
<> 144:ef7eb2e8f9f7 124
<> 144:ef7eb2e8f9f7 125 /* Find the instance index from base address mappings. */
<> 144:ef7eb2e8f9f7 126 for (instance = 0; instance < FSL_FEATURE_SOC_LPUART_COUNT; instance++)
<> 144:ef7eb2e8f9f7 127 {
<> 144:ef7eb2e8f9f7 128 if (s_lpuartBases[instance] == base)
<> 144:ef7eb2e8f9f7 129 {
<> 144:ef7eb2e8f9f7 130 break;
<> 144:ef7eb2e8f9f7 131 }
<> 144:ef7eb2e8f9f7 132 }
<> 144:ef7eb2e8f9f7 133
<> 144:ef7eb2e8f9f7 134 assert(instance < FSL_FEATURE_SOC_LPUART_COUNT);
<> 144:ef7eb2e8f9f7 135
<> 144:ef7eb2e8f9f7 136 return instance;
<> 144:ef7eb2e8f9f7 137 }
<> 144:ef7eb2e8f9f7 138
<> 144:ef7eb2e8f9f7 139 static size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 140 {
<> 144:ef7eb2e8f9f7 141 size_t size;
<> 144:ef7eb2e8f9f7 142
<> 144:ef7eb2e8f9f7 143 if (handle->rxRingBufferTail > handle->rxRingBufferHead)
<> 144:ef7eb2e8f9f7 144 {
<> 144:ef7eb2e8f9f7 145 size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
<> 144:ef7eb2e8f9f7 146 }
<> 144:ef7eb2e8f9f7 147 else
<> 144:ef7eb2e8f9f7 148 {
<> 144:ef7eb2e8f9f7 149 size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
<> 144:ef7eb2e8f9f7 150 }
<> 144:ef7eb2e8f9f7 151
<> 144:ef7eb2e8f9f7 152 return size;
<> 144:ef7eb2e8f9f7 153 }
<> 144:ef7eb2e8f9f7 154
<> 144:ef7eb2e8f9f7 155 static bool LPUART_TransferIsRxRingBufferFull(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 156 {
<> 144:ef7eb2e8f9f7 157 bool full;
<> 144:ef7eb2e8f9f7 158
<> 144:ef7eb2e8f9f7 159 if (LPUART_TransferGetRxRingBufferLength(base, handle) == (handle->rxRingBufferSize - 1U))
<> 144:ef7eb2e8f9f7 160 {
<> 144:ef7eb2e8f9f7 161 full = true;
<> 144:ef7eb2e8f9f7 162 }
<> 144:ef7eb2e8f9f7 163 else
<> 144:ef7eb2e8f9f7 164 {
<> 144:ef7eb2e8f9f7 165 full = false;
<> 144:ef7eb2e8f9f7 166 }
<> 144:ef7eb2e8f9f7 167 return full;
<> 144:ef7eb2e8f9f7 168 }
<> 144:ef7eb2e8f9f7 169
<> 144:ef7eb2e8f9f7 170 static void LPUART_WriteNonBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
<> 144:ef7eb2e8f9f7 171 {
<> 144:ef7eb2e8f9f7 172 size_t i;
<> 144:ef7eb2e8f9f7 173
<> 144:ef7eb2e8f9f7 174 /* The Non Blocking write data API assume user have ensured there is enough space in
<> 144:ef7eb2e8f9f7 175 peripheral to write. */
<> 144:ef7eb2e8f9f7 176 for (i = 0; i < length; i++)
<> 144:ef7eb2e8f9f7 177 {
<> 144:ef7eb2e8f9f7 178 base->DATA = data[i];
<> 144:ef7eb2e8f9f7 179 }
<> 144:ef7eb2e8f9f7 180 }
<> 144:ef7eb2e8f9f7 181
<> 144:ef7eb2e8f9f7 182 static void LPUART_ReadNonBlocking(LPUART_Type *base, uint8_t *data, size_t length)
<> 144:ef7eb2e8f9f7 183 {
<> 144:ef7eb2e8f9f7 184 size_t i;
<> 144:ef7eb2e8f9f7 185
<> 144:ef7eb2e8f9f7 186 /* The Non Blocking read data API assume user have ensured there is enough space in
<> 144:ef7eb2e8f9f7 187 peripheral to write. */
<> 144:ef7eb2e8f9f7 188 for (i = 0; i < length; i++)
<> 144:ef7eb2e8f9f7 189 {
<> 144:ef7eb2e8f9f7 190 data[i] = base->DATA;
<> 144:ef7eb2e8f9f7 191 }
<> 144:ef7eb2e8f9f7 192 }
<> 144:ef7eb2e8f9f7 193
<> 144:ef7eb2e8f9f7 194 void LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz)
<> 144:ef7eb2e8f9f7 195 {
<> 144:ef7eb2e8f9f7 196 assert(config);
<> 144:ef7eb2e8f9f7 197 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 198 assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->txFifoWatermark);
<> 144:ef7eb2e8f9f7 199 assert(FSL_FEATURE_LPUART_FIFO_SIZEn(base) >= config->rxFifoWatermark);
<> 144:ef7eb2e8f9f7 200 #endif
<> 144:ef7eb2e8f9f7 201 uint32_t temp;
<> 144:ef7eb2e8f9f7 202 uint16_t sbr, sbrTemp;
<> 144:ef7eb2e8f9f7 203 uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff;
<> 144:ef7eb2e8f9f7 204
<> 144:ef7eb2e8f9f7 205 /* Enable lpuart clock */
<> 144:ef7eb2e8f9f7 206 CLOCK_EnableClock(s_lpuartClock[LPUART_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 207
<> 144:ef7eb2e8f9f7 208 /* Disable LPUART TX RX before setting. */
<> 144:ef7eb2e8f9f7 209 base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
<> 144:ef7eb2e8f9f7 210
<> 144:ef7eb2e8f9f7 211 /* This LPUART instantiation uses a slightly different baud rate calculation
<> 144:ef7eb2e8f9f7 212 * The idea is to use the best OSR (over-sampling rate) possible
<> 144:ef7eb2e8f9f7 213 * Note, OSR is typically hard-set to 16 in other LPUART instantiations
<> 144:ef7eb2e8f9f7 214 * loop to find the best OSR value possible, one that generates minimum baudDiff
<> 144:ef7eb2e8f9f7 215 * iterate through the rest of the supported values of OSR */
<> 144:ef7eb2e8f9f7 216
<> 144:ef7eb2e8f9f7 217 baudDiff = config->baudRate_Bps;
<> 144:ef7eb2e8f9f7 218 osr = 0;
<> 144:ef7eb2e8f9f7 219 sbr = 0;
<> 144:ef7eb2e8f9f7 220 for (osrTemp = 4; osrTemp <= 32; osrTemp++)
<> 144:ef7eb2e8f9f7 221 {
<> 144:ef7eb2e8f9f7 222 /* calculate the temporary sbr value */
<> 144:ef7eb2e8f9f7 223 sbrTemp = (srcClock_Hz / (config->baudRate_Bps * osrTemp));
<> 144:ef7eb2e8f9f7 224 /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
<> 144:ef7eb2e8f9f7 225 if (sbrTemp == 0)
<> 144:ef7eb2e8f9f7 226 {
<> 144:ef7eb2e8f9f7 227 sbrTemp = 1;
<> 144:ef7eb2e8f9f7 228 }
<> 144:ef7eb2e8f9f7 229 /* Calculate the baud rate based on the temporary OSR and SBR values */
<> 144:ef7eb2e8f9f7 230 calculatedBaud = (srcClock_Hz / (osrTemp * sbrTemp));
<> 144:ef7eb2e8f9f7 231
<> 144:ef7eb2e8f9f7 232 tempDiff = calculatedBaud - config->baudRate_Bps;
<> 144:ef7eb2e8f9f7 233
<> 144:ef7eb2e8f9f7 234 /* Select the better value between srb and (sbr + 1) */
<> 144:ef7eb2e8f9f7 235 if (tempDiff > (config->baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)))))
<> 144:ef7eb2e8f9f7 236 {
<> 144:ef7eb2e8f9f7 237 tempDiff = config->baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)));
<> 144:ef7eb2e8f9f7 238 sbrTemp++;
<> 144:ef7eb2e8f9f7 239 }
<> 144:ef7eb2e8f9f7 240
<> 144:ef7eb2e8f9f7 241 if (tempDiff <= baudDiff)
<> 144:ef7eb2e8f9f7 242 {
<> 144:ef7eb2e8f9f7 243 baudDiff = tempDiff;
<> 144:ef7eb2e8f9f7 244 osr = osrTemp; /* update and store the best OSR value calculated */
<> 144:ef7eb2e8f9f7 245 sbr = sbrTemp; /* update store the best SBR value calculated */
<> 144:ef7eb2e8f9f7 246 }
<> 144:ef7eb2e8f9f7 247 }
<> 144:ef7eb2e8f9f7 248
<> 144:ef7eb2e8f9f7 249 /* Check to see if actual baud rate is within 3% of desired baud rate
<> 144:ef7eb2e8f9f7 250 * based on the best calculate OSR value */
<> 144:ef7eb2e8f9f7 251 if (baudDiff < ((config->baudRate_Bps / 100) * 3))
<> 144:ef7eb2e8f9f7 252 {
<> 144:ef7eb2e8f9f7 253 temp = base->BAUD;
<> 144:ef7eb2e8f9f7 254
<> 144:ef7eb2e8f9f7 255 /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
<> 144:ef7eb2e8f9f7 256 * If so, then "BOTHEDGE" sampling must be turned on */
<> 144:ef7eb2e8f9f7 257 if ((osr > 3) && (osr < 8))
<> 144:ef7eb2e8f9f7 258 {
<> 144:ef7eb2e8f9f7 259 temp |= LPUART_BAUD_BOTHEDGE_MASK;
<> 144:ef7eb2e8f9f7 260 }
<> 144:ef7eb2e8f9f7 261
<> 144:ef7eb2e8f9f7 262 /* program the osr value (bit value is one less than actual value) */
<> 144:ef7eb2e8f9f7 263 temp &= ~LPUART_BAUD_OSR_MASK;
<> 144:ef7eb2e8f9f7 264 temp |= LPUART_BAUD_OSR(osr - 1);
<> 144:ef7eb2e8f9f7 265
<> 144:ef7eb2e8f9f7 266 /* write the sbr value to the BAUD registers */
<> 144:ef7eb2e8f9f7 267 temp &= ~LPUART_BAUD_SBR_MASK;
<> 144:ef7eb2e8f9f7 268 base->BAUD = temp | LPUART_BAUD_SBR(sbr);
<> 144:ef7eb2e8f9f7 269 }
<> 144:ef7eb2e8f9f7 270
<> 144:ef7eb2e8f9f7 271 /* Set bit count and parity mode. */
<> 144:ef7eb2e8f9f7 272 base->BAUD &= ~LPUART_BAUD_M10_MASK;
<> 144:ef7eb2e8f9f7 273
<> 144:ef7eb2e8f9f7 274 temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
<> 144:ef7eb2e8f9f7 275
<> 144:ef7eb2e8f9f7 276 if (kLPUART_ParityDisabled != config->parityMode)
<> 144:ef7eb2e8f9f7 277 {
<> 144:ef7eb2e8f9f7 278 temp |= (LPUART_CTRL_M_MASK | (uint8_t)config->parityMode);
<> 144:ef7eb2e8f9f7 279 }
<> 144:ef7eb2e8f9f7 280
<> 144:ef7eb2e8f9f7 281 base->CTRL = temp;
<> 144:ef7eb2e8f9f7 282
<> 144:ef7eb2e8f9f7 283 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
<> 144:ef7eb2e8f9f7 284 /* set stop bit per char */
<> 144:ef7eb2e8f9f7 285 temp = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
<> 144:ef7eb2e8f9f7 286 base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)config->stopBitCount);
<> 144:ef7eb2e8f9f7 287 #endif
<> 144:ef7eb2e8f9f7 288
<> 144:ef7eb2e8f9f7 289 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 290 /* Set tx/rx WATER watermark */
<> 144:ef7eb2e8f9f7 291 base->WATER = (((uint32_t)(config->rxFifoWatermark) << 16) | config->txFifoWatermark);
<> 144:ef7eb2e8f9f7 292
<> 144:ef7eb2e8f9f7 293 /* Enable tx/rx FIFO */
<> 144:ef7eb2e8f9f7 294 base->FIFO |= (LPUART_FIFO_TXFE_MASK | LPUART_FIFO_RXFE_MASK);
<> 144:ef7eb2e8f9f7 295
<> 144:ef7eb2e8f9f7 296 /* Flush FIFO */
<> 144:ef7eb2e8f9f7 297 base->FIFO |= (LPUART_FIFO_TXFLUSH_MASK | LPUART_FIFO_RXFLUSH_MASK);
<> 144:ef7eb2e8f9f7 298 #endif
<> 144:ef7eb2e8f9f7 299
<> 144:ef7eb2e8f9f7 300 /* Clear all status flags */
<> 144:ef7eb2e8f9f7 301 temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
<> 144:ef7eb2e8f9f7 302 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
<> 144:ef7eb2e8f9f7 303
<> 144:ef7eb2e8f9f7 304 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
<> 144:ef7eb2e8f9f7 305 temp |= LPUART_STAT_IDLE_MASK;
<> 144:ef7eb2e8f9f7 306 #endif
<> 144:ef7eb2e8f9f7 307
<> 144:ef7eb2e8f9f7 308 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
<> 144:ef7eb2e8f9f7 309 temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
<> 144:ef7eb2e8f9f7 310 #endif
<> 144:ef7eb2e8f9f7 311
<> 144:ef7eb2e8f9f7 312 base->STAT |= temp;
<> 144:ef7eb2e8f9f7 313
<> 144:ef7eb2e8f9f7 314 /* Enable TX/RX base on configure structure. */
<> 144:ef7eb2e8f9f7 315 temp = base->CTRL;
<> 144:ef7eb2e8f9f7 316 if (config->enableTx)
<> 144:ef7eb2e8f9f7 317 {
<> 144:ef7eb2e8f9f7 318 temp |= LPUART_CTRL_TE_MASK;
<> 144:ef7eb2e8f9f7 319 }
<> 144:ef7eb2e8f9f7 320
<> 144:ef7eb2e8f9f7 321 if (config->enableRx)
<> 144:ef7eb2e8f9f7 322 {
<> 144:ef7eb2e8f9f7 323 temp |= LPUART_CTRL_RE_MASK;
<> 144:ef7eb2e8f9f7 324 }
<> 144:ef7eb2e8f9f7 325
<> 144:ef7eb2e8f9f7 326 base->CTRL = temp;
<> 144:ef7eb2e8f9f7 327 }
<> 144:ef7eb2e8f9f7 328 void LPUART_Deinit(LPUART_Type *base)
<> 144:ef7eb2e8f9f7 329 {
<> 144:ef7eb2e8f9f7 330 uint32_t temp;
<> 144:ef7eb2e8f9f7 331
<> 144:ef7eb2e8f9f7 332 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 333 /* Wait tx FIFO send out*/
<> 144:ef7eb2e8f9f7 334 while (0 != ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXWATER_SHIFT))
<> 144:ef7eb2e8f9f7 335 {
<> 144:ef7eb2e8f9f7 336 }
<> 144:ef7eb2e8f9f7 337 #endif
<> 144:ef7eb2e8f9f7 338 /* Wait last char shoft out */
<> 144:ef7eb2e8f9f7 339 while (0 == (base->STAT & LPUART_STAT_TC_MASK))
<> 144:ef7eb2e8f9f7 340 {
<> 144:ef7eb2e8f9f7 341 }
<> 144:ef7eb2e8f9f7 342
<> 144:ef7eb2e8f9f7 343 /* Clear all status flags */
<> 144:ef7eb2e8f9f7 344 temp = (LPUART_STAT_LBKDIF_MASK | LPUART_STAT_RXEDGIF_MASK | LPUART_STAT_OR_MASK | LPUART_STAT_NF_MASK |
<> 144:ef7eb2e8f9f7 345 LPUART_STAT_FE_MASK | LPUART_STAT_PF_MASK);
<> 144:ef7eb2e8f9f7 346
<> 144:ef7eb2e8f9f7 347 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
<> 144:ef7eb2e8f9f7 348 temp |= LPUART_STAT_IDLE_MASK;
<> 144:ef7eb2e8f9f7 349 #endif
<> 144:ef7eb2e8f9f7 350
<> 144:ef7eb2e8f9f7 351 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
<> 144:ef7eb2e8f9f7 352 temp |= (LPUART_STAT_MA1F_MASK | LPUART_STAT_MA2F_MASK);
<> 144:ef7eb2e8f9f7 353 #endif
<> 144:ef7eb2e8f9f7 354
<> 144:ef7eb2e8f9f7 355 base->STAT |= temp;
<> 144:ef7eb2e8f9f7 356
<> 144:ef7eb2e8f9f7 357 /* Disable the module. */
<> 144:ef7eb2e8f9f7 358 base->CTRL = 0;
<> 144:ef7eb2e8f9f7 359
<> 144:ef7eb2e8f9f7 360 /* Disable lpuart clock */
<> 144:ef7eb2e8f9f7 361 CLOCK_DisableClock(s_lpuartClock[LPUART_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 362 }
<> 144:ef7eb2e8f9f7 363
<> 144:ef7eb2e8f9f7 364 void LPUART_GetDefaultConfig(lpuart_config_t *config)
<> 144:ef7eb2e8f9f7 365 {
<> 144:ef7eb2e8f9f7 366 assert(config);
<> 144:ef7eb2e8f9f7 367 config->baudRate_Bps = 115200U;
<> 144:ef7eb2e8f9f7 368 config->parityMode = kLPUART_ParityDisabled;
<> 144:ef7eb2e8f9f7 369 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
<> 144:ef7eb2e8f9f7 370 config->stopBitCount = kLPUART_OneStopBit;
<> 144:ef7eb2e8f9f7 371 #endif
<> 144:ef7eb2e8f9f7 372 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 373 config->txFifoWatermark = 0;
<> 144:ef7eb2e8f9f7 374 config->rxFifoWatermark = 0;
<> 144:ef7eb2e8f9f7 375 #endif
<> 144:ef7eb2e8f9f7 376 config->enableTx = false;
<> 144:ef7eb2e8f9f7 377 config->enableRx = false;
<> 144:ef7eb2e8f9f7 378 }
<> 144:ef7eb2e8f9f7 379
<> 144:ef7eb2e8f9f7 380 void LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
<> 144:ef7eb2e8f9f7 381 {
<> 144:ef7eb2e8f9f7 382 uint32_t temp, oldCtrl;
<> 144:ef7eb2e8f9f7 383 uint16_t sbr, sbrTemp;
<> 144:ef7eb2e8f9f7 384 uint32_t osr, osrTemp, tempDiff, calculatedBaud, baudDiff;
<> 144:ef7eb2e8f9f7 385
<> 144:ef7eb2e8f9f7 386 /* Store CTRL before disable Tx and Rx */
<> 144:ef7eb2e8f9f7 387 oldCtrl = base->CTRL;
<> 144:ef7eb2e8f9f7 388
<> 144:ef7eb2e8f9f7 389 /* Disable LPUART TX RX before setting. */
<> 144:ef7eb2e8f9f7 390 base->CTRL &= ~(LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK);
<> 144:ef7eb2e8f9f7 391
<> 144:ef7eb2e8f9f7 392 /* This LPUART instantiation uses a slightly different baud rate calculation
<> 144:ef7eb2e8f9f7 393 * The idea is to use the best OSR (over-sampling rate) possible
<> 144:ef7eb2e8f9f7 394 * Note, OSR is typically hard-set to 16 in other LPUART instantiations
<> 144:ef7eb2e8f9f7 395 * loop to find the best OSR value possible, one that generates minimum baudDiff
<> 144:ef7eb2e8f9f7 396 * iterate through the rest of the supported values of OSR */
<> 144:ef7eb2e8f9f7 397
<> 144:ef7eb2e8f9f7 398 baudDiff = baudRate_Bps;
<> 144:ef7eb2e8f9f7 399 osr = 0;
<> 144:ef7eb2e8f9f7 400 sbr = 0;
<> 144:ef7eb2e8f9f7 401 for (osrTemp = 4; osrTemp <= 32; osrTemp++)
<> 144:ef7eb2e8f9f7 402 {
<> 144:ef7eb2e8f9f7 403 /* calculate the temporary sbr value */
<> 144:ef7eb2e8f9f7 404 sbrTemp = (srcClock_Hz / (baudRate_Bps * osrTemp));
<> 144:ef7eb2e8f9f7 405 /*set sbrTemp to 1 if the sourceClockInHz can not satisfy the desired baud rate*/
<> 144:ef7eb2e8f9f7 406 if (sbrTemp == 0)
<> 144:ef7eb2e8f9f7 407 {
<> 144:ef7eb2e8f9f7 408 sbrTemp = 1;
<> 144:ef7eb2e8f9f7 409 }
<> 144:ef7eb2e8f9f7 410 /* Calculate the baud rate based on the temporary OSR and SBR values */
<> 144:ef7eb2e8f9f7 411 calculatedBaud = (srcClock_Hz / (osrTemp * sbrTemp));
<> 144:ef7eb2e8f9f7 412
<> 144:ef7eb2e8f9f7 413 tempDiff = calculatedBaud - baudRate_Bps;
<> 144:ef7eb2e8f9f7 414
<> 144:ef7eb2e8f9f7 415 /* Select the better value between srb and (sbr + 1) */
<> 144:ef7eb2e8f9f7 416 if (tempDiff > (baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)))))
<> 144:ef7eb2e8f9f7 417 {
<> 144:ef7eb2e8f9f7 418 tempDiff = baudRate_Bps - (srcClock_Hz / (osrTemp * (sbrTemp + 1)));
<> 144:ef7eb2e8f9f7 419 sbrTemp++;
<> 144:ef7eb2e8f9f7 420 }
<> 144:ef7eb2e8f9f7 421
<> 144:ef7eb2e8f9f7 422 if (tempDiff <= baudDiff)
<> 144:ef7eb2e8f9f7 423 {
<> 144:ef7eb2e8f9f7 424 baudDiff = tempDiff;
<> 144:ef7eb2e8f9f7 425 osr = osrTemp; /* update and store the best OSR value calculated */
<> 144:ef7eb2e8f9f7 426 sbr = sbrTemp; /* update store the best SBR value calculated */
<> 144:ef7eb2e8f9f7 427 }
<> 144:ef7eb2e8f9f7 428 }
<> 144:ef7eb2e8f9f7 429
<> 144:ef7eb2e8f9f7 430 /* Check to see if actual baud rate is within 3% of desired baud rate
<> 144:ef7eb2e8f9f7 431 * based on the best calculate OSR value */
<> 144:ef7eb2e8f9f7 432 if (baudDiff < ((baudRate_Bps / 100) * 3))
<> 144:ef7eb2e8f9f7 433 {
<> 144:ef7eb2e8f9f7 434 temp = base->BAUD;
<> 144:ef7eb2e8f9f7 435
<> 144:ef7eb2e8f9f7 436 /* Acceptable baud rate, check if OSR is between 4x and 7x oversampling.
<> 144:ef7eb2e8f9f7 437 * If so, then "BOTHEDGE" sampling must be turned on */
<> 144:ef7eb2e8f9f7 438 if ((osr > 3) && (osr < 8))
<> 144:ef7eb2e8f9f7 439 {
<> 144:ef7eb2e8f9f7 440 temp |= LPUART_BAUD_BOTHEDGE_MASK;
<> 144:ef7eb2e8f9f7 441 }
<> 144:ef7eb2e8f9f7 442
<> 144:ef7eb2e8f9f7 443 /* program the osr value (bit value is one less than actual value) */
<> 144:ef7eb2e8f9f7 444 temp &= ~LPUART_BAUD_OSR_MASK;
<> 144:ef7eb2e8f9f7 445 temp |= LPUART_BAUD_OSR(osr - 1);
<> 144:ef7eb2e8f9f7 446
<> 144:ef7eb2e8f9f7 447 /* write the sbr value to the BAUD registers */
<> 144:ef7eb2e8f9f7 448 temp &= ~LPUART_BAUD_SBR_MASK;
<> 144:ef7eb2e8f9f7 449 base->BAUD = temp | LPUART_BAUD_SBR(sbr);
<> 144:ef7eb2e8f9f7 450 }
<> 144:ef7eb2e8f9f7 451
<> 144:ef7eb2e8f9f7 452 /* Restore CTRL. */
<> 144:ef7eb2e8f9f7 453 base->CTRL = oldCtrl;
<> 144:ef7eb2e8f9f7 454 }
<> 144:ef7eb2e8f9f7 455
<> 144:ef7eb2e8f9f7 456 void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
<> 144:ef7eb2e8f9f7 457 {
<> 144:ef7eb2e8f9f7 458 base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
<> 144:ef7eb2e8f9f7 459 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 460 base->FIFO |= ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
<> 144:ef7eb2e8f9f7 461 #endif
<> 144:ef7eb2e8f9f7 462 mask &= 0xFFFFFF00U;
<> 144:ef7eb2e8f9f7 463 base->CTRL |= mask;
<> 144:ef7eb2e8f9f7 464 }
<> 144:ef7eb2e8f9f7 465
<> 144:ef7eb2e8f9f7 466 void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask)
<> 144:ef7eb2e8f9f7 467 {
<> 144:ef7eb2e8f9f7 468 base->BAUD &= ~((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
<> 144:ef7eb2e8f9f7 469 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 470 base->FIFO &= ~((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
<> 144:ef7eb2e8f9f7 471 #endif
<> 144:ef7eb2e8f9f7 472 mask &= 0xFFFFFF00U;
<> 144:ef7eb2e8f9f7 473 base->CTRL &= ~mask;
<> 144:ef7eb2e8f9f7 474 }
<> 144:ef7eb2e8f9f7 475
<> 144:ef7eb2e8f9f7 476 uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base)
<> 144:ef7eb2e8f9f7 477 {
<> 144:ef7eb2e8f9f7 478 uint32_t temp;
<> 144:ef7eb2e8f9f7 479 temp = (base->BAUD & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK)) >> 8;
<> 144:ef7eb2e8f9f7 480 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 481 temp |= (base->FIFO & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK)) >> 8;
<> 144:ef7eb2e8f9f7 482 #endif
<> 144:ef7eb2e8f9f7 483 temp |= (base->CTRL & 0xFF0C000);
<> 144:ef7eb2e8f9f7 484
<> 144:ef7eb2e8f9f7 485 return temp;
<> 144:ef7eb2e8f9f7 486 }
<> 144:ef7eb2e8f9f7 487
<> 144:ef7eb2e8f9f7 488 uint32_t LPUART_GetStatusFlags(LPUART_Type *base)
<> 144:ef7eb2e8f9f7 489 {
<> 144:ef7eb2e8f9f7 490 uint32_t temp;
<> 144:ef7eb2e8f9f7 491 temp = base->STAT;
<> 144:ef7eb2e8f9f7 492 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 493 temp |= (base->FIFO &
<> 144:ef7eb2e8f9f7 494 (LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >>
<> 144:ef7eb2e8f9f7 495 16;
<> 144:ef7eb2e8f9f7 496 #endif
<> 144:ef7eb2e8f9f7 497 return temp;
<> 144:ef7eb2e8f9f7 498 }
<> 144:ef7eb2e8f9f7 499
<> 144:ef7eb2e8f9f7 500 status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask)
<> 144:ef7eb2e8f9f7 501 {
<> 144:ef7eb2e8f9f7 502 uint32_t temp;
<> 144:ef7eb2e8f9f7 503 status_t status;
<> 144:ef7eb2e8f9f7 504 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 505 temp = (uint32_t)base->FIFO;
<> 144:ef7eb2e8f9f7 506 temp &= (uint32_t)(~(kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag));
<> 144:ef7eb2e8f9f7 507 temp |= mask & (kLPUART_TxFifoOverflowFlag | kLPUART_RxFifoUnderflowFlag);
<> 144:ef7eb2e8f9f7 508 base->FIFO = temp;
<> 144:ef7eb2e8f9f7 509 #endif
<> 144:ef7eb2e8f9f7 510 temp = (uint32_t)base->STAT;
<> 144:ef7eb2e8f9f7 511 #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
<> 144:ef7eb2e8f9f7 512 temp &= (uint32_t)(~(kLPUART_LinBreakFlag));
<> 144:ef7eb2e8f9f7 513 temp |= mask & kLPUART_LinBreakFlag;
<> 144:ef7eb2e8f9f7 514 #endif
<> 144:ef7eb2e8f9f7 515 temp &= (uint32_t)(~(kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag |
<> 144:ef7eb2e8f9f7 516 kLPUART_NoiseErrorFlag | kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag));
<> 144:ef7eb2e8f9f7 517 temp |= mask & (kLPUART_RxActiveEdgeFlag | kLPUART_IdleLineFlag | kLPUART_RxOverrunFlag | kLPUART_NoiseErrorFlag |
<> 144:ef7eb2e8f9f7 518 kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag);
<> 144:ef7eb2e8f9f7 519 #if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
<> 144:ef7eb2e8f9f7 520 temp &= (uint32_t)(~(kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag));
<> 144:ef7eb2e8f9f7 521 temp |= mask & (kLPUART_DataMatch2Flag | kLPUART_DataMatch2Flag);
<> 144:ef7eb2e8f9f7 522 #endif
<> 144:ef7eb2e8f9f7 523 base->STAT |= temp;
<> 144:ef7eb2e8f9f7 524 /* If some flags still pending. */
<> 144:ef7eb2e8f9f7 525 if (mask & LPUART_GetStatusFlags(base))
<> 144:ef7eb2e8f9f7 526 {
<> 144:ef7eb2e8f9f7 527 /* Some flags can only clear or set by the hardware itself, these flags are: kLPUART_TxDataRegEmptyFlag,
<> 144:ef7eb2e8f9f7 528 kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag, kLPUART_RxActiveFlag,
<> 144:ef7eb2e8f9f7 529 kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
<> 144:ef7eb2e8f9f7 530 kLPUART_TxFifoEmptyFlag, kLPUART_RxFifoEmptyFlag. */
<> 144:ef7eb2e8f9f7 531 status = kStatus_LPUART_FlagCannotClearManually; /* flags can not clear manually */
<> 144:ef7eb2e8f9f7 532 }
<> 144:ef7eb2e8f9f7 533 else
<> 144:ef7eb2e8f9f7 534 {
<> 144:ef7eb2e8f9f7 535 status = kStatus_Success;
<> 144:ef7eb2e8f9f7 536 }
<> 144:ef7eb2e8f9f7 537
<> 144:ef7eb2e8f9f7 538 return status;
<> 144:ef7eb2e8f9f7 539 }
<> 144:ef7eb2e8f9f7 540
<> 144:ef7eb2e8f9f7 541 void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
<> 144:ef7eb2e8f9f7 542 {
<> 144:ef7eb2e8f9f7 543 /* This API can only ensure that the data is written into the data buffer but can't
<> 144:ef7eb2e8f9f7 544 ensure all data in the data buffer are sent into the transmit shift buffer. */
<> 144:ef7eb2e8f9f7 545 while (length--)
<> 144:ef7eb2e8f9f7 546 {
<> 144:ef7eb2e8f9f7 547 while (!(base->STAT & LPUART_STAT_TDRE_MASK))
<> 144:ef7eb2e8f9f7 548 {
<> 144:ef7eb2e8f9f7 549 }
<> 144:ef7eb2e8f9f7 550 base->DATA = *(data++);
<> 144:ef7eb2e8f9f7 551 }
<> 144:ef7eb2e8f9f7 552 }
<> 144:ef7eb2e8f9f7 553
<> 144:ef7eb2e8f9f7 554 status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length)
<> 144:ef7eb2e8f9f7 555 {
<> 144:ef7eb2e8f9f7 556 uint32_t statusFlag;
<> 144:ef7eb2e8f9f7 557
<> 144:ef7eb2e8f9f7 558 while (length--)
<> 144:ef7eb2e8f9f7 559 {
<> 144:ef7eb2e8f9f7 560 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 561 while (0 == ((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT))
<> 144:ef7eb2e8f9f7 562 #else
<> 144:ef7eb2e8f9f7 563 while (!(base->STAT & LPUART_STAT_RDRF_MASK))
<> 144:ef7eb2e8f9f7 564 #endif
<> 144:ef7eb2e8f9f7 565 {
<> 144:ef7eb2e8f9f7 566 statusFlag = LPUART_GetStatusFlags(base);
<> 144:ef7eb2e8f9f7 567
<> 144:ef7eb2e8f9f7 568 if (statusFlag & kLPUART_RxOverrunFlag)
<> 144:ef7eb2e8f9f7 569 {
<> 144:ef7eb2e8f9f7 570 LPUART_ClearStatusFlags(base, kLPUART_RxOverrunFlag);
<> 144:ef7eb2e8f9f7 571 return kStatus_LPUART_RxHardwareOverrun;
<> 144:ef7eb2e8f9f7 572 }
<> 144:ef7eb2e8f9f7 573
<> 144:ef7eb2e8f9f7 574 if (statusFlag & kLPUART_NoiseErrorFlag)
<> 144:ef7eb2e8f9f7 575 {
<> 144:ef7eb2e8f9f7 576 LPUART_ClearStatusFlags(base, kLPUART_NoiseErrorFlag);
<> 144:ef7eb2e8f9f7 577 return kStatus_LPUART_NoiseError;
<> 144:ef7eb2e8f9f7 578 }
<> 144:ef7eb2e8f9f7 579
<> 144:ef7eb2e8f9f7 580 if (statusFlag & kLPUART_FramingErrorFlag)
<> 144:ef7eb2e8f9f7 581 {
<> 144:ef7eb2e8f9f7 582 LPUART_ClearStatusFlags(base, kLPUART_FramingErrorFlag);
<> 144:ef7eb2e8f9f7 583 return kStatus_LPUART_FramingError;
<> 144:ef7eb2e8f9f7 584 }
<> 144:ef7eb2e8f9f7 585
<> 144:ef7eb2e8f9f7 586 if (statusFlag & kLPUART_ParityErrorFlag)
<> 144:ef7eb2e8f9f7 587 {
<> 144:ef7eb2e8f9f7 588 LPUART_ClearStatusFlags(base, kLPUART_ParityErrorFlag);
<> 144:ef7eb2e8f9f7 589 return kStatus_LPUART_ParityError;
<> 144:ef7eb2e8f9f7 590 }
<> 144:ef7eb2e8f9f7 591 }
<> 144:ef7eb2e8f9f7 592 *(data++) = base->DATA;
<> 144:ef7eb2e8f9f7 593 }
<> 144:ef7eb2e8f9f7 594
<> 144:ef7eb2e8f9f7 595 return kStatus_Success;
<> 144:ef7eb2e8f9f7 596 }
<> 144:ef7eb2e8f9f7 597
<> 144:ef7eb2e8f9f7 598 void LPUART_TransferCreateHandle(LPUART_Type *base,
<> 144:ef7eb2e8f9f7 599 lpuart_handle_t *handle,
<> 144:ef7eb2e8f9f7 600 lpuart_transfer_callback_t callback,
<> 144:ef7eb2e8f9f7 601 void *userData)
<> 144:ef7eb2e8f9f7 602 {
<> 144:ef7eb2e8f9f7 603 assert(handle);
<> 144:ef7eb2e8f9f7 604
<> 144:ef7eb2e8f9f7 605 uint32_t instance;
<> 144:ef7eb2e8f9f7 606
<> 144:ef7eb2e8f9f7 607 /* Zero the handle. */
<> 144:ef7eb2e8f9f7 608 memset(handle, 0, sizeof(lpuart_handle_t));
<> 144:ef7eb2e8f9f7 609
<> 144:ef7eb2e8f9f7 610 /* Set the TX/RX state. */
<> 144:ef7eb2e8f9f7 611 handle->rxState = kLPUART_RxIdle;
<> 144:ef7eb2e8f9f7 612 handle->txState = kLPUART_TxIdle;
<> 144:ef7eb2e8f9f7 613
<> 144:ef7eb2e8f9f7 614 /* Set the callback and user data. */
<> 144:ef7eb2e8f9f7 615 handle->callback = callback;
<> 144:ef7eb2e8f9f7 616 handle->userData = userData;
<> 144:ef7eb2e8f9f7 617
<> 144:ef7eb2e8f9f7 618 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 619 /* Note:
<> 144:ef7eb2e8f9f7 620 Take care of the RX FIFO, RX interrupt request only assert when received bytes
<> 144:ef7eb2e8f9f7 621 equal or more than RX water mark, there is potential issue if RX water
<> 144:ef7eb2e8f9f7 622 mark larger than 1.
<> 144:ef7eb2e8f9f7 623 For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
<> 144:ef7eb2e8f9f7 624 5 bytes are received. the last byte will be saved in FIFO but not trigger
<> 144:ef7eb2e8f9f7 625 RX interrupt because the water mark is 2.
<> 144:ef7eb2e8f9f7 626 */
<> 144:ef7eb2e8f9f7 627 base->WATER &= (~LPUART_WATER_RXWATER_SHIFT);
<> 144:ef7eb2e8f9f7 628 #endif
<> 144:ef7eb2e8f9f7 629
<> 144:ef7eb2e8f9f7 630 /* Get instance from peripheral base address. */
<> 144:ef7eb2e8f9f7 631 instance = LPUART_GetInstance(base);
<> 144:ef7eb2e8f9f7 632
<> 144:ef7eb2e8f9f7 633 /* Save the handle in global variables to support the double weak mechanism. */
<> 144:ef7eb2e8f9f7 634 s_lpuartHandle[instance] = handle;
<> 144:ef7eb2e8f9f7 635
<> 144:ef7eb2e8f9f7 636 s_lpuartIsr = LPUART_TransferHandleIRQ;
<> 144:ef7eb2e8f9f7 637
<> 144:ef7eb2e8f9f7 638 /* Enable interrupt in NVIC. */
<> 144:ef7eb2e8f9f7 639 EnableIRQ(s_lpuartIRQ[instance]);
<> 144:ef7eb2e8f9f7 640 }
<> 144:ef7eb2e8f9f7 641
<> 144:ef7eb2e8f9f7 642 void LPUART_TransferStartRingBuffer(LPUART_Type *base,
<> 144:ef7eb2e8f9f7 643 lpuart_handle_t *handle,
<> 144:ef7eb2e8f9f7 644 uint8_t *ringBuffer,
<> 144:ef7eb2e8f9f7 645 size_t ringBufferSize)
<> 144:ef7eb2e8f9f7 646 {
<> 144:ef7eb2e8f9f7 647 assert(handle);
<> 144:ef7eb2e8f9f7 648
<> 144:ef7eb2e8f9f7 649 /* Setup the ring buffer address */
<> 144:ef7eb2e8f9f7 650 if (ringBuffer)
<> 144:ef7eb2e8f9f7 651 {
<> 144:ef7eb2e8f9f7 652 handle->rxRingBuffer = ringBuffer;
<> 144:ef7eb2e8f9f7 653 handle->rxRingBufferSize = ringBufferSize;
<> 144:ef7eb2e8f9f7 654 handle->rxRingBufferHead = 0U;
<> 144:ef7eb2e8f9f7 655 handle->rxRingBufferTail = 0U;
<> 144:ef7eb2e8f9f7 656
<> 144:ef7eb2e8f9f7 657 /* Enable the interrupt to accept the data when user need the ring buffer. */
<> 144:ef7eb2e8f9f7 658 LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
<> 144:ef7eb2e8f9f7 659 }
<> 144:ef7eb2e8f9f7 660 }
<> 144:ef7eb2e8f9f7 661
<> 144:ef7eb2e8f9f7 662 void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 663 {
<> 144:ef7eb2e8f9f7 664 assert(handle);
<> 144:ef7eb2e8f9f7 665
<> 144:ef7eb2e8f9f7 666 if (handle->rxState == kLPUART_RxIdle)
<> 144:ef7eb2e8f9f7 667 {
<> 144:ef7eb2e8f9f7 668 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
<> 144:ef7eb2e8f9f7 669 }
<> 144:ef7eb2e8f9f7 670
<> 144:ef7eb2e8f9f7 671 handle->rxRingBuffer = NULL;
<> 144:ef7eb2e8f9f7 672 handle->rxRingBufferSize = 0U;
<> 144:ef7eb2e8f9f7 673 handle->rxRingBufferHead = 0U;
<> 144:ef7eb2e8f9f7 674 handle->rxRingBufferTail = 0U;
<> 144:ef7eb2e8f9f7 675 }
<> 144:ef7eb2e8f9f7 676
<> 144:ef7eb2e8f9f7 677 status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer)
<> 144:ef7eb2e8f9f7 678 {
<> 144:ef7eb2e8f9f7 679 status_t status;
<> 144:ef7eb2e8f9f7 680
<> 144:ef7eb2e8f9f7 681 /* Return error if xfer invalid. */
<> 144:ef7eb2e8f9f7 682 if ((0U == xfer->dataSize) || (NULL == xfer->data))
<> 144:ef7eb2e8f9f7 683 {
<> 144:ef7eb2e8f9f7 684 return kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 685 }
<> 144:ef7eb2e8f9f7 686
<> 144:ef7eb2e8f9f7 687 /* Return error if current TX busy. */
<> 144:ef7eb2e8f9f7 688 if (kLPUART_TxBusy == handle->txState)
<> 144:ef7eb2e8f9f7 689 {
<> 144:ef7eb2e8f9f7 690 status = kStatus_LPUART_TxBusy;
<> 144:ef7eb2e8f9f7 691 }
<> 144:ef7eb2e8f9f7 692 else
<> 144:ef7eb2e8f9f7 693 {
<> 144:ef7eb2e8f9f7 694 handle->txData = xfer->data;
<> 144:ef7eb2e8f9f7 695 handle->txDataSize = xfer->dataSize;
<> 144:ef7eb2e8f9f7 696 handle->txDataSizeAll = xfer->dataSize;
<> 144:ef7eb2e8f9f7 697 handle->txState = kLPUART_TxBusy;
<> 144:ef7eb2e8f9f7 698
<> 144:ef7eb2e8f9f7 699 /* Enable transmiter interrupt. */
<> 144:ef7eb2e8f9f7 700 LPUART_EnableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable);
<> 144:ef7eb2e8f9f7 701
<> 144:ef7eb2e8f9f7 702 status = kStatus_Success;
<> 144:ef7eb2e8f9f7 703 }
<> 144:ef7eb2e8f9f7 704
<> 144:ef7eb2e8f9f7 705 return status;
<> 144:ef7eb2e8f9f7 706 }
<> 144:ef7eb2e8f9f7 707
<> 144:ef7eb2e8f9f7 708 void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 709 {
<> 144:ef7eb2e8f9f7 710 LPUART_DisableInterrupts(base, kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_TransmissionCompleteInterruptEnable);
<> 144:ef7eb2e8f9f7 711
<> 144:ef7eb2e8f9f7 712 handle->txDataSize = 0;
<> 144:ef7eb2e8f9f7 713 handle->txState = kLPUART_TxIdle;
<> 144:ef7eb2e8f9f7 714 }
<> 144:ef7eb2e8f9f7 715
<> 144:ef7eb2e8f9f7 716 status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
<> 144:ef7eb2e8f9f7 717 {
<> 144:ef7eb2e8f9f7 718 if (kLPUART_TxIdle == handle->txState)
<> 144:ef7eb2e8f9f7 719 {
<> 144:ef7eb2e8f9f7 720 return kStatus_NoTransferInProgress;
<> 144:ef7eb2e8f9f7 721 }
<> 144:ef7eb2e8f9f7 722
<> 144:ef7eb2e8f9f7 723 if (!count)
<> 144:ef7eb2e8f9f7 724 {
<> 144:ef7eb2e8f9f7 725 return kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 726 }
<> 144:ef7eb2e8f9f7 727
<> 144:ef7eb2e8f9f7 728 *count = handle->txDataSizeAll - handle->txDataSize;
<> 144:ef7eb2e8f9f7 729
<> 144:ef7eb2e8f9f7 730 return kStatus_Success;
<> 144:ef7eb2e8f9f7 731 }
<> 144:ef7eb2e8f9f7 732
<> 144:ef7eb2e8f9f7 733 status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
<> 144:ef7eb2e8f9f7 734 lpuart_handle_t *handle,
<> 144:ef7eb2e8f9f7 735 lpuart_transfer_t *xfer,
<> 144:ef7eb2e8f9f7 736 size_t *receivedBytes)
<> 144:ef7eb2e8f9f7 737 {
<> 144:ef7eb2e8f9f7 738 uint32_t i;
<> 144:ef7eb2e8f9f7 739 status_t status;
<> 144:ef7eb2e8f9f7 740 /* How many bytes to copy from ring buffer to user memory. */
<> 144:ef7eb2e8f9f7 741 size_t bytesToCopy = 0U;
<> 144:ef7eb2e8f9f7 742 /* How many bytes to receive. */
<> 144:ef7eb2e8f9f7 743 size_t bytesToReceive;
<> 144:ef7eb2e8f9f7 744 /* How many bytes currently have received. */
<> 144:ef7eb2e8f9f7 745 size_t bytesCurrentReceived;
<> 144:ef7eb2e8f9f7 746 uint32_t regPrimask = 0U;
<> 144:ef7eb2e8f9f7 747
<> 144:ef7eb2e8f9f7 748 /* Return error if xfer invalid. */
<> 144:ef7eb2e8f9f7 749 if ((0U == xfer->dataSize) || (NULL == xfer->data))
<> 144:ef7eb2e8f9f7 750 {
<> 144:ef7eb2e8f9f7 751 return kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 752 }
<> 144:ef7eb2e8f9f7 753
<> 144:ef7eb2e8f9f7 754 /* How to get data:
<> 144:ef7eb2e8f9f7 755 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
<> 144:ef7eb2e8f9f7 756 to lpuart handle, enable interrupt to store received data to xfer->data. When
<> 144:ef7eb2e8f9f7 757 all data received, trigger callback.
<> 144:ef7eb2e8f9f7 758 2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
<> 144:ef7eb2e8f9f7 759 If there are enough data in ring buffer, copy them to xfer->data and return.
<> 144:ef7eb2e8f9f7 760 If there are not enough data in ring buffer, copy all of them to xfer->data,
<> 144:ef7eb2e8f9f7 761 save the xfer->data remained empty space to lpuart handle, receive data
<> 144:ef7eb2e8f9f7 762 to this empty space and trigger callback when finished. */
<> 144:ef7eb2e8f9f7 763
<> 144:ef7eb2e8f9f7 764 if (kLPUART_RxBusy == handle->rxState)
<> 144:ef7eb2e8f9f7 765 {
<> 144:ef7eb2e8f9f7 766 status = kStatus_LPUART_RxBusy;
<> 144:ef7eb2e8f9f7 767 }
<> 144:ef7eb2e8f9f7 768 else
<> 144:ef7eb2e8f9f7 769 {
<> 144:ef7eb2e8f9f7 770 bytesToReceive = xfer->dataSize;
<> 144:ef7eb2e8f9f7 771 bytesCurrentReceived = 0;
<> 144:ef7eb2e8f9f7 772
<> 144:ef7eb2e8f9f7 773 /* If RX ring buffer is used. */
<> 144:ef7eb2e8f9f7 774 if (handle->rxRingBuffer)
<> 144:ef7eb2e8f9f7 775 {
<> 144:ef7eb2e8f9f7 776 /* Disable IRQ, protect ring buffer. */
<> 144:ef7eb2e8f9f7 777 regPrimask = DisableGlobalIRQ();
<> 144:ef7eb2e8f9f7 778
<> 144:ef7eb2e8f9f7 779 /* How many bytes in RX ring buffer currently. */
<> 144:ef7eb2e8f9f7 780 bytesToCopy = LPUART_TransferGetRxRingBufferLength(base, handle);
<> 144:ef7eb2e8f9f7 781
<> 144:ef7eb2e8f9f7 782 if (bytesToCopy)
<> 144:ef7eb2e8f9f7 783 {
<> 144:ef7eb2e8f9f7 784 bytesToCopy = MIN(bytesToReceive, bytesToCopy);
<> 144:ef7eb2e8f9f7 785
<> 144:ef7eb2e8f9f7 786 bytesToReceive -= bytesToCopy;
<> 144:ef7eb2e8f9f7 787
<> 144:ef7eb2e8f9f7 788 /* Copy data from ring buffer to user memory. */
<> 144:ef7eb2e8f9f7 789 for (i = 0U; i < bytesToCopy; i++)
<> 144:ef7eb2e8f9f7 790 {
<> 144:ef7eb2e8f9f7 791 xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
<> 144:ef7eb2e8f9f7 792
<> 144:ef7eb2e8f9f7 793 /* Wrap to 0. Not use modulo (%) because it might be large and slow. */
<> 144:ef7eb2e8f9f7 794 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
<> 144:ef7eb2e8f9f7 795 {
<> 144:ef7eb2e8f9f7 796 handle->rxRingBufferTail = 0U;
<> 144:ef7eb2e8f9f7 797 }
<> 144:ef7eb2e8f9f7 798 else
<> 144:ef7eb2e8f9f7 799 {
<> 144:ef7eb2e8f9f7 800 handle->rxRingBufferTail++;
<> 144:ef7eb2e8f9f7 801 }
<> 144:ef7eb2e8f9f7 802 }
<> 144:ef7eb2e8f9f7 803 }
<> 144:ef7eb2e8f9f7 804
<> 144:ef7eb2e8f9f7 805 /* If ring buffer does not have enough data, still need to read more data. */
<> 144:ef7eb2e8f9f7 806 if (bytesToReceive)
<> 144:ef7eb2e8f9f7 807 {
<> 144:ef7eb2e8f9f7 808 /* No data in ring buffer, save the request to LPUART handle. */
<> 144:ef7eb2e8f9f7 809 handle->rxData = xfer->data + bytesCurrentReceived;
<> 144:ef7eb2e8f9f7 810 handle->rxDataSize = bytesToReceive;
<> 144:ef7eb2e8f9f7 811 handle->rxDataSizeAll = bytesToReceive;
<> 144:ef7eb2e8f9f7 812 handle->rxState = kLPUART_RxBusy;
<> 144:ef7eb2e8f9f7 813 }
<> 144:ef7eb2e8f9f7 814 /* Enable IRQ if previously enabled. */
<> 144:ef7eb2e8f9f7 815 EnableGlobalIRQ(regPrimask);
<> 144:ef7eb2e8f9f7 816
<> 144:ef7eb2e8f9f7 817 /* Call user callback since all data are received. */
<> 144:ef7eb2e8f9f7 818 if (0 == bytesToReceive)
<> 144:ef7eb2e8f9f7 819 {
<> 144:ef7eb2e8f9f7 820 if (handle->callback)
<> 144:ef7eb2e8f9f7 821 {
<> 144:ef7eb2e8f9f7 822 handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
<> 144:ef7eb2e8f9f7 823 }
<> 144:ef7eb2e8f9f7 824 }
<> 144:ef7eb2e8f9f7 825 }
<> 144:ef7eb2e8f9f7 826 /* Ring buffer not used. */
<> 144:ef7eb2e8f9f7 827 else
<> 144:ef7eb2e8f9f7 828 {
<> 144:ef7eb2e8f9f7 829 handle->rxData = xfer->data + bytesCurrentReceived;
<> 144:ef7eb2e8f9f7 830 handle->rxDataSize = bytesToReceive;
<> 144:ef7eb2e8f9f7 831 handle->rxDataSizeAll = bytesToReceive;
<> 144:ef7eb2e8f9f7 832 handle->rxState = kLPUART_RxBusy;
<> 144:ef7eb2e8f9f7 833
<> 144:ef7eb2e8f9f7 834 /* Enable RX interrupt. */
<> 144:ef7eb2e8f9f7 835 LPUART_EnableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
<> 144:ef7eb2e8f9f7 836 }
<> 144:ef7eb2e8f9f7 837
<> 144:ef7eb2e8f9f7 838 /* Return the how many bytes have read. */
<> 144:ef7eb2e8f9f7 839 if (receivedBytes)
<> 144:ef7eb2e8f9f7 840 {
<> 144:ef7eb2e8f9f7 841 *receivedBytes = bytesCurrentReceived;
<> 144:ef7eb2e8f9f7 842 }
<> 144:ef7eb2e8f9f7 843
<> 144:ef7eb2e8f9f7 844 status = kStatus_Success;
<> 144:ef7eb2e8f9f7 845 }
<> 144:ef7eb2e8f9f7 846
<> 144:ef7eb2e8f9f7 847 return status;
<> 144:ef7eb2e8f9f7 848 }
<> 144:ef7eb2e8f9f7 849
<> 144:ef7eb2e8f9f7 850 void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 851 {
<> 144:ef7eb2e8f9f7 852 /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
<> 144:ef7eb2e8f9f7 853 if (!handle->rxRingBuffer)
<> 144:ef7eb2e8f9f7 854 {
<> 144:ef7eb2e8f9f7 855 /* Disable RX interrupt. */
<> 144:ef7eb2e8f9f7 856 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
<> 144:ef7eb2e8f9f7 857 }
<> 144:ef7eb2e8f9f7 858
<> 144:ef7eb2e8f9f7 859 handle->rxDataSize = 0U;
<> 144:ef7eb2e8f9f7 860 handle->rxState = kLPUART_RxIdle;
<> 144:ef7eb2e8f9f7 861 }
<> 144:ef7eb2e8f9f7 862
<> 144:ef7eb2e8f9f7 863 status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count)
<> 144:ef7eb2e8f9f7 864 {
<> 144:ef7eb2e8f9f7 865 if (kLPUART_RxIdle == handle->rxState)
<> 144:ef7eb2e8f9f7 866 {
<> 144:ef7eb2e8f9f7 867 return kStatus_NoTransferInProgress;
<> 144:ef7eb2e8f9f7 868 }
<> 144:ef7eb2e8f9f7 869
<> 144:ef7eb2e8f9f7 870 if (!count)
<> 144:ef7eb2e8f9f7 871 {
<> 144:ef7eb2e8f9f7 872 return kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 873 }
<> 144:ef7eb2e8f9f7 874
<> 144:ef7eb2e8f9f7 875 *count = handle->rxDataSizeAll - handle->rxDataSize;
<> 144:ef7eb2e8f9f7 876
<> 144:ef7eb2e8f9f7 877 return kStatus_Success;
<> 144:ef7eb2e8f9f7 878 }
<> 144:ef7eb2e8f9f7 879
<> 144:ef7eb2e8f9f7 880 void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 881 {
<> 144:ef7eb2e8f9f7 882 uint8_t count;
<> 144:ef7eb2e8f9f7 883 uint8_t tempCount;
<> 144:ef7eb2e8f9f7 884 volatile uint8_t dummy;
<> 144:ef7eb2e8f9f7 885
<> 144:ef7eb2e8f9f7 886 assert(handle);
<> 144:ef7eb2e8f9f7 887
<> 144:ef7eb2e8f9f7 888 /* If RX overrun. */
<> 144:ef7eb2e8f9f7 889 if (LPUART_STAT_OR_MASK & base->STAT)
<> 144:ef7eb2e8f9f7 890 {
<> 144:ef7eb2e8f9f7 891 /* Read base->DATA, otherwise the RX does not work. */
<> 144:ef7eb2e8f9f7 892 dummy = base->DATA;
<> 144:ef7eb2e8f9f7 893 /* Avoid optimization */
<> 144:ef7eb2e8f9f7 894 dummy++;
<> 144:ef7eb2e8f9f7 895 /* Trigger callback. */
<> 144:ef7eb2e8f9f7 896 if (handle->callback)
<> 144:ef7eb2e8f9f7 897 {
<> 144:ef7eb2e8f9f7 898 handle->callback(base, handle, kStatus_LPUART_RxHardwareOverrun, handle->userData);
<> 144:ef7eb2e8f9f7 899 }
<> 144:ef7eb2e8f9f7 900 }
<> 144:ef7eb2e8f9f7 901
<> 144:ef7eb2e8f9f7 902 /* Receive data register full */
<> 144:ef7eb2e8f9f7 903 if ((LPUART_STAT_RDRF_MASK & base->STAT) && (LPUART_CTRL_RIE_MASK & base->CTRL))
<> 144:ef7eb2e8f9f7 904 {
<> 144:ef7eb2e8f9f7 905 /* Get the size that can be stored into buffer for this interrupt. */
<> 144:ef7eb2e8f9f7 906 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 907 count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
<> 144:ef7eb2e8f9f7 908 #else
<> 144:ef7eb2e8f9f7 909 count = 1;
<> 144:ef7eb2e8f9f7 910 #endif
<> 144:ef7eb2e8f9f7 911
<> 144:ef7eb2e8f9f7 912 /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
<> 144:ef7eb2e8f9f7 913 while ((count) && (handle->rxDataSize))
<> 144:ef7eb2e8f9f7 914 {
<> 144:ef7eb2e8f9f7 915 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 916 tempCount = MIN(handle->rxDataSize, count);
<> 144:ef7eb2e8f9f7 917 #else
<> 144:ef7eb2e8f9f7 918 tempCount = 1;
<> 144:ef7eb2e8f9f7 919 #endif
<> 144:ef7eb2e8f9f7 920
<> 144:ef7eb2e8f9f7 921 /* Using non block API to read the data from the registers. */
<> 144:ef7eb2e8f9f7 922 LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
<> 144:ef7eb2e8f9f7 923 handle->rxData += tempCount;
<> 144:ef7eb2e8f9f7 924 handle->rxDataSize -= tempCount;
<> 144:ef7eb2e8f9f7 925 count -= tempCount;
<> 144:ef7eb2e8f9f7 926
<> 144:ef7eb2e8f9f7 927 /* If all the data required for upper layer is ready, trigger callback. */
<> 144:ef7eb2e8f9f7 928 if (!handle->rxDataSize)
<> 144:ef7eb2e8f9f7 929 {
<> 144:ef7eb2e8f9f7 930 handle->rxState = kLPUART_RxIdle;
<> 144:ef7eb2e8f9f7 931
<> 144:ef7eb2e8f9f7 932 if (handle->callback)
<> 144:ef7eb2e8f9f7 933 {
<> 144:ef7eb2e8f9f7 934 handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
<> 144:ef7eb2e8f9f7 935 }
<> 144:ef7eb2e8f9f7 936 }
<> 144:ef7eb2e8f9f7 937 }
<> 144:ef7eb2e8f9f7 938
<> 144:ef7eb2e8f9f7 939 /* If use RX ring buffer, receive data to ring buffer. */
<> 144:ef7eb2e8f9f7 940 if (handle->rxRingBuffer)
<> 144:ef7eb2e8f9f7 941 {
<> 144:ef7eb2e8f9f7 942 while (count--)
<> 144:ef7eb2e8f9f7 943 {
<> 144:ef7eb2e8f9f7 944 /* If RX ring buffer is full, trigger callback to notify over run. */
<> 144:ef7eb2e8f9f7 945 if (LPUART_TransferIsRxRingBufferFull(base, handle))
<> 144:ef7eb2e8f9f7 946 {
<> 144:ef7eb2e8f9f7 947 if (handle->callback)
<> 144:ef7eb2e8f9f7 948 {
<> 144:ef7eb2e8f9f7 949 handle->callback(base, handle, kStatus_LPUART_RxRingBufferOverrun, handle->userData);
<> 144:ef7eb2e8f9f7 950 }
<> 144:ef7eb2e8f9f7 951 }
<> 144:ef7eb2e8f9f7 952
<> 144:ef7eb2e8f9f7 953 /* If ring buffer is still full after callback function, the oldest data is overrided. */
<> 144:ef7eb2e8f9f7 954 if (LPUART_TransferIsRxRingBufferFull(base, handle))
<> 144:ef7eb2e8f9f7 955 {
<> 144:ef7eb2e8f9f7 956 /* Increase handle->rxRingBufferTail to make room for new data. */
<> 144:ef7eb2e8f9f7 957 if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
<> 144:ef7eb2e8f9f7 958 {
<> 144:ef7eb2e8f9f7 959 handle->rxRingBufferTail = 0U;
<> 144:ef7eb2e8f9f7 960 }
<> 144:ef7eb2e8f9f7 961 else
<> 144:ef7eb2e8f9f7 962 {
<> 144:ef7eb2e8f9f7 963 handle->rxRingBufferTail++;
<> 144:ef7eb2e8f9f7 964 }
<> 144:ef7eb2e8f9f7 965 }
<> 144:ef7eb2e8f9f7 966
<> 144:ef7eb2e8f9f7 967 /* Read data. */
<> 144:ef7eb2e8f9f7 968 handle->rxRingBuffer[handle->rxRingBufferHead] = base->DATA;
<> 144:ef7eb2e8f9f7 969
<> 144:ef7eb2e8f9f7 970 /* Increase handle->rxRingBufferHead. */
<> 144:ef7eb2e8f9f7 971 if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
<> 144:ef7eb2e8f9f7 972 {
<> 144:ef7eb2e8f9f7 973 handle->rxRingBufferHead = 0U;
<> 144:ef7eb2e8f9f7 974 }
<> 144:ef7eb2e8f9f7 975 else
<> 144:ef7eb2e8f9f7 976 {
<> 144:ef7eb2e8f9f7 977 handle->rxRingBufferHead++;
<> 144:ef7eb2e8f9f7 978 }
<> 144:ef7eb2e8f9f7 979 }
<> 144:ef7eb2e8f9f7 980 }
<> 144:ef7eb2e8f9f7 981 /* If no receive requst pending, stop RX interrupt. */
<> 144:ef7eb2e8f9f7 982 else if (!handle->rxDataSize)
<> 144:ef7eb2e8f9f7 983 {
<> 144:ef7eb2e8f9f7 984 LPUART_DisableInterrupts(base, kLPUART_RxDataRegFullInterruptEnable | kLPUART_RxOverrunInterruptEnable);
<> 144:ef7eb2e8f9f7 985 }
<> 144:ef7eb2e8f9f7 986 else
<> 144:ef7eb2e8f9f7 987 {
<> 144:ef7eb2e8f9f7 988 }
<> 144:ef7eb2e8f9f7 989 }
<> 144:ef7eb2e8f9f7 990
<> 144:ef7eb2e8f9f7 991 /* Send data register empty and the interrupt is enabled. */
<> 144:ef7eb2e8f9f7 992 if ((base->STAT & LPUART_STAT_TDRE_MASK) && (base->CTRL & LPUART_CTRL_TIE_MASK))
<> 144:ef7eb2e8f9f7 993 {
<> 144:ef7eb2e8f9f7 994 /* Get the bytes that available at this moment. */
<> 144:ef7eb2e8f9f7 995 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 996 count = FSL_FEATURE_LPUART_FIFO_SIZEn(base) -
<> 144:ef7eb2e8f9f7 997 ((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT);
<> 144:ef7eb2e8f9f7 998 #else
<> 144:ef7eb2e8f9f7 999 count = 1;
<> 144:ef7eb2e8f9f7 1000 #endif
<> 144:ef7eb2e8f9f7 1001
<> 144:ef7eb2e8f9f7 1002 while ((count) && (handle->txDataSize))
<> 144:ef7eb2e8f9f7 1003 {
<> 144:ef7eb2e8f9f7 1004 #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
<> 144:ef7eb2e8f9f7 1005 tempCount = MIN(handle->txDataSize, count);
<> 144:ef7eb2e8f9f7 1006 #else
<> 144:ef7eb2e8f9f7 1007 tempCount = 1;
<> 144:ef7eb2e8f9f7 1008 #endif
<> 144:ef7eb2e8f9f7 1009
<> 144:ef7eb2e8f9f7 1010 /* Using non block API to write the data to the registers. */
<> 144:ef7eb2e8f9f7 1011 LPUART_WriteNonBlocking(base, handle->txData, tempCount);
<> 144:ef7eb2e8f9f7 1012 handle->txData += tempCount;
<> 144:ef7eb2e8f9f7 1013 handle->txDataSize -= tempCount;
<> 144:ef7eb2e8f9f7 1014 count -= tempCount;
<> 144:ef7eb2e8f9f7 1015
<> 144:ef7eb2e8f9f7 1016 /* If all the data are written to data register, notify user with the callback, then TX finished. */
<> 144:ef7eb2e8f9f7 1017 if (!handle->txDataSize)
<> 144:ef7eb2e8f9f7 1018 {
<> 144:ef7eb2e8f9f7 1019 handle->txState = kLPUART_TxIdle;
<> 144:ef7eb2e8f9f7 1020
<> 144:ef7eb2e8f9f7 1021 /* Disable TX register empty interrupt. */
<> 144:ef7eb2e8f9f7 1022 base->CTRL = (base->CTRL & ~LPUART_CTRL_TIE_MASK);
<> 144:ef7eb2e8f9f7 1023
<> 144:ef7eb2e8f9f7 1024 /* Trigger callback. */
<> 144:ef7eb2e8f9f7 1025 if (handle->callback)
<> 144:ef7eb2e8f9f7 1026 {
<> 144:ef7eb2e8f9f7 1027 handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData);
<> 144:ef7eb2e8f9f7 1028 }
<> 144:ef7eb2e8f9f7 1029 }
<> 144:ef7eb2e8f9f7 1030 }
<> 144:ef7eb2e8f9f7 1031 }
<> 144:ef7eb2e8f9f7 1032 }
<> 144:ef7eb2e8f9f7 1033
<> 144:ef7eb2e8f9f7 1034 void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle)
<> 144:ef7eb2e8f9f7 1035 {
<> 144:ef7eb2e8f9f7 1036 /* TODO: To be implemented. */
<> 144:ef7eb2e8f9f7 1037 }
<> 144:ef7eb2e8f9f7 1038
<> 144:ef7eb2e8f9f7 1039 #if defined(LPUART0)
<> 144:ef7eb2e8f9f7 1040 void LPUART0_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1041 {
<> 144:ef7eb2e8f9f7 1042 s_lpuartIsr(LPUART0, s_lpuartHandle[0]);
<> 144:ef7eb2e8f9f7 1043 }
<> 144:ef7eb2e8f9f7 1044 void LPUART0_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1045 {
<> 144:ef7eb2e8f9f7 1046 LPUART0_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1047 }
<> 144:ef7eb2e8f9f7 1048 #endif
<> 144:ef7eb2e8f9f7 1049
<> 144:ef7eb2e8f9f7 1050 #if defined(LPUART1)
<> 144:ef7eb2e8f9f7 1051 void LPUART1_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1052 {
<> 144:ef7eb2e8f9f7 1053 s_lpuartIsr(LPUART1, s_lpuartHandle[1]);
<> 144:ef7eb2e8f9f7 1054 }
<> 144:ef7eb2e8f9f7 1055 void LPUART1_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1056 {
<> 144:ef7eb2e8f9f7 1057 LPUART1_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1058 }
<> 144:ef7eb2e8f9f7 1059 #endif
<> 144:ef7eb2e8f9f7 1060
<> 144:ef7eb2e8f9f7 1061 #if defined(LPUART2)
<> 144:ef7eb2e8f9f7 1062 void LPUART2_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1063 {
<> 144:ef7eb2e8f9f7 1064 s_lpuartIsr(LPUART2, s_lpuartHandle[2]);
<> 144:ef7eb2e8f9f7 1065 }
<> 144:ef7eb2e8f9f7 1066 void LPUART2_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1067 {
<> 144:ef7eb2e8f9f7 1068 LPUART2_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1069 }
<> 144:ef7eb2e8f9f7 1070 #endif
<> 144:ef7eb2e8f9f7 1071
<> 144:ef7eb2e8f9f7 1072 #if defined(LPUART3)
<> 144:ef7eb2e8f9f7 1073 void LPUART3_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1074 {
<> 144:ef7eb2e8f9f7 1075 s_lpuartIsr(LPUART3, s_lpuartHandle[3]);
<> 144:ef7eb2e8f9f7 1076 }
<> 144:ef7eb2e8f9f7 1077 void LPUART3_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1078 {
<> 144:ef7eb2e8f9f7 1079 LPUART3_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1080 }
<> 144:ef7eb2e8f9f7 1081 #endif
<> 144:ef7eb2e8f9f7 1082
<> 144:ef7eb2e8f9f7 1083 #if defined(LPUART4)
<> 144:ef7eb2e8f9f7 1084 void LPUART4_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1085 {
<> 144:ef7eb2e8f9f7 1086 s_lpuartIsr(LPUART4, s_lpuartHandle[4]);
<> 144:ef7eb2e8f9f7 1087 }
<> 144:ef7eb2e8f9f7 1088 void LPUART4_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1089 {
<> 144:ef7eb2e8f9f7 1090 LPUART4_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1091 }
<> 144:ef7eb2e8f9f7 1092 #endif
<> 144:ef7eb2e8f9f7 1093
<> 144:ef7eb2e8f9f7 1094 #if defined(LPUART5)
<> 144:ef7eb2e8f9f7 1095 void LPUART5_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1096 {
<> 144:ef7eb2e8f9f7 1097 s_lpuartIsr(LPUART5, s_lpuartHandle[5]);
<> 144:ef7eb2e8f9f7 1098 }
<> 144:ef7eb2e8f9f7 1099 void LPUART5_RX_TX_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1100 {
<> 144:ef7eb2e8f9f7 1101 LPUART5_DriverIRQHandler();
<> 144:ef7eb2e8f9f7 1102 }
<> 144:ef7eb2e8f9f7 1103 #endif