test

Committer:
elijahsj
Date:
Mon Nov 09 00:33:19 2020 -0500
Revision:
2:4364577b5ad8
Parent:
1:8a094db1347f
copied mbed library

Who changed what in which revision?

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