mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

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