mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /*
elessair 0:f269e3021894 2 * Copyright (c) 2013 Nordic Semiconductor ASA
elessair 0:f269e3021894 3 * All rights reserved.
elessair 0:f269e3021894 4 *
elessair 0:f269e3021894 5 * Redistribution and use in source and binary forms, with or without modification,
elessair 0:f269e3021894 6 * are permitted provided that the following conditions are met:
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * 1. Redistributions of source code must retain the above copyright notice, this list
elessair 0:f269e3021894 9 * of conditions and the following disclaimer.
elessair 0:f269e3021894 10 *
elessair 0:f269e3021894 11 * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
elessair 0:f269e3021894 12 * integrated circuit in a product or a software update for such product, must reproduce
elessair 0:f269e3021894 13 * the above copyright notice, this list of conditions and the following disclaimer in
elessair 0:f269e3021894 14 * the documentation and/or other materials provided with the distribution.
elessair 0:f269e3021894 15 *
elessair 0:f269e3021894 16 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
elessair 0:f269e3021894 17 * used to endorse or promote products derived from this software without specific prior
elessair 0:f269e3021894 18 * written permission.
elessair 0:f269e3021894 19 *
elessair 0:f269e3021894 20 * 4. This software, with or without modification, must only be used with a
elessair 0:f269e3021894 21 * Nordic Semiconductor ASA integrated circuit.
elessair 0:f269e3021894 22 *
elessair 0:f269e3021894 23 * 5. Any software provided in binary or object form under this license must not be reverse
elessair 0:f269e3021894 24 * engineered, decompiled, modified and/or disassembled.
elessair 0:f269e3021894 25 *
elessair 0:f269e3021894 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
elessair 0:f269e3021894 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
elessair 0:f269e3021894 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
elessair 0:f269e3021894 29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
elessair 0:f269e3021894 30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
elessair 0:f269e3021894 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
elessair 0:f269e3021894 32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
elessair 0:f269e3021894 33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
elessair 0:f269e3021894 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
elessair 0:f269e3021894 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
elessair 0:f269e3021894 36 *
elessair 0:f269e3021894 37 */
elessair 0:f269e3021894 38
elessair 0:f269e3021894 39 #include "serial_api.h"
elessair 0:f269e3021894 40
elessair 0:f269e3021894 41 #if DEVICE_SERIAL
elessair 0:f269e3021894 42
elessair 0:f269e3021894 43 #include <string.h>
elessair 0:f269e3021894 44 #include "mbed_assert.h"
elessair 0:f269e3021894 45 #include "mbed_error.h"
elessair 0:f269e3021894 46 #include "nrf_uart.h"
elessair 0:f269e3021894 47 #include "nrf_drv_common.h"
elessair 0:f269e3021894 48 #include "nrf_drv_config.h"
elessair 0:f269e3021894 49 #include "app_util_platform.h"
elessair 0:f269e3021894 50 #include "nrf_gpio.h"
elessair 0:f269e3021894 51
elessair 0:f269e3021894 52 #define UART_INSTANCE_COUNT 1
elessair 0:f269e3021894 53 #define UART_INSTANCE NRF_UART0
elessair 0:f269e3021894 54 #define UART_IRQn UART0_IRQn
elessair 0:f269e3021894 55 #define UART_IRQ_HANDLER UART0_IRQHandler
elessair 0:f269e3021894 56 #define UART_INSTANCE_ID 0
elessair 0:f269e3021894 57 #define UART_CB uart_cb[UART_INSTANCE_ID]
elessair 0:f269e3021894 58
elessair 0:f269e3021894 59 #define UART_DEFAULT_BAUDRATE UART0_CONFIG_BAUDRATE
elessair 0:f269e3021894 60 #define UART_DEFAULT_PARITY UART0_CONFIG_PARITY
elessair 0:f269e3021894 61
elessair 0:f269e3021894 62 // expected the macro from mbed configuration system
elessair 0:f269e3021894 63 #ifndef MBED_CONF_NORDIC_UART_HWFC
elessair 0:f269e3021894 64 #define MBED_CONF_NORDIC_UART_HWFC 1
elessair 0:f269e3021894 65 #warning None of UART flow control configuration (expected macro MBED_CONF_NORDIC_UART_HWFC). The RTSCTS flow control is used by default .
elessair 0:f269e3021894 66 #endif
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 #if MBED_CONF_NORDIC_UART_HWFC == 1
elessair 0:f269e3021894 69 #define UART_DEFAULT_HWFC UART0_CONFIG_HWFC
elessair 0:f269e3021894 70 #else
elessair 0:f269e3021894 71 #define UART_DEFAULT_HWFC NRF_UART_HWFC_DISABLED
elessair 0:f269e3021894 72 #endif
elessair 0:f269e3021894 73
elessair 0:f269e3021894 74 #define UART_DEFAULT_CTS UART0_CONFIG_PSEL_CTS
elessair 0:f269e3021894 75 #define UART_DEFAULT_RTS UART0_CONFIG_PSEL_RTS
elessair 0:f269e3021894 76
elessair 0:f269e3021894 77 // Required by "retarget.cpp".
elessair 0:f269e3021894 78 int stdio_uart_inited = 0;
elessair 0:f269e3021894 79 serial_t stdio_uart;
elessair 0:f269e3021894 80
elessair 0:f269e3021894 81 typedef struct {
elessair 0:f269e3021894 82 bool initialized;
elessair 0:f269e3021894 83 uint32_t irq_context;
elessair 0:f269e3021894 84 uart_irq_handler irq_handler;
elessair 0:f269e3021894 85
elessair 0:f269e3021894 86 uint32_t pselrxd;
elessair 0:f269e3021894 87 uint32_t pseltxd;
elessair 0:f269e3021894 88 uint32_t pselcts;
elessair 0:f269e3021894 89 uint32_t pselrts;
elessair 0:f269e3021894 90 nrf_uart_hwfc_t hwfc;
elessair 0:f269e3021894 91 nrf_uart_parity_t parity;
elessair 0:f269e3021894 92 nrf_uart_baudrate_t baudrate;
elessair 0:f269e3021894 93
elessair 0:f269e3021894 94 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 95 bool volatile rx_active;
elessair 0:f269e3021894 96 uint8_t *rx_buffer;
elessair 0:f269e3021894 97 size_t rx_length;
elessair 0:f269e3021894 98 size_t rx_pos;
elessair 0:f269e3021894 99 void (*rx_asynch_handler)();
elessair 0:f269e3021894 100 uint8_t char_match;
elessair 0:f269e3021894 101
elessair 0:f269e3021894 102 bool volatile tx_active;
elessair 0:f269e3021894 103 const uint8_t *tx_buffer;
elessair 0:f269e3021894 104 size_t tx_length;
elessair 0:f269e3021894 105 size_t tx_pos;
elessair 0:f269e3021894 106 void (*tx_asynch_handler)();
elessair 0:f269e3021894 107
elessair 0:f269e3021894 108 uint32_t events_wanted;
elessair 0:f269e3021894 109 uint32_t events_occured;
elessair 0:f269e3021894 110
elessair 0:f269e3021894 111 #define UART_IRQ_TX 1
elessair 0:f269e3021894 112 #define UART_IRQ_RX 2
elessair 0:f269e3021894 113 uint8_t irq_enabled;
elessair 0:f269e3021894 114 #endif // DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 115 } uart_ctlblock_t;
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 static uart_ctlblock_t uart_cb[UART_INSTANCE_COUNT];
elessair 0:f269e3021894 118
elessair 0:f269e3021894 119 static void internal_set_hwfc(FlowControl type,
elessair 0:f269e3021894 120 PinName rxflow, PinName txflow);
elessair 0:f269e3021894 121
elessair 0:f269e3021894 122
elessair 0:f269e3021894 123 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 124 static void end_asynch_rx(void)
elessair 0:f269e3021894 125 {
elessair 0:f269e3021894 126 // If RX interrupt is activated for synchronous operations,
elessair 0:f269e3021894 127 // don't disable it, just stop handling it here.
elessair 0:f269e3021894 128 if (!(UART_CB.irq_enabled & UART_IRQ_RX)) {
elessair 0:f269e3021894 129 nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY);
elessair 0:f269e3021894 130 }
elessair 0:f269e3021894 131 UART_CB.rx_active = false;
elessair 0:f269e3021894 132 }
elessair 0:f269e3021894 133 static void end_asynch_tx(void)
elessair 0:f269e3021894 134 {
elessair 0:f269e3021894 135 // If TX interrupt is activated for synchronous operations,
elessair 0:f269e3021894 136 // don't disable it, just stop handling it here.
elessair 0:f269e3021894 137 if (!(UART_CB.irq_enabled & UART_IRQ_TX)) {
elessair 0:f269e3021894 138 nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
elessair 0:f269e3021894 139 }
elessair 0:f269e3021894 140 UART_CB.tx_active = false;
elessair 0:f269e3021894 141 }
elessair 0:f269e3021894 142 #endif // DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 143
elessair 0:f269e3021894 144 void UART_IRQ_HANDLER(void)
elessair 0:f269e3021894 145 {
elessair 0:f269e3021894 146 if (nrf_uart_int_enable_check(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY) &&
elessair 0:f269e3021894 147 nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY)) {
elessair 0:f269e3021894 148
elessair 0:f269e3021894 149 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 150 if (UART_CB.rx_active) {
elessair 0:f269e3021894 151 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
elessair 0:f269e3021894 152
elessair 0:f269e3021894 153 uint8_t rx_data = nrf_uart_rxd_get(UART_INSTANCE);
elessair 0:f269e3021894 154 UART_CB.rx_buffer[UART_CB.rx_pos] = rx_data;
elessair 0:f269e3021894 155
elessair 0:f269e3021894 156 bool end_rx = false;
elessair 0:f269e3021894 157 // If character matching should be performed, check if the current
elessair 0:f269e3021894 158 // data matches the given one.
elessair 0:f269e3021894 159 if (UART_CB.char_match != SERIAL_RESERVED_CHAR_MATCH &&
elessair 0:f269e3021894 160 rx_data == UART_CB.char_match) {
elessair 0:f269e3021894 161 // If it does, report the match and abort further receiving.
elessair 0:f269e3021894 162 UART_CB.events_occured |= SERIAL_EVENT_RX_CHARACTER_MATCH;
elessair 0:f269e3021894 163 if (UART_CB.events_wanted & SERIAL_EVENT_RX_CHARACTER_MATCH) {
elessair 0:f269e3021894 164 end_rx = true;
elessair 0:f269e3021894 165 }
elessair 0:f269e3021894 166 }
elessair 0:f269e3021894 167 if (++UART_CB.rx_pos >= UART_CB.rx_length) {
elessair 0:f269e3021894 168 UART_CB.events_occured |= SERIAL_EVENT_RX_COMPLETE;
elessair 0:f269e3021894 169 end_rx = true;
elessair 0:f269e3021894 170 }
elessair 0:f269e3021894 171 if (end_rx) {
elessair 0:f269e3021894 172 end_asynch_rx();
elessair 0:f269e3021894 173
elessair 0:f269e3021894 174 if (UART_CB.rx_asynch_handler) {
elessair 0:f269e3021894 175 // Use local variable to make it possible to start a next
elessair 0:f269e3021894 176 // transfer from callback routine.
elessair 0:f269e3021894 177 void (*handler)() = UART_CB.rx_asynch_handler;
elessair 0:f269e3021894 178 UART_CB.rx_asynch_handler = NULL;
elessair 0:f269e3021894 179 handler();
elessair 0:f269e3021894 180 }
elessair 0:f269e3021894 181 }
elessair 0:f269e3021894 182 }
elessair 0:f269e3021894 183 else
elessair 0:f269e3021894 184 #endif
elessair 0:f269e3021894 185
elessair 0:f269e3021894 186 if (UART_CB.irq_handler) {
elessair 0:f269e3021894 187 UART_CB.irq_handler(UART_CB.irq_context, RxIrq);
elessair 0:f269e3021894 188 }
elessair 0:f269e3021894 189 }
elessair 0:f269e3021894 190
elessair 0:f269e3021894 191 if (nrf_uart_int_enable_check(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY) &&
elessair 0:f269e3021894 192 nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) {
elessair 0:f269e3021894 193
elessair 0:f269e3021894 194 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 195 if (UART_CB.tx_active) {
elessair 0:f269e3021894 196 if (++UART_CB.tx_pos <= UART_CB.tx_length) {
elessair 0:f269e3021894 197 // When there is still something to send, clear the TXDRDY event
elessair 0:f269e3021894 198 // and put next byte to transmitter.
elessair 0:f269e3021894 199 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
elessair 0:f269e3021894 200 nrf_uart_txd_set(UART_INSTANCE,
elessair 0:f269e3021894 201 UART_CB.tx_buffer[UART_CB.tx_pos]);
elessair 0:f269e3021894 202 }
elessair 0:f269e3021894 203 else {
elessair 0:f269e3021894 204 // When the TXDRDY event is set after the last byte to be sent
elessair 0:f269e3021894 205 // has been passed to the transmitter, the job is done and TX
elessair 0:f269e3021894 206 // complete can be indicated.
elessair 0:f269e3021894 207 // Don't clear the TXDRDY event, it needs to remain set for the
elessair 0:f269e3021894 208 // 'serial_writable' function to work properly.
elessair 0:f269e3021894 209 end_asynch_tx();
elessair 0:f269e3021894 210
elessair 0:f269e3021894 211 UART_CB.events_occured |= SERIAL_EVENT_TX_COMPLETE;
elessair 0:f269e3021894 212 if (UART_CB.tx_asynch_handler) {
elessair 0:f269e3021894 213 // Use local variable to make it possible to start a next
elessair 0:f269e3021894 214 // transfer from callback routine.
elessair 0:f269e3021894 215 void (*handler)() = UART_CB.tx_asynch_handler;
elessair 0:f269e3021894 216 UART_CB.tx_asynch_handler = NULL;
elessair 0:f269e3021894 217 handler();
elessair 0:f269e3021894 218 }
elessair 0:f269e3021894 219 }
elessair 0:f269e3021894 220 }
elessair 0:f269e3021894 221 else
elessair 0:f269e3021894 222 #endif
elessair 0:f269e3021894 223
elessair 0:f269e3021894 224 if (UART_CB.irq_handler) {
elessair 0:f269e3021894 225 UART_CB.irq_handler(UART_CB.irq_context, TxIrq);
elessair 0:f269e3021894 226 }
elessair 0:f269e3021894 227 }
elessair 0:f269e3021894 228
elessair 0:f269e3021894 229 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 230 if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_ERROR)) {
elessair 0:f269e3021894 231 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR);
elessair 0:f269e3021894 232
elessair 0:f269e3021894 233 uint8_t errorsrc = nrf_uart_errorsrc_get_and_clear(UART_INSTANCE);
elessair 0:f269e3021894 234 if (UART_CB.rx_asynch_handler) {
elessair 0:f269e3021894 235 UART_CB.events_occured |= SERIAL_EVENT_ERROR;
elessair 0:f269e3021894 236 if (errorsrc & NRF_UART_ERROR_PARITY_MASK) {
elessair 0:f269e3021894 237 UART_CB.events_occured |= SERIAL_EVENT_RX_PARITY_ERROR;
elessair 0:f269e3021894 238 }
elessair 0:f269e3021894 239 if (errorsrc & NRF_UART_ERROR_FRAMING_MASK) {
elessair 0:f269e3021894 240 UART_CB.events_occured |= SERIAL_EVENT_RX_FRAMING_ERROR;
elessair 0:f269e3021894 241 }
elessair 0:f269e3021894 242 if (errorsrc & NRF_UART_ERROR_OVERRUN_MASK) {
elessair 0:f269e3021894 243 UART_CB.events_occured |= SERIAL_EVENT_RX_OVERRUN_ERROR;
elessair 0:f269e3021894 244 }
elessair 0:f269e3021894 245 UART_CB.rx_asynch_handler();
elessair 0:f269e3021894 246 }
elessair 0:f269e3021894 247 }
elessair 0:f269e3021894 248 #endif // DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 249 }
elessair 0:f269e3021894 250
elessair 0:f269e3021894 251 void serial_init(serial_t *obj, PinName tx, PinName rx) {
elessair 0:f269e3021894 252 UART_CB.pseltxd =
elessair 0:f269e3021894 253 (tx == NC) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)tx;
elessair 0:f269e3021894 254 UART_CB.pselrxd =
elessair 0:f269e3021894 255 (rx == NC) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)rx;
elessair 0:f269e3021894 256 if (UART_CB.pseltxd != NRF_UART_PSEL_DISCONNECTED) {
elessair 0:f269e3021894 257 nrf_gpio_pin_set(UART_CB.pseltxd);
elessair 0:f269e3021894 258 nrf_gpio_cfg_output(UART_CB.pseltxd);
elessair 0:f269e3021894 259 }
elessair 0:f269e3021894 260 if (UART_CB.pselrxd != NRF_UART_PSEL_DISCONNECTED) {
elessair 0:f269e3021894 261 nrf_gpio_cfg_input(UART_CB.pselrxd, NRF_GPIO_PIN_NOPULL);
elessair 0:f269e3021894 262 }
elessair 0:f269e3021894 263
elessair 0:f269e3021894 264 if (UART_CB.initialized) {
elessair 0:f269e3021894 265 // For already initialized peripheral it is sufficient to reconfigure
elessair 0:f269e3021894 266 // RX/TX pins only.
elessair 0:f269e3021894 267
elessair 0:f269e3021894 268 // Ensure that there is no unfinished TX transfer.
elessair 0:f269e3021894 269 while (!serial_writable(obj)) {
elessair 0:f269e3021894 270 }
elessair 0:f269e3021894 271 // UART pins can be configured only when the peripheral is disabled.
elessair 0:f269e3021894 272 nrf_uart_disable(UART_INSTANCE);
elessair 0:f269e3021894 273 nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
elessair 0:f269e3021894 274 nrf_uart_enable(UART_INSTANCE);
elessair 0:f269e3021894 275 }
elessair 0:f269e3021894 276 else {
elessair 0:f269e3021894 277 UART_CB.baudrate = UART_DEFAULT_BAUDRATE;
elessair 0:f269e3021894 278 UART_CB.parity = UART_DEFAULT_PARITY;
elessair 0:f269e3021894 279 UART_CB.hwfc = UART_DEFAULT_HWFC;
elessair 0:f269e3021894 280 UART_CB.pselcts = UART_DEFAULT_CTS;
elessair 0:f269e3021894 281 UART_CB.pselrts = UART_DEFAULT_RTS;
elessair 0:f269e3021894 282
elessair 0:f269e3021894 283 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
elessair 0:f269e3021894 284 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
elessair 0:f269e3021894 285 nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);
elessair 0:f269e3021894 286 nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTTX);
elessair 0:f269e3021894 287
elessair 0:f269e3021894 288 nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY |
elessair 0:f269e3021894 289 NRF_UART_INT_MASK_TXDRDY);
elessair 0:f269e3021894 290 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 291 nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_ERROR);
elessair 0:f269e3021894 292 #endif
elessair 0:f269e3021894 293 nrf_drv_common_irq_enable(UART_IRQn, APP_IRQ_PRIORITY_LOW);
elessair 0:f269e3021894 294
elessair 0:f269e3021894 295 // TX interrupt needs to be signaled when transmitter buffer is empty,
elessair 0:f269e3021894 296 // so a dummy transmission is needed to get the TXDRDY event initially
elessair 0:f269e3021894 297 // set.
elessair 0:f269e3021894 298 nrf_uart_configure(UART_INSTANCE,
elessair 0:f269e3021894 299 NRF_UART_PARITY_EXCLUDED, NRF_UART_HWFC_DISABLED);
elessair 0:f269e3021894 300 // Use maximum baud rate, so this dummy transmission takes as little
elessair 0:f269e3021894 301 // time as possible.
elessair 0:f269e3021894 302 nrf_uart_baudrate_set(UART_INSTANCE, NRF_UART_BAUDRATE_1000000);
elessair 0:f269e3021894 303 // Perform it with disconnected TX pin, so nothing actually comes out
elessair 0:f269e3021894 304 // of the device.
elessair 0:f269e3021894 305 nrf_uart_txrx_pins_disconnect(UART_INSTANCE);
elessair 0:f269e3021894 306 nrf_uart_hwfc_pins_disconnect(UART_INSTANCE);
elessair 0:f269e3021894 307 nrf_uart_enable(UART_INSTANCE);
elessair 0:f269e3021894 308 nrf_uart_txd_set(UART_INSTANCE, 0);
elessair 0:f269e3021894 309 while (!nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) {
elessair 0:f269e3021894 310 }
elessair 0:f269e3021894 311 nrf_uart_disable(UART_INSTANCE);
elessair 0:f269e3021894 312
elessair 0:f269e3021894 313 // Now everything is prepared to set the default configuration and
elessair 0:f269e3021894 314 // connect the peripheral to actual pins.
elessair 0:f269e3021894 315 nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
elessair 0:f269e3021894 316 nrf_uart_baudrate_set(UART_INSTANCE, UART_CB.baudrate);
elessair 0:f269e3021894 317 nrf_uart_configure(UART_INSTANCE, UART_CB.parity, UART_CB.hwfc);
elessair 0:f269e3021894 318 if (UART_CB.hwfc == NRF_UART_HWFC_ENABLED) {
elessair 0:f269e3021894 319 internal_set_hwfc(FlowControlRTSCTS,
elessair 0:f269e3021894 320 (PinName) UART_CB.pselrts, (PinName) UART_CB.pselcts);
elessair 0:f269e3021894 321 }
elessair 0:f269e3021894 322
elessair 0:f269e3021894 323 nrf_uart_enable(UART_INSTANCE);
elessair 0:f269e3021894 324
elessair 0:f269e3021894 325 UART_CB.initialized = true;
elessair 0:f269e3021894 326 }
elessair 0:f269e3021894 327
elessair 0:f269e3021894 328 if (tx == STDIO_UART_TX && rx == STDIO_UART_RX) {
elessair 0:f269e3021894 329 stdio_uart_inited = 1;
elessair 0:f269e3021894 330 memcpy(&stdio_uart, obj, sizeof(serial_t));
elessair 0:f269e3021894 331 }
elessair 0:f269e3021894 332 else {
elessair 0:f269e3021894 333 stdio_uart_inited = 0;
elessair 0:f269e3021894 334 }
elessair 0:f269e3021894 335 }
elessair 0:f269e3021894 336
elessair 0:f269e3021894 337 void serial_free(serial_t *obj)
elessair 0:f269e3021894 338 {
elessair 0:f269e3021894 339 (void)obj;
elessair 0:f269e3021894 340
elessair 0:f269e3021894 341 if (UART_CB.initialized) {
elessair 0:f269e3021894 342 nrf_uart_disable(UART_INSTANCE);
elessair 0:f269e3021894 343 nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY |
elessair 0:f269e3021894 344 NRF_UART_INT_MASK_TXDRDY |
elessair 0:f269e3021894 345 NRF_UART_INT_MASK_ERROR);
elessair 0:f269e3021894 346 nrf_drv_common_irq_disable(UART_IRQn);
elessair 0:f269e3021894 347 UART_CB.initialized = false;
elessair 0:f269e3021894 348
elessair 0:f269e3021894 349 // There is only one UART instance, thus at this point the stdio UART
elessair 0:f269e3021894 350 // can no longer be initialized.
elessair 0:f269e3021894 351 stdio_uart_inited = 0;
elessair 0:f269e3021894 352 }
elessair 0:f269e3021894 353 }
elessair 0:f269e3021894 354
elessair 0:f269e3021894 355 void serial_baud(serial_t *obj, int baudrate)
elessair 0:f269e3021894 356 {
elessair 0:f269e3021894 357 // nrf_uart_baudrate_set() is not used here (registers are accessed
elessair 0:f269e3021894 358 // directly) to make it possible to set special baud rates like 56000
elessair 0:f269e3021894 359 // or 31250.
elessair 0:f269e3021894 360
elessair 0:f269e3021894 361 static uint32_t const acceptedSpeeds[][2] = {
elessair 0:f269e3021894 362 { 1200, UART_BAUDRATE_BAUDRATE_Baud1200 },
elessair 0:f269e3021894 363 { 2400, UART_BAUDRATE_BAUDRATE_Baud2400 },
elessair 0:f269e3021894 364 { 4800, UART_BAUDRATE_BAUDRATE_Baud4800 },
elessair 0:f269e3021894 365 { 9600, UART_BAUDRATE_BAUDRATE_Baud9600 },
elessair 0:f269e3021894 366 { 14400, UART_BAUDRATE_BAUDRATE_Baud14400 },
elessair 0:f269e3021894 367 { 19200, UART_BAUDRATE_BAUDRATE_Baud19200 },
elessair 0:f269e3021894 368 { 28800, UART_BAUDRATE_BAUDRATE_Baud28800 },
elessair 0:f269e3021894 369 { 31250, (0x00800000UL) /* 31250 baud */ },
elessair 0:f269e3021894 370 { 38400, UART_BAUDRATE_BAUDRATE_Baud38400 },
elessair 0:f269e3021894 371 { 56000, (0x00E51000UL) /* 56000 baud */ },
elessair 0:f269e3021894 372 { 57600, UART_BAUDRATE_BAUDRATE_Baud57600 },
elessair 0:f269e3021894 373 { 76800, UART_BAUDRATE_BAUDRATE_Baud76800 },
elessair 0:f269e3021894 374 { 115200, UART_BAUDRATE_BAUDRATE_Baud115200 },
elessair 0:f269e3021894 375 { 230400, UART_BAUDRATE_BAUDRATE_Baud230400 },
elessair 0:f269e3021894 376 { 250000, UART_BAUDRATE_BAUDRATE_Baud250000 },
elessair 0:f269e3021894 377 { 460800, UART_BAUDRATE_BAUDRATE_Baud460800 },
elessair 0:f269e3021894 378 { 921600, UART_BAUDRATE_BAUDRATE_Baud921600 },
elessair 0:f269e3021894 379 { 1000000, UART_BAUDRATE_BAUDRATE_Baud1M }
elessair 0:f269e3021894 380 };
elessair 0:f269e3021894 381
elessair 0:f269e3021894 382 if (baudrate <= 1200) {
elessair 0:f269e3021894 383 UART_INSTANCE->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
elessair 0:f269e3021894 384 return;
elessair 0:f269e3021894 385 }
elessair 0:f269e3021894 386
elessair 0:f269e3021894 387 int const item_cnt = sizeof(acceptedSpeeds)/sizeof(acceptedSpeeds[0]);
elessair 0:f269e3021894 388 for (int i = 1; i < item_cnt; i++) {
elessair 0:f269e3021894 389 if ((uint32_t)baudrate < acceptedSpeeds[i][0]) {
elessair 0:f269e3021894 390 UART_INSTANCE->BAUDRATE = acceptedSpeeds[i - 1][1];
elessair 0:f269e3021894 391 return;
elessair 0:f269e3021894 392 }
elessair 0:f269e3021894 393 }
elessair 0:f269e3021894 394
elessair 0:f269e3021894 395 UART_INSTANCE->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
elessair 0:f269e3021894 396 }
elessair 0:f269e3021894 397
elessair 0:f269e3021894 398 void serial_format(serial_t *obj,
elessair 0:f269e3021894 399 int data_bits, SerialParity parity, int stop_bits)
elessair 0:f269e3021894 400 {
elessair 0:f269e3021894 401 (void)obj;
elessair 0:f269e3021894 402
elessair 0:f269e3021894 403 if (data_bits != 8) {
elessair 0:f269e3021894 404 error("UART supports only 8 data bits.\r\n");
elessair 0:f269e3021894 405 }
elessair 0:f269e3021894 406 if (stop_bits != 1) {
elessair 0:f269e3021894 407 error("UART supports only 1 stop bits.\r\n");
elessair 0:f269e3021894 408 }
elessair 0:f269e3021894 409 if (parity == ParityNone) {
elessair 0:f269e3021894 410 UART_CB.parity = NRF_UART_PARITY_EXCLUDED;
elessair 0:f269e3021894 411 } else if (parity == ParityEven) {
elessair 0:f269e3021894 412 UART_CB.parity = NRF_UART_PARITY_INCLUDED;
elessair 0:f269e3021894 413 } else {
elessair 0:f269e3021894 414 error("UART supports only even parity.\r\n");
elessair 0:f269e3021894 415 }
elessair 0:f269e3021894 416
elessair 0:f269e3021894 417 // Reconfigure UART peripheral.
elessair 0:f269e3021894 418 nrf_uart_configure(UART_INSTANCE, UART_CB.parity, UART_CB.hwfc);
elessair 0:f269e3021894 419 }
elessair 0:f269e3021894 420
elessair 0:f269e3021894 421 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
elessair 0:f269e3021894 422 {
elessair 0:f269e3021894 423 (void)obj;
elessair 0:f269e3021894 424 UART_CB.irq_handler = handler;
elessair 0:f269e3021894 425 UART_CB.irq_context = id;
elessair 0:f269e3021894 426 }
elessair 0:f269e3021894 427
elessair 0:f269e3021894 428 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
elessair 0:f269e3021894 429 {
elessair 0:f269e3021894 430 (void)obj;
elessair 0:f269e3021894 431 if (enable) {
elessair 0:f269e3021894 432 switch (irq) {
elessair 0:f269e3021894 433 case RxIrq:
elessair 0:f269e3021894 434 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 435 UART_CB.irq_enabled |= UART_IRQ_RX;
elessair 0:f269e3021894 436 #endif
elessair 0:f269e3021894 437 nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY);
elessair 0:f269e3021894 438 break;
elessair 0:f269e3021894 439
elessair 0:f269e3021894 440 case TxIrq:
elessair 0:f269e3021894 441 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 442 UART_CB.irq_enabled |= UART_IRQ_TX;
elessair 0:f269e3021894 443 #endif
elessair 0:f269e3021894 444 nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
elessair 0:f269e3021894 445 break;
elessair 0:f269e3021894 446 }
elessair 0:f269e3021894 447 } else {
elessair 0:f269e3021894 448 switch (irq) {
elessair 0:f269e3021894 449 case RxIrq:
elessair 0:f269e3021894 450 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 451 UART_CB.irq_enabled &= ~UART_IRQ_RX;
elessair 0:f269e3021894 452 if (!UART_CB.rx_active)
elessair 0:f269e3021894 453 #endif
elessair 0:f269e3021894 454 {
elessair 0:f269e3021894 455 nrf_uart_int_disable(UART_INSTANCE,
elessair 0:f269e3021894 456 NRF_UART_INT_MASK_RXDRDY);
elessair 0:f269e3021894 457 }
elessair 0:f269e3021894 458 break;
elessair 0:f269e3021894 459
elessair 0:f269e3021894 460 case TxIrq:
elessair 0:f269e3021894 461 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 462 UART_CB.irq_enabled &= ~UART_IRQ_TX;
elessair 0:f269e3021894 463 if (!UART_CB.tx_active)
elessair 0:f269e3021894 464 #endif
elessair 0:f269e3021894 465 {
elessair 0:f269e3021894 466 nrf_uart_int_disable(UART_INSTANCE,
elessair 0:f269e3021894 467 NRF_UART_INT_MASK_TXDRDY);
elessair 0:f269e3021894 468 }
elessair 0:f269e3021894 469 break;
elessair 0:f269e3021894 470 }
elessair 0:f269e3021894 471 }
elessair 0:f269e3021894 472 }
elessair 0:f269e3021894 473
elessair 0:f269e3021894 474 int serial_getc(serial_t *obj)
elessair 0:f269e3021894 475 {
elessair 0:f269e3021894 476 while (!serial_readable(obj)) {
elessair 0:f269e3021894 477 }
elessair 0:f269e3021894 478
elessair 0:f269e3021894 479 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
elessair 0:f269e3021894 480 return nrf_uart_rxd_get(UART_INSTANCE);
elessair 0:f269e3021894 481 }
elessair 0:f269e3021894 482
elessair 0:f269e3021894 483 void serial_putc(serial_t *obj, int c)
elessair 0:f269e3021894 484 {
elessair 0:f269e3021894 485 while (!serial_writable(obj)) {
elessair 0:f269e3021894 486 }
elessair 0:f269e3021894 487
elessair 0:f269e3021894 488 nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
elessair 0:f269e3021894 489 nrf_uart_txd_set(UART_INSTANCE, (uint8_t)c);
elessair 0:f269e3021894 490 }
elessair 0:f269e3021894 491
elessair 0:f269e3021894 492 int serial_readable(serial_t *obj)
elessair 0:f269e3021894 493 {
elessair 0:f269e3021894 494 (void)obj;
elessair 0:f269e3021894 495 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 496 if (UART_CB.rx_active) {
elessair 0:f269e3021894 497 return 0;
elessair 0:f269e3021894 498 }
elessair 0:f269e3021894 499 #endif
elessair 0:f269e3021894 500 return (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY));
elessair 0:f269e3021894 501 }
elessair 0:f269e3021894 502
elessair 0:f269e3021894 503 int serial_writable(serial_t *obj)
elessair 0:f269e3021894 504 {
elessair 0:f269e3021894 505 (void)obj;
elessair 0:f269e3021894 506 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 507 if (UART_CB.tx_active) {
elessair 0:f269e3021894 508 return 0;
elessair 0:f269e3021894 509 }
elessair 0:f269e3021894 510 #endif
elessair 0:f269e3021894 511 return (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY));
elessair 0:f269e3021894 512 }
elessair 0:f269e3021894 513
elessair 0:f269e3021894 514 void serial_break_set(serial_t *obj)
elessair 0:f269e3021894 515 {
elessair 0:f269e3021894 516 (void)obj;
elessair 0:f269e3021894 517 nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_SUSPEND);
elessair 0:f269e3021894 518 nrf_uart_txrx_pins_disconnect(UART_INSTANCE);
elessair 0:f269e3021894 519 nrf_gpio_pin_clear(UART_CB.pseltxd);
elessair 0:f269e3021894 520 }
elessair 0:f269e3021894 521
elessair 0:f269e3021894 522 void serial_break_clear(serial_t *obj)
elessair 0:f269e3021894 523 {
elessair 0:f269e3021894 524 (void)obj;
elessair 0:f269e3021894 525 nrf_gpio_pin_set(UART_CB.pseltxd);
elessair 0:f269e3021894 526 nrf_uart_txrx_pins_set(UART_INSTANCE, UART_CB.pseltxd, UART_CB.pselrxd);
elessair 0:f269e3021894 527 nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);
elessair 0:f269e3021894 528 nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTTX);
elessair 0:f269e3021894 529 }
elessair 0:f269e3021894 530
elessair 0:f269e3021894 531
elessair 0:f269e3021894 532 static void internal_set_hwfc(FlowControl type,
elessair 0:f269e3021894 533 PinName rxflow, PinName txflow)
elessair 0:f269e3021894 534 {
elessair 0:f269e3021894 535 UART_CB.pselrts =
elessair 0:f269e3021894 536 ((rxflow == NC) || (type == FlowControlCTS)) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)rxflow;
elessair 0:f269e3021894 537 UART_CB.pselcts =
elessair 0:f269e3021894 538 ((txflow == NC) || (type == FlowControlRTS)) ? NRF_UART_PSEL_DISCONNECTED : (uint32_t)txflow;
elessair 0:f269e3021894 539
elessair 0:f269e3021894 540 if (UART_CB.pselrts != NRF_UART_PSEL_DISCONNECTED) {
elessair 0:f269e3021894 541 nrf_gpio_pin_set(UART_CB.pselrts);
elessair 0:f269e3021894 542 nrf_gpio_cfg_output(UART_CB.pselrts);
elessair 0:f269e3021894 543 }
elessair 0:f269e3021894 544 if (UART_CB.pselcts != NRF_UART_PSEL_DISCONNECTED) {
elessair 0:f269e3021894 545 nrf_gpio_cfg_input(UART_CB.pselcts, NRF_GPIO_PIN_NOPULL);
elessair 0:f269e3021894 546 }
elessair 0:f269e3021894 547
elessair 0:f269e3021894 548 UART_CB.hwfc = (type == FlowControlNone)? NRF_UART_HWFC_DISABLED : UART0_CONFIG_HWFC;
elessair 0:f269e3021894 549
elessair 0:f269e3021894 550 nrf_uart_configure(UART_INSTANCE, UART_CB.parity, UART_CB.hwfc);
elessair 0:f269e3021894 551 nrf_uart_hwfc_pins_set(UART_INSTANCE, UART_CB.pselrts, UART_CB.pselcts);
elessair 0:f269e3021894 552 }
elessair 0:f269e3021894 553
elessair 0:f269e3021894 554 void serial_set_flow_control(serial_t *obj, FlowControl type,
elessair 0:f269e3021894 555 PinName rxflow, PinName txflow)
elessair 0:f269e3021894 556 {
elessair 0:f269e3021894 557 (void)obj;
elessair 0:f269e3021894 558
elessair 0:f269e3021894 559 nrf_uart_disable(UART_INSTANCE);
elessair 0:f269e3021894 560 internal_set_hwfc(type, rxflow, txflow);
elessair 0:f269e3021894 561 nrf_uart_enable(UART_INSTANCE);
elessair 0:f269e3021894 562 }
elessair 0:f269e3021894 563
elessair 0:f269e3021894 564
elessair 0:f269e3021894 565 void serial_clear(serial_t *obj) {
elessair 0:f269e3021894 566 (void)obj;
elessair 0:f269e3021894 567 }
elessair 0:f269e3021894 568
elessair 0:f269e3021894 569 #if DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 570
elessair 0:f269e3021894 571 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length,
elessair 0:f269e3021894 572 uint8_t tx_width, uint32_t handler, uint32_t event,
elessair 0:f269e3021894 573 DMAUsage hint)
elessair 0:f269e3021894 574 {
elessair 0:f269e3021894 575 (void)obj;
elessair 0:f269e3021894 576 (void)tx_width;
elessair 0:f269e3021894 577 (void)hint;
elessair 0:f269e3021894 578 if (UART_CB.tx_active || !tx_length) {
elessair 0:f269e3021894 579 return 0;
elessair 0:f269e3021894 580 }
elessair 0:f269e3021894 581
elessair 0:f269e3021894 582 UART_CB.tx_buffer = tx;
elessair 0:f269e3021894 583 UART_CB.tx_length = tx_length;
elessair 0:f269e3021894 584 UART_CB.tx_pos = 0;
elessair 0:f269e3021894 585 UART_CB.tx_asynch_handler = (void(*)())handler;
elessair 0:f269e3021894 586 UART_CB.events_wanted &= ~SERIAL_EVENT_TX_ALL;
elessair 0:f269e3021894 587 UART_CB.events_wanted |= event;
elessair 0:f269e3021894 588
elessair 0:f269e3021894 589 UART_CB.tx_active = true;
elessair 0:f269e3021894 590 nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
elessair 0:f269e3021894 591
elessair 0:f269e3021894 592 return 0;
elessair 0:f269e3021894 593 }
elessair 0:f269e3021894 594
elessair 0:f269e3021894 595 void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length,
elessair 0:f269e3021894 596 uint8_t rx_width, uint32_t handler, uint32_t event,
elessair 0:f269e3021894 597 uint8_t char_match, DMAUsage hint)
elessair 0:f269e3021894 598 {
elessair 0:f269e3021894 599 (void)obj;
elessair 0:f269e3021894 600 (void)rx_width;
elessair 0:f269e3021894 601 (void)hint;
elessair 0:f269e3021894 602 if (UART_CB.rx_active || !rx_length) {
elessair 0:f269e3021894 603 return;
elessair 0:f269e3021894 604 }
elessair 0:f269e3021894 605
elessair 0:f269e3021894 606 UART_CB.rx_buffer = rx;
elessair 0:f269e3021894 607 UART_CB.rx_length = rx_length;
elessair 0:f269e3021894 608 UART_CB.rx_pos = 0;
elessair 0:f269e3021894 609 UART_CB.rx_asynch_handler = (void(*)())handler;
elessair 0:f269e3021894 610 UART_CB.events_wanted &= ~SERIAL_EVENT_RX_ALL;
elessair 0:f269e3021894 611 UART_CB.events_wanted |= event;
elessair 0:f269e3021894 612 UART_CB.char_match = char_match;
elessair 0:f269e3021894 613
elessair 0:f269e3021894 614 UART_CB.rx_active = true;
elessair 0:f269e3021894 615 nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY);
elessair 0:f269e3021894 616 }
elessair 0:f269e3021894 617
elessair 0:f269e3021894 618 uint8_t serial_tx_active(serial_t *obj)
elessair 0:f269e3021894 619 {
elessair 0:f269e3021894 620 (void)obj;
elessair 0:f269e3021894 621 return UART_CB.tx_active;
elessair 0:f269e3021894 622 }
elessair 0:f269e3021894 623
elessair 0:f269e3021894 624 uint8_t serial_rx_active(serial_t *obj)
elessair 0:f269e3021894 625 {
elessair 0:f269e3021894 626 (void)obj;
elessair 0:f269e3021894 627 return UART_CB.rx_active;
elessair 0:f269e3021894 628 }
elessair 0:f269e3021894 629
elessair 0:f269e3021894 630 int serial_irq_handler_asynch(serial_t *obj)
elessair 0:f269e3021894 631 {
elessair 0:f269e3021894 632 (void)obj;
elessair 0:f269e3021894 633 uint32_t events_to_report = UART_CB.events_wanted & UART_CB.events_occured;
elessair 0:f269e3021894 634 UART_CB.events_occured &= (~events_to_report);
elessair 0:f269e3021894 635 return events_to_report;
elessair 0:f269e3021894 636 }
elessair 0:f269e3021894 637
elessair 0:f269e3021894 638 void serial_tx_abort_asynch(serial_t *obj)
elessair 0:f269e3021894 639 {
elessair 0:f269e3021894 640 (void)obj;
elessair 0:f269e3021894 641 end_asynch_tx();
elessair 0:f269e3021894 642 UART_CB.tx_asynch_handler = NULL;
elessair 0:f269e3021894 643 }
elessair 0:f269e3021894 644
elessair 0:f269e3021894 645 void serial_rx_abort_asynch(serial_t *obj)
elessair 0:f269e3021894 646 {
elessair 0:f269e3021894 647 (void)obj;
elessair 0:f269e3021894 648 end_asynch_rx();
elessair 0:f269e3021894 649 UART_CB.rx_asynch_handler = NULL;
elessair 0:f269e3021894 650 }
elessair 0:f269e3021894 651
elessair 0:f269e3021894 652 #endif // DEVICE_SERIAL_ASYNCH
elessair 0:f269e3021894 653
elessair 0:f269e3021894 654 #endif // DEVICE_SERIAL