mbed library sources. Supersedes mbed-src. Fixed broken STM32F1xx RTC on rtc_api.c

Dependents:   Nucleo_F103RB_RTC_battery_bkup_pwr_off_okay

Fork of mbed-dev by mbed official

Committer:
maxxir
Date:
Tue Nov 07 16:46:29 2017 +0000
Revision:
177:619788de047e
Parent:
157:ff67d9f36b67
To fix broken RTC on Nucleo_F103RB / STM32F103 BluePill etc..;  Used direct RTC register manipulation for STM32F1xx;  rtc_read() && rtc_write()  (native rtc_init() - works good);  also added stub for non-working on STM32F1xx rtc_read_subseconds().

Who changed what in which revision?

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