mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Thu Sep 06 13:40:20 2018 +0100
Revision:
187:0387e8f68319
Child:
188:bcfe06ba3d64
mbed-dev library. Release version 163

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