mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Nov 08 11:46:34 2018 +0000
Revision:
188:bcfe06ba3d64
Parent:
187:0387e8f68319
Child:
189:f392fc9709a3
mbed-dev library. Release version 164

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 187:0387e8f68319 1 /* mbed Microcontroller Library
AnnaBridge 187:0387e8f68319 2 * Copyright (c) 2017-2018 Nuvoton
AnnaBridge 187:0387e8f68319 3 *
AnnaBridge 187:0387e8f68319 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 187:0387e8f68319 5 * you may not use this file except in compliance with the License.
AnnaBridge 187:0387e8f68319 6 * You may obtain a copy of the License at
AnnaBridge 187:0387e8f68319 7 *
AnnaBridge 187:0387e8f68319 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 187:0387e8f68319 9 *
AnnaBridge 187:0387e8f68319 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 187:0387e8f68319 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 187:0387e8f68319 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 187:0387e8f68319 13 * See the License for the specific language governing permissions and
AnnaBridge 187:0387e8f68319 14 * limitations under the License.
AnnaBridge 187:0387e8f68319 15 */
AnnaBridge 187:0387e8f68319 16
AnnaBridge 187:0387e8f68319 17 #include "serial_api.h"
AnnaBridge 187:0387e8f68319 18
AnnaBridge 187:0387e8f68319 19 #if DEVICE_SERIAL
AnnaBridge 187:0387e8f68319 20
AnnaBridge 187:0387e8f68319 21 #include "cmsis.h"
AnnaBridge 187:0387e8f68319 22 #include "mbed_error.h"
AnnaBridge 187:0387e8f68319 23 #include "mbed_assert.h"
AnnaBridge 187:0387e8f68319 24 #include "PeripheralPins.h"
AnnaBridge 187:0387e8f68319 25 #include "nu_modutil.h"
AnnaBridge 187:0387e8f68319 26 #include "nu_bitutil.h"
AnnaBridge 187:0387e8f68319 27 #include <string.h>
AnnaBridge 188:bcfe06ba3d64 28 #include <stdbool.h>
AnnaBridge 187:0387e8f68319 29
AnnaBridge 187:0387e8f68319 30 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 31 #include "dma_api.h"
AnnaBridge 187:0387e8f68319 32 #include "dma.h"
AnnaBridge 187:0387e8f68319 33 #endif
AnnaBridge 187:0387e8f68319 34
AnnaBridge 187:0387e8f68319 35 struct nu_uart_var {
AnnaBridge 187:0387e8f68319 36 uint32_t ref_cnt; // Reference count of the H/W module
AnnaBridge 187:0387e8f68319 37 serial_t * obj;
AnnaBridge 187:0387e8f68319 38 uint32_t fifo_size_tx;
AnnaBridge 187:0387e8f68319 39 uint32_t fifo_size_rx;
AnnaBridge 187:0387e8f68319 40 void (*vec)(void);
AnnaBridge 187:0387e8f68319 41 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 42 void (*vec_async)(void);
AnnaBridge 187:0387e8f68319 43 uint8_t pdma_perp_tx;
AnnaBridge 187:0387e8f68319 44 uint8_t pdma_perp_rx;
AnnaBridge 187:0387e8f68319 45 #endif
AnnaBridge 187:0387e8f68319 46 };
AnnaBridge 187:0387e8f68319 47
AnnaBridge 187:0387e8f68319 48 static void uart0_vec(void);
AnnaBridge 187:0387e8f68319 49 static void uart1_vec(void);
AnnaBridge 187:0387e8f68319 50 static void uart2_vec(void);
AnnaBridge 187:0387e8f68319 51 static void uart3_vec(void);
AnnaBridge 187:0387e8f68319 52 static void uart4_vec(void);
AnnaBridge 187:0387e8f68319 53 static void uart5_vec(void);
AnnaBridge 187:0387e8f68319 54 static void uart_irq(serial_t *obj);
AnnaBridge 187:0387e8f68319 55
AnnaBridge 187:0387e8f68319 56 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 57 static void uart0_vec_async(void);
AnnaBridge 187:0387e8f68319 58 static void uart1_vec_async(void);
AnnaBridge 187:0387e8f68319 59 static void uart2_vec_async(void);
AnnaBridge 187:0387e8f68319 60 static void uart3_vec_async(void);
AnnaBridge 187:0387e8f68319 61 static void uart4_vec_async(void);
AnnaBridge 187:0387e8f68319 62 static void uart5_vec_async(void);
AnnaBridge 187:0387e8f68319 63 static void uart_irq_async(serial_t *obj);
AnnaBridge 187:0387e8f68319 64
AnnaBridge 187:0387e8f68319 65 static void uart_dma_handler_tx(uint32_t id, uint32_t event);
AnnaBridge 187:0387e8f68319 66 static void uart_dma_handler_rx(uint32_t id, uint32_t event);
AnnaBridge 187:0387e8f68319 67
AnnaBridge 187:0387e8f68319 68 static void serial_tx_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable);
AnnaBridge 187:0387e8f68319 69 static void serial_rx_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable);
AnnaBridge 187:0387e8f68319 70 static void serial_enable_interrupt(serial_t *obj, SerialIrq irq, uint32_t enable);
AnnaBridge 187:0387e8f68319 71 static void serial_rollback_interrupt(serial_t *obj, SerialIrq irq);
AnnaBridge 187:0387e8f68319 72 static int serial_write_async(serial_t *obj);
AnnaBridge 187:0387e8f68319 73 static int serial_read_async(serial_t *obj);
AnnaBridge 187:0387e8f68319 74
AnnaBridge 187:0387e8f68319 75 static uint32_t serial_rx_event_check(serial_t *obj);
AnnaBridge 187:0387e8f68319 76 static uint32_t serial_tx_event_check(serial_t *obj);
AnnaBridge 187:0387e8f68319 77
AnnaBridge 187:0387e8f68319 78 static int serial_is_tx_complete(serial_t *obj);
AnnaBridge 187:0387e8f68319 79 static void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable);
AnnaBridge 187:0387e8f68319 80
AnnaBridge 187:0387e8f68319 81 static void serial_tx_buffer_set(serial_t *obj, const void *tx, size_t length, uint8_t width);
AnnaBridge 187:0387e8f68319 82 static void serial_rx_buffer_set(serial_t *obj, void *rx, size_t length, uint8_t width);
AnnaBridge 187:0387e8f68319 83 static void serial_rx_set_char_match(serial_t *obj, uint8_t char_match);
AnnaBridge 187:0387e8f68319 84 static void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable);
AnnaBridge 187:0387e8f68319 85 static int serial_is_rx_complete(serial_t *obj);
AnnaBridge 187:0387e8f68319 86
AnnaBridge 187:0387e8f68319 87 static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch);
AnnaBridge 187:0387e8f68319 88 static int serial_is_irq_en(serial_t *obj, SerialIrq irq);
AnnaBridge 187:0387e8f68319 89 #endif
AnnaBridge 187:0387e8f68319 90
AnnaBridge 188:bcfe06ba3d64 91 bool serial_can_deep_sleep(void);
AnnaBridge 188:bcfe06ba3d64 92
AnnaBridge 187:0387e8f68319 93 static struct nu_uart_var uart0_var = {
AnnaBridge 187:0387e8f68319 94 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 95 .obj = NULL,
AnnaBridge 187:0387e8f68319 96 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 97 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 98 .vec = uart0_vec,
AnnaBridge 187:0387e8f68319 99 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 100 .vec_async = uart0_vec_async,
AnnaBridge 187:0387e8f68319 101 .pdma_perp_tx = PDMA_UART0_TX,
AnnaBridge 187:0387e8f68319 102 .pdma_perp_rx = PDMA_UART0_RX
AnnaBridge 187:0387e8f68319 103 #endif
AnnaBridge 187:0387e8f68319 104 };
AnnaBridge 187:0387e8f68319 105 static struct nu_uart_var uart1_var = {
AnnaBridge 187:0387e8f68319 106 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 107 .obj = NULL,
AnnaBridge 187:0387e8f68319 108 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 109 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 110 .vec = uart1_vec,
AnnaBridge 187:0387e8f68319 111 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 112 .vec_async = uart1_vec_async,
AnnaBridge 187:0387e8f68319 113 .pdma_perp_tx = PDMA_UART1_TX,
AnnaBridge 187:0387e8f68319 114 .pdma_perp_rx = PDMA_UART1_RX
AnnaBridge 187:0387e8f68319 115 #endif
AnnaBridge 187:0387e8f68319 116 };
AnnaBridge 187:0387e8f68319 117 static struct nu_uart_var uart2_var = {
AnnaBridge 187:0387e8f68319 118 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 119 .obj = NULL,
AnnaBridge 187:0387e8f68319 120 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 121 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 122 .vec = uart2_vec,
AnnaBridge 187:0387e8f68319 123 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 124 .vec_async = uart2_vec_async,
AnnaBridge 187:0387e8f68319 125 .pdma_perp_tx = PDMA_UART2_TX,
AnnaBridge 187:0387e8f68319 126 .pdma_perp_rx = PDMA_UART2_RX
AnnaBridge 187:0387e8f68319 127 #endif
AnnaBridge 187:0387e8f68319 128 };
AnnaBridge 187:0387e8f68319 129 static struct nu_uart_var uart3_var = {
AnnaBridge 187:0387e8f68319 130 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 131 .obj = NULL,
AnnaBridge 187:0387e8f68319 132 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 133 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 134 .vec = uart3_vec,
AnnaBridge 187:0387e8f68319 135 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 136 .vec_async = uart3_vec_async,
AnnaBridge 187:0387e8f68319 137 .pdma_perp_tx = PDMA_UART3_TX,
AnnaBridge 187:0387e8f68319 138 .pdma_perp_rx = PDMA_UART3_RX
AnnaBridge 187:0387e8f68319 139 #endif
AnnaBridge 187:0387e8f68319 140 };
AnnaBridge 187:0387e8f68319 141 static struct nu_uart_var uart4_var = {
AnnaBridge 187:0387e8f68319 142 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 143 .obj = NULL,
AnnaBridge 187:0387e8f68319 144 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 145 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 146 .vec = uart4_vec,
AnnaBridge 187:0387e8f68319 147 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 148 .vec_async = uart4_vec_async,
AnnaBridge 187:0387e8f68319 149 .pdma_perp_tx = PDMA_UART4_TX,
AnnaBridge 187:0387e8f68319 150 .pdma_perp_rx = PDMA_UART4_RX
AnnaBridge 187:0387e8f68319 151 #endif
AnnaBridge 187:0387e8f68319 152 };
AnnaBridge 187:0387e8f68319 153 static struct nu_uart_var uart5_var = {
AnnaBridge 187:0387e8f68319 154 .ref_cnt = 0,
AnnaBridge 187:0387e8f68319 155 .obj = NULL,
AnnaBridge 187:0387e8f68319 156 .fifo_size_tx = 16,
AnnaBridge 187:0387e8f68319 157 .fifo_size_rx = 16,
AnnaBridge 187:0387e8f68319 158 .vec = uart5_vec,
AnnaBridge 187:0387e8f68319 159 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 160 .vec_async = uart5_vec_async,
AnnaBridge 187:0387e8f68319 161 .pdma_perp_tx = PDMA_UART5_TX,
AnnaBridge 187:0387e8f68319 162 .pdma_perp_rx = PDMA_UART5_RX
AnnaBridge 187:0387e8f68319 163 #endif
AnnaBridge 187:0387e8f68319 164 };
AnnaBridge 187:0387e8f68319 165
AnnaBridge 187:0387e8f68319 166
AnnaBridge 187:0387e8f68319 167 int stdio_uart_inited = 0;
AnnaBridge 187:0387e8f68319 168 serial_t stdio_uart;
AnnaBridge 187:0387e8f68319 169 static uint32_t uart_modinit_mask = 0;
AnnaBridge 187:0387e8f68319 170
AnnaBridge 187:0387e8f68319 171 static const struct nu_modinit_s uart_modinit_tab[] = {
AnnaBridge 187:0387e8f68319 172 {UART_0, UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1), UART0_RST, UART0_IRQn, &uart0_var},
AnnaBridge 187:0387e8f68319 173 {UART_1, UART1_MODULE, CLK_CLKSEL1_UART1SEL_HIRC, CLK_CLKDIV0_UART1(1), UART1_RST, UART1_IRQn, &uart1_var},
AnnaBridge 187:0387e8f68319 174 {UART_2, UART2_MODULE, CLK_CLKSEL3_UART2SEL_HIRC, CLK_CLKDIV4_UART2(1), UART2_RST, UART2_IRQn, &uart2_var},
AnnaBridge 187:0387e8f68319 175 {UART_3, UART3_MODULE, CLK_CLKSEL3_UART3SEL_HIRC, CLK_CLKDIV4_UART3(1), UART3_RST, UART3_IRQn, &uart3_var},
AnnaBridge 187:0387e8f68319 176 {UART_4, UART4_MODULE, CLK_CLKSEL3_UART4SEL_HIRC, CLK_CLKDIV4_UART4(1), UART4_RST, UART4_IRQn, &uart4_var},
AnnaBridge 187:0387e8f68319 177 {UART_5, UART5_MODULE, CLK_CLKSEL3_UART5SEL_HIRC, CLK_CLKDIV4_UART5(1), UART5_RST, UART5_IRQn, &uart5_var},
AnnaBridge 187:0387e8f68319 178
AnnaBridge 187:0387e8f68319 179 {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
AnnaBridge 187:0387e8f68319 180 };
AnnaBridge 187:0387e8f68319 181
AnnaBridge 187:0387e8f68319 182 extern void mbed_sdk_init(void);
AnnaBridge 187:0387e8f68319 183
AnnaBridge 187:0387e8f68319 184 void serial_init(serial_t *obj, PinName tx, PinName rx)
AnnaBridge 187:0387e8f68319 185 {
AnnaBridge 187:0387e8f68319 186 // NOTE: With armcc, serial_init() gets called from _sys_open() timing of which is before main()/mbed_sdk_init().
AnnaBridge 187:0387e8f68319 187 mbed_sdk_init();
AnnaBridge 187:0387e8f68319 188
AnnaBridge 187:0387e8f68319 189 // Determine which UART_x the pins are used for
AnnaBridge 187:0387e8f68319 190 uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX);
AnnaBridge 187:0387e8f68319 191 uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX);
AnnaBridge 187:0387e8f68319 192 // Get the peripheral name (UART_x) from the pins and assign it to the object
AnnaBridge 187:0387e8f68319 193 obj->serial.uart = (UARTName) pinmap_merge(uart_tx, uart_rx);
AnnaBridge 187:0387e8f68319 194 MBED_ASSERT((int)obj->serial.uart != NC);
AnnaBridge 187:0387e8f68319 195
AnnaBridge 187:0387e8f68319 196 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 197 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 198 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 199
AnnaBridge 187:0387e8f68319 200 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 201
AnnaBridge 187:0387e8f68319 202 if (! var->ref_cnt) {
AnnaBridge 187:0387e8f68319 203 do {
AnnaBridge 187:0387e8f68319 204 /* Reset module
AnnaBridge 187:0387e8f68319 205 *
AnnaBridge 187:0387e8f68319 206 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 207 */
AnnaBridge 187:0387e8f68319 208 SYS_ResetModule_S(modinit->rsetidx);
AnnaBridge 187:0387e8f68319 209
AnnaBridge 187:0387e8f68319 210 /* Select IP clock source
AnnaBridge 187:0387e8f68319 211 *
AnnaBridge 187:0387e8f68319 212 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 213 */
AnnaBridge 187:0387e8f68319 214 CLK_SetModuleClock_S(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
AnnaBridge 187:0387e8f68319 215
AnnaBridge 187:0387e8f68319 216 /* Enable IP clock
AnnaBridge 187:0387e8f68319 217 *
AnnaBridge 187:0387e8f68319 218 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 219 */
AnnaBridge 187:0387e8f68319 220 CLK_EnableModuleClock_S(modinit->clkidx);
AnnaBridge 187:0387e8f68319 221
AnnaBridge 187:0387e8f68319 222 pinmap_pinout(tx, PinMap_UART_TX);
AnnaBridge 187:0387e8f68319 223 pinmap_pinout(rx, PinMap_UART_RX);
AnnaBridge 187:0387e8f68319 224 } while (0);
AnnaBridge 187:0387e8f68319 225
AnnaBridge 187:0387e8f68319 226 obj->serial.pin_tx = tx;
AnnaBridge 187:0387e8f68319 227 obj->serial.pin_rx = rx;
AnnaBridge 187:0387e8f68319 228 }
AnnaBridge 187:0387e8f68319 229 var->ref_cnt ++;
AnnaBridge 187:0387e8f68319 230
AnnaBridge 187:0387e8f68319 231 // Configure the UART module and set its baudrate
AnnaBridge 187:0387e8f68319 232 serial_baud(obj, 9600);
AnnaBridge 187:0387e8f68319 233 // Configure data bits, parity, and stop bits
AnnaBridge 187:0387e8f68319 234 serial_format(obj, 8, ParityNone, 1);
AnnaBridge 187:0387e8f68319 235
AnnaBridge 187:0387e8f68319 236 obj->serial.vec = var->vec;
AnnaBridge 187:0387e8f68319 237 obj->serial.irq_en = 0;
AnnaBridge 187:0387e8f68319 238
AnnaBridge 187:0387e8f68319 239 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 240 obj->serial.dma_usage_tx = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 241 obj->serial.dma_usage_rx = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 242 obj->serial.event = 0;
AnnaBridge 187:0387e8f68319 243 obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 244 obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 245 #endif
AnnaBridge 187:0387e8f68319 246
AnnaBridge 187:0387e8f68319 247 // For stdio management
AnnaBridge 187:0387e8f68319 248 if (obj->serial.uart == STDIO_UART) {
AnnaBridge 187:0387e8f68319 249 stdio_uart_inited = 1;
AnnaBridge 187:0387e8f68319 250 memcpy(&stdio_uart, obj, sizeof(serial_t));
AnnaBridge 187:0387e8f68319 251 }
AnnaBridge 187:0387e8f68319 252
AnnaBridge 187:0387e8f68319 253 if (var->ref_cnt) {
AnnaBridge 187:0387e8f68319 254 // Mark this module to be inited.
AnnaBridge 187:0387e8f68319 255 int i = modinit - uart_modinit_tab;
AnnaBridge 187:0387e8f68319 256 uart_modinit_mask |= 1 << i;
AnnaBridge 187:0387e8f68319 257 }
AnnaBridge 187:0387e8f68319 258 }
AnnaBridge 187:0387e8f68319 259
AnnaBridge 187:0387e8f68319 260 void serial_free(serial_t *obj)
AnnaBridge 187:0387e8f68319 261 {
AnnaBridge 187:0387e8f68319 262 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 263 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 264 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 265
AnnaBridge 187:0387e8f68319 266 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 267
AnnaBridge 187:0387e8f68319 268 var->ref_cnt --;
AnnaBridge 187:0387e8f68319 269 if (! var->ref_cnt) {
AnnaBridge 187:0387e8f68319 270 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 271 if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 272 dma_channel_free(obj->serial.dma_chn_id_tx);
AnnaBridge 187:0387e8f68319 273 obj->serial.dma_chn_id_tx = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 274 }
AnnaBridge 187:0387e8f68319 275 if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 276 dma_channel_free(obj->serial.dma_chn_id_rx);
AnnaBridge 187:0387e8f68319 277 obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 278 }
AnnaBridge 187:0387e8f68319 279 #endif
AnnaBridge 187:0387e8f68319 280
AnnaBridge 187:0387e8f68319 281 do {
AnnaBridge 187:0387e8f68319 282 UART_Close((UART_T *) NU_MODBASE(obj->serial.uart));
AnnaBridge 187:0387e8f68319 283
AnnaBridge 187:0387e8f68319 284 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 285 NVIC_DisableIRQ(modinit->irq_n);
AnnaBridge 187:0387e8f68319 286
AnnaBridge 187:0387e8f68319 287 /* Disable IP clock
AnnaBridge 187:0387e8f68319 288 *
AnnaBridge 187:0387e8f68319 289 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 290 */
AnnaBridge 187:0387e8f68319 291 CLK_DisableModuleClock_S(modinit->clkidx);
AnnaBridge 187:0387e8f68319 292 } while (0);
AnnaBridge 187:0387e8f68319 293 }
AnnaBridge 187:0387e8f68319 294
AnnaBridge 187:0387e8f68319 295 if (var->obj == obj) {
AnnaBridge 187:0387e8f68319 296 var->obj = NULL;
AnnaBridge 187:0387e8f68319 297 }
AnnaBridge 187:0387e8f68319 298
AnnaBridge 187:0387e8f68319 299 if (obj->serial.uart == STDIO_UART) {
AnnaBridge 187:0387e8f68319 300 stdio_uart_inited = 0;
AnnaBridge 187:0387e8f68319 301 }
AnnaBridge 187:0387e8f68319 302
AnnaBridge 187:0387e8f68319 303 if (! var->ref_cnt) {
AnnaBridge 187:0387e8f68319 304 // Mark this module to be deinited.
AnnaBridge 187:0387e8f68319 305 int i = modinit - uart_modinit_tab;
AnnaBridge 187:0387e8f68319 306 uart_modinit_mask &= ~(1 << i);
AnnaBridge 187:0387e8f68319 307 }
AnnaBridge 187:0387e8f68319 308 }
AnnaBridge 187:0387e8f68319 309
AnnaBridge 187:0387e8f68319 310 void serial_baud(serial_t *obj, int baudrate)
AnnaBridge 187:0387e8f68319 311 {
AnnaBridge 187:0387e8f68319 312 // Flush Tx FIFO. Otherwise, output data may get lost on this change.
AnnaBridge 187:0387e8f68319 313 while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 314
AnnaBridge 187:0387e8f68319 315 obj->serial.baudrate = baudrate;
AnnaBridge 187:0387e8f68319 316 UART_Open((UART_T *) NU_MODBASE(obj->serial.uart), baudrate);
AnnaBridge 187:0387e8f68319 317 }
AnnaBridge 187:0387e8f68319 318
AnnaBridge 187:0387e8f68319 319 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
AnnaBridge 187:0387e8f68319 320 {
AnnaBridge 187:0387e8f68319 321 // Flush Tx FIFO. Otherwise, output data may get lost on this change.
AnnaBridge 187:0387e8f68319 322 while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 323
AnnaBridge 187:0387e8f68319 324 // Sanity check arguments
AnnaBridge 187:0387e8f68319 325 MBED_ASSERT((data_bits == 5) || (data_bits == 6) || (data_bits == 7) || (data_bits == 8));
AnnaBridge 187:0387e8f68319 326 MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) || (parity == ParityForced1) || (parity == ParityForced0));
AnnaBridge 187:0387e8f68319 327 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2));
AnnaBridge 187:0387e8f68319 328
AnnaBridge 187:0387e8f68319 329 obj->serial.databits = data_bits;
AnnaBridge 187:0387e8f68319 330 obj->serial.parity = parity;
AnnaBridge 187:0387e8f68319 331 obj->serial.stopbits = stop_bits;
AnnaBridge 187:0387e8f68319 332
AnnaBridge 187:0387e8f68319 333 uint32_t databits_intern = (data_bits == 5) ? UART_WORD_LEN_5 :
AnnaBridge 187:0387e8f68319 334 (data_bits == 6) ? UART_WORD_LEN_6 :
AnnaBridge 187:0387e8f68319 335 (data_bits == 7) ? UART_WORD_LEN_7 :
AnnaBridge 187:0387e8f68319 336 UART_WORD_LEN_8;
AnnaBridge 187:0387e8f68319 337 uint32_t parity_intern = (parity == ParityOdd || parity == ParityForced1) ? UART_PARITY_ODD :
AnnaBridge 187:0387e8f68319 338 (parity == ParityEven || parity == ParityForced0) ? UART_PARITY_EVEN :
AnnaBridge 187:0387e8f68319 339 UART_PARITY_NONE;
AnnaBridge 187:0387e8f68319 340 uint32_t stopbits_intern = (stop_bits == 2) ? UART_STOP_BIT_2 : UART_STOP_BIT_1;
AnnaBridge 187:0387e8f68319 341 UART_SetLineConfig((UART_T *) NU_MODBASE(obj->serial.uart),
AnnaBridge 187:0387e8f68319 342 0, // Don't change baudrate
AnnaBridge 187:0387e8f68319 343 databits_intern,
AnnaBridge 187:0387e8f68319 344 parity_intern,
AnnaBridge 187:0387e8f68319 345 stopbits_intern);
AnnaBridge 187:0387e8f68319 346 }
AnnaBridge 187:0387e8f68319 347
AnnaBridge 187:0387e8f68319 348 #if DEVICE_SERIAL_FC
AnnaBridge 187:0387e8f68319 349
AnnaBridge 187:0387e8f68319 350 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
AnnaBridge 187:0387e8f68319 351 {
AnnaBridge 187:0387e8f68319 352 UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
AnnaBridge 187:0387e8f68319 353
AnnaBridge 187:0387e8f68319 354 // First, disable flow control completely.
AnnaBridge 187:0387e8f68319 355 uart_base->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
AnnaBridge 187:0387e8f68319 356
AnnaBridge 187:0387e8f68319 357 if ((type == FlowControlRTS || type == FlowControlRTSCTS) && rxflow != NC) {
AnnaBridge 187:0387e8f68319 358 // Check if RTS pin matches.
AnnaBridge 187:0387e8f68319 359 uint32_t uart_rts = pinmap_peripheral(rxflow, PinMap_UART_RTS);
AnnaBridge 187:0387e8f68319 360 MBED_ASSERT(uart_rts == obj->serial.uart);
AnnaBridge 187:0387e8f68319 361 // Enable the pin for RTS function
AnnaBridge 187:0387e8f68319 362 pinmap_pinout(rxflow, PinMap_UART_RTS);
AnnaBridge 187:0387e8f68319 363
AnnaBridge 187:0387e8f68319 364 // NOTE: Added in M480/M2351. Before configuring RTSACTLV, disable TX/RX.
AnnaBridge 187:0387e8f68319 365 uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk;
AnnaBridge 187:0387e8f68319 366 while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk);
AnnaBridge 187:0387e8f68319 367 // nRTS pin output is low level active
AnnaBridge 187:0387e8f68319 368 uart_base->MODEM |= UART_MODEM_RTSACTLV_Msk;
AnnaBridge 187:0387e8f68319 369 // NOTE: Added in M480/M2351. After configuring RTSACTLV, re-enable TX/RX.
AnnaBridge 187:0387e8f68319 370 uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
AnnaBridge 187:0387e8f68319 371
AnnaBridge 187:0387e8f68319 372 uart_base->FIFO = (uart_base->FIFO & ~UART_FIFO_RTSTRGLV_Msk) | UART_FIFO_RTSTRGLV_8BYTES;
AnnaBridge 187:0387e8f68319 373
AnnaBridge 187:0387e8f68319 374 // Enable RTS
AnnaBridge 187:0387e8f68319 375 uart_base->INTEN |= UART_INTEN_ATORTSEN_Msk;
AnnaBridge 187:0387e8f68319 376 }
AnnaBridge 187:0387e8f68319 377
AnnaBridge 187:0387e8f68319 378 if ((type == FlowControlCTS || type == FlowControlRTSCTS) && txflow != NC) {
AnnaBridge 187:0387e8f68319 379 // Check if CTS pin matches.
AnnaBridge 187:0387e8f68319 380 uint32_t uart_cts = pinmap_peripheral(txflow, PinMap_UART_CTS);
AnnaBridge 187:0387e8f68319 381 MBED_ASSERT(uart_cts == obj->serial.uart);
AnnaBridge 187:0387e8f68319 382 // Enable the pin for CTS function
AnnaBridge 187:0387e8f68319 383 pinmap_pinout(txflow, PinMap_UART_CTS);
AnnaBridge 187:0387e8f68319 384
AnnaBridge 187:0387e8f68319 385 // NOTE: Added in M480/M2351. Before configuring CTSACTLV, disable TX/RX.
AnnaBridge 187:0387e8f68319 386 uart_base->FUNCSEL |= UART_FUNCSEL_TXRXDIS_Msk;
AnnaBridge 187:0387e8f68319 387 while (uart_base->FIFOSTS & UART_FIFOSTS_TXRXACT_Msk);
AnnaBridge 187:0387e8f68319 388 // nCTS pin input is low level active
AnnaBridge 187:0387e8f68319 389 uart_base->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
AnnaBridge 187:0387e8f68319 390 // NOTE: Added in M480/M2351. After configuring CTSACTLV, re-enable TX/RX.
AnnaBridge 187:0387e8f68319 391 uart_base->FUNCSEL &= ~UART_FUNCSEL_TXRXDIS_Msk;
AnnaBridge 187:0387e8f68319 392
AnnaBridge 187:0387e8f68319 393 // Enable CTS
AnnaBridge 187:0387e8f68319 394 uart_base->INTEN |= UART_INTEN_ATOCTSEN_Msk;
AnnaBridge 187:0387e8f68319 395 }
AnnaBridge 187:0387e8f68319 396 }
AnnaBridge 187:0387e8f68319 397
AnnaBridge 187:0387e8f68319 398 #endif //DEVICE_SERIAL_FC
AnnaBridge 187:0387e8f68319 399
AnnaBridge 187:0387e8f68319 400 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
AnnaBridge 187:0387e8f68319 401 {
AnnaBridge 187:0387e8f68319 402 // Flush Tx FIFO. Otherwise, output data may get lost on this change.
AnnaBridge 187:0387e8f68319 403 while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 404
AnnaBridge 187:0387e8f68319 405 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 406 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 407 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 408
AnnaBridge 187:0387e8f68319 409 obj->serial.irq_handler = (uint32_t) handler;
AnnaBridge 187:0387e8f68319 410 obj->serial.irq_id = id;
AnnaBridge 187:0387e8f68319 411
AnnaBridge 187:0387e8f68319 412 // Restore sync-mode vector
AnnaBridge 187:0387e8f68319 413 obj->serial.vec = ((struct nu_uart_var *) modinit->var)->vec;
AnnaBridge 187:0387e8f68319 414 }
AnnaBridge 187:0387e8f68319 415
AnnaBridge 187:0387e8f68319 416 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
AnnaBridge 187:0387e8f68319 417 {
AnnaBridge 187:0387e8f68319 418 obj->serial.irq_en = enable;
AnnaBridge 187:0387e8f68319 419 serial_enable_interrupt(obj, irq, enable);
AnnaBridge 187:0387e8f68319 420 }
AnnaBridge 187:0387e8f68319 421
AnnaBridge 187:0387e8f68319 422 int serial_getc(serial_t *obj)
AnnaBridge 187:0387e8f68319 423 {
AnnaBridge 187:0387e8f68319 424 // NOTE: Every byte access requires accompaniment of one interrupt. This has side effect of performance degradation.
AnnaBridge 187:0387e8f68319 425 while (! serial_readable(obj));
AnnaBridge 187:0387e8f68319 426 int c = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 427
AnnaBridge 187:0387e8f68319 428 // NOTE: On Nuvoton targets, no H/W IRQ to match TxIrq/RxIrq.
AnnaBridge 187:0387e8f68319 429 // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively.
AnnaBridge 187:0387e8f68319 430 if (obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)) {
AnnaBridge 187:0387e8f68319 431 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 432 }
AnnaBridge 187:0387e8f68319 433
AnnaBridge 187:0387e8f68319 434 return c;
AnnaBridge 187:0387e8f68319 435 }
AnnaBridge 187:0387e8f68319 436
AnnaBridge 187:0387e8f68319 437 void serial_putc(serial_t *obj, int c)
AnnaBridge 187:0387e8f68319 438 {
AnnaBridge 187:0387e8f68319 439 // NOTE: Every byte access requires accompaniment of one interrupt. This has side effect of performance degradation.
AnnaBridge 187:0387e8f68319 440 while (! serial_writable(obj));
AnnaBridge 187:0387e8f68319 441 UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), c);
AnnaBridge 187:0387e8f68319 442
AnnaBridge 187:0387e8f68319 443 // NOTE: On Nuvoton targets, no H/W IRQ to match TxIrq/RxIrq.
AnnaBridge 187:0387e8f68319 444 // Simulation of TxIrq/RxIrq requires the call to Serial::putc()/Serial::getc() respectively.
AnnaBridge 187:0387e8f68319 445 if (obj->serial.inten_msk & UART_INTEN_THREIEN_Msk) {
AnnaBridge 187:0387e8f68319 446 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 447 }
AnnaBridge 187:0387e8f68319 448 }
AnnaBridge 187:0387e8f68319 449
AnnaBridge 187:0387e8f68319 450 int serial_readable(serial_t *obj)
AnnaBridge 187:0387e8f68319 451 {
AnnaBridge 187:0387e8f68319 452 return ! UART_GET_RX_EMPTY(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 453 }
AnnaBridge 187:0387e8f68319 454
AnnaBridge 187:0387e8f68319 455 int serial_writable(serial_t *obj)
AnnaBridge 187:0387e8f68319 456 {
AnnaBridge 187:0387e8f68319 457 return ! UART_IS_TX_FULL(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 458 }
AnnaBridge 187:0387e8f68319 459
AnnaBridge 187:0387e8f68319 460 void serial_pinout_tx(PinName tx)
AnnaBridge 187:0387e8f68319 461 {
AnnaBridge 187:0387e8f68319 462 pinmap_pinout(tx, PinMap_UART_TX);
AnnaBridge 187:0387e8f68319 463 }
AnnaBridge 187:0387e8f68319 464
AnnaBridge 187:0387e8f68319 465 void serial_break_set(serial_t *obj)
AnnaBridge 187:0387e8f68319 466 {
AnnaBridge 187:0387e8f68319 467 ((UART_T *) NU_MODBASE(obj->serial.uart))->LINE |= UART_LINE_BCB_Msk;
AnnaBridge 187:0387e8f68319 468 }
AnnaBridge 187:0387e8f68319 469
AnnaBridge 187:0387e8f68319 470 void serial_break_clear(serial_t *obj)
AnnaBridge 187:0387e8f68319 471 {
AnnaBridge 187:0387e8f68319 472 ((UART_T *) NU_MODBASE(obj->serial.uart))->LINE &= ~UART_LINE_BCB_Msk;
AnnaBridge 187:0387e8f68319 473 }
AnnaBridge 187:0387e8f68319 474
AnnaBridge 187:0387e8f68319 475 static void uart0_vec(void)
AnnaBridge 187:0387e8f68319 476 {
AnnaBridge 187:0387e8f68319 477 uart_irq(uart0_var.obj);
AnnaBridge 187:0387e8f68319 478 }
AnnaBridge 187:0387e8f68319 479
AnnaBridge 187:0387e8f68319 480 static void uart1_vec(void)
AnnaBridge 187:0387e8f68319 481 {
AnnaBridge 187:0387e8f68319 482 uart_irq(uart1_var.obj);
AnnaBridge 187:0387e8f68319 483 }
AnnaBridge 187:0387e8f68319 484
AnnaBridge 187:0387e8f68319 485 static void uart2_vec(void)
AnnaBridge 187:0387e8f68319 486 {
AnnaBridge 187:0387e8f68319 487 uart_irq(uart2_var.obj);
AnnaBridge 187:0387e8f68319 488 }
AnnaBridge 187:0387e8f68319 489
AnnaBridge 187:0387e8f68319 490 static void uart3_vec(void)
AnnaBridge 187:0387e8f68319 491 {
AnnaBridge 187:0387e8f68319 492 uart_irq(uart3_var.obj);
AnnaBridge 187:0387e8f68319 493 }
AnnaBridge 187:0387e8f68319 494
AnnaBridge 187:0387e8f68319 495 static void uart4_vec(void)
AnnaBridge 187:0387e8f68319 496 {
AnnaBridge 187:0387e8f68319 497 uart_irq(uart4_var.obj);
AnnaBridge 187:0387e8f68319 498 }
AnnaBridge 187:0387e8f68319 499
AnnaBridge 187:0387e8f68319 500 static void uart5_vec(void)
AnnaBridge 187:0387e8f68319 501 {
AnnaBridge 187:0387e8f68319 502 uart_irq(uart5_var.obj);
AnnaBridge 187:0387e8f68319 503 }
AnnaBridge 187:0387e8f68319 504
AnnaBridge 187:0387e8f68319 505 static void uart_irq(serial_t *obj)
AnnaBridge 187:0387e8f68319 506 {
AnnaBridge 187:0387e8f68319 507 UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
AnnaBridge 187:0387e8f68319 508
AnnaBridge 187:0387e8f68319 509 if (uart_base->INTSTS & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) {
AnnaBridge 187:0387e8f68319 510 // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next read.
AnnaBridge 187:0387e8f68319 511 UART_DISABLE_INT(uart_base, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 512 if (obj->serial.irq_handler) {
AnnaBridge 187:0387e8f68319 513 ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, RxIrq);
AnnaBridge 187:0387e8f68319 514 }
AnnaBridge 187:0387e8f68319 515 }
AnnaBridge 187:0387e8f68319 516
AnnaBridge 187:0387e8f68319 517 if (uart_base->INTSTS & UART_INTSTS_THREINT_Msk) {
AnnaBridge 187:0387e8f68319 518 // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next write.
AnnaBridge 187:0387e8f68319 519 UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 520 if (obj->serial.irq_handler) {
AnnaBridge 187:0387e8f68319 521 ((uart_irq_handler) obj->serial.irq_handler)(obj->serial.irq_id, TxIrq);
AnnaBridge 187:0387e8f68319 522 }
AnnaBridge 187:0387e8f68319 523 }
AnnaBridge 187:0387e8f68319 524
AnnaBridge 187:0387e8f68319 525 // FIXME: Ignore all other interrupt flags. Clear them. Otherwise, program will get stuck in interrupt.
AnnaBridge 187:0387e8f68319 526 uart_base->INTSTS = uart_base->INTSTS;
AnnaBridge 187:0387e8f68319 527 uart_base->FIFOSTS = uart_base->FIFOSTS;
AnnaBridge 187:0387e8f68319 528 }
AnnaBridge 187:0387e8f68319 529
AnnaBridge 187:0387e8f68319 530
AnnaBridge 187:0387e8f68319 531 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 187:0387e8f68319 532 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
AnnaBridge 187:0387e8f68319 533 {
AnnaBridge 187:0387e8f68319 534 MBED_ASSERT(tx_width == 8 || tx_width == 16 || tx_width == 32);
AnnaBridge 187:0387e8f68319 535
AnnaBridge 187:0387e8f68319 536 obj->serial.dma_usage_tx = hint;
AnnaBridge 187:0387e8f68319 537 serial_check_dma_usage(&obj->serial.dma_usage_tx, &obj->serial.dma_chn_id_tx);
AnnaBridge 187:0387e8f68319 538
AnnaBridge 187:0387e8f68319 539 // UART IRQ is necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 540 serial_tx_enable_event(obj, event, 1);
AnnaBridge 187:0387e8f68319 541 serial_tx_buffer_set(obj, tx, tx_length, tx_width);
AnnaBridge 187:0387e8f68319 542
AnnaBridge 187:0387e8f68319 543 int n_word = 0;
AnnaBridge 187:0387e8f68319 544 if (obj->serial.dma_usage_tx == DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 545 // Interrupt way
AnnaBridge 187:0387e8f68319 546 n_word = serial_write_async(obj);
AnnaBridge 187:0387e8f68319 547 serial_tx_enable_interrupt(obj, handler, 1);
AnnaBridge 187:0387e8f68319 548 } else {
AnnaBridge 187:0387e8f68319 549 // DMA way
AnnaBridge 187:0387e8f68319 550 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 551 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 552 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 553
AnnaBridge 187:0387e8f68319 554 PDMA_T *pdma_base = dma_modbase();
AnnaBridge 187:0387e8f68319 555
AnnaBridge 187:0387e8f68319 556 pdma_base->CHCTL |= 1 << obj->serial.dma_chn_id_tx; // Enable this DMA channel
AnnaBridge 187:0387e8f68319 557 PDMA_SetTransferMode(pdma_base,
AnnaBridge 187:0387e8f68319 558 obj->serial.dma_chn_id_tx,
AnnaBridge 187:0387e8f68319 559 ((struct nu_uart_var *) modinit->var)->pdma_perp_tx, // Peripheral connected to this PDMA
AnnaBridge 187:0387e8f68319 560 0, // Scatter-gather disabled
AnnaBridge 187:0387e8f68319 561 0); // Scatter-gather descriptor address
AnnaBridge 187:0387e8f68319 562 PDMA_SetTransferCnt(pdma_base,
AnnaBridge 187:0387e8f68319 563 obj->serial.dma_chn_id_tx,
AnnaBridge 187:0387e8f68319 564 (tx_width == 8) ? PDMA_WIDTH_8 : (tx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32,
AnnaBridge 187:0387e8f68319 565 tx_length);
AnnaBridge 187:0387e8f68319 566 PDMA_SetTransferAddr(pdma_base,
AnnaBridge 187:0387e8f68319 567 obj->serial.dma_chn_id_tx,
AnnaBridge 187:0387e8f68319 568 (uint32_t) tx, // NOTE:
AnnaBridge 187:0387e8f68319 569 // NUC472: End of source address
AnnaBridge 187:0387e8f68319 570 // M451: Start of source address
AnnaBridge 187:0387e8f68319 571 // M480: Start of source address
AnnaBridge 187:0387e8f68319 572 // M2351: Start of source address
AnnaBridge 187:0387e8f68319 573 PDMA_SAR_INC, // Source address incremental
AnnaBridge 187:0387e8f68319 574 (uint32_t) NU_MODBASE(obj->serial.uart), // Destination address
AnnaBridge 187:0387e8f68319 575 PDMA_DAR_FIX); // Destination address fixed
AnnaBridge 187:0387e8f68319 576 PDMA_SetBurstType(pdma_base,
AnnaBridge 187:0387e8f68319 577 obj->serial.dma_chn_id_tx,
AnnaBridge 187:0387e8f68319 578 PDMA_REQ_SINGLE, // Single mode
AnnaBridge 187:0387e8f68319 579 0); // Burst size
AnnaBridge 187:0387e8f68319 580 PDMA_EnableInt(pdma_base,
AnnaBridge 187:0387e8f68319 581 obj->serial.dma_chn_id_tx,
AnnaBridge 187:0387e8f68319 582 PDMA_INT_TRANS_DONE); // Interrupt type
AnnaBridge 187:0387e8f68319 583 // Register DMA event handler
AnnaBridge 187:0387e8f68319 584 dma_set_handler(obj->serial.dma_chn_id_tx, (uint32_t) uart_dma_handler_tx, (uint32_t) obj, DMA_EVENT_ALL);
AnnaBridge 187:0387e8f68319 585 serial_tx_enable_interrupt(obj, handler, 1);
AnnaBridge 187:0387e8f68319 586 /* We needn't actually enable UART INT to go UART ISR -> handler.
AnnaBridge 187:0387e8f68319 587 * Instead, as PDMA INT is triggered, we will go PDMA ISR -> UART ISR -> handler
AnnaBridge 187:0387e8f68319 588 * with serial_tx/rx_enable_interrupt having set up this call path. */
AnnaBridge 187:0387e8f68319 589 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 590
AnnaBridge 187:0387e8f68319 591 ((UART_T *) NU_MODBASE(obj->serial.uart))->INTEN |= UART_INTEN_TXPDMAEN_Msk; // Start DMA transfer
AnnaBridge 187:0387e8f68319 592 }
AnnaBridge 187:0387e8f68319 593
AnnaBridge 187:0387e8f68319 594 return n_word;
AnnaBridge 187:0387e8f68319 595 }
AnnaBridge 187:0387e8f68319 596
AnnaBridge 187:0387e8f68319 597 void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
AnnaBridge 187:0387e8f68319 598 {
AnnaBridge 187:0387e8f68319 599 MBED_ASSERT(rx_width == 8 || rx_width == 16 || rx_width == 32);
AnnaBridge 187:0387e8f68319 600
AnnaBridge 187:0387e8f68319 601 obj->serial.dma_usage_rx = hint;
AnnaBridge 187:0387e8f68319 602 serial_check_dma_usage(&obj->serial.dma_usage_rx, &obj->serial.dma_chn_id_rx);
AnnaBridge 187:0387e8f68319 603 // DMA doesn't support char match, so fall back to IRQ if it is requested.
AnnaBridge 187:0387e8f68319 604 if (obj->serial.dma_usage_rx != DMA_USAGE_NEVER &&
AnnaBridge 187:0387e8f68319 605 (event & SERIAL_EVENT_RX_CHARACTER_MATCH) &&
AnnaBridge 187:0387e8f68319 606 char_match != SERIAL_RESERVED_CHAR_MATCH) {
AnnaBridge 187:0387e8f68319 607 obj->serial.dma_usage_rx = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 608 dma_channel_free(obj->serial.dma_chn_id_rx);
AnnaBridge 187:0387e8f68319 609 obj->serial.dma_chn_id_rx = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 610 }
AnnaBridge 187:0387e8f68319 611
AnnaBridge 187:0387e8f68319 612 // UART IRQ is necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 613 serial_rx_enable_event(obj, event, 1);
AnnaBridge 187:0387e8f68319 614 serial_rx_buffer_set(obj, rx, rx_length, rx_width);
AnnaBridge 187:0387e8f68319 615 serial_rx_set_char_match(obj, char_match);
AnnaBridge 187:0387e8f68319 616
AnnaBridge 187:0387e8f68319 617 if (obj->serial.dma_usage_rx == DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 618 // Interrupt way
AnnaBridge 187:0387e8f68319 619 serial_rx_enable_interrupt(obj, handler, 1);
AnnaBridge 187:0387e8f68319 620 } else {
AnnaBridge 187:0387e8f68319 621 // DMA way
AnnaBridge 187:0387e8f68319 622 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 623 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 624 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 625
AnnaBridge 187:0387e8f68319 626 PDMA_T *pdma_base = dma_modbase();
AnnaBridge 187:0387e8f68319 627
AnnaBridge 187:0387e8f68319 628 pdma_base->CHCTL |= 1 << obj->serial.dma_chn_id_rx; // Enable this DMA channel
AnnaBridge 187:0387e8f68319 629 PDMA_SetTransferMode(pdma_base,
AnnaBridge 187:0387e8f68319 630 obj->serial.dma_chn_id_rx,
AnnaBridge 187:0387e8f68319 631 ((struct nu_uart_var *) modinit->var)->pdma_perp_rx, // Peripheral connected to this PDMA
AnnaBridge 187:0387e8f68319 632 0, // Scatter-gather disabled
AnnaBridge 187:0387e8f68319 633 0); // Scatter-gather descriptor address
AnnaBridge 187:0387e8f68319 634 PDMA_SetTransferCnt(pdma_base,
AnnaBridge 187:0387e8f68319 635 obj->serial.dma_chn_id_rx,
AnnaBridge 187:0387e8f68319 636 (rx_width == 8) ? PDMA_WIDTH_8 : (rx_width == 16) ? PDMA_WIDTH_16 : PDMA_WIDTH_32,
AnnaBridge 187:0387e8f68319 637 rx_length);
AnnaBridge 187:0387e8f68319 638 PDMA_SetTransferAddr(pdma_base,
AnnaBridge 187:0387e8f68319 639 obj->serial.dma_chn_id_rx,
AnnaBridge 187:0387e8f68319 640 (uint32_t) NU_MODBASE(obj->serial.uart), // Source address
AnnaBridge 187:0387e8f68319 641 PDMA_SAR_FIX, // Source address fixed
AnnaBridge 187:0387e8f68319 642 (uint32_t) rx, // NOTE:
AnnaBridge 187:0387e8f68319 643 // NUC472: End of destination address
AnnaBridge 187:0387e8f68319 644 // M451: Start of destination address
AnnaBridge 187:0387e8f68319 645 // M480: Start of destination address
AnnaBridge 187:0387e8f68319 646 // M2351: Start of destination address
AnnaBridge 187:0387e8f68319 647 PDMA_DAR_INC); // Destination address incremental
AnnaBridge 187:0387e8f68319 648 PDMA_SetBurstType(pdma_base,
AnnaBridge 187:0387e8f68319 649 obj->serial.dma_chn_id_rx,
AnnaBridge 187:0387e8f68319 650 PDMA_REQ_SINGLE, // Single mode
AnnaBridge 187:0387e8f68319 651 0); // Burst size
AnnaBridge 187:0387e8f68319 652 PDMA_EnableInt(pdma_base,
AnnaBridge 187:0387e8f68319 653 obj->serial.dma_chn_id_rx,
AnnaBridge 187:0387e8f68319 654 PDMA_INT_TRANS_DONE); // Interrupt type
AnnaBridge 187:0387e8f68319 655 // Register DMA event handler
AnnaBridge 187:0387e8f68319 656 dma_set_handler(obj->serial.dma_chn_id_rx, (uint32_t) uart_dma_handler_rx, (uint32_t) obj, DMA_EVENT_ALL);
AnnaBridge 187:0387e8f68319 657 serial_rx_enable_interrupt(obj, handler, 1);
AnnaBridge 187:0387e8f68319 658 /* We needn't actually enable UART INT to go UART ISR -> handler.
AnnaBridge 187:0387e8f68319 659 * Instead, as PDMA INT is triggered, we will go PDMA ISR -> UART ISR -> handler
AnnaBridge 187:0387e8f68319 660 * with serial_tx/rx_enable_interrupt having set up this call path. */
AnnaBridge 187:0387e8f68319 661 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 662 ((UART_T *) NU_MODBASE(obj->serial.uart))->INTEN |= UART_INTEN_RXPDMAEN_Msk; // Start DMA transfer
AnnaBridge 187:0387e8f68319 663 }
AnnaBridge 187:0387e8f68319 664 }
AnnaBridge 187:0387e8f68319 665
AnnaBridge 187:0387e8f68319 666 void serial_tx_abort_asynch(serial_t *obj)
AnnaBridge 187:0387e8f68319 667 {
AnnaBridge 187:0387e8f68319 668 // Flush Tx FIFO. Otherwise, output data may get lost on this change.
AnnaBridge 187:0387e8f68319 669 while (! UART_IS_TX_EMPTY((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 670
AnnaBridge 187:0387e8f68319 671 if (obj->serial.dma_usage_tx != DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 672 PDMA_T *pdma_base = dma_modbase();
AnnaBridge 187:0387e8f68319 673
AnnaBridge 187:0387e8f68319 674 if (obj->serial.dma_chn_id_tx != DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 675 PDMA_DisableInt(pdma_base, obj->serial.dma_chn_id_tx, PDMA_INT_TRANS_DONE);
AnnaBridge 187:0387e8f68319 676 // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown.
AnnaBridge 187:0387e8f68319 677 pdma_base->CHCTL &= ~(1 << obj->serial.dma_chn_id_tx);
AnnaBridge 187:0387e8f68319 678 }
AnnaBridge 187:0387e8f68319 679 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_TXPDMAEN_Msk);
AnnaBridge 187:0387e8f68319 680 }
AnnaBridge 187:0387e8f68319 681
AnnaBridge 187:0387e8f68319 682 // Necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 683 serial_enable_interrupt(obj, TxIrq, 0);
AnnaBridge 187:0387e8f68319 684 serial_rollback_interrupt(obj, TxIrq);
AnnaBridge 187:0387e8f68319 685 }
AnnaBridge 187:0387e8f68319 686
AnnaBridge 187:0387e8f68319 687 void serial_rx_abort_asynch(serial_t *obj)
AnnaBridge 187:0387e8f68319 688 {
AnnaBridge 187:0387e8f68319 689 if (obj->serial.dma_usage_rx != DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 690 PDMA_T *pdma_base = dma_modbase();
AnnaBridge 187:0387e8f68319 691
AnnaBridge 187:0387e8f68319 692 if (obj->serial.dma_chn_id_rx != DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 693 PDMA_DisableInt(pdma_base, obj->serial.dma_chn_id_rx, PDMA_INT_TRANS_DONE);
AnnaBridge 187:0387e8f68319 694 // NOTE: On NUC472, next PDMA transfer will fail with PDMA_STOP() called. Cause is unknown.
AnnaBridge 187:0387e8f68319 695 pdma_base->CHCTL &= ~(1 << obj->serial.dma_chn_id_rx);
AnnaBridge 187:0387e8f68319 696 }
AnnaBridge 187:0387e8f68319 697 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_RXPDMAEN_Msk);
AnnaBridge 187:0387e8f68319 698 }
AnnaBridge 187:0387e8f68319 699
AnnaBridge 187:0387e8f68319 700 // Necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 701 serial_enable_interrupt(obj, RxIrq, 0);
AnnaBridge 187:0387e8f68319 702 serial_rollback_interrupt(obj, RxIrq);
AnnaBridge 187:0387e8f68319 703 }
AnnaBridge 187:0387e8f68319 704
AnnaBridge 187:0387e8f68319 705 uint8_t serial_tx_active(serial_t *obj)
AnnaBridge 187:0387e8f68319 706 {
AnnaBridge 187:0387e8f68319 707 // NOTE: Judge by serial_is_irq_en(obj, TxIrq) doesn't work with sync/async modes interleaved. Change with TX FIFO empty flag.
AnnaBridge 187:0387e8f68319 708 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 709 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 710 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 711
AnnaBridge 187:0387e8f68319 712 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 713 return (obj->serial.vec == var->vec_async);
AnnaBridge 187:0387e8f68319 714 }
AnnaBridge 187:0387e8f68319 715
AnnaBridge 187:0387e8f68319 716 uint8_t serial_rx_active(serial_t *obj)
AnnaBridge 187:0387e8f68319 717 {
AnnaBridge 187:0387e8f68319 718 // NOTE: Judge by serial_is_irq_en(obj, RxIrq) doesn't work with sync/async modes interleaved. Change with RX FIFO empty flag.
AnnaBridge 187:0387e8f68319 719 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 720 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 721 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 722
AnnaBridge 187:0387e8f68319 723 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 724 return (obj->serial.vec == var->vec_async);
AnnaBridge 187:0387e8f68319 725 }
AnnaBridge 187:0387e8f68319 726
AnnaBridge 187:0387e8f68319 727 int serial_irq_handler_asynch(serial_t *obj)
AnnaBridge 187:0387e8f68319 728 {
AnnaBridge 187:0387e8f68319 729 int event_rx = 0;
AnnaBridge 187:0387e8f68319 730 int event_tx = 0;
AnnaBridge 187:0387e8f68319 731
AnnaBridge 187:0387e8f68319 732 // Necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 733 if (serial_is_irq_en(obj, RxIrq)) {
AnnaBridge 187:0387e8f68319 734 event_rx = serial_rx_event_check(obj);
AnnaBridge 187:0387e8f68319 735 if (event_rx) {
AnnaBridge 187:0387e8f68319 736 serial_rx_abort_asynch(obj);
AnnaBridge 187:0387e8f68319 737 }
AnnaBridge 187:0387e8f68319 738 }
AnnaBridge 187:0387e8f68319 739
AnnaBridge 187:0387e8f68319 740 if (serial_is_irq_en(obj, TxIrq)) {
AnnaBridge 187:0387e8f68319 741 event_tx = serial_tx_event_check(obj);
AnnaBridge 187:0387e8f68319 742 if (event_tx) {
AnnaBridge 187:0387e8f68319 743 serial_tx_abort_asynch(obj);
AnnaBridge 187:0387e8f68319 744 }
AnnaBridge 187:0387e8f68319 745 }
AnnaBridge 187:0387e8f68319 746
AnnaBridge 187:0387e8f68319 747 return (obj->serial.event & (event_rx | event_tx));
AnnaBridge 187:0387e8f68319 748 }
AnnaBridge 187:0387e8f68319 749
AnnaBridge 187:0387e8f68319 750 static void uart0_vec_async(void)
AnnaBridge 187:0387e8f68319 751 {
AnnaBridge 187:0387e8f68319 752 uart_irq_async(uart0_var.obj);
AnnaBridge 187:0387e8f68319 753 }
AnnaBridge 187:0387e8f68319 754
AnnaBridge 187:0387e8f68319 755 static void uart1_vec_async(void)
AnnaBridge 187:0387e8f68319 756 {
AnnaBridge 187:0387e8f68319 757 uart_irq_async(uart1_var.obj);
AnnaBridge 187:0387e8f68319 758 }
AnnaBridge 187:0387e8f68319 759
AnnaBridge 187:0387e8f68319 760 static void uart2_vec_async(void)
AnnaBridge 187:0387e8f68319 761 {
AnnaBridge 187:0387e8f68319 762 uart_irq_async(uart2_var.obj);
AnnaBridge 187:0387e8f68319 763 }
AnnaBridge 187:0387e8f68319 764
AnnaBridge 187:0387e8f68319 765 static void uart3_vec_async(void)
AnnaBridge 187:0387e8f68319 766 {
AnnaBridge 187:0387e8f68319 767 uart_irq_async(uart3_var.obj);
AnnaBridge 187:0387e8f68319 768 }
AnnaBridge 187:0387e8f68319 769
AnnaBridge 187:0387e8f68319 770 static void uart4_vec_async(void)
AnnaBridge 187:0387e8f68319 771 {
AnnaBridge 187:0387e8f68319 772 uart_irq_async(uart4_var.obj);
AnnaBridge 187:0387e8f68319 773 }
AnnaBridge 187:0387e8f68319 774
AnnaBridge 187:0387e8f68319 775 static void uart5_vec_async(void)
AnnaBridge 187:0387e8f68319 776 {
AnnaBridge 187:0387e8f68319 777 uart_irq_async(uart5_var.obj);
AnnaBridge 187:0387e8f68319 778 }
AnnaBridge 187:0387e8f68319 779
AnnaBridge 187:0387e8f68319 780 static void uart_irq_async(serial_t *obj)
AnnaBridge 187:0387e8f68319 781 {
AnnaBridge 187:0387e8f68319 782 if (serial_is_irq_en(obj, RxIrq)) {
AnnaBridge 187:0387e8f68319 783 (*obj->serial.irq_handler_rx_async)();
AnnaBridge 187:0387e8f68319 784 }
AnnaBridge 187:0387e8f68319 785 if (serial_is_irq_en(obj, TxIrq)) {
AnnaBridge 187:0387e8f68319 786 (*obj->serial.irq_handler_tx_async)();
AnnaBridge 187:0387e8f68319 787 }
AnnaBridge 187:0387e8f68319 788 }
AnnaBridge 187:0387e8f68319 789
AnnaBridge 187:0387e8f68319 790 static void serial_rx_set_char_match(serial_t *obj, uint8_t char_match)
AnnaBridge 187:0387e8f68319 791 {
AnnaBridge 187:0387e8f68319 792 obj->char_match = char_match;
AnnaBridge 187:0387e8f68319 793 obj->char_found = 0;
AnnaBridge 187:0387e8f68319 794 }
AnnaBridge 187:0387e8f68319 795
AnnaBridge 187:0387e8f68319 796 static void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable)
AnnaBridge 187:0387e8f68319 797 {
AnnaBridge 187:0387e8f68319 798 obj->serial.event &= ~SERIAL_EVENT_TX_MASK;
AnnaBridge 187:0387e8f68319 799 obj->serial.event |= (event & SERIAL_EVENT_TX_MASK);
AnnaBridge 187:0387e8f68319 800
AnnaBridge 187:0387e8f68319 801 if (event & SERIAL_EVENT_TX_COMPLETE) {
AnnaBridge 187:0387e8f68319 802 // N/A
AnnaBridge 187:0387e8f68319 803 }
AnnaBridge 187:0387e8f68319 804 }
AnnaBridge 187:0387e8f68319 805
AnnaBridge 187:0387e8f68319 806 static void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
AnnaBridge 187:0387e8f68319 807 {
AnnaBridge 187:0387e8f68319 808 obj->serial.event &= ~SERIAL_EVENT_RX_MASK;
AnnaBridge 187:0387e8f68319 809 obj->serial.event |= (event & SERIAL_EVENT_RX_MASK);
AnnaBridge 187:0387e8f68319 810
AnnaBridge 187:0387e8f68319 811 if (event & SERIAL_EVENT_RX_COMPLETE) {
AnnaBridge 187:0387e8f68319 812 // N/A
AnnaBridge 187:0387e8f68319 813 }
AnnaBridge 187:0387e8f68319 814 if (event & SERIAL_EVENT_RX_OVERRUN_ERROR) {
AnnaBridge 187:0387e8f68319 815 // N/A
AnnaBridge 187:0387e8f68319 816 }
AnnaBridge 187:0387e8f68319 817 if (event & SERIAL_EVENT_RX_FRAMING_ERROR) {
AnnaBridge 187:0387e8f68319 818 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_RLSIEN_Msk);
AnnaBridge 187:0387e8f68319 819 }
AnnaBridge 187:0387e8f68319 820 if (event & SERIAL_EVENT_RX_PARITY_ERROR) {
AnnaBridge 187:0387e8f68319 821 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_RLSIEN_Msk);
AnnaBridge 187:0387e8f68319 822 }
AnnaBridge 187:0387e8f68319 823 if (event & SERIAL_EVENT_RX_OVERFLOW) {
AnnaBridge 187:0387e8f68319 824 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_BUFERRIEN_Msk);
AnnaBridge 187:0387e8f68319 825 }
AnnaBridge 187:0387e8f68319 826 if (event & SERIAL_EVENT_RX_CHARACTER_MATCH) {
AnnaBridge 187:0387e8f68319 827 // N/A
AnnaBridge 187:0387e8f68319 828 }
AnnaBridge 187:0387e8f68319 829 }
AnnaBridge 187:0387e8f68319 830
AnnaBridge 187:0387e8f68319 831 static int serial_is_tx_complete(serial_t *obj)
AnnaBridge 187:0387e8f68319 832 {
AnnaBridge 187:0387e8f68319 833 // NOTE: Exclude tx fifo empty check due to no such interrupt on DMA way
AnnaBridge 187:0387e8f68319 834 return (obj->tx_buff.pos == obj->tx_buff.length);
AnnaBridge 187:0387e8f68319 835 }
AnnaBridge 187:0387e8f68319 836
AnnaBridge 187:0387e8f68319 837 static int serial_is_rx_complete(serial_t *obj)
AnnaBridge 187:0387e8f68319 838 {
AnnaBridge 187:0387e8f68319 839 return (obj->rx_buff.pos == obj->rx_buff.length);
AnnaBridge 187:0387e8f68319 840 }
AnnaBridge 187:0387e8f68319 841
AnnaBridge 187:0387e8f68319 842 static uint32_t serial_tx_event_check(serial_t *obj)
AnnaBridge 187:0387e8f68319 843 {
AnnaBridge 187:0387e8f68319 844 UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
AnnaBridge 187:0387e8f68319 845
AnnaBridge 187:0387e8f68319 846 if (uart_base->INTSTS & UART_INTSTS_THREINT_Msk) {
AnnaBridge 187:0387e8f68319 847 // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next write.
AnnaBridge 187:0387e8f68319 848 UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 849 }
AnnaBridge 187:0387e8f68319 850
AnnaBridge 187:0387e8f68319 851 uint32_t event = 0;
AnnaBridge 187:0387e8f68319 852
AnnaBridge 187:0387e8f68319 853 if (obj->serial.dma_usage_tx == DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 854 serial_write_async(obj);
AnnaBridge 187:0387e8f68319 855 }
AnnaBridge 187:0387e8f68319 856
AnnaBridge 187:0387e8f68319 857 if (serial_is_tx_complete(obj)) {
AnnaBridge 187:0387e8f68319 858 event |= SERIAL_EVENT_TX_COMPLETE;
AnnaBridge 187:0387e8f68319 859 }
AnnaBridge 187:0387e8f68319 860
AnnaBridge 187:0387e8f68319 861 return event;
AnnaBridge 187:0387e8f68319 862 }
AnnaBridge 187:0387e8f68319 863
AnnaBridge 187:0387e8f68319 864 static uint32_t serial_rx_event_check(serial_t *obj)
AnnaBridge 187:0387e8f68319 865 {
AnnaBridge 187:0387e8f68319 866 UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
AnnaBridge 187:0387e8f68319 867
AnnaBridge 187:0387e8f68319 868 if (uart_base->INTSTS & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) {
AnnaBridge 187:0387e8f68319 869 // Simulate clear of the interrupt flag. Temporarily disable the interrupt here and to be recovered on next read.
AnnaBridge 187:0387e8f68319 870 UART_DISABLE_INT(uart_base, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 871 }
AnnaBridge 187:0387e8f68319 872
AnnaBridge 187:0387e8f68319 873 uint32_t event = 0;
AnnaBridge 187:0387e8f68319 874
AnnaBridge 187:0387e8f68319 875 if (uart_base->FIFOSTS & UART_FIFOSTS_BIF_Msk) {
AnnaBridge 187:0387e8f68319 876 uart_base->FIFOSTS = UART_FIFOSTS_BIF_Msk;
AnnaBridge 187:0387e8f68319 877 }
AnnaBridge 187:0387e8f68319 878 if (uart_base->FIFOSTS & UART_FIFOSTS_FEF_Msk) {
AnnaBridge 187:0387e8f68319 879 uart_base->FIFOSTS = UART_FIFOSTS_FEF_Msk;
AnnaBridge 187:0387e8f68319 880 event |= SERIAL_EVENT_RX_FRAMING_ERROR;
AnnaBridge 187:0387e8f68319 881 }
AnnaBridge 187:0387e8f68319 882 if (uart_base->FIFOSTS & UART_FIFOSTS_PEF_Msk) {
AnnaBridge 187:0387e8f68319 883 uart_base->FIFOSTS = UART_FIFOSTS_PEF_Msk;
AnnaBridge 187:0387e8f68319 884 event |= SERIAL_EVENT_RX_PARITY_ERROR;
AnnaBridge 187:0387e8f68319 885 }
AnnaBridge 187:0387e8f68319 886
AnnaBridge 187:0387e8f68319 887 if (uart_base->FIFOSTS & UART_FIFOSTS_RXOVIF_Msk) {
AnnaBridge 187:0387e8f68319 888 uart_base->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk;
AnnaBridge 187:0387e8f68319 889 event |= SERIAL_EVENT_RX_OVERFLOW;
AnnaBridge 187:0387e8f68319 890 }
AnnaBridge 187:0387e8f68319 891
AnnaBridge 187:0387e8f68319 892 if (obj->serial.dma_usage_rx == DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 893 serial_read_async(obj);
AnnaBridge 187:0387e8f68319 894 }
AnnaBridge 187:0387e8f68319 895
AnnaBridge 187:0387e8f68319 896 if (serial_is_rx_complete(obj)) {
AnnaBridge 187:0387e8f68319 897 event |= SERIAL_EVENT_RX_COMPLETE;
AnnaBridge 187:0387e8f68319 898 }
AnnaBridge 187:0387e8f68319 899 if ((obj->char_match != SERIAL_RESERVED_CHAR_MATCH) && obj->char_found) {
AnnaBridge 187:0387e8f68319 900 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
AnnaBridge 187:0387e8f68319 901 }
AnnaBridge 187:0387e8f68319 902
AnnaBridge 187:0387e8f68319 903 return event;
AnnaBridge 187:0387e8f68319 904 }
AnnaBridge 187:0387e8f68319 905
AnnaBridge 187:0387e8f68319 906 static void uart_dma_handler_tx(uint32_t id, uint32_t event_dma)
AnnaBridge 187:0387e8f68319 907 {
AnnaBridge 187:0387e8f68319 908 serial_t *obj = (serial_t *) id;
AnnaBridge 187:0387e8f68319 909
AnnaBridge 187:0387e8f68319 910 // FIXME: Pass this error to caller
AnnaBridge 187:0387e8f68319 911 if (event_dma & DMA_EVENT_ABORT) {
AnnaBridge 187:0387e8f68319 912 }
AnnaBridge 187:0387e8f68319 913 // Expect UART IRQ will catch this transfer done event
AnnaBridge 187:0387e8f68319 914 if (event_dma & DMA_EVENT_TRANSFER_DONE) {
AnnaBridge 187:0387e8f68319 915 obj->tx_buff.pos = obj->tx_buff.length;
AnnaBridge 187:0387e8f68319 916 }
AnnaBridge 187:0387e8f68319 917 // FIXME: Pass this error to caller
AnnaBridge 187:0387e8f68319 918 if (event_dma & DMA_EVENT_TIMEOUT) {
AnnaBridge 187:0387e8f68319 919 }
AnnaBridge 187:0387e8f68319 920
AnnaBridge 187:0387e8f68319 921 uart_irq_async(obj);
AnnaBridge 187:0387e8f68319 922 }
AnnaBridge 187:0387e8f68319 923
AnnaBridge 187:0387e8f68319 924 static void uart_dma_handler_rx(uint32_t id, uint32_t event_dma)
AnnaBridge 187:0387e8f68319 925 {
AnnaBridge 187:0387e8f68319 926 serial_t *obj = (serial_t *) id;
AnnaBridge 187:0387e8f68319 927
AnnaBridge 187:0387e8f68319 928 // FIXME: Pass this error to caller
AnnaBridge 187:0387e8f68319 929 if (event_dma & DMA_EVENT_ABORT) {
AnnaBridge 187:0387e8f68319 930 }
AnnaBridge 187:0387e8f68319 931 // Expect UART IRQ will catch this transfer done event
AnnaBridge 187:0387e8f68319 932 if (event_dma & DMA_EVENT_TRANSFER_DONE) {
AnnaBridge 187:0387e8f68319 933 obj->rx_buff.pos = obj->rx_buff.length;
AnnaBridge 187:0387e8f68319 934 }
AnnaBridge 187:0387e8f68319 935 // FIXME: Pass this error to caller
AnnaBridge 187:0387e8f68319 936 if (event_dma & DMA_EVENT_TIMEOUT) {
AnnaBridge 187:0387e8f68319 937 }
AnnaBridge 187:0387e8f68319 938
AnnaBridge 187:0387e8f68319 939 uart_irq_async(obj);
AnnaBridge 187:0387e8f68319 940 }
AnnaBridge 187:0387e8f68319 941
AnnaBridge 187:0387e8f68319 942 static int serial_write_async(serial_t *obj)
AnnaBridge 187:0387e8f68319 943 {
AnnaBridge 187:0387e8f68319 944 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 945 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 946 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 947
AnnaBridge 187:0387e8f68319 948 UART_T *uart_base = (UART_T *) NU_MODBASE(obj->serial.uart);
AnnaBridge 187:0387e8f68319 949
AnnaBridge 187:0387e8f68319 950 uint32_t tx_fifo_max = ((struct nu_uart_var *) modinit->var)->fifo_size_tx;
AnnaBridge 187:0387e8f68319 951 uint32_t tx_fifo_busy = (uart_base->FIFOSTS & UART_FIFOSTS_TXPTR_Msk) >> UART_FIFOSTS_TXPTR_Pos;
AnnaBridge 187:0387e8f68319 952 if (uart_base->FIFOSTS & UART_FIFOSTS_TXFULL_Msk) {
AnnaBridge 187:0387e8f68319 953 tx_fifo_busy = tx_fifo_max;
AnnaBridge 187:0387e8f68319 954 }
AnnaBridge 187:0387e8f68319 955 uint32_t tx_fifo_free = tx_fifo_max - tx_fifo_busy;
AnnaBridge 187:0387e8f68319 956 if (tx_fifo_free == 0) {
AnnaBridge 187:0387e8f68319 957 // Simulate clear of the interrupt flag
AnnaBridge 187:0387e8f68319 958 if (obj->serial.inten_msk & UART_INTEN_THREIEN_Msk) {
AnnaBridge 187:0387e8f68319 959 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 960 }
AnnaBridge 187:0387e8f68319 961 return 0;
AnnaBridge 187:0387e8f68319 962 }
AnnaBridge 187:0387e8f68319 963
AnnaBridge 187:0387e8f68319 964 uint32_t bytes_per_word = obj->tx_buff.width / 8;
AnnaBridge 187:0387e8f68319 965
AnnaBridge 187:0387e8f68319 966 uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer) + bytes_per_word * obj->tx_buff.pos;
AnnaBridge 187:0387e8f68319 967 int n_words = 0;
AnnaBridge 187:0387e8f68319 968 while (obj->tx_buff.pos < obj->tx_buff.length && tx_fifo_free >= bytes_per_word) {
AnnaBridge 187:0387e8f68319 969 switch (bytes_per_word) {
AnnaBridge 187:0387e8f68319 970 case 4:
AnnaBridge 187:0387e8f68319 971 UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++);
AnnaBridge 187:0387e8f68319 972 UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++);
AnnaBridge 187:0387e8f68319 973 case 2:
AnnaBridge 187:0387e8f68319 974 UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++);
AnnaBridge 187:0387e8f68319 975 case 1:
AnnaBridge 187:0387e8f68319 976 UART_WRITE(((UART_T *) NU_MODBASE(obj->serial.uart)), *tx ++);
AnnaBridge 187:0387e8f68319 977 }
AnnaBridge 187:0387e8f68319 978
AnnaBridge 187:0387e8f68319 979 n_words ++;
AnnaBridge 187:0387e8f68319 980 tx_fifo_free -= bytes_per_word;
AnnaBridge 187:0387e8f68319 981 obj->tx_buff.pos ++;
AnnaBridge 187:0387e8f68319 982 }
AnnaBridge 187:0387e8f68319 983
AnnaBridge 187:0387e8f68319 984 if (n_words) {
AnnaBridge 187:0387e8f68319 985 // Simulate clear of the interrupt flag
AnnaBridge 187:0387e8f68319 986 if (obj->serial.inten_msk & UART_INTEN_THREIEN_Msk) {
AnnaBridge 187:0387e8f68319 987 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 988 }
AnnaBridge 187:0387e8f68319 989 }
AnnaBridge 187:0387e8f68319 990
AnnaBridge 187:0387e8f68319 991 return n_words;
AnnaBridge 187:0387e8f68319 992 }
AnnaBridge 187:0387e8f68319 993
AnnaBridge 187:0387e8f68319 994 static int serial_read_async(serial_t *obj)
AnnaBridge 187:0387e8f68319 995 {
AnnaBridge 187:0387e8f68319 996 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 997 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 998 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 999
AnnaBridge 187:0387e8f68319 1000 uint32_t rx_fifo_busy = (((UART_T *) NU_MODBASE(obj->serial.uart))->FIFOSTS & UART_FIFOSTS_RXPTR_Msk) >> UART_FIFOSTS_RXPTR_Pos;
AnnaBridge 187:0387e8f68319 1001
AnnaBridge 187:0387e8f68319 1002 uint32_t bytes_per_word = obj->rx_buff.width / 8;
AnnaBridge 187:0387e8f68319 1003
AnnaBridge 187:0387e8f68319 1004 uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer) + bytes_per_word * obj->rx_buff.pos;
AnnaBridge 187:0387e8f68319 1005 int n_words = 0;
AnnaBridge 187:0387e8f68319 1006 while (obj->rx_buff.pos < obj->rx_buff.length && rx_fifo_busy >= bytes_per_word) {
AnnaBridge 187:0387e8f68319 1007 switch (bytes_per_word) {
AnnaBridge 187:0387e8f68319 1008 case 4:
AnnaBridge 187:0387e8f68319 1009 *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 1010 *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 1011 case 2:
AnnaBridge 187:0387e8f68319 1012 *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 1013 case 1:
AnnaBridge 187:0387e8f68319 1014 *rx ++ = UART_READ(((UART_T *) NU_MODBASE(obj->serial.uart)));
AnnaBridge 187:0387e8f68319 1015 }
AnnaBridge 187:0387e8f68319 1016
AnnaBridge 187:0387e8f68319 1017 n_words ++;
AnnaBridge 187:0387e8f68319 1018 rx_fifo_busy -= bytes_per_word;
AnnaBridge 187:0387e8f68319 1019 obj->rx_buff.pos ++;
AnnaBridge 187:0387e8f68319 1020
AnnaBridge 187:0387e8f68319 1021 if ((obj->serial.event & SERIAL_EVENT_RX_CHARACTER_MATCH) &&
AnnaBridge 187:0387e8f68319 1022 obj->char_match != SERIAL_RESERVED_CHAR_MATCH) {
AnnaBridge 187:0387e8f68319 1023 uint8_t *rx_cmp = rx;
AnnaBridge 187:0387e8f68319 1024 switch (bytes_per_word) {
AnnaBridge 187:0387e8f68319 1025 case 4:
AnnaBridge 187:0387e8f68319 1026 rx_cmp -= 2;
AnnaBridge 187:0387e8f68319 1027 case 2:
AnnaBridge 187:0387e8f68319 1028 rx_cmp --;
AnnaBridge 187:0387e8f68319 1029 case 1:
AnnaBridge 187:0387e8f68319 1030 rx_cmp --;
AnnaBridge 187:0387e8f68319 1031 }
AnnaBridge 187:0387e8f68319 1032 if (*rx_cmp == obj->char_match) {
AnnaBridge 187:0387e8f68319 1033 obj->char_found = 1;
AnnaBridge 187:0387e8f68319 1034 break;
AnnaBridge 187:0387e8f68319 1035 }
AnnaBridge 187:0387e8f68319 1036 }
AnnaBridge 187:0387e8f68319 1037 }
AnnaBridge 187:0387e8f68319 1038
AnnaBridge 187:0387e8f68319 1039 if (n_words) {
AnnaBridge 187:0387e8f68319 1040 // Simulate clear of the interrupt flag
AnnaBridge 187:0387e8f68319 1041 if (obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)) {
AnnaBridge 187:0387e8f68319 1042 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 1043 }
AnnaBridge 187:0387e8f68319 1044 }
AnnaBridge 187:0387e8f68319 1045
AnnaBridge 187:0387e8f68319 1046 return n_words;
AnnaBridge 187:0387e8f68319 1047 }
AnnaBridge 187:0387e8f68319 1048
AnnaBridge 187:0387e8f68319 1049 static void serial_tx_buffer_set(serial_t *obj, const void *tx, size_t length, uint8_t width)
AnnaBridge 187:0387e8f68319 1050 {
AnnaBridge 187:0387e8f68319 1051 obj->tx_buff.buffer = (void *) tx;
AnnaBridge 187:0387e8f68319 1052 obj->tx_buff.length = length;
AnnaBridge 187:0387e8f68319 1053 obj->tx_buff.pos = 0;
AnnaBridge 187:0387e8f68319 1054 obj->tx_buff.width = width;
AnnaBridge 187:0387e8f68319 1055 }
AnnaBridge 187:0387e8f68319 1056
AnnaBridge 187:0387e8f68319 1057 static void serial_rx_buffer_set(serial_t *obj, void *rx, size_t length, uint8_t width)
AnnaBridge 187:0387e8f68319 1058 {
AnnaBridge 187:0387e8f68319 1059 obj->rx_buff.buffer = rx;
AnnaBridge 187:0387e8f68319 1060 obj->rx_buff.length = length;
AnnaBridge 187:0387e8f68319 1061 obj->rx_buff.pos = 0;
AnnaBridge 187:0387e8f68319 1062 obj->rx_buff.width = width;
AnnaBridge 187:0387e8f68319 1063 }
AnnaBridge 187:0387e8f68319 1064
AnnaBridge 187:0387e8f68319 1065 static void serial_tx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t enable)
AnnaBridge 187:0387e8f68319 1066 {
AnnaBridge 187:0387e8f68319 1067 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 1068 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 1069 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 1070
AnnaBridge 187:0387e8f68319 1071 // Necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 1072 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 1073 // With our own async vector, tx/rx handlers can be different.
AnnaBridge 187:0387e8f68319 1074 obj->serial.vec = var->vec_async;
AnnaBridge 187:0387e8f68319 1075 obj->serial.irq_handler_tx_async = (void (*)(void)) handler;
AnnaBridge 187:0387e8f68319 1076 serial_enable_interrupt(obj, TxIrq, enable);
AnnaBridge 187:0387e8f68319 1077 }
AnnaBridge 187:0387e8f68319 1078
AnnaBridge 187:0387e8f68319 1079 static void serial_rx_enable_interrupt(serial_t *obj, uint32_t handler, uint8_t enable)
AnnaBridge 187:0387e8f68319 1080 {
AnnaBridge 187:0387e8f68319 1081 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 1082 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 1083 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 1084
AnnaBridge 187:0387e8f68319 1085 // Necessary for both interrupt way and DMA way
AnnaBridge 187:0387e8f68319 1086 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 1087 // With our own async vector, tx/rx handlers can be different.
AnnaBridge 187:0387e8f68319 1088 obj->serial.vec = var->vec_async;
AnnaBridge 187:0387e8f68319 1089 obj->serial.irq_handler_rx_async = (void (*) (void)) handler;
AnnaBridge 187:0387e8f68319 1090 serial_enable_interrupt(obj, RxIrq, enable);
AnnaBridge 187:0387e8f68319 1091 }
AnnaBridge 187:0387e8f68319 1092
AnnaBridge 187:0387e8f68319 1093 static void serial_enable_interrupt(serial_t *obj, SerialIrq irq, uint32_t enable)
AnnaBridge 187:0387e8f68319 1094 {
AnnaBridge 187:0387e8f68319 1095 if (enable) {
AnnaBridge 187:0387e8f68319 1096 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 1097 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 1098 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 1099
AnnaBridge 187:0387e8f68319 1100 NVIC_SetVector(modinit->irq_n, (uint32_t) obj->serial.vec);
AnnaBridge 187:0387e8f68319 1101 NVIC_EnableIRQ(modinit->irq_n);
AnnaBridge 187:0387e8f68319 1102
AnnaBridge 187:0387e8f68319 1103 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 1104 // Multiple serial S/W objects for single UART H/W module possibly.
AnnaBridge 187:0387e8f68319 1105 // Bind serial S/W object to UART H/W module as interrupt is enabled.
AnnaBridge 187:0387e8f68319 1106 var->obj = obj;
AnnaBridge 187:0387e8f68319 1107
AnnaBridge 187:0387e8f68319 1108 switch (irq) {
AnnaBridge 187:0387e8f68319 1109 // NOTE: Setting inten_msk first to avoid race condition
AnnaBridge 187:0387e8f68319 1110 case RxIrq:
AnnaBridge 187:0387e8f68319 1111 obj->serial.inten_msk = obj->serial.inten_msk | (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk);
AnnaBridge 187:0387e8f68319 1112 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 1113 break;
AnnaBridge 187:0387e8f68319 1114 case TxIrq:
AnnaBridge 187:0387e8f68319 1115 obj->serial.inten_msk = obj->serial.inten_msk | UART_INTEN_THREIEN_Msk;
AnnaBridge 187:0387e8f68319 1116 UART_ENABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 1117 break;
AnnaBridge 187:0387e8f68319 1118 }
AnnaBridge 187:0387e8f68319 1119 } else { // disable
AnnaBridge 187:0387e8f68319 1120 switch (irq) {
AnnaBridge 187:0387e8f68319 1121 case RxIrq:
AnnaBridge 187:0387e8f68319 1122 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
AnnaBridge 187:0387e8f68319 1123 obj->serial.inten_msk = obj->serial.inten_msk & ~(UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk);
AnnaBridge 187:0387e8f68319 1124 break;
AnnaBridge 187:0387e8f68319 1125 case TxIrq:
AnnaBridge 187:0387e8f68319 1126 UART_DISABLE_INT(((UART_T *) NU_MODBASE(obj->serial.uart)), UART_INTEN_THREIEN_Msk);
AnnaBridge 187:0387e8f68319 1127 obj->serial.inten_msk = obj->serial.inten_msk & ~UART_INTEN_THREIEN_Msk;
AnnaBridge 187:0387e8f68319 1128 break;
AnnaBridge 187:0387e8f68319 1129 }
AnnaBridge 187:0387e8f68319 1130 }
AnnaBridge 187:0387e8f68319 1131 }
AnnaBridge 187:0387e8f68319 1132
AnnaBridge 187:0387e8f68319 1133 static void serial_rollback_interrupt(serial_t *obj, SerialIrq irq)
AnnaBridge 187:0387e8f68319 1134 {
AnnaBridge 187:0387e8f68319 1135 const struct nu_modinit_s *modinit = get_modinit(obj->serial.uart, uart_modinit_tab);
AnnaBridge 187:0387e8f68319 1136 MBED_ASSERT(modinit != NULL);
AnnaBridge 187:0387e8f68319 1137 MBED_ASSERT(modinit->modname == (int) obj->serial.uart);
AnnaBridge 187:0387e8f68319 1138
AnnaBridge 187:0387e8f68319 1139 struct nu_uart_var *var = (struct nu_uart_var *) modinit->var;
AnnaBridge 187:0387e8f68319 1140
AnnaBridge 187:0387e8f68319 1141 obj->serial.vec = var->vec;
AnnaBridge 187:0387e8f68319 1142 serial_enable_interrupt(obj, irq, obj->serial.irq_en);
AnnaBridge 187:0387e8f68319 1143 }
AnnaBridge 187:0387e8f68319 1144
AnnaBridge 187:0387e8f68319 1145 static void serial_check_dma_usage(DMAUsage *dma_usage, int *dma_ch)
AnnaBridge 187:0387e8f68319 1146 {
AnnaBridge 187:0387e8f68319 1147 if (*dma_usage != DMA_USAGE_NEVER) {
AnnaBridge 187:0387e8f68319 1148 if (*dma_ch == DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 1149 *dma_ch = dma_channel_allocate(DMA_CAP_NONE);
AnnaBridge 187:0387e8f68319 1150 }
AnnaBridge 187:0387e8f68319 1151 if (*dma_ch == DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 1152 *dma_usage = DMA_USAGE_NEVER;
AnnaBridge 187:0387e8f68319 1153 }
AnnaBridge 187:0387e8f68319 1154 } else {
AnnaBridge 187:0387e8f68319 1155 dma_channel_free(*dma_ch);
AnnaBridge 187:0387e8f68319 1156 *dma_ch = DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 1157 }
AnnaBridge 187:0387e8f68319 1158 }
AnnaBridge 187:0387e8f68319 1159
AnnaBridge 187:0387e8f68319 1160 static int serial_is_irq_en(serial_t *obj, SerialIrq irq)
AnnaBridge 187:0387e8f68319 1161 {
AnnaBridge 187:0387e8f68319 1162 int inten_msk = 0;
AnnaBridge 187:0387e8f68319 1163
AnnaBridge 187:0387e8f68319 1164 switch (irq) {
AnnaBridge 187:0387e8f68319 1165 case RxIrq:
AnnaBridge 187:0387e8f68319 1166 inten_msk = obj->serial.inten_msk & (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk);
AnnaBridge 187:0387e8f68319 1167 break;
AnnaBridge 187:0387e8f68319 1168 case TxIrq:
AnnaBridge 187:0387e8f68319 1169 inten_msk = obj->serial.inten_msk & UART_INTEN_THREIEN_Msk;
AnnaBridge 187:0387e8f68319 1170 break;
AnnaBridge 187:0387e8f68319 1171 }
AnnaBridge 187:0387e8f68319 1172
AnnaBridge 187:0387e8f68319 1173 return !! inten_msk;
AnnaBridge 187:0387e8f68319 1174 }
AnnaBridge 187:0387e8f68319 1175
AnnaBridge 187:0387e8f68319 1176 #endif // #if DEVICE_SERIAL_ASYNCH
AnnaBridge 188:bcfe06ba3d64 1177
AnnaBridge 188:bcfe06ba3d64 1178 bool serial_can_deep_sleep(void)
AnnaBridge 188:bcfe06ba3d64 1179 {
AnnaBridge 188:bcfe06ba3d64 1180 bool sleep_allowed = 1;
AnnaBridge 188:bcfe06ba3d64 1181 const struct nu_modinit_s *modinit = uart_modinit_tab;
AnnaBridge 188:bcfe06ba3d64 1182 while (modinit->var != NULL) {
AnnaBridge 188:bcfe06ba3d64 1183 struct nu_uart_var *uart_var = (struct nu_uart_var *) modinit->var;
AnnaBridge 188:bcfe06ba3d64 1184 UART_T *uart_base = (UART_T *) NU_MODBASE(modinit->modname);
AnnaBridge 188:bcfe06ba3d64 1185 if (uart_var->ref_cnt > 0) {
AnnaBridge 188:bcfe06ba3d64 1186 if (!UART_IS_TX_EMPTY(uart_base)) {
AnnaBridge 188:bcfe06ba3d64 1187 sleep_allowed = 0;
AnnaBridge 188:bcfe06ba3d64 1188 break;
AnnaBridge 188:bcfe06ba3d64 1189 }
AnnaBridge 188:bcfe06ba3d64 1190 }
AnnaBridge 188:bcfe06ba3d64 1191 modinit++;
AnnaBridge 188:bcfe06ba3d64 1192 }
AnnaBridge 188:bcfe06ba3d64 1193 return sleep_allowed;
AnnaBridge 188:bcfe06ba3d64 1194 }
AnnaBridge 188:bcfe06ba3d64 1195
AnnaBridge 187:0387e8f68319 1196 #endif // #if DEVICE_SERIAL