added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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