t

Fork of mbed-dev by mbed official

Committer:
amithy
Date:
Thu Nov 09 22:14:37 2017 +0000
Revision:
178:c26431f84b0d
Parent:
150:02e0a0aed4ec
test export

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 150:02e0a0aed4ec 1 /*******************************************************************************
<> 150:02e0a0aed4ec 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
<> 150:02e0a0aed4ec 3 *
<> 150:02e0a0aed4ec 4 * Permission is hereby granted, free of charge, to any person obtaining a
<> 150:02e0a0aed4ec 5 * copy of this software and associated documentation files (the "Software"),
<> 150:02e0a0aed4ec 6 * to deal in the Software without restriction, including without limitation
<> 150:02e0a0aed4ec 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
<> 150:02e0a0aed4ec 8 * and/or sell copies of the Software, and to permit persons to whom the
<> 150:02e0a0aed4ec 9 * Software is furnished to do so, subject to the following conditions:
<> 150:02e0a0aed4ec 10 *
<> 150:02e0a0aed4ec 11 * The above copyright notice and this permission notice shall be included
<> 150:02e0a0aed4ec 12 * in all copies or substantial portions of the Software.
<> 150:02e0a0aed4ec 13 *
<> 150:02e0a0aed4ec 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
<> 150:02e0a0aed4ec 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
<> 150:02e0a0aed4ec 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
<> 150:02e0a0aed4ec 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
<> 150:02e0a0aed4ec 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
<> 150:02e0a0aed4ec 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
<> 150:02e0a0aed4ec 20 * OTHER DEALINGS IN THE SOFTWARE.
<> 150:02e0a0aed4ec 21 *
<> 150:02e0a0aed4ec 22 * Except as contained in this notice, the name of Maxim Integrated
<> 150:02e0a0aed4ec 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
<> 150:02e0a0aed4ec 24 * Products, Inc. Branding Policy.
<> 150:02e0a0aed4ec 25 *
<> 150:02e0a0aed4ec 26 * The mere transfer of this software does not imply any licenses
<> 150:02e0a0aed4ec 27 * of trade secrets, proprietary technology, copyrights, patents,
<> 150:02e0a0aed4ec 28 * trademarks, maskwork rights, or any other form of intellectual
<> 150:02e0a0aed4ec 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
<> 150:02e0a0aed4ec 30 * ownership rights.
<> 150:02e0a0aed4ec 31 *
<> 150:02e0a0aed4ec 32 * $Date: 2016-07-28 15:01:10 -0500 (Thu, 28 Jul 2016) $
<> 150:02e0a0aed4ec 33 * $Revision: 23823 $
<> 150:02e0a0aed4ec 34 *
<> 150:02e0a0aed4ec 35 ******************************************************************************/
<> 150:02e0a0aed4ec 36
<> 150:02e0a0aed4ec 37 /**
<> 150:02e0a0aed4ec 38 * @file uart.c
<> 150:02e0a0aed4ec 39 * @brief UART diver source.
<> 150:02e0a0aed4ec 40 */
<> 150:02e0a0aed4ec 41
<> 150:02e0a0aed4ec 42 /***** Includes *****/
<> 150:02e0a0aed4ec 43 #include <string.h>
<> 150:02e0a0aed4ec 44 #include "mxc_assert.h"
<> 150:02e0a0aed4ec 45 #include "mxc_lock.h"
<> 150:02e0a0aed4ec 46 #include "mxc_sys.h"
<> 150:02e0a0aed4ec 47 #include "uart.h"
<> 150:02e0a0aed4ec 48
<> 150:02e0a0aed4ec 49 /***** Definitions *****/
<> 150:02e0a0aed4ec 50 #define UART_ERRORS (MXC_F_UART_INTEN_RX_FIFO_OVERFLOW | \
<> 150:02e0a0aed4ec 51 MXC_F_UART_INTEN_RX_FRAMING_ERR | \
<> 150:02e0a0aed4ec 52 MXC_F_UART_INTEN_RX_PARITY_ERR)
<> 150:02e0a0aed4ec 53
<> 150:02e0a0aed4ec 54 #define UART_READ_INTS (MXC_F_UART_INTEN_RX_FIFO_AF | \
<> 150:02e0a0aed4ec 55 MXC_F_UART_INTEN_RX_FIFO_NOT_EMPTY | \
<> 150:02e0a0aed4ec 56 MXC_F_UART_INTEN_RX_STALLED | \
<> 150:02e0a0aed4ec 57 UART_ERRORS)
<> 150:02e0a0aed4ec 58
<> 150:02e0a0aed4ec 59 #define UART_WRITE_INTS (MXC_F_UART_INTEN_TX_UNSTALLED | \
<> 150:02e0a0aed4ec 60 MXC_F_UART_INTEN_TX_FIFO_AE)
<> 150:02e0a0aed4ec 61
<> 150:02e0a0aed4ec 62 #define UART_RXFIFO_USABLE (MXC_UART_FIFO_DEPTH-3)
<> 150:02e0a0aed4ec 63
<> 150:02e0a0aed4ec 64 /***** Globals *****/
<> 150:02e0a0aed4ec 65
<> 150:02e0a0aed4ec 66 // Saves the state of the non-blocking read requests
<> 150:02e0a0aed4ec 67 static uart_req_t *rx_states[MXC_CFG_UART_INSTANCES];
<> 150:02e0a0aed4ec 68
<> 150:02e0a0aed4ec 69 // Saves the state of the non-blocking write requests
<> 150:02e0a0aed4ec 70 static uart_req_t *tx_states[MXC_CFG_UART_INSTANCES];
<> 150:02e0a0aed4ec 71
<> 150:02e0a0aed4ec 72 /***** Functions *****/
<> 150:02e0a0aed4ec 73 static void UART_WriteHandler(mxc_uart_regs_t *uart, uart_req_t *req, int uart_num);
<> 150:02e0a0aed4ec 74 static void UART_ReadHandler(mxc_uart_regs_t *uart, uart_req_t *req, int uart_num,
<> 150:02e0a0aed4ec 75 uint32_t flags);
<> 150:02e0a0aed4ec 76
<> 150:02e0a0aed4ec 77 /******************************************************************************/
<> 150:02e0a0aed4ec 78 int UART_Init(mxc_uart_regs_t *uart, const uart_cfg_t *cfg, const sys_cfg_uart_t *sys_cfg)
<> 150:02e0a0aed4ec 79 {
<> 150:02e0a0aed4ec 80 int err;
<> 150:02e0a0aed4ec 81 int uart_num;
<> 150:02e0a0aed4ec 82 uint32_t uart_clk;
<> 150:02e0a0aed4ec 83 uint8_t baud_shift;
<> 150:02e0a0aed4ec 84 uint16_t baud_div;
<> 150:02e0a0aed4ec 85 uint32_t baud, diff_baud;
<> 150:02e0a0aed4ec 86 uint32_t baud_1, diff_baud_1;
<> 150:02e0a0aed4ec 87
<> 150:02e0a0aed4ec 88 // Check the input parameters
<> 150:02e0a0aed4ec 89 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 90 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 91
<> 150:02e0a0aed4ec 92 // Set system level configurations
<> 150:02e0a0aed4ec 93 if(sys_cfg != NULL) {
<> 150:02e0a0aed4ec 94 if ((err = SYS_UART_Init(uart, cfg, sys_cfg)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 95 return err;
<> 150:02e0a0aed4ec 96 }
<> 150:02e0a0aed4ec 97 }
<> 150:02e0a0aed4ec 98
<> 150:02e0a0aed4ec 99 // Initialize state pointers
<> 150:02e0a0aed4ec 100 rx_states[uart_num] = NULL;
<> 150:02e0a0aed4ec 101 tx_states[uart_num] = NULL;
<> 150:02e0a0aed4ec 102
<> 150:02e0a0aed4ec 103 // Drain FIFOs and enable UART
<> 150:02e0a0aed4ec 104 uart->ctrl = 0;
<> 150:02e0a0aed4ec 105 uart->ctrl = (MXC_F_UART_CTRL_UART_EN | MXC_F_UART_CTRL_TX_FIFO_EN |
<> 150:02e0a0aed4ec 106 MXC_F_UART_CTRL_RX_FIFO_EN |
<> 150:02e0a0aed4ec 107 (UART_RXFIFO_USABLE << MXC_F_UART_CTRL_RTS_LEVEL_POS));
<> 150:02e0a0aed4ec 108
<> 150:02e0a0aed4ec 109 // Configure data size, stop bit, parity, cts, and rts
<> 150:02e0a0aed4ec 110 uart->ctrl |= ((cfg->size << MXC_F_UART_CTRL_DATA_SIZE_POS) |
<> 150:02e0a0aed4ec 111 (cfg->extra_stop << MXC_F_UART_CTRL_EXTRA_STOP_POS) |
<> 150:02e0a0aed4ec 112 (cfg->parity << MXC_F_UART_CTRL_PARITY_POS) |
<> 150:02e0a0aed4ec 113 (cfg->cts << MXC_F_UART_CTRL_CTS_EN_POS) |
<> 150:02e0a0aed4ec 114 (cfg->rts << MXC_F_UART_CTRL_RTS_EN_POS));
<> 150:02e0a0aed4ec 115
<> 150:02e0a0aed4ec 116 // Configure the baud rate and divisor
<> 150:02e0a0aed4ec 117 uart_clk = SYS_UART_GetFreq(uart);
<> 150:02e0a0aed4ec 118 MXC_ASSERT(uart_clk > 0);
<> 150:02e0a0aed4ec 119
<> 150:02e0a0aed4ec 120 baud_shift = 2;
<> 150:02e0a0aed4ec 121 baud_div = (uart_clk / (cfg->baud * 4));
<> 150:02e0a0aed4ec 122
<> 150:02e0a0aed4ec 123 // Can not support higher frequencies
<> 150:02e0a0aed4ec 124 if(!baud_div) {
<> 150:02e0a0aed4ec 125 return E_NOT_SUPPORTED;
<> 150:02e0a0aed4ec 126 }
<> 150:02e0a0aed4ec 127
<> 150:02e0a0aed4ec 128 // Decrease the divisor if baud_div is overflowing
<> 150:02e0a0aed4ec 129 while(baud_div > 0xFF) {
<> 150:02e0a0aed4ec 130 if(baud_shift == 0) {
<> 150:02e0a0aed4ec 131 return E_NOT_SUPPORTED;
<> 150:02e0a0aed4ec 132 }
<> 150:02e0a0aed4ec 133 baud_shift--;
<> 150:02e0a0aed4ec 134 baud_div = (uart_clk / (cfg->baud * (16 >> baud_shift)));
<> 150:02e0a0aed4ec 135 }
<> 150:02e0a0aed4ec 136
<> 150:02e0a0aed4ec 137 // Adjust baud_div so we don't overflow with the calculations below
<> 150:02e0a0aed4ec 138 if(baud_div == 0xFF) {
<> 150:02e0a0aed4ec 139 baud_div = 0xFE;
<> 150:02e0a0aed4ec 140 }
<> 150:02e0a0aed4ec 141 if(baud_div == 0) {
<> 150:02e0a0aed4ec 142 baud_div = 1;
<> 150:02e0a0aed4ec 143 }
<> 150:02e0a0aed4ec 144
<> 150:02e0a0aed4ec 145 // Figure out if the truncation increased the error
<> 150:02e0a0aed4ec 146 baud = (uart_clk / (baud_div * (16 >> baud_shift)));
<> 150:02e0a0aed4ec 147 baud_1 = (uart_clk / ((baud_div+1) * (16 >> baud_shift)));
<> 150:02e0a0aed4ec 148
<> 150:02e0a0aed4ec 149 if(cfg->baud > baud) {
<> 150:02e0a0aed4ec 150 diff_baud = cfg->baud - baud;
<> 150:02e0a0aed4ec 151 } else {
<> 150:02e0a0aed4ec 152 diff_baud = baud - cfg->baud;
<> 150:02e0a0aed4ec 153 }
<> 150:02e0a0aed4ec 154
<> 150:02e0a0aed4ec 155 if(cfg->baud > baud_1) {
<> 150:02e0a0aed4ec 156 diff_baud_1 = cfg->baud - baud_1;
<> 150:02e0a0aed4ec 157 } else {
<> 150:02e0a0aed4ec 158 diff_baud_1 = baud_1 - cfg->baud;
<> 150:02e0a0aed4ec 159 }
<> 150:02e0a0aed4ec 160
<> 150:02e0a0aed4ec 161 if(diff_baud < diff_baud_1) {
<> 150:02e0a0aed4ec 162 uart->baud = ((baud_div & MXC_F_UART_BAUD_BAUD_DIVISOR) |
<> 150:02e0a0aed4ec 163 (baud_shift << MXC_F_UART_BAUD_BAUD_MODE_POS));
<> 150:02e0a0aed4ec 164 } else {
<> 150:02e0a0aed4ec 165 uart->baud = (((baud_div+1) & MXC_F_UART_BAUD_BAUD_DIVISOR) |
<> 150:02e0a0aed4ec 166 (baud_shift << MXC_F_UART_BAUD_BAUD_MODE_POS));
<> 150:02e0a0aed4ec 167 }
<> 150:02e0a0aed4ec 168
<> 150:02e0a0aed4ec 169 return E_NO_ERROR;
<> 150:02e0a0aed4ec 170 }
<> 150:02e0a0aed4ec 171
<> 150:02e0a0aed4ec 172 /******************************************************************************/
<> 150:02e0a0aed4ec 173 int UART_Shutdown(mxc_uart_regs_t *uart)
<> 150:02e0a0aed4ec 174 {
<> 150:02e0a0aed4ec 175 int uart_num, err;
<> 150:02e0a0aed4ec 176 uart_req_t *temp_req;
<> 150:02e0a0aed4ec 177
<> 150:02e0a0aed4ec 178 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 179 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 180
<> 150:02e0a0aed4ec 181 // Disable and clear interrupts
<> 150:02e0a0aed4ec 182 uart->inten = 0;
<> 150:02e0a0aed4ec 183 uart->intfl = uart->intfl;
<> 150:02e0a0aed4ec 184
<> 150:02e0a0aed4ec 185 // Disable UART and FIFOS
<> 150:02e0a0aed4ec 186 uart->ctrl &= ~(MXC_F_UART_CTRL_UART_EN | MXC_F_UART_CTRL_TX_FIFO_EN |
<> 150:02e0a0aed4ec 187 MXC_F_UART_CTRL_RX_FIFO_EN);
<> 150:02e0a0aed4ec 188
<> 150:02e0a0aed4ec 189 // Call all of the pending callbacks for this UART
<> 150:02e0a0aed4ec 190 if(rx_states[uart_num] != NULL) {
<> 150:02e0a0aed4ec 191
<> 150:02e0a0aed4ec 192 // Save the request
<> 150:02e0a0aed4ec 193 temp_req = rx_states[uart_num];
<> 150:02e0a0aed4ec 194
<> 150:02e0a0aed4ec 195 // Unlock this UART to read
<> 150:02e0a0aed4ec 196 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 197
<> 150:02e0a0aed4ec 198 // Callback if not NULL
<> 150:02e0a0aed4ec 199 if(temp_req->callback != NULL) {
<> 150:02e0a0aed4ec 200 temp_req->callback(temp_req, E_SHUTDOWN);
<> 150:02e0a0aed4ec 201 }
<> 150:02e0a0aed4ec 202 }
<> 150:02e0a0aed4ec 203
<> 150:02e0a0aed4ec 204 if(tx_states[uart_num] != NULL) {
<> 150:02e0a0aed4ec 205
<> 150:02e0a0aed4ec 206 // Save the request
<> 150:02e0a0aed4ec 207 temp_req = tx_states[uart_num];
<> 150:02e0a0aed4ec 208
<> 150:02e0a0aed4ec 209 // Unlock this UART to write
<> 150:02e0a0aed4ec 210 mxc_free_lock((uint32_t*)&tx_states[uart_num]);
<> 150:02e0a0aed4ec 211
<> 150:02e0a0aed4ec 212 // Callback if not NULL
<> 150:02e0a0aed4ec 213 if(temp_req->callback != NULL) {
<> 150:02e0a0aed4ec 214 temp_req->callback(temp_req, E_SHUTDOWN);
<> 150:02e0a0aed4ec 215 }
<> 150:02e0a0aed4ec 216 }
<> 150:02e0a0aed4ec 217
<> 150:02e0a0aed4ec 218 // Clears system level configurations
<> 150:02e0a0aed4ec 219 if ((err = SYS_UART_Shutdown(uart)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 220 return err;
<> 150:02e0a0aed4ec 221 }
<> 150:02e0a0aed4ec 222
<> 150:02e0a0aed4ec 223 return E_NO_ERROR;
<> 150:02e0a0aed4ec 224 }
<> 150:02e0a0aed4ec 225
<> 150:02e0a0aed4ec 226 /******************************************************************************/
<> 150:02e0a0aed4ec 227 int UART_Write(mxc_uart_regs_t *uart, uint8_t* data, int len)
<> 150:02e0a0aed4ec 228 {
<> 150:02e0a0aed4ec 229 int num, uart_num;
<> 150:02e0a0aed4ec 230 mxc_uart_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 231
<> 150:02e0a0aed4ec 232 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 233 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 234
<> 150:02e0a0aed4ec 235 if(data == NULL) {
<> 150:02e0a0aed4ec 236 return E_NULL_PTR;
<> 150:02e0a0aed4ec 237 }
<> 150:02e0a0aed4ec 238
<> 150:02e0a0aed4ec 239 // Make sure the UART has been initialized
<> 150:02e0a0aed4ec 240 if(!(uart->ctrl & MXC_F_UART_CTRL_UART_EN)) {
<> 150:02e0a0aed4ec 241 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 242 }
<> 150:02e0a0aed4ec 243
<> 150:02e0a0aed4ec 244 if(!(len > 0)) {
<> 150:02e0a0aed4ec 245 return E_NO_ERROR;
<> 150:02e0a0aed4ec 246 }
<> 150:02e0a0aed4ec 247
<> 150:02e0a0aed4ec 248 // Lock this UART from writing
<> 150:02e0a0aed4ec 249 while(mxc_get_lock((uint32_t*)&tx_states[uart_num], 1) != E_NO_ERROR) {}
<> 150:02e0a0aed4ec 250
<> 150:02e0a0aed4ec 251 // Get the FIFO for this UART
<> 150:02e0a0aed4ec 252 fifo = MXC_UART_GET_FIFO(uart_num);
<> 150:02e0a0aed4ec 253
<> 150:02e0a0aed4ec 254 num = 0;
<> 150:02e0a0aed4ec 255
<> 150:02e0a0aed4ec 256 while(num < len) {
<> 150:02e0a0aed4ec 257
<> 150:02e0a0aed4ec 258 // Wait for TXFIFO to not be full
<> 150:02e0a0aed4ec 259 while((uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) ==
<> 150:02e0a0aed4ec 260 MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) {}
<> 150:02e0a0aed4ec 261
<> 150:02e0a0aed4ec 262 // Write the data to the FIFO
<> 150:02e0a0aed4ec 263 #if(MXC_UART_REV == 0)
<> 150:02e0a0aed4ec 264 uart->intfl = MXC_F_UART_INTFL_TX_DONE;
<> 150:02e0a0aed4ec 265 #endif
<> 150:02e0a0aed4ec 266 fifo->tx = data[num++];
<> 150:02e0a0aed4ec 267 }
<> 150:02e0a0aed4ec 268
<> 150:02e0a0aed4ec 269 // Unlock this UART to write
<> 150:02e0a0aed4ec 270 mxc_free_lock((uint32_t*)&tx_states[uart_num]);
<> 150:02e0a0aed4ec 271
<> 150:02e0a0aed4ec 272 return num;
<> 150:02e0a0aed4ec 273 }
<> 150:02e0a0aed4ec 274
<> 150:02e0a0aed4ec 275 /******************************************************************************/
<> 150:02e0a0aed4ec 276 int UART_Read(mxc_uart_regs_t *uart, uint8_t* data, int len, int *num)
<> 150:02e0a0aed4ec 277 {
<> 150:02e0a0aed4ec 278 int num_local, remain, uart_num;
<> 150:02e0a0aed4ec 279 mxc_uart_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 280
<> 150:02e0a0aed4ec 281 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 282 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 283
<> 150:02e0a0aed4ec 284 if(data == NULL) {
<> 150:02e0a0aed4ec 285 return E_NULL_PTR;
<> 150:02e0a0aed4ec 286 }
<> 150:02e0a0aed4ec 287
<> 150:02e0a0aed4ec 288 // Make sure the UART has been initialized
<> 150:02e0a0aed4ec 289 if(!(uart->ctrl & MXC_F_UART_CTRL_UART_EN)) {
<> 150:02e0a0aed4ec 290 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 291 }
<> 150:02e0a0aed4ec 292
<> 150:02e0a0aed4ec 293 if(!(len > 0)) {
<> 150:02e0a0aed4ec 294 return E_NO_ERROR;
<> 150:02e0a0aed4ec 295 }
<> 150:02e0a0aed4ec 296
<> 150:02e0a0aed4ec 297 // Lock this UART from reading
<> 150:02e0a0aed4ec 298 while(mxc_get_lock((uint32_t*)&rx_states[uart_num], 1) != E_NO_ERROR) {}
<> 150:02e0a0aed4ec 299
<> 150:02e0a0aed4ec 300 // Get the FIFO for this UART
<> 150:02e0a0aed4ec 301 fifo = MXC_UART_GET_FIFO(uart_num);
<> 150:02e0a0aed4ec 302
<> 150:02e0a0aed4ec 303 num_local = 0;
<> 150:02e0a0aed4ec 304 remain = len;
<> 150:02e0a0aed4ec 305 while(remain) {
<> 150:02e0a0aed4ec 306
<> 150:02e0a0aed4ec 307 // Save the data in the FIFO
<> 150:02e0a0aed4ec 308 while((uart->rx_fifo_ctrl & MXC_F_UART_RX_FIFO_CTRL_FIFO_ENTRY) && remain) {
<> 150:02e0a0aed4ec 309 data[num_local] = fifo->rx;
<> 150:02e0a0aed4ec 310 num_local++;
<> 150:02e0a0aed4ec 311 remain--;
<> 150:02e0a0aed4ec 312 }
<> 150:02e0a0aed4ec 313
<> 150:02e0a0aed4ec 314 // Break if there is an error
<> 150:02e0a0aed4ec 315 if(uart->intfl & UART_ERRORS) {
<> 150:02e0a0aed4ec 316 break;
<> 150:02e0a0aed4ec 317 }
<> 150:02e0a0aed4ec 318 }
<> 150:02e0a0aed4ec 319
<> 150:02e0a0aed4ec 320 // Save the number of bytes read if pointer is valid
<> 150:02e0a0aed4ec 321 if(num != NULL) {
<> 150:02e0a0aed4ec 322 *num = num_local;
<> 150:02e0a0aed4ec 323 }
<> 150:02e0a0aed4ec 324
<> 150:02e0a0aed4ec 325 // Check for errors
<> 150:02e0a0aed4ec 326 if(uart->intfl & MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) {
<> 150:02e0a0aed4ec 327
<> 150:02e0a0aed4ec 328 // Clear errors and return error code
<> 150:02e0a0aed4ec 329 uart->intfl = UART_ERRORS;
<> 150:02e0a0aed4ec 330
<> 150:02e0a0aed4ec 331
<> 150:02e0a0aed4ec 332 // Unlock this UART to read
<> 150:02e0a0aed4ec 333 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 334
<> 150:02e0a0aed4ec 335 return E_OVERFLOW;
<> 150:02e0a0aed4ec 336
<> 150:02e0a0aed4ec 337 } else if(uart->intfl & (MXC_F_UART_INTFL_RX_FRAMING_ERR |
<> 150:02e0a0aed4ec 338 MXC_F_UART_INTFL_RX_PARITY_ERR)) {
<> 150:02e0a0aed4ec 339
<> 150:02e0a0aed4ec 340 // Clear errors and return error code
<> 150:02e0a0aed4ec 341 uart->intfl = UART_ERRORS;
<> 150:02e0a0aed4ec 342
<> 150:02e0a0aed4ec 343
<> 150:02e0a0aed4ec 344 // Unlock this UART to read
<> 150:02e0a0aed4ec 345 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 346
<> 150:02e0a0aed4ec 347 return E_COMM_ERR;
<> 150:02e0a0aed4ec 348 }
<> 150:02e0a0aed4ec 349
<> 150:02e0a0aed4ec 350 // Unlock this UART to read
<> 150:02e0a0aed4ec 351 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 352
<> 150:02e0a0aed4ec 353 return num_local;
<> 150:02e0a0aed4ec 354 }
<> 150:02e0a0aed4ec 355
<> 150:02e0a0aed4ec 356 /******************************************************************************/
<> 150:02e0a0aed4ec 357 int UART_WriteAsync(mxc_uart_regs_t *uart, uart_req_t *req)
<> 150:02e0a0aed4ec 358 {
<> 150:02e0a0aed4ec 359 int uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 360 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 361
<> 150:02e0a0aed4ec 362 // Check the input parameters
<> 150:02e0a0aed4ec 363 if(req->data == NULL) {
<> 150:02e0a0aed4ec 364 return E_NULL_PTR;
<> 150:02e0a0aed4ec 365 }
<> 150:02e0a0aed4ec 366
<> 150:02e0a0aed4ec 367 // Make sure the UART has been initialized
<> 150:02e0a0aed4ec 368 if(!(uart->ctrl & MXC_F_UART_CTRL_UART_EN)) {
<> 150:02e0a0aed4ec 369 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 370 }
<> 150:02e0a0aed4ec 371
<> 150:02e0a0aed4ec 372 if(!(req->len > 0)) {
<> 150:02e0a0aed4ec 373 return E_NO_ERROR;
<> 150:02e0a0aed4ec 374 }
<> 150:02e0a0aed4ec 375
<> 150:02e0a0aed4ec 376 // Attempt to register this write request
<> 150:02e0a0aed4ec 377 if(mxc_get_lock((uint32_t*)&tx_states[uart_num], (uint32_t)req) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 378 return E_BUSY;
<> 150:02e0a0aed4ec 379 }
<> 150:02e0a0aed4ec 380
<> 150:02e0a0aed4ec 381 // Clear the number of bytes counter
<> 150:02e0a0aed4ec 382 req->num = 0;
<> 150:02e0a0aed4ec 383
<> 150:02e0a0aed4ec 384 // Start the write
<> 150:02e0a0aed4ec 385 UART_WriteHandler(uart, req, uart_num);
<> 150:02e0a0aed4ec 386
<> 150:02e0a0aed4ec 387 return E_NO_ERROR;
<> 150:02e0a0aed4ec 388 }
<> 150:02e0a0aed4ec 389
<> 150:02e0a0aed4ec 390 /******************************************************************************/
<> 150:02e0a0aed4ec 391 int UART_ReadAsync(mxc_uart_regs_t *uart, uart_req_t *req)
<> 150:02e0a0aed4ec 392 {
<> 150:02e0a0aed4ec 393 int uart_num;
<> 150:02e0a0aed4ec 394 uint32_t flags;
<> 150:02e0a0aed4ec 395
<> 150:02e0a0aed4ec 396 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 397 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 398
<> 150:02e0a0aed4ec 399 if(req->data == NULL) {
<> 150:02e0a0aed4ec 400 return E_NULL_PTR;
<> 150:02e0a0aed4ec 401 }
<> 150:02e0a0aed4ec 402
<> 150:02e0a0aed4ec 403 // Make sure the UART has been initialized
<> 150:02e0a0aed4ec 404 if(!(uart->ctrl & MXC_F_UART_CTRL_UART_EN)) {
<> 150:02e0a0aed4ec 405 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 406 }
<> 150:02e0a0aed4ec 407
<> 150:02e0a0aed4ec 408 if(!(req->len > 0)) {
<> 150:02e0a0aed4ec 409 return E_NO_ERROR;
<> 150:02e0a0aed4ec 410 }
<> 150:02e0a0aed4ec 411
<> 150:02e0a0aed4ec 412 // Attempt to register this write request
<> 150:02e0a0aed4ec 413 if(mxc_get_lock((uint32_t*)&rx_states[uart_num], (uint32_t)req) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 414 return E_BUSY;
<> 150:02e0a0aed4ec 415 }
<> 150:02e0a0aed4ec 416
<> 150:02e0a0aed4ec 417 // Clear the number of bytes counter
<> 150:02e0a0aed4ec 418 req->num = 0;
<> 150:02e0a0aed4ec 419
<> 150:02e0a0aed4ec 420 // Start the read
<> 150:02e0a0aed4ec 421 flags = uart->intfl;
<> 150:02e0a0aed4ec 422 uart->intfl = flags;
<> 150:02e0a0aed4ec 423 UART_ReadHandler(uart, req, uart_num, flags);
<> 150:02e0a0aed4ec 424
<> 150:02e0a0aed4ec 425 return E_NO_ERROR;
<> 150:02e0a0aed4ec 426 }
<> 150:02e0a0aed4ec 427
<> 150:02e0a0aed4ec 428 /******************************************************************************/
<> 150:02e0a0aed4ec 429 int UART_AbortAsync(uart_req_t *req)
<> 150:02e0a0aed4ec 430 {
<> 150:02e0a0aed4ec 431 int uart_num;
<> 150:02e0a0aed4ec 432
<> 150:02e0a0aed4ec 433 // Figure out if this was a read or write request, find the request, set to NULL
<> 150:02e0a0aed4ec 434 for(uart_num = 0; uart_num < MXC_CFG_UART_INSTANCES; uart_num++) {
<> 150:02e0a0aed4ec 435 if(req == rx_states[uart_num]) {
<> 150:02e0a0aed4ec 436
<> 150:02e0a0aed4ec 437 // Disable read interrupts, clear flags.
<> 150:02e0a0aed4ec 438 MXC_UART_GET_UART(uart_num)->inten &= ~UART_READ_INTS;
<> 150:02e0a0aed4ec 439 MXC_UART_GET_UART(uart_num)->intfl = UART_READ_INTS;
<> 150:02e0a0aed4ec 440
<> 150:02e0a0aed4ec 441 // Unlock this UART to read
<> 150:02e0a0aed4ec 442 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 443
<> 150:02e0a0aed4ec 444 // Callback if not NULL
<> 150:02e0a0aed4ec 445 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 446 req->callback(req, E_ABORT);
<> 150:02e0a0aed4ec 447 }
<> 150:02e0a0aed4ec 448
<> 150:02e0a0aed4ec 449 return E_NO_ERROR;
<> 150:02e0a0aed4ec 450 }
<> 150:02e0a0aed4ec 451
<> 150:02e0a0aed4ec 452 if(req == tx_states[uart_num]) {
<> 150:02e0a0aed4ec 453
<> 150:02e0a0aed4ec 454 // Disable write interrupts, clear flags.
<> 150:02e0a0aed4ec 455 MXC_UART_GET_UART(uart_num)->inten &= ~(UART_WRITE_INTS);
<> 150:02e0a0aed4ec 456 MXC_UART_GET_UART(uart_num)->intfl = UART_WRITE_INTS;
<> 150:02e0a0aed4ec 457
<> 150:02e0a0aed4ec 458 // Unlock this UART to write
<> 150:02e0a0aed4ec 459 mxc_free_lock((uint32_t*)&tx_states[uart_num]);
<> 150:02e0a0aed4ec 460
<> 150:02e0a0aed4ec 461 // Callback if not NULL
<> 150:02e0a0aed4ec 462 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 463 req->callback(req, E_ABORT);
<> 150:02e0a0aed4ec 464 }
<> 150:02e0a0aed4ec 465
<> 150:02e0a0aed4ec 466 return E_NO_ERROR;
<> 150:02e0a0aed4ec 467 }
<> 150:02e0a0aed4ec 468 }
<> 150:02e0a0aed4ec 469
<> 150:02e0a0aed4ec 470 return E_BAD_PARAM;
<> 150:02e0a0aed4ec 471 }
<> 150:02e0a0aed4ec 472
<> 150:02e0a0aed4ec 473 /******************************************************************************/
<> 150:02e0a0aed4ec 474 void UART_Handler(mxc_uart_regs_t *uart)
<> 150:02e0a0aed4ec 475 {
<> 150:02e0a0aed4ec 476 int uart_num;
<> 150:02e0a0aed4ec 477 uint32_t flags;
<> 150:02e0a0aed4ec 478
<> 150:02e0a0aed4ec 479 uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 480 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 481
<> 150:02e0a0aed4ec 482 flags = uart->intfl;
<> 150:02e0a0aed4ec 483 uart->intfl = flags;
<> 150:02e0a0aed4ec 484
<> 150:02e0a0aed4ec 485 // Figure out if this UART has an active Read request
<> 150:02e0a0aed4ec 486 if((rx_states[uart_num] != NULL) && (flags & UART_READ_INTS)) {
<> 150:02e0a0aed4ec 487 UART_ReadHandler(uart, rx_states[uart_num], uart_num, flags);
<> 150:02e0a0aed4ec 488 }
<> 150:02e0a0aed4ec 489
<> 150:02e0a0aed4ec 490 // Figure out if this UART has an active Write request
<> 150:02e0a0aed4ec 491 if((tx_states[uart_num] != NULL) && (flags & (UART_WRITE_INTS))) {
<> 150:02e0a0aed4ec 492
<> 150:02e0a0aed4ec 493 UART_WriteHandler(uart, tx_states[uart_num], uart_num);
<> 150:02e0a0aed4ec 494 }
<> 150:02e0a0aed4ec 495 }
<> 150:02e0a0aed4ec 496 /******************************************************************************/
<> 150:02e0a0aed4ec 497 int UART_Busy(mxc_uart_regs_t *uart)
<> 150:02e0a0aed4ec 498 {
<> 150:02e0a0aed4ec 499 int uart_num = MXC_UART_GET_IDX(uart);
<> 150:02e0a0aed4ec 500 MXC_ASSERT(uart_num >= 0);
<> 150:02e0a0aed4ec 501
<> 150:02e0a0aed4ec 502 // Check to see if there are any ongoing transactions or if the UART is disabled
<> 150:02e0a0aed4ec 503 if(((tx_states[uart_num] == NULL) &&
<> 150:02e0a0aed4ec 504 !(uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) &&
<> 150:02e0a0aed4ec 505 #if(MXC_UART_REV == 0)
<> 150:02e0a0aed4ec 506 (uart->intfl & MXC_F_UART_INTFL_TX_DONE)) ||
<> 150:02e0a0aed4ec 507 #else
<> 150:02e0a0aed4ec 508 (uart->idle & MXC_F_UART_IDLE_TX_RX_IDLE)) ||
<> 150:02e0a0aed4ec 509 #endif
<> 150:02e0a0aed4ec 510 !(uart->ctrl & MXC_F_UART_CTRL_UART_EN)) {
<> 150:02e0a0aed4ec 511
<> 150:02e0a0aed4ec 512 return E_NO_ERROR;
<> 150:02e0a0aed4ec 513 }
<> 150:02e0a0aed4ec 514
<> 150:02e0a0aed4ec 515 return E_BUSY;
<> 150:02e0a0aed4ec 516 }
<> 150:02e0a0aed4ec 517
<> 150:02e0a0aed4ec 518 /******************************************************************************/
<> 150:02e0a0aed4ec 519 int UART_PrepForSleep(mxc_uart_regs_t *uart)
<> 150:02e0a0aed4ec 520 {
<> 150:02e0a0aed4ec 521 if(UART_Busy(uart) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 522 return E_BUSY;
<> 150:02e0a0aed4ec 523 }
<> 150:02e0a0aed4ec 524
<> 150:02e0a0aed4ec 525 // Leave read interrupts enabled, if already enabled
<> 150:02e0a0aed4ec 526 uart->inten &= UART_READ_INTS;
<> 150:02e0a0aed4ec 527
<> 150:02e0a0aed4ec 528 return E_NO_ERROR;
<> 150:02e0a0aed4ec 529 }
<> 150:02e0a0aed4ec 530
<> 150:02e0a0aed4ec 531 /******************************************************************************/
<> 150:02e0a0aed4ec 532 static void UART_WriteHandler(mxc_uart_regs_t *uart, uart_req_t *req, int uart_num)
<> 150:02e0a0aed4ec 533 {
<> 150:02e0a0aed4ec 534 int avail, remain;
<> 150:02e0a0aed4ec 535 mxc_uart_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 536
<> 150:02e0a0aed4ec 537 // Disable write interrupts
<> 150:02e0a0aed4ec 538 uart->inten &= ~(UART_WRITE_INTS);
<> 150:02e0a0aed4ec 539
<> 150:02e0a0aed4ec 540 // Get the FIFO for this UART
<> 150:02e0a0aed4ec 541 fifo = MXC_UART_GET_FIFO(uart_num);
<> 150:02e0a0aed4ec 542
<> 150:02e0a0aed4ec 543 // Refill the TX FIFO
<> 150:02e0a0aed4ec 544 avail = UART_NumWriteAvail(uart);
<> 150:02e0a0aed4ec 545 remain = req->len - req->num;
<> 150:02e0a0aed4ec 546
<> 150:02e0a0aed4ec 547 while(avail && remain) {
<> 150:02e0a0aed4ec 548
<> 150:02e0a0aed4ec 549 // Write the data to the FIFO
<> 150:02e0a0aed4ec 550 #if(MXC_UART_REV == 0)
<> 150:02e0a0aed4ec 551 uart->intfl = MXC_F_UART_INTFL_TX_DONE;
<> 150:02e0a0aed4ec 552 #endif
<> 150:02e0a0aed4ec 553 fifo->tx = req->data[req->num++];
<> 150:02e0a0aed4ec 554 remain--;
<> 150:02e0a0aed4ec 555 avail--;
<> 150:02e0a0aed4ec 556 }
<> 150:02e0a0aed4ec 557
<> 150:02e0a0aed4ec 558 // All of the bytes have been written to the FIFO
<> 150:02e0a0aed4ec 559 if(!remain) {
<> 150:02e0a0aed4ec 560
<> 150:02e0a0aed4ec 561 // Unlock this UART to write
<> 150:02e0a0aed4ec 562 mxc_free_lock((uint32_t*)&tx_states[uart_num]);
<> 150:02e0a0aed4ec 563
<> 150:02e0a0aed4ec 564 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 565 req->callback(req, E_NO_ERROR);
<> 150:02e0a0aed4ec 566 }
<> 150:02e0a0aed4ec 567
<> 150:02e0a0aed4ec 568 } else {
<> 150:02e0a0aed4ec 569
<> 150:02e0a0aed4ec 570 // Interrupt when there is one byte left in the TXFIFO
<> 150:02e0a0aed4ec 571 uart->tx_fifo_ctrl = ((MXC_UART_FIFO_DEPTH - 1) << MXC_F_UART_TX_FIFO_CTRL_FIFO_AE_LVL_POS);
<> 150:02e0a0aed4ec 572
<> 150:02e0a0aed4ec 573 // Enable almost empty interrupt
<> 150:02e0a0aed4ec 574 uart->inten |= (MXC_F_UART_INTEN_TX_FIFO_AE);
<> 150:02e0a0aed4ec 575 }
<> 150:02e0a0aed4ec 576 }
<> 150:02e0a0aed4ec 577
<> 150:02e0a0aed4ec 578 /******************************************************************************/
<> 150:02e0a0aed4ec 579 static void UART_ReadHandler(mxc_uart_regs_t *uart, uart_req_t *req, int uart_num,
<> 150:02e0a0aed4ec 580 uint32_t flags)
<> 150:02e0a0aed4ec 581 {
<> 150:02e0a0aed4ec 582 int avail, remain;
<> 150:02e0a0aed4ec 583 mxc_uart_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 584
<> 150:02e0a0aed4ec 585 // Disable interrupts
<> 150:02e0a0aed4ec 586 uart->inten &= ~UART_READ_INTS;
<> 150:02e0a0aed4ec 587
<> 150:02e0a0aed4ec 588 // Get the FIFO for this UART, uart_num
<> 150:02e0a0aed4ec 589 fifo = MXC_UART_GET_FIFO(uart_num);
<> 150:02e0a0aed4ec 590
<> 150:02e0a0aed4ec 591 // Save the data in the FIFO while we still need data
<> 150:02e0a0aed4ec 592 avail = UART_NumReadAvail(uart);
<> 150:02e0a0aed4ec 593 remain = req->len - req->num;
<> 150:02e0a0aed4ec 594 while(avail && remain) {
<> 150:02e0a0aed4ec 595 req->data[req->num++] = fifo->rx;
<> 150:02e0a0aed4ec 596 remain--;
<> 150:02e0a0aed4ec 597 avail--;
<> 150:02e0a0aed4ec 598 }
<> 150:02e0a0aed4ec 599
<> 150:02e0a0aed4ec 600 // Check for errors
<> 150:02e0a0aed4ec 601 if(flags & MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) {
<> 150:02e0a0aed4ec 602
<> 150:02e0a0aed4ec 603 // Unlock this UART to read
<> 150:02e0a0aed4ec 604 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 605
<> 150:02e0a0aed4ec 606 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 607 req->callback(req, E_OVERFLOW);
<> 150:02e0a0aed4ec 608 }
<> 150:02e0a0aed4ec 609
<> 150:02e0a0aed4ec 610 return;
<> 150:02e0a0aed4ec 611 }
<> 150:02e0a0aed4ec 612
<> 150:02e0a0aed4ec 613 if(flags & (MXC_F_UART_INTFL_RX_FRAMING_ERR |
<> 150:02e0a0aed4ec 614 MXC_F_UART_INTFL_RX_PARITY_ERR)) {
<> 150:02e0a0aed4ec 615
<> 150:02e0a0aed4ec 616 // Unlock this UART to read
<> 150:02e0a0aed4ec 617 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 618
<> 150:02e0a0aed4ec 619 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 620 req->callback(req, E_COMM_ERR);
<> 150:02e0a0aed4ec 621 }
<> 150:02e0a0aed4ec 622
<> 150:02e0a0aed4ec 623 return;
<> 150:02e0a0aed4ec 624 }
<> 150:02e0a0aed4ec 625
<> 150:02e0a0aed4ec 626 // Check to see if we're done receiving
<> 150:02e0a0aed4ec 627 if(remain == 0) {
<> 150:02e0a0aed4ec 628
<> 150:02e0a0aed4ec 629 // Unlock this UART to read
<> 150:02e0a0aed4ec 630 mxc_free_lock((uint32_t*)&rx_states[uart_num]);
<> 150:02e0a0aed4ec 631
<> 150:02e0a0aed4ec 632 if(req->callback != NULL) {
<> 150:02e0a0aed4ec 633 req->callback(req, E_NO_ERROR);
<> 150:02e0a0aed4ec 634 }
<> 150:02e0a0aed4ec 635
<> 150:02e0a0aed4ec 636 return;
<> 150:02e0a0aed4ec 637 }
<> 150:02e0a0aed4ec 638
<> 150:02e0a0aed4ec 639 if(remain == 1) {
<> 150:02e0a0aed4ec 640 uart->inten |= (MXC_F_UART_INTEN_RX_FIFO_NOT_EMPTY | UART_ERRORS);
<> 150:02e0a0aed4ec 641
<> 150:02e0a0aed4ec 642 } else {
<> 150:02e0a0aed4ec 643 // Set the RX FIFO AF threshold
<> 150:02e0a0aed4ec 644 if(remain < UART_RXFIFO_USABLE) {
<> 150:02e0a0aed4ec 645 uart->rx_fifo_ctrl = ((remain - 1) <<
<> 150:02e0a0aed4ec 646 MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL_POS);
<> 150:02e0a0aed4ec 647 } else {
<> 150:02e0a0aed4ec 648 uart->rx_fifo_ctrl = (UART_RXFIFO_USABLE <<
<> 150:02e0a0aed4ec 649 MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL_POS);
<> 150:02e0a0aed4ec 650 }
<> 150:02e0a0aed4ec 651 uart->inten |= (MXC_F_UART_INTEN_RX_FIFO_AF | UART_ERRORS);
<> 150:02e0a0aed4ec 652 }
<> 150:02e0a0aed4ec 653 }