mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Thu Dec 07 14:01:42 2017 +0000
Revision:
179:b0033dcd6934
Parent:
150:02e0a0aed4ec
Child:
180:96ed750bd169
mbed-dev library. Release version 157

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /***************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file serial_api.c
<> 144:ef7eb2e8f9f7 3 *******************************************************************************
<> 144:ef7eb2e8f9f7 4 * @section License
<> 144:ef7eb2e8f9f7 5 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
<> 144:ef7eb2e8f9f7 6 *******************************************************************************
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * SPDX-License-Identifier: Apache-2.0
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
<> 144:ef7eb2e8f9f7 11 * not use this file except in compliance with the License.
<> 144:ef7eb2e8f9f7 12 * You may obtain a copy of the License at
<> 144:ef7eb2e8f9f7 13 *
<> 144:ef7eb2e8f9f7 14 * http://www.apache.org/licenses/LICENSE-2.0
<> 144:ef7eb2e8f9f7 15 *
<> 144:ef7eb2e8f9f7 16 * Unless required by applicable law or agreed to in writing, software
<> 144:ef7eb2e8f9f7 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
<> 144:ef7eb2e8f9f7 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 144:ef7eb2e8f9f7 19 * See the License for the specific language governing permissions and
<> 144:ef7eb2e8f9f7 20 * limitations under the License.
<> 144:ef7eb2e8f9f7 21 *
<> 144:ef7eb2e8f9f7 22 ******************************************************************************/
<> 144:ef7eb2e8f9f7 23
<> 144:ef7eb2e8f9f7 24 #include "device.h"
<> 144:ef7eb2e8f9f7 25 #include "clocking.h"
<> 144:ef7eb2e8f9f7 26 #if DEVICE_SERIAL
<> 144:ef7eb2e8f9f7 27
<> 144:ef7eb2e8f9f7 28 #include "mbed_assert.h"
<> 144:ef7eb2e8f9f7 29 #include "serial_api.h"
<> 144:ef7eb2e8f9f7 30 #include "serial_api_HAL.h"
<> 144:ef7eb2e8f9f7 31 #include <string.h>
<> 144:ef7eb2e8f9f7 32 #include <stdbool.h>
<> 144:ef7eb2e8f9f7 33
<> 144:ef7eb2e8f9f7 34 #include "pinmap.h"
<> 144:ef7eb2e8f9f7 35 #include "pinmap_function.h"
<> 144:ef7eb2e8f9f7 36 #include "PeripheralPins.h"
<> 144:ef7eb2e8f9f7 37 #include "PeripheralNames.h"
<> 144:ef7eb2e8f9f7 38
<> 144:ef7eb2e8f9f7 39 #include "em_usart.h"
<> 144:ef7eb2e8f9f7 40 #include "em_leuart.h"
<> 144:ef7eb2e8f9f7 41 #include "em_cmu.h"
<> 144:ef7eb2e8f9f7 42 #include "em_dma.h"
<> 144:ef7eb2e8f9f7 43 #include "dma_api_HAL.h"
<> 144:ef7eb2e8f9f7 44 #include "dma_api.h"
<> 144:ef7eb2e8f9f7 45 #include "sleep_api.h"
<> 144:ef7eb2e8f9f7 46 #include "buffer.h"
<> 144:ef7eb2e8f9f7 47 #include "sleepmodes.h"
<> 144:ef7eb2e8f9f7 48
<> 144:ef7eb2e8f9f7 49 #define SERIAL_LEAST_ACTIVE_SLEEPMODE EM1
<> 144:ef7eb2e8f9f7 50 #define SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART EM2
<> 144:ef7eb2e8f9f7 51
<> 144:ef7eb2e8f9f7 52 /** Validation of LEUART register block pointer reference
<> 144:ef7eb2e8f9f7 53 * for assert statements. */
<> 144:ef7eb2e8f9f7 54 #if !defined(LEUART_COUNT)
<> 144:ef7eb2e8f9f7 55 #define LEUART_REF_VALID(ref) (0)
<> 144:ef7eb2e8f9f7 56 #elif (LEUART_COUNT == 1)
<> 144:ef7eb2e8f9f7 57 #define LEUART_REF_VALID(ref) ((ref) == LEUART0)
<> 144:ef7eb2e8f9f7 58 #elif (LEUART_COUNT == 2)
<> 144:ef7eb2e8f9f7 59 #define LEUART_REF_VALID(ref) (((ref) == LEUART0) || ((ref) == LEUART1))
<> 144:ef7eb2e8f9f7 60 #else
<> 144:ef7eb2e8f9f7 61 #error Undefined number of low energy UARTs (LEUART).
<> 144:ef7eb2e8f9f7 62 #endif
<> 144:ef7eb2e8f9f7 63
<> 150:02e0a0aed4ec 64 #ifndef UART_PRESENT
<> 150:02e0a0aed4ec 65 #define UART_COUNT (0)
<> 150:02e0a0aed4ec 66 #endif
<> 150:02e0a0aed4ec 67 #ifndef USART_PRESENT
<> 150:02e0a0aed4ec 68 #define USART_COUNT (0)
<> 150:02e0a0aed4ec 69 #endif
<> 150:02e0a0aed4ec 70 #ifndef LEUART_PRESENT
<> 150:02e0a0aed4ec 71 #define LEUART_COUNT (0)
<> 150:02e0a0aed4ec 72 #endif
<> 150:02e0a0aed4ec 73
<> 150:02e0a0aed4ec 74 #define MODULES_SIZE_SERIAL (UART_COUNT + USART_COUNT + LEUART_COUNT)
<> 150:02e0a0aed4ec 75
<> 144:ef7eb2e8f9f7 76 /* Store IRQ id for each UART */
<> 144:ef7eb2e8f9f7 77 static uint32_t serial_irq_ids[MODULES_SIZE_SERIAL] = { 0 };
<> 144:ef7eb2e8f9f7 78 /* Interrupt handler from mbed common */
<> 144:ef7eb2e8f9f7 79 static uart_irq_handler irq_handler;
<> 144:ef7eb2e8f9f7 80 /* Keep track of incoming DMA IRQ's */
AnnaBridge 179:b0033dcd6934 81 static bool serial_dma_irq_fired[DMA_CHAN_COUNT] = { false };
<> 144:ef7eb2e8f9f7 82
<> 144:ef7eb2e8f9f7 83 /* Serial interface on USBTX/USBRX retargets stdio */
<> 144:ef7eb2e8f9f7 84 int stdio_uart_inited = 0;
<> 144:ef7eb2e8f9f7 85 serial_t stdio_uart;
<> 144:ef7eb2e8f9f7 86
<> 144:ef7eb2e8f9f7 87 static void uart_irq(UARTName, SerialIrq);
<> 144:ef7eb2e8f9f7 88 static uint8_t serial_get_index(serial_t *obj);
<> 144:ef7eb2e8f9f7 89 static void serial_enable(serial_t *obj, uint8_t enable);
<> 144:ef7eb2e8f9f7 90 static void serial_enable_pins(serial_t *obj, uint8_t enable);
<> 144:ef7eb2e8f9f7 91 static void serial_set_route(serial_t *obj);
<> 144:ef7eb2e8f9f7 92 static IRQn_Type serial_get_rx_irq_index(serial_t *obj);
<> 144:ef7eb2e8f9f7 93 static IRQn_Type serial_get_tx_irq_index(serial_t *obj);
<> 144:ef7eb2e8f9f7 94 static CMU_Clock_TypeDef serial_get_clock(serial_t *obj);
<> 144:ef7eb2e8f9f7 95 static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx);
<> 144:ef7eb2e8f9f7 96 static void serial_rx_abort_asynch_intern(serial_t *obj, int unblock_sleep);
<> 144:ef7eb2e8f9f7 97 static void serial_tx_abort_asynch_intern(serial_t *obj, int unblock_sleep);
<> 144:ef7eb2e8f9f7 98 static void serial_block_sleep(serial_t *obj);
<> 144:ef7eb2e8f9f7 99 static void serial_unblock_sleep(serial_t *obj);
<> 144:ef7eb2e8f9f7 100 static void serial_leuart_baud(serial_t *obj, int baudrate);
<> 144:ef7eb2e8f9f7 101
<> 144:ef7eb2e8f9f7 102 /* ISRs for RX and TX events */
<> 144:ef7eb2e8f9f7 103 #ifdef UART0
<> 144:ef7eb2e8f9f7 104 static void uart0_rx_irq() { uart_irq(UART_0, RxIrq); }
<> 144:ef7eb2e8f9f7 105 static void uart0_tx_irq() { uart_irq(UART_0, TxIrq); USART_IntClear((USART_TypeDef*)UART_0, USART_IFC_TXC);}
<> 144:ef7eb2e8f9f7 106 #endif
<> 144:ef7eb2e8f9f7 107 #ifdef UART1
<> 144:ef7eb2e8f9f7 108 static void uart1_rx_irq() { uart_irq(UART_1, RxIrq); }
<> 144:ef7eb2e8f9f7 109 static void uart1_tx_irq() { uart_irq(UART_1, TxIrq); USART_IntClear((USART_TypeDef*)UART_1, USART_IFC_TXC);}
<> 144:ef7eb2e8f9f7 110 #endif
<> 144:ef7eb2e8f9f7 111 #ifdef USART0
<> 144:ef7eb2e8f9f7 112 static void usart0_rx_irq() { uart_irq(USART_0, RxIrq); }
<> 144:ef7eb2e8f9f7 113 static void usart0_tx_irq() { uart_irq(USART_0, TxIrq); USART_IntClear((USART_TypeDef*)USART_0, USART_IFC_TXC);}
<> 144:ef7eb2e8f9f7 114 #endif
<> 144:ef7eb2e8f9f7 115 #ifdef USART1
<> 144:ef7eb2e8f9f7 116 static void usart1_rx_irq() { uart_irq(USART_1, RxIrq); }
<> 144:ef7eb2e8f9f7 117 static void usart1_tx_irq() { uart_irq(USART_1, TxIrq); USART_IntClear((USART_TypeDef*)USART_1, USART_IFC_TXC);}
<> 144:ef7eb2e8f9f7 118 #endif
<> 144:ef7eb2e8f9f7 119 #ifdef USART2
<> 144:ef7eb2e8f9f7 120 static void usart2_rx_irq() { uart_irq(USART_2, RxIrq); }
<> 144:ef7eb2e8f9f7 121 static void usart2_tx_irq() { uart_irq(USART_2, TxIrq); USART_IntClear((USART_TypeDef*)USART_2, USART_IFC_TXC);}
<> 144:ef7eb2e8f9f7 122 #endif
AnnaBridge 179:b0033dcd6934 123 #ifdef USART3
AnnaBridge 179:b0033dcd6934 124 static void usart3_rx_irq() { uart_irq(USART_3, RxIrq); }
AnnaBridge 179:b0033dcd6934 125 static void usart3_tx_irq() { uart_irq(USART_3, TxIrq); USART_IntClear((USART_TypeDef*)USART_3, USART_IFC_TXC);}
AnnaBridge 179:b0033dcd6934 126 #endif
AnnaBridge 179:b0033dcd6934 127 #ifdef USART4
AnnaBridge 179:b0033dcd6934 128 static void usart4_rx_irq() { uart_irq(USART_4, RxIrq); }
AnnaBridge 179:b0033dcd6934 129 static void usart4_tx_irq() { uart_irq(USART_4, TxIrq); USART_IntClear((USART_TypeDef*)USART_4, USART_IFC_TXC);}
AnnaBridge 179:b0033dcd6934 130 #endif
AnnaBridge 179:b0033dcd6934 131 #ifdef USART5
AnnaBridge 179:b0033dcd6934 132 static void usart5_rx_irq() { uart_irq(USART_5, RxIrq); }
AnnaBridge 179:b0033dcd6934 133 static void usart5_tx_irq() { uart_irq(USART_5, TxIrq); USART_IntClear((USART_TypeDef*)USART_5, USART_IFC_TXC);}
AnnaBridge 179:b0033dcd6934 134 #endif
<> 144:ef7eb2e8f9f7 135 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 136 static void leuart0_irq()
<> 144:ef7eb2e8f9f7 137 {
<> 144:ef7eb2e8f9f7 138 if(LEUART_IntGetEnabled(LEUART0) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF)) {
<> 144:ef7eb2e8f9f7 139 uart_irq(LEUART_0, RxIrq);
<> 144:ef7eb2e8f9f7 140 }
<> 144:ef7eb2e8f9f7 141
<> 144:ef7eb2e8f9f7 142 if(LEUART_IntGetEnabled(LEUART0) & (LEUART_IF_TXC | LEUART_IF_TXBL | LEUART_IF_TXOF)) {
<> 144:ef7eb2e8f9f7 143 uart_irq(LEUART_0, TxIrq);
<> 144:ef7eb2e8f9f7 144 LEUART_IntClear(LEUART0, LEUART_IFC_TXC);
<> 144:ef7eb2e8f9f7 145 }
<> 144:ef7eb2e8f9f7 146 }
<> 144:ef7eb2e8f9f7 147 #endif
<> 144:ef7eb2e8f9f7 148 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 149 static void leuart1_irq()
<> 144:ef7eb2e8f9f7 150 {
<> 144:ef7eb2e8f9f7 151 if(LEUART_IntGetEnabled(LEUART1) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF)) {
<> 144:ef7eb2e8f9f7 152 uart_irq(LEUART_1, RxIrq);
<> 144:ef7eb2e8f9f7 153 }
<> 144:ef7eb2e8f9f7 154
<> 144:ef7eb2e8f9f7 155 if(LEUART_IntGetEnabled(LEUART1) & (LEUART_IF_TXC | LEUART_IF_TXBL | LEUART_IF_TXOF)) {
<> 144:ef7eb2e8f9f7 156 uart_irq(LEUART_1, TxIrq);
<> 144:ef7eb2e8f9f7 157 LEUART_IntClear(LEUART1, LEUART_IFC_TXC);
<> 144:ef7eb2e8f9f7 158 }
<> 144:ef7eb2e8f9f7 159 }
<> 144:ef7eb2e8f9f7 160 #endif
<> 144:ef7eb2e8f9f7 161
<> 144:ef7eb2e8f9f7 162 /**
<> 144:ef7eb2e8f9f7 163 * Initialize the UART using default settings, overridden by settings from serial object
<> 144:ef7eb2e8f9f7 164 *
<> 144:ef7eb2e8f9f7 165 * @param obj pointer to serial object
<> 144:ef7eb2e8f9f7 166 */
<> 144:ef7eb2e8f9f7 167 static void uart_init(serial_t *obj, uint32_t baudrate, SerialParity parity, int stop_bits)
<> 144:ef7eb2e8f9f7 168 {
<> 144:ef7eb2e8f9f7 169 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 170 LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
<> 144:ef7eb2e8f9f7 171
<> 144:ef7eb2e8f9f7 172 if (stop_bits == 2) {
<> 144:ef7eb2e8f9f7 173 init.stopbits = leuartStopbits2;
<> 144:ef7eb2e8f9f7 174 } else {
<> 144:ef7eb2e8f9f7 175 init.stopbits = leuartStopbits1;
<> 144:ef7eb2e8f9f7 176 }
<> 144:ef7eb2e8f9f7 177
<> 144:ef7eb2e8f9f7 178 switch (parity) {
<> 144:ef7eb2e8f9f7 179 case ParityOdd:
<> 144:ef7eb2e8f9f7 180 case ParityForced0:
<> 144:ef7eb2e8f9f7 181 init.parity = leuartOddParity;
<> 144:ef7eb2e8f9f7 182 break;
<> 144:ef7eb2e8f9f7 183 case ParityEven:
<> 144:ef7eb2e8f9f7 184 case ParityForced1:
<> 144:ef7eb2e8f9f7 185 init.parity = leuartEvenParity;
<> 144:ef7eb2e8f9f7 186 break;
<> 144:ef7eb2e8f9f7 187 default: /* ParityNone */
<> 144:ef7eb2e8f9f7 188 init.parity = leuartNoParity;
<> 144:ef7eb2e8f9f7 189 break;
<> 144:ef7eb2e8f9f7 190 }
<> 144:ef7eb2e8f9f7 191
<> 144:ef7eb2e8f9f7 192 init.enable = leuartDisable;
<> 144:ef7eb2e8f9f7 193 init.baudrate = 9600;
<> 144:ef7eb2e8f9f7 194 init.databits = leuartDatabits8;
<> 144:ef7eb2e8f9f7 195 #ifdef LEUART_USING_LFXO
<> 144:ef7eb2e8f9f7 196 init.refFreq = LEUART_LF_REF_FREQ;
<> 144:ef7eb2e8f9f7 197 #else
<> 144:ef7eb2e8f9f7 198 init.refFreq = LEUART_REF_FREQ;
<> 144:ef7eb2e8f9f7 199 #endif
<> 144:ef7eb2e8f9f7 200 LEUART_Init(obj->serial.periph.leuart, &init);
<> 144:ef7eb2e8f9f7 201
<> 144:ef7eb2e8f9f7 202 if (baudrate != 9600) {
<> 144:ef7eb2e8f9f7 203 serial_baud(obj, baudrate);
<> 144:ef7eb2e8f9f7 204 }
<> 144:ef7eb2e8f9f7 205 } else {
<> 144:ef7eb2e8f9f7 206 USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
<> 144:ef7eb2e8f9f7 207
<> 144:ef7eb2e8f9f7 208 if (stop_bits == 2) {
<> 144:ef7eb2e8f9f7 209 init.stopbits = usartStopbits2;
<> 144:ef7eb2e8f9f7 210 } else {
<> 144:ef7eb2e8f9f7 211 init.stopbits = usartStopbits1;
<> 144:ef7eb2e8f9f7 212 }
<> 144:ef7eb2e8f9f7 213 switch (parity) {
<> 144:ef7eb2e8f9f7 214 case ParityOdd:
<> 144:ef7eb2e8f9f7 215 case ParityForced0:
<> 144:ef7eb2e8f9f7 216 init.parity = usartOddParity;
<> 144:ef7eb2e8f9f7 217 break;
<> 144:ef7eb2e8f9f7 218 case ParityEven:
<> 144:ef7eb2e8f9f7 219 case ParityForced1:
<> 144:ef7eb2e8f9f7 220 init.parity = usartEvenParity;
<> 144:ef7eb2e8f9f7 221 break;
<> 144:ef7eb2e8f9f7 222 default: /* ParityNone */
<> 144:ef7eb2e8f9f7 223 init.parity = usartNoParity;
<> 144:ef7eb2e8f9f7 224 break;
<> 144:ef7eb2e8f9f7 225 }
<> 144:ef7eb2e8f9f7 226
<> 144:ef7eb2e8f9f7 227 init.enable = usartDisable;
<> 144:ef7eb2e8f9f7 228 init.baudrate = baudrate;
<> 144:ef7eb2e8f9f7 229 init.oversampling = usartOVS16;
<> 144:ef7eb2e8f9f7 230 init.databits = usartDatabits8;
<> 144:ef7eb2e8f9f7 231 init.refFreq = REFERENCE_FREQUENCY;
<> 144:ef7eb2e8f9f7 232
<> 144:ef7eb2e8f9f7 233 USART_InitAsync(obj->serial.periph.uart, &init);
<> 144:ef7eb2e8f9f7 234 }
<> 144:ef7eb2e8f9f7 235 }
<> 144:ef7eb2e8f9f7 236 /**
<> 144:ef7eb2e8f9f7 237 * Get index of serial object, relating it to the physical peripheral.
<> 144:ef7eb2e8f9f7 238 *
<> 144:ef7eb2e8f9f7 239 * @param obj pointer to serial peripheral (= base address of periph)
<> 144:ef7eb2e8f9f7 240 * @return internal index of U(S)ART peripheral
<> 144:ef7eb2e8f9f7 241 */
<> 144:ef7eb2e8f9f7 242 static inline uint8_t serial_pointer_get_index(uint32_t serial_ptr)
<> 144:ef7eb2e8f9f7 243 {
<> 144:ef7eb2e8f9f7 244 uint8_t index = 0;
<> 144:ef7eb2e8f9f7 245 #ifdef UART0
<> 144:ef7eb2e8f9f7 246 if (serial_ptr == UART_0) return index;
<> 144:ef7eb2e8f9f7 247 index++;
<> 144:ef7eb2e8f9f7 248 #endif
<> 144:ef7eb2e8f9f7 249 #ifdef UART1
<> 144:ef7eb2e8f9f7 250 if (serial_ptr == UART_1) return index;
<> 144:ef7eb2e8f9f7 251 index++;
<> 144:ef7eb2e8f9f7 252 #endif
<> 144:ef7eb2e8f9f7 253 #ifdef USART0
<> 144:ef7eb2e8f9f7 254 if (serial_ptr == USART_0) return index;
<> 144:ef7eb2e8f9f7 255 index++;
<> 144:ef7eb2e8f9f7 256 #endif
<> 144:ef7eb2e8f9f7 257 #ifdef USART1
<> 144:ef7eb2e8f9f7 258 if (serial_ptr == USART_1) return index;
<> 144:ef7eb2e8f9f7 259 index++;
<> 144:ef7eb2e8f9f7 260 #endif
<> 144:ef7eb2e8f9f7 261 #ifdef USART2
<> 144:ef7eb2e8f9f7 262 if (serial_ptr == USART_2) return index;
<> 144:ef7eb2e8f9f7 263 index++;
<> 144:ef7eb2e8f9f7 264 #endif
AnnaBridge 179:b0033dcd6934 265 #ifdef USART3
AnnaBridge 179:b0033dcd6934 266 if (serial_ptr == USART_3) return index;
AnnaBridge 179:b0033dcd6934 267 index++;
AnnaBridge 179:b0033dcd6934 268 #endif
AnnaBridge 179:b0033dcd6934 269 #ifdef USART4
AnnaBridge 179:b0033dcd6934 270 if (serial_ptr == USART_4) return index;
AnnaBridge 179:b0033dcd6934 271 index++;
AnnaBridge 179:b0033dcd6934 272 #endif
AnnaBridge 179:b0033dcd6934 273 #ifdef USART5
AnnaBridge 179:b0033dcd6934 274 if (serial_ptr == USART_5) return index;
AnnaBridge 179:b0033dcd6934 275 index++;
AnnaBridge 179:b0033dcd6934 276 #endif
<> 144:ef7eb2e8f9f7 277 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 278 if (serial_ptr == LEUART_0) return index;
<> 144:ef7eb2e8f9f7 279 index++;
<> 144:ef7eb2e8f9f7 280 #endif
<> 144:ef7eb2e8f9f7 281 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 282 if (serial_ptr == LEUART_1) return index;
<> 144:ef7eb2e8f9f7 283 index++;
<> 144:ef7eb2e8f9f7 284 #endif
<> 144:ef7eb2e8f9f7 285 return 0;
<> 144:ef7eb2e8f9f7 286 }
<> 144:ef7eb2e8f9f7 287
<> 144:ef7eb2e8f9f7 288 /**
<> 144:ef7eb2e8f9f7 289 * Get index of serial object, relating it to the physical peripheral.
<> 144:ef7eb2e8f9f7 290 *
<> 144:ef7eb2e8f9f7 291 * @param obj pointer to serial object (mbed object)
<> 144:ef7eb2e8f9f7 292 * @return internal index of U(S)ART peripheral
<> 144:ef7eb2e8f9f7 293 */
<> 144:ef7eb2e8f9f7 294 static inline uint8_t serial_get_index(serial_t *obj)
<> 144:ef7eb2e8f9f7 295 {
<> 144:ef7eb2e8f9f7 296 return serial_pointer_get_index((uint32_t)obj->serial.periph.uart);
<> 144:ef7eb2e8f9f7 297 }
<> 144:ef7eb2e8f9f7 298
<> 144:ef7eb2e8f9f7 299 /**
<> 144:ef7eb2e8f9f7 300 * Get index of serial object RX IRQ, relating it to the physical peripheral.
<> 144:ef7eb2e8f9f7 301 *
<> 144:ef7eb2e8f9f7 302 * @param obj pointer to serial object
<> 144:ef7eb2e8f9f7 303 * @return internal NVIC RX IRQ index of U(S)ART peripheral
<> 144:ef7eb2e8f9f7 304 */
<> 144:ef7eb2e8f9f7 305 static inline IRQn_Type serial_get_rx_irq_index(serial_t *obj)
<> 144:ef7eb2e8f9f7 306 {
<> 144:ef7eb2e8f9f7 307 switch ((uint32_t)obj->serial.periph.uart) {
<> 144:ef7eb2e8f9f7 308 #ifdef UART0
<> 144:ef7eb2e8f9f7 309 case UART_0:
<> 144:ef7eb2e8f9f7 310 return UART0_RX_IRQn;
<> 144:ef7eb2e8f9f7 311 #endif
<> 144:ef7eb2e8f9f7 312 #ifdef UART1
<> 144:ef7eb2e8f9f7 313 case UART_1:
<> 144:ef7eb2e8f9f7 314 return UART1_RX_IRQn;
<> 144:ef7eb2e8f9f7 315 #endif
<> 144:ef7eb2e8f9f7 316 #ifdef USART0
<> 144:ef7eb2e8f9f7 317 case USART_0:
<> 144:ef7eb2e8f9f7 318 return USART0_RX_IRQn;
<> 144:ef7eb2e8f9f7 319 #endif
<> 144:ef7eb2e8f9f7 320 #ifdef USART1
<> 144:ef7eb2e8f9f7 321 case USART_1:
<> 144:ef7eb2e8f9f7 322 return USART1_RX_IRQn;
<> 144:ef7eb2e8f9f7 323 #endif
<> 144:ef7eb2e8f9f7 324 #ifdef USART2
<> 144:ef7eb2e8f9f7 325 case USART_2:
<> 144:ef7eb2e8f9f7 326 return USART2_RX_IRQn;
<> 144:ef7eb2e8f9f7 327 #endif
AnnaBridge 179:b0033dcd6934 328 #ifdef USART3
AnnaBridge 179:b0033dcd6934 329 case USART_3:
AnnaBridge 179:b0033dcd6934 330 return USART3_RX_IRQn;
AnnaBridge 179:b0033dcd6934 331 #endif
AnnaBridge 179:b0033dcd6934 332 #ifdef USART4
AnnaBridge 179:b0033dcd6934 333 case USART_4:
AnnaBridge 179:b0033dcd6934 334 return USART4_RX_IRQn;
AnnaBridge 179:b0033dcd6934 335 #endif
AnnaBridge 179:b0033dcd6934 336 #ifdef USART5
AnnaBridge 179:b0033dcd6934 337 case USART_5:
AnnaBridge 179:b0033dcd6934 338 return USART5_RX_IRQn;
AnnaBridge 179:b0033dcd6934 339 #endif
<> 144:ef7eb2e8f9f7 340 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 341 case LEUART_0:
<> 144:ef7eb2e8f9f7 342 return LEUART0_IRQn;
<> 144:ef7eb2e8f9f7 343 #endif
<> 144:ef7eb2e8f9f7 344 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 345 case LEUART_1:
<> 144:ef7eb2e8f9f7 346 return LEUART1_IRQn;
<> 144:ef7eb2e8f9f7 347 #endif
<> 144:ef7eb2e8f9f7 348 default:
<> 144:ef7eb2e8f9f7 349 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 350 }
<> 144:ef7eb2e8f9f7 351 return (IRQn_Type)0;
<> 144:ef7eb2e8f9f7 352 }
<> 144:ef7eb2e8f9f7 353
<> 144:ef7eb2e8f9f7 354 /**
<> 144:ef7eb2e8f9f7 355 * Get index of serial object TX IRQ, relating it to the physical peripheral.
<> 144:ef7eb2e8f9f7 356 *
<> 144:ef7eb2e8f9f7 357 * @param obj pointer to serial object
<> 144:ef7eb2e8f9f7 358 * @return internal NVIC TX IRQ index of U(S)ART peripheral
<> 144:ef7eb2e8f9f7 359 */
<> 144:ef7eb2e8f9f7 360 static inline IRQn_Type serial_get_tx_irq_index(serial_t *obj)
<> 144:ef7eb2e8f9f7 361 {
<> 144:ef7eb2e8f9f7 362 switch ((uint32_t)obj->serial.periph.uart) {
<> 144:ef7eb2e8f9f7 363 #ifdef UART0
<> 144:ef7eb2e8f9f7 364 case UART_0:
<> 144:ef7eb2e8f9f7 365 return UART0_TX_IRQn;
<> 144:ef7eb2e8f9f7 366 #endif
<> 144:ef7eb2e8f9f7 367 #ifdef UART1
<> 144:ef7eb2e8f9f7 368 case UART_1:
<> 144:ef7eb2e8f9f7 369 return UART1_TX_IRQn;
<> 144:ef7eb2e8f9f7 370 #endif
<> 144:ef7eb2e8f9f7 371 #ifdef USART0
<> 144:ef7eb2e8f9f7 372 case USART_0:
<> 144:ef7eb2e8f9f7 373 return USART0_TX_IRQn;
<> 144:ef7eb2e8f9f7 374 #endif
<> 144:ef7eb2e8f9f7 375 #ifdef USART1
<> 144:ef7eb2e8f9f7 376 case USART_1:
<> 144:ef7eb2e8f9f7 377 return USART1_TX_IRQn;
<> 144:ef7eb2e8f9f7 378 #endif
<> 144:ef7eb2e8f9f7 379 #ifdef USART2
<> 144:ef7eb2e8f9f7 380 case USART_2:
<> 144:ef7eb2e8f9f7 381 return USART2_TX_IRQn;
<> 144:ef7eb2e8f9f7 382 #endif
AnnaBridge 179:b0033dcd6934 383 #ifdef USART3
AnnaBridge 179:b0033dcd6934 384 case USART_3:
AnnaBridge 179:b0033dcd6934 385 return USART3_TX_IRQn;
AnnaBridge 179:b0033dcd6934 386 #endif
AnnaBridge 179:b0033dcd6934 387 #ifdef USART4
AnnaBridge 179:b0033dcd6934 388 case USART_4:
AnnaBridge 179:b0033dcd6934 389 return USART4_TX_IRQn;
AnnaBridge 179:b0033dcd6934 390 #endif
AnnaBridge 179:b0033dcd6934 391 #ifdef USART5
AnnaBridge 179:b0033dcd6934 392 case USART_5:
AnnaBridge 179:b0033dcd6934 393 return USART5_TX_IRQn;
AnnaBridge 179:b0033dcd6934 394 #endif
<> 144:ef7eb2e8f9f7 395 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 396 case LEUART_0:
<> 144:ef7eb2e8f9f7 397 return LEUART0_IRQn;
<> 144:ef7eb2e8f9f7 398 #endif
<> 144:ef7eb2e8f9f7 399 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 400 case LEUART_1:
<> 144:ef7eb2e8f9f7 401 return LEUART1_IRQn;
<> 144:ef7eb2e8f9f7 402 #endif
<> 144:ef7eb2e8f9f7 403 default:
<> 144:ef7eb2e8f9f7 404 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 405 }
<> 144:ef7eb2e8f9f7 406 return (IRQn_Type)0;
<> 144:ef7eb2e8f9f7 407 }
<> 144:ef7eb2e8f9f7 408
<> 144:ef7eb2e8f9f7 409 /**
<> 144:ef7eb2e8f9f7 410 * Get clock tree for serial peripheral pointed to by obj.
<> 144:ef7eb2e8f9f7 411 *
<> 144:ef7eb2e8f9f7 412 * @param obj pointer to serial object
<> 144:ef7eb2e8f9f7 413 * @return CMU_Clock_TypeDef for U(S)ART
<> 144:ef7eb2e8f9f7 414 */
<> 144:ef7eb2e8f9f7 415 inline CMU_Clock_TypeDef serial_get_clock(serial_t *obj)
<> 144:ef7eb2e8f9f7 416 {
<> 144:ef7eb2e8f9f7 417 switch ((uint32_t)obj->serial.periph.uart) {
<> 144:ef7eb2e8f9f7 418 #ifdef UART0
<> 144:ef7eb2e8f9f7 419 case UART_0:
<> 144:ef7eb2e8f9f7 420 return cmuClock_UART0;
<> 144:ef7eb2e8f9f7 421 #endif
<> 144:ef7eb2e8f9f7 422 #ifdef UART1
<> 144:ef7eb2e8f9f7 423 case UART_1:
<> 144:ef7eb2e8f9f7 424 return cmuClock_UART1;
<> 144:ef7eb2e8f9f7 425 #endif
<> 144:ef7eb2e8f9f7 426 #ifdef USART0
<> 144:ef7eb2e8f9f7 427 case USART_0:
<> 144:ef7eb2e8f9f7 428 return cmuClock_USART0;
<> 144:ef7eb2e8f9f7 429 #endif
<> 144:ef7eb2e8f9f7 430 #ifdef USART1
<> 144:ef7eb2e8f9f7 431 case USART_1:
<> 144:ef7eb2e8f9f7 432 return cmuClock_USART1;
<> 144:ef7eb2e8f9f7 433 #endif
<> 144:ef7eb2e8f9f7 434 #ifdef USART2
<> 144:ef7eb2e8f9f7 435 case USART_2:
<> 144:ef7eb2e8f9f7 436 return cmuClock_USART2;
<> 144:ef7eb2e8f9f7 437 #endif
AnnaBridge 179:b0033dcd6934 438 #ifdef USART3
AnnaBridge 179:b0033dcd6934 439 case USART_3:
AnnaBridge 179:b0033dcd6934 440 return cmuClock_USART3;
AnnaBridge 179:b0033dcd6934 441 #endif
AnnaBridge 179:b0033dcd6934 442 #ifdef USART4
AnnaBridge 179:b0033dcd6934 443 case USART_4:
AnnaBridge 179:b0033dcd6934 444 return cmuClock_USART4;
AnnaBridge 179:b0033dcd6934 445 #endif
AnnaBridge 179:b0033dcd6934 446 #ifdef USART5
AnnaBridge 179:b0033dcd6934 447 case USART_5:
AnnaBridge 179:b0033dcd6934 448 return cmuClock_USART5;
AnnaBridge 179:b0033dcd6934 449 #endif
<> 144:ef7eb2e8f9f7 450 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 451 case LEUART_0:
<> 144:ef7eb2e8f9f7 452 return cmuClock_LEUART0;
<> 144:ef7eb2e8f9f7 453 #endif
<> 144:ef7eb2e8f9f7 454 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 455 case LEUART_1:
<> 144:ef7eb2e8f9f7 456 return cmuClock_LEUART1;
<> 144:ef7eb2e8f9f7 457 #endif
<> 144:ef7eb2e8f9f7 458 default:
<> 144:ef7eb2e8f9f7 459 return cmuClock_HFPER;
<> 144:ef7eb2e8f9f7 460 }
<> 144:ef7eb2e8f9f7 461 }
<> 144:ef7eb2e8f9f7 462
<> 144:ef7eb2e8f9f7 463 void serial_preinit(serial_t *obj, PinName tx, PinName rx)
<> 144:ef7eb2e8f9f7 464 {
<> 144:ef7eb2e8f9f7 465 /* Get UART object connected to the given pins */
<> 144:ef7eb2e8f9f7 466 UARTName uart_tx = (UARTName) pinmap_peripheral(tx, PinMap_UART_TX);
<> 144:ef7eb2e8f9f7 467 UARTName uart_rx = (UARTName) pinmap_peripheral(rx, PinMap_UART_RX);
<> 144:ef7eb2e8f9f7 468 /* Check that pins are connected to same UART */
<> 144:ef7eb2e8f9f7 469 UARTName uart = (UARTName) pinmap_merge(uart_tx, uart_rx);
AnnaBridge 179:b0033dcd6934 470 MBED_ASSERT((unsigned int) uart != NC);
<> 144:ef7eb2e8f9f7 471
<> 144:ef7eb2e8f9f7 472 obj->serial.periph.uart = (USART_TypeDef *) uart;
<> 144:ef7eb2e8f9f7 473
<> 144:ef7eb2e8f9f7 474 /* Get location */
<> 144:ef7eb2e8f9f7 475 uint32_t uart_tx_loc = pin_location(tx, PinMap_UART_TX);
<> 144:ef7eb2e8f9f7 476 uint32_t uart_rx_loc = pin_location(rx, PinMap_UART_RX);
<> 144:ef7eb2e8f9f7 477
<> 144:ef7eb2e8f9f7 478 #if defined(_SILICON_LABS_32B_PLATFORM_1)
<> 144:ef7eb2e8f9f7 479 /* Check that pins are used by same location for the given UART */
<> 144:ef7eb2e8f9f7 480 obj->serial.location = pinmap_merge(uart_tx_loc, uart_rx_loc);
AnnaBridge 179:b0033dcd6934 481 MBED_ASSERT(obj->serial.location != NC);
<> 144:ef7eb2e8f9f7 482 #else
<> 144:ef7eb2e8f9f7 483 obj->serial.location_tx = uart_tx_loc;
<> 144:ef7eb2e8f9f7 484 obj->serial.location_rx = uart_rx_loc;
<> 144:ef7eb2e8f9f7 485 #endif
<> 144:ef7eb2e8f9f7 486
<> 144:ef7eb2e8f9f7 487 /* Store pins in object for easy disabling in serial_free() */
<> 144:ef7eb2e8f9f7 488 //TODO: replace all usages with AF_USARTx_TX_PORT(location) macro to save 8 bytes from struct
<> 144:ef7eb2e8f9f7 489 obj->serial.rx_pin = rx;
<> 144:ef7eb2e8f9f7 490 obj->serial.tx_pin = tx;
<> 144:ef7eb2e8f9f7 491
<> 144:ef7eb2e8f9f7 492 /* Select interrupt */
<> 144:ef7eb2e8f9f7 493 switch ((uint32_t)obj->serial.periph.uart) {
<> 144:ef7eb2e8f9f7 494 #ifdef UART0
<> 144:ef7eb2e8f9f7 495 case UART_0:
<> 144:ef7eb2e8f9f7 496 NVIC_SetVector(UART0_RX_IRQn, (uint32_t) &uart0_rx_irq);
<> 144:ef7eb2e8f9f7 497 NVIC_SetVector(UART0_TX_IRQn, (uint32_t) &uart0_tx_irq);
<> 144:ef7eb2e8f9f7 498 NVIC_SetPriority(UART0_TX_IRQn, 1);
<> 144:ef7eb2e8f9f7 499 break;
<> 144:ef7eb2e8f9f7 500 #endif
<> 144:ef7eb2e8f9f7 501 #ifdef UART1
<> 144:ef7eb2e8f9f7 502 case UART_1:
<> 144:ef7eb2e8f9f7 503 NVIC_SetVector(UART1_RX_IRQn, (uint32_t) &uart1_rx_irq);
<> 144:ef7eb2e8f9f7 504 NVIC_SetVector(UART1_TX_IRQn, (uint32_t) &uart1_tx_irq);
<> 144:ef7eb2e8f9f7 505 NVIC_SetPriority(UART1_TX_IRQn, 1);
<> 144:ef7eb2e8f9f7 506 break;
<> 144:ef7eb2e8f9f7 507 #endif
<> 144:ef7eb2e8f9f7 508 #ifdef USART0
<> 144:ef7eb2e8f9f7 509 case USART_0:
<> 144:ef7eb2e8f9f7 510 NVIC_SetVector(USART0_RX_IRQn, (uint32_t) &usart0_rx_irq);
<> 144:ef7eb2e8f9f7 511 NVIC_SetVector(USART0_TX_IRQn, (uint32_t) &usart0_tx_irq);
<> 144:ef7eb2e8f9f7 512 NVIC_SetPriority(USART0_TX_IRQn, 1);
<> 144:ef7eb2e8f9f7 513 break;
<> 144:ef7eb2e8f9f7 514 #endif
<> 144:ef7eb2e8f9f7 515 #ifdef USART1
<> 144:ef7eb2e8f9f7 516 case USART_1:
<> 144:ef7eb2e8f9f7 517 NVIC_SetVector(USART1_RX_IRQn, (uint32_t) &usart1_rx_irq);
<> 144:ef7eb2e8f9f7 518 NVIC_SetVector(USART1_TX_IRQn, (uint32_t) &usart1_tx_irq);
<> 144:ef7eb2e8f9f7 519 NVIC_SetPriority(USART1_TX_IRQn, 1);
<> 144:ef7eb2e8f9f7 520 break;
<> 144:ef7eb2e8f9f7 521 #endif
<> 144:ef7eb2e8f9f7 522 #ifdef USART2
<> 144:ef7eb2e8f9f7 523 case USART_2:
<> 144:ef7eb2e8f9f7 524 NVIC_SetVector(USART2_RX_IRQn, (uint32_t) &usart2_rx_irq);
<> 144:ef7eb2e8f9f7 525 NVIC_SetVector(USART2_TX_IRQn, (uint32_t) &usart2_tx_irq);
<> 144:ef7eb2e8f9f7 526 NVIC_SetPriority(USART2_TX_IRQn, 1);
<> 144:ef7eb2e8f9f7 527 break;
<> 144:ef7eb2e8f9f7 528 #endif
AnnaBridge 179:b0033dcd6934 529 #ifdef USART3
AnnaBridge 179:b0033dcd6934 530 case USART_3:
AnnaBridge 179:b0033dcd6934 531 NVIC_SetVector(USART3_RX_IRQn, (uint32_t) &usart3_rx_irq);
AnnaBridge 179:b0033dcd6934 532 NVIC_SetVector(USART3_TX_IRQn, (uint32_t) &usart3_tx_irq);
AnnaBridge 179:b0033dcd6934 533 NVIC_SetPriority(USART3_TX_IRQn, 1);
AnnaBridge 179:b0033dcd6934 534 break;
AnnaBridge 179:b0033dcd6934 535 #endif
AnnaBridge 179:b0033dcd6934 536 #ifdef USART4
AnnaBridge 179:b0033dcd6934 537 case USART_4:
AnnaBridge 179:b0033dcd6934 538 NVIC_SetVector(USART4_RX_IRQn, (uint32_t) &usart4_rx_irq);
AnnaBridge 179:b0033dcd6934 539 NVIC_SetVector(USART4_TX_IRQn, (uint32_t) &usart4_tx_irq);
AnnaBridge 179:b0033dcd6934 540 NVIC_SetPriority(USART4_TX_IRQn, 1);
AnnaBridge 179:b0033dcd6934 541 break;
AnnaBridge 179:b0033dcd6934 542 #endif
AnnaBridge 179:b0033dcd6934 543 #ifdef USART5
AnnaBridge 179:b0033dcd6934 544 case USART_5:
AnnaBridge 179:b0033dcd6934 545 NVIC_SetVector(USART5_RX_IRQn, (uint32_t) &usart5_rx_irq);
AnnaBridge 179:b0033dcd6934 546 NVIC_SetVector(USART5_TX_IRQn, (uint32_t) &usart5_tx_irq);
AnnaBridge 179:b0033dcd6934 547 NVIC_SetPriority(USART5_TX_IRQn, 1);
AnnaBridge 179:b0033dcd6934 548 break;
AnnaBridge 179:b0033dcd6934 549 #endif
<> 144:ef7eb2e8f9f7 550 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 551 case LEUART_0:
<> 144:ef7eb2e8f9f7 552 NVIC_SetVector(LEUART0_IRQn, (uint32_t) &leuart0_irq);
<> 144:ef7eb2e8f9f7 553 break;
<> 144:ef7eb2e8f9f7 554 #endif
<> 144:ef7eb2e8f9f7 555 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 556 case LEUART_1:
<> 144:ef7eb2e8f9f7 557 NVIC_SetVector(LEUART1_IRQn, (uint32_t) &leuart1_irq);
<> 144:ef7eb2e8f9f7 558 break;
<> 144:ef7eb2e8f9f7 559 #endif
<> 144:ef7eb2e8f9f7 560 }
<> 144:ef7eb2e8f9f7 561 }
<> 144:ef7eb2e8f9f7 562
<> 144:ef7eb2e8f9f7 563 static void serial_enable_pins(serial_t *obj, uint8_t enable)
<> 144:ef7eb2e8f9f7 564 {
<> 144:ef7eb2e8f9f7 565 if (enable) {
<> 144:ef7eb2e8f9f7 566 /* Configure GPIO pins*/
<> 144:ef7eb2e8f9f7 567 if(obj->serial.rx_pin != NC) {
<> 144:ef7eb2e8f9f7 568 pin_mode(obj->serial.rx_pin, Input);
<> 144:ef7eb2e8f9f7 569 }
<> 144:ef7eb2e8f9f7 570 /* Set DOUT first to prevent glitches */
<> 144:ef7eb2e8f9f7 571 if(obj->serial.tx_pin != NC) {
<> 144:ef7eb2e8f9f7 572 GPIO_PinOutSet((GPIO_Port_TypeDef)(obj->serial.tx_pin >> 4 & 0xF), obj->serial.tx_pin & 0xF);
<> 144:ef7eb2e8f9f7 573 pin_mode(obj->serial.tx_pin, PushPull);
<> 144:ef7eb2e8f9f7 574 }
<> 144:ef7eb2e8f9f7 575 } else {
<> 144:ef7eb2e8f9f7 576 if(obj->serial.rx_pin != NC) {
<> 144:ef7eb2e8f9f7 577 pin_mode(obj->serial.rx_pin, Disabled);
<> 144:ef7eb2e8f9f7 578 }
<> 144:ef7eb2e8f9f7 579 if(obj->serial.tx_pin != NC) {
<> 144:ef7eb2e8f9f7 580 pin_mode(obj->serial.tx_pin, Disabled);
<> 144:ef7eb2e8f9f7 581 }
<> 144:ef7eb2e8f9f7 582 }
<> 144:ef7eb2e8f9f7 583 }
<> 144:ef7eb2e8f9f7 584
<> 144:ef7eb2e8f9f7 585 static void serial_set_route(serial_t *obj)
<> 144:ef7eb2e8f9f7 586 {
<> 144:ef7eb2e8f9f7 587 /* Enable pins for UART at correct location */
<> 144:ef7eb2e8f9f7 588 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 589 #ifdef _LEUART_ROUTE_LOCATION_SHIFT
<> 144:ef7eb2e8f9f7 590 obj->serial.periph.leuart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
AnnaBridge 179:b0033dcd6934 591 if(obj->serial.tx_pin != NC) {
<> 144:ef7eb2e8f9f7 592 obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_TXPEN;
<> 144:ef7eb2e8f9f7 593 } else {
<> 144:ef7eb2e8f9f7 594 obj->serial.periph.leuart->ROUTE &= ~LEUART_ROUTE_TXPEN;
<> 144:ef7eb2e8f9f7 595 }
AnnaBridge 179:b0033dcd6934 596 if(obj->serial.rx_pin != NC) {
<> 144:ef7eb2e8f9f7 597 obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_RXPEN;
<> 144:ef7eb2e8f9f7 598 } else {
<> 144:ef7eb2e8f9f7 599 obj->serial.periph.leuart->CMD = LEUART_CMD_RXBLOCKEN;
<> 144:ef7eb2e8f9f7 600 obj->serial.periph.leuart->ROUTE &= ~LEUART_ROUTE_RXPEN;
<> 144:ef7eb2e8f9f7 601 }
<> 144:ef7eb2e8f9f7 602 #else
<> 144:ef7eb2e8f9f7 603 if(obj->serial.location_tx != NC) {
<> 144:ef7eb2e8f9f7 604 obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT);
<> 144:ef7eb2e8f9f7 605 obj->serial.periph.leuart->ROUTEPEN = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK)) | LEUART_ROUTEPEN_TXPEN;
<> 144:ef7eb2e8f9f7 606 } else {
<> 144:ef7eb2e8f9f7 607 obj->serial.periph.leuart->ROUTEPEN = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK));
<> 144:ef7eb2e8f9f7 608 }
<> 144:ef7eb2e8f9f7 609 if(obj->serial.location_rx != NC) {
<> 144:ef7eb2e8f9f7 610 obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
<> 144:ef7eb2e8f9f7 611 obj->serial.periph.leuart->ROUTEPEN = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK)) | LEUART_ROUTEPEN_RXPEN;
<> 144:ef7eb2e8f9f7 612 } else {
<> 144:ef7eb2e8f9f7 613 obj->serial.periph.leuart->CMD = LEUART_CMD_RXBLOCKEN;
<> 144:ef7eb2e8f9f7 614 obj->serial.periph.leuart->ROUTEPEN = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK));
<> 144:ef7eb2e8f9f7 615 }
<> 144:ef7eb2e8f9f7 616 #endif
<> 144:ef7eb2e8f9f7 617 } else {
<> 144:ef7eb2e8f9f7 618 #ifdef _USART_ROUTE_LOCATION_SHIFT
<> 144:ef7eb2e8f9f7 619 obj->serial.periph.uart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
AnnaBridge 179:b0033dcd6934 620 if(obj->serial.tx_pin != NC) {
<> 144:ef7eb2e8f9f7 621 obj->serial.periph.uart->ROUTE |= USART_ROUTE_TXPEN;
<> 144:ef7eb2e8f9f7 622 } else {
<> 144:ef7eb2e8f9f7 623 obj->serial.periph.uart->ROUTE &= ~USART_ROUTE_TXPEN;
<> 144:ef7eb2e8f9f7 624 }
AnnaBridge 179:b0033dcd6934 625 if(obj->serial.rx_pin != NC) {
<> 144:ef7eb2e8f9f7 626 obj->serial.periph.uart->ROUTE |= USART_ROUTE_RXPEN;
<> 144:ef7eb2e8f9f7 627 } else {
<> 144:ef7eb2e8f9f7 628 obj->serial.periph.uart->CMD = USART_CMD_RXBLOCKEN;
<> 144:ef7eb2e8f9f7 629 obj->serial.periph.uart->ROUTE &= ~USART_ROUTE_RXPEN;
<> 144:ef7eb2e8f9f7 630 }
<> 144:ef7eb2e8f9f7 631 #else
<> 144:ef7eb2e8f9f7 632 if(obj->serial.location_tx != NC) {
<> 144:ef7eb2e8f9f7 633 obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT);
<> 144:ef7eb2e8f9f7 634 obj->serial.periph.uart->ROUTEPEN = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK)) | USART_ROUTEPEN_TXPEN;
<> 144:ef7eb2e8f9f7 635 } else {
<> 144:ef7eb2e8f9f7 636 obj->serial.periph.uart->ROUTEPEN = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK));
<> 144:ef7eb2e8f9f7 637 }
<> 144:ef7eb2e8f9f7 638 if(obj->serial.location_rx != NC) {
<> 144:ef7eb2e8f9f7 639 obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
<> 144:ef7eb2e8f9f7 640 obj->serial.periph.uart->ROUTEPEN = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK)) | USART_ROUTEPEN_RXPEN;
<> 144:ef7eb2e8f9f7 641 } else {
<> 144:ef7eb2e8f9f7 642 obj->serial.periph.uart->CMD = USART_CMD_RXBLOCKEN;
<> 144:ef7eb2e8f9f7 643 obj->serial.periph.uart->ROUTEPEN = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK));
<> 144:ef7eb2e8f9f7 644 }
<> 144:ef7eb2e8f9f7 645 #endif
<> 144:ef7eb2e8f9f7 646 }
<> 144:ef7eb2e8f9f7 647 }
<> 144:ef7eb2e8f9f7 648
<> 144:ef7eb2e8f9f7 649 void serial_init(serial_t *obj, PinName tx, PinName rx)
<> 144:ef7eb2e8f9f7 650 {
<> 144:ef7eb2e8f9f7 651 serial_preinit(obj, tx, rx);
<> 144:ef7eb2e8f9f7 652
<> 144:ef7eb2e8f9f7 653 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 654 // Set up LEUART clock tree
<> 144:ef7eb2e8f9f7 655 #ifdef LEUART_USING_LFXO
<> 144:ef7eb2e8f9f7 656 //set to use LFXO
<> 144:ef7eb2e8f9f7 657 CMU_ClockEnable(cmuClock_CORELE, true);
<> 144:ef7eb2e8f9f7 658 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
<> 144:ef7eb2e8f9f7 659 #else
<> 144:ef7eb2e8f9f7 660 //set to use high-speed clock
<> 144:ef7eb2e8f9f7 661 #ifdef _SILICON_LABS_32B_PLATFORM_2
<> 144:ef7eb2e8f9f7 662 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_HFCLKLE);
<> 144:ef7eb2e8f9f7 663 #else
<> 144:ef7eb2e8f9f7 664 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
<> 144:ef7eb2e8f9f7 665 #endif
<> 144:ef7eb2e8f9f7 666 #endif
<> 144:ef7eb2e8f9f7 667 }
<> 144:ef7eb2e8f9f7 668
<> 144:ef7eb2e8f9f7 669 CMU_ClockEnable(serial_get_clock(obj), true);
<> 144:ef7eb2e8f9f7 670
<> 144:ef7eb2e8f9f7 671 /* Configure UART for async operation */
<> 150:02e0a0aed4ec 672 uart_init(obj, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE, ParityNone, 1);
<> 144:ef7eb2e8f9f7 673
<> 144:ef7eb2e8f9f7 674 /* Enable pins for UART at correct location */
<> 144:ef7eb2e8f9f7 675 serial_set_route(obj);
<> 144:ef7eb2e8f9f7 676
<> 144:ef7eb2e8f9f7 677 /* Reset interrupts */
<> 144:ef7eb2e8f9f7 678 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 679 obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
<> 144:ef7eb2e8f9f7 680 obj->serial.periph.leuart->CTRL |= LEUART_CTRL_RXDMAWU | LEUART_CTRL_TXDMAWU;
<> 144:ef7eb2e8f9f7 681 } else {
<> 144:ef7eb2e8f9f7 682 obj->serial.periph.uart->IFC = USART_IFC_TXC;
<> 144:ef7eb2e8f9f7 683 }
<> 144:ef7eb2e8f9f7 684
<> 144:ef7eb2e8f9f7 685 /* If this is the UART to be used for stdio, copy it to the stdio_uart struct */
<> 150:02e0a0aed4ec 686 if(obj == &stdio_uart) {
<> 144:ef7eb2e8f9f7 687 stdio_uart_inited = 1;
<> 144:ef7eb2e8f9f7 688 memcpy(&stdio_uart, obj, sizeof(serial_t));
<> 144:ef7eb2e8f9f7 689 }
<> 144:ef7eb2e8f9f7 690
<> 144:ef7eb2e8f9f7 691 serial_enable_pins(obj, true);
<> 144:ef7eb2e8f9f7 692 serial_enable(obj, true);
<> 144:ef7eb2e8f9f7 693
<> 144:ef7eb2e8f9f7 694 obj->serial.dmaOptionsTX.dmaChannel = -1;
<> 144:ef7eb2e8f9f7 695 obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
<> 144:ef7eb2e8f9f7 696
<> 144:ef7eb2e8f9f7 697 obj->serial.dmaOptionsRX.dmaChannel = -1;
<> 144:ef7eb2e8f9f7 698 obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
<> 144:ef7eb2e8f9f7 699
<> 144:ef7eb2e8f9f7 700 }
<> 144:ef7eb2e8f9f7 701
<> 144:ef7eb2e8f9f7 702 void serial_free(serial_t *obj)
<> 144:ef7eb2e8f9f7 703 {
<> 144:ef7eb2e8f9f7 704 if( LEUART_REF_VALID(obj->serial.periph.leuart) ) {
<> 144:ef7eb2e8f9f7 705 LEUART_Enable(obj->serial.periph.leuart, leuartDisable);
<> 144:ef7eb2e8f9f7 706 } else {
<> 144:ef7eb2e8f9f7 707 USART_Enable(obj->serial.periph.uart, usartDisable);
<> 144:ef7eb2e8f9f7 708 }
<> 144:ef7eb2e8f9f7 709 serial_enable_pins(obj, false);
<> 144:ef7eb2e8f9f7 710 }
<> 144:ef7eb2e8f9f7 711
<> 144:ef7eb2e8f9f7 712 static void serial_enable(serial_t *obj, uint8_t enable)
<> 144:ef7eb2e8f9f7 713 {
<> 144:ef7eb2e8f9f7 714 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 715 if (enable) {
<> 144:ef7eb2e8f9f7 716 LEUART_Enable(obj->serial.periph.leuart, leuartEnable);
<> 144:ef7eb2e8f9f7 717 } else {
<> 144:ef7eb2e8f9f7 718 LEUART_Enable(obj->serial.periph.leuart, leuartDisable);
<> 144:ef7eb2e8f9f7 719 }
<> 144:ef7eb2e8f9f7 720 } else {
<> 144:ef7eb2e8f9f7 721 if (enable) {
<> 144:ef7eb2e8f9f7 722 USART_Enable(obj->serial.periph.uart, usartEnable);
<> 144:ef7eb2e8f9f7 723 } else {
<> 144:ef7eb2e8f9f7 724 USART_Enable(obj->serial.periph.uart, usartDisable);
<> 144:ef7eb2e8f9f7 725 }
<> 144:ef7eb2e8f9f7 726 }
<> 144:ef7eb2e8f9f7 727 serial_irq_ids[serial_get_index(obj)] = 0;
<> 144:ef7eb2e8f9f7 728 }
<> 144:ef7eb2e8f9f7 729
<> 144:ef7eb2e8f9f7 730 /**
<> 144:ef7eb2e8f9f7 731 * Set UART baud rate
<> 144:ef7eb2e8f9f7 732 */
<> 144:ef7eb2e8f9f7 733 void serial_baud(serial_t *obj, int baudrate)
<> 144:ef7eb2e8f9f7 734 {
<> 144:ef7eb2e8f9f7 735 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 736 serial_leuart_baud(obj, baudrate);
<> 144:ef7eb2e8f9f7 737 } else {
<> 144:ef7eb2e8f9f7 738 USART_BaudrateAsyncSet(obj->serial.periph.uart, REFERENCE_FREQUENCY, (uint32_t)baudrate, usartOVS16);
<> 144:ef7eb2e8f9f7 739 }
<> 144:ef7eb2e8f9f7 740 }
<> 144:ef7eb2e8f9f7 741
<> 144:ef7eb2e8f9f7 742 /**
<> 144:ef7eb2e8f9f7 743 * Set LEUART baud rate
<> 144:ef7eb2e8f9f7 744 * Calculate whether LF or HF clock should be used.
<> 144:ef7eb2e8f9f7 745 */
<> 144:ef7eb2e8f9f7 746 static void serial_leuart_baud(serial_t *obj, int baudrate)
<> 144:ef7eb2e8f9f7 747 {
<> 144:ef7eb2e8f9f7 748 #ifdef LEUART_USING_LFXO
<> 144:ef7eb2e8f9f7 749 /* check if baudrate is within allowed range */
<> 144:ef7eb2e8f9f7 750 #if defined(_SILICON_LABS_32B_PLATFORM_2)
<> 144:ef7eb2e8f9f7 751 // P2 has 9 bits + 5 fractional bits in LEUART CLKDIV register
<> 144:ef7eb2e8f9f7 752 MBED_ASSERT(baudrate >= (LEUART_LF_REF_FREQ >> 9));
<> 144:ef7eb2e8f9f7 753 #else
<> 144:ef7eb2e8f9f7 754 // P1 has 7 bits + 5 fractional bits in LEUART CLKDIV register
<> 144:ef7eb2e8f9f7 755 MBED_ASSERT(baudrate >= (LEUART_LF_REF_FREQ >> 7));
<> 144:ef7eb2e8f9f7 756 #endif
<> 144:ef7eb2e8f9f7 757
<> 144:ef7eb2e8f9f7 758 if(baudrate > (LEUART_LF_REF_FREQ >> 1)){
<> 144:ef7eb2e8f9f7 759 // Baudrate is bigger than LFCLK/2 - we need to use the HF clock
<> 144:ef7eb2e8f9f7 760 uint8_t divisor = 1;
<> 144:ef7eb2e8f9f7 761
<> 144:ef7eb2e8f9f7 762 #if defined(_SILICON_LABS_32B_PLATFORM_2)
<> 144:ef7eb2e8f9f7 763 /* Check if baudrate is within allowed range: (HFCLK/4096, HFCLK/2] */
<> 144:ef7eb2e8f9f7 764 MBED_ASSERT((baudrate <= (LEUART_HF_REF_FREQ >> 1)) && (baudrate > (LEUART_HF_REF_FREQ >> 12)));
<> 144:ef7eb2e8f9f7 765
<> 144:ef7eb2e8f9f7 766 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_HFCLKLE);
<> 144:ef7eb2e8f9f7 767
<> 144:ef7eb2e8f9f7 768 if(baudrate > (LEUART_HF_REF_FREQ >> 9)){
<> 144:ef7eb2e8f9f7 769 divisor = 1;
<> 144:ef7eb2e8f9f7 770 }else if(baudrate > (LEUART_HF_REF_FREQ >> 10)){
<> 144:ef7eb2e8f9f7 771 divisor = 2;
<> 144:ef7eb2e8f9f7 772 }else if(baudrate > (LEUART_HF_REF_FREQ >> 11)){
<> 144:ef7eb2e8f9f7 773 divisor = 4;
<> 144:ef7eb2e8f9f7 774 }else{
<> 144:ef7eb2e8f9f7 775 divisor = 8;
<> 144:ef7eb2e8f9f7 776 }
<> 144:ef7eb2e8f9f7 777 #else // P1
<> 144:ef7eb2e8f9f7 778 /* Check if baudrate is within allowed range */
<> 144:ef7eb2e8f9f7 779 MBED_ASSERT((baudrate <= (LEUART_HF_REF_FREQ >> 1)) && (baudrate > (LEUART_HF_REF_FREQ >> 10)));
<> 144:ef7eb2e8f9f7 780
<> 144:ef7eb2e8f9f7 781 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
<> 144:ef7eb2e8f9f7 782
<> 144:ef7eb2e8f9f7 783 if(baudrate > (LEUART_HF_REF_FREQ >> 7)){
<> 144:ef7eb2e8f9f7 784 divisor = 1;
<> 144:ef7eb2e8f9f7 785 }else if(baudrate > (LEUART_HF_REF_FREQ >> 8)){
<> 144:ef7eb2e8f9f7 786 divisor = 2;
<> 144:ef7eb2e8f9f7 787 }else if(baudrate > (LEUART_HF_REF_FREQ >> 9)){
<> 144:ef7eb2e8f9f7 788 divisor = 4;
<> 144:ef7eb2e8f9f7 789 }else{
<> 144:ef7eb2e8f9f7 790 divisor = 8;
<> 144:ef7eb2e8f9f7 791 }
<> 144:ef7eb2e8f9f7 792 #endif
<> 144:ef7eb2e8f9f7 793 CMU_ClockDivSet(serial_get_clock(obj), divisor);
<> 144:ef7eb2e8f9f7 794 LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_HF_REF_FREQ/divisor, (uint32_t)baudrate);
<> 144:ef7eb2e8f9f7 795 }else{
<> 144:ef7eb2e8f9f7 796 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
<> 144:ef7eb2e8f9f7 797 CMU_ClockDivSet(serial_get_clock(obj), 1);
<> 144:ef7eb2e8f9f7 798 LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_LF_REF_FREQ, (uint32_t)baudrate);
<> 144:ef7eb2e8f9f7 799 }
<> 144:ef7eb2e8f9f7 800 #else
<> 144:ef7eb2e8f9f7 801 /* check if baudrate is within allowed range */
<> 144:ef7eb2e8f9f7 802 MBED_ASSERT((baudrate > (LEUART_REF_FREQ >> 10)) && (baudrate <= (LEUART_REF_FREQ >> 1)));
<> 144:ef7eb2e8f9f7 803 uint8_t divisor = 1;
<> 144:ef7eb2e8f9f7 804 if(baudrate > (LEUART_REF_FREQ >> 7)){
<> 144:ef7eb2e8f9f7 805 divisor = 1;
<> 144:ef7eb2e8f9f7 806 }else if(baudrate > (LEUART_REF_FREQ >> 8)){
<> 144:ef7eb2e8f9f7 807 divisor = 2;
<> 144:ef7eb2e8f9f7 808 }else if(baudrate > (LEUART_REF_FREQ >> 9)){
<> 144:ef7eb2e8f9f7 809 divisor = 4;
<> 144:ef7eb2e8f9f7 810 }else{
<> 144:ef7eb2e8f9f7 811 divisor = 8;
<> 144:ef7eb2e8f9f7 812 }
<> 144:ef7eb2e8f9f7 813 CMU_ClockDivSet(serial_get_clock(obj), divisor);
<> 144:ef7eb2e8f9f7 814 LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_REF_FREQ/divisor, (uint32_t)baudrate);
<> 144:ef7eb2e8f9f7 815 #endif
<> 144:ef7eb2e8f9f7 816 }
<> 144:ef7eb2e8f9f7 817
<> 144:ef7eb2e8f9f7 818 /**
<> 144:ef7eb2e8f9f7 819 * Set UART format by re-initializing the peripheral.
<> 144:ef7eb2e8f9f7 820 */
<> 144:ef7eb2e8f9f7 821 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
<> 144:ef7eb2e8f9f7 822 {
<> 144:ef7eb2e8f9f7 823 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 824 /* Save the serial state */
<> 144:ef7eb2e8f9f7 825 uint8_t was_enabled = LEUART_StatusGet(obj->serial.periph.leuart) & (LEUART_STATUS_TXENS | LEUART_STATUS_RXENS);
<> 144:ef7eb2e8f9f7 826 uint32_t enabled_interrupts = obj->serial.periph.leuart->IEN;
<> 144:ef7eb2e8f9f7 827
<> 144:ef7eb2e8f9f7 828 LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
<> 144:ef7eb2e8f9f7 829
<> 144:ef7eb2e8f9f7 830 /* We support 8 data bits ONLY on LEUART*/
<> 144:ef7eb2e8f9f7 831 MBED_ASSERT(data_bits == 8);
<> 144:ef7eb2e8f9f7 832
<> 144:ef7eb2e8f9f7 833 /* Re-init the UART */
<> 144:ef7eb2e8f9f7 834 init.enable = (was_enabled == 0 ? leuartDisable : leuartEnable);
<> 144:ef7eb2e8f9f7 835 init.baudrate = LEUART_BaudrateGet(obj->serial.periph.leuart);
<> 144:ef7eb2e8f9f7 836 if (stop_bits == 2) {
<> 144:ef7eb2e8f9f7 837 init.stopbits = leuartStopbits2;
<> 144:ef7eb2e8f9f7 838 } else {
<> 144:ef7eb2e8f9f7 839 init.stopbits = leuartStopbits1;
<> 144:ef7eb2e8f9f7 840 }
<> 144:ef7eb2e8f9f7 841 switch (parity) {
<> 144:ef7eb2e8f9f7 842 case ParityOdd:
<> 144:ef7eb2e8f9f7 843 case ParityForced0:
<> 144:ef7eb2e8f9f7 844 init.parity = leuartOddParity;
<> 144:ef7eb2e8f9f7 845 break;
<> 144:ef7eb2e8f9f7 846 case ParityEven:
<> 144:ef7eb2e8f9f7 847 case ParityForced1:
<> 144:ef7eb2e8f9f7 848 init.parity = leuartEvenParity;
<> 144:ef7eb2e8f9f7 849 break;
<> 144:ef7eb2e8f9f7 850 default: /* ParityNone */
<> 144:ef7eb2e8f9f7 851 init.parity = leuartNoParity;
<> 144:ef7eb2e8f9f7 852 break;
<> 144:ef7eb2e8f9f7 853 }
<> 144:ef7eb2e8f9f7 854
<> 144:ef7eb2e8f9f7 855 LEUART_Init(obj->serial.periph.leuart, &init);
<> 144:ef7eb2e8f9f7 856
<> 144:ef7eb2e8f9f7 857 /* Re-enable pins for UART at correct location */
<> 144:ef7eb2e8f9f7 858 serial_set_route(obj);
<> 144:ef7eb2e8f9f7 859
<> 144:ef7eb2e8f9f7 860 /* Re-enable interrupts */
<> 144:ef7eb2e8f9f7 861 if(was_enabled != 0) {
<> 144:ef7eb2e8f9f7 862 obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
<> 144:ef7eb2e8f9f7 863 obj->serial.periph.leuart->IEN = enabled_interrupts;
<> 144:ef7eb2e8f9f7 864 }
<> 144:ef7eb2e8f9f7 865 } else {
<> 144:ef7eb2e8f9f7 866 /* Save the serial state */
<> 144:ef7eb2e8f9f7 867 uint8_t was_enabled = USART_StatusGet(obj->serial.periph.uart) & (USART_STATUS_TXENS | USART_STATUS_RXENS);
<> 144:ef7eb2e8f9f7 868 uint32_t enabled_interrupts = obj->serial.periph.uart->IEN;
<> 144:ef7eb2e8f9f7 869
<> 144:ef7eb2e8f9f7 870
<> 144:ef7eb2e8f9f7 871 USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
<> 144:ef7eb2e8f9f7 872
<> 144:ef7eb2e8f9f7 873 /* We support 4 to 8 data bits */
<> 144:ef7eb2e8f9f7 874 MBED_ASSERT(data_bits >= 4 && data_bits <= 8);
<> 144:ef7eb2e8f9f7 875
<> 144:ef7eb2e8f9f7 876 /* Re-init the UART */
<> 144:ef7eb2e8f9f7 877 init.enable = (was_enabled == 0 ? usartDisable : usartEnable);
<> 144:ef7eb2e8f9f7 878 init.baudrate = USART_BaudrateGet(obj->serial.periph.uart);
<> 144:ef7eb2e8f9f7 879 init.oversampling = usartOVS16;
<> 144:ef7eb2e8f9f7 880 init.databits = (USART_Databits_TypeDef)((data_bits - 3) << _USART_FRAME_DATABITS_SHIFT);
<> 144:ef7eb2e8f9f7 881 if (stop_bits == 2) {
<> 144:ef7eb2e8f9f7 882 init.stopbits = usartStopbits2;
<> 144:ef7eb2e8f9f7 883 } else {
<> 144:ef7eb2e8f9f7 884 init.stopbits = usartStopbits1;
<> 144:ef7eb2e8f9f7 885 }
<> 144:ef7eb2e8f9f7 886 switch (parity) {
<> 144:ef7eb2e8f9f7 887 case ParityOdd:
<> 144:ef7eb2e8f9f7 888 case ParityForced0:
<> 144:ef7eb2e8f9f7 889 init.parity = usartOddParity;
<> 144:ef7eb2e8f9f7 890 break;
<> 144:ef7eb2e8f9f7 891 case ParityEven:
<> 144:ef7eb2e8f9f7 892 case ParityForced1:
<> 144:ef7eb2e8f9f7 893 init.parity = usartEvenParity;
<> 144:ef7eb2e8f9f7 894 break;
<> 144:ef7eb2e8f9f7 895 default: /* ParityNone */
<> 144:ef7eb2e8f9f7 896 init.parity = usartNoParity;
<> 144:ef7eb2e8f9f7 897 break;
<> 144:ef7eb2e8f9f7 898 }
<> 144:ef7eb2e8f9f7 899
<> 144:ef7eb2e8f9f7 900 USART_InitAsync(obj->serial.periph.uart, &init);
<> 144:ef7eb2e8f9f7 901
<> 144:ef7eb2e8f9f7 902 /* Re-enable pins for UART at correct location */
<> 144:ef7eb2e8f9f7 903 serial_set_route(obj);
<> 144:ef7eb2e8f9f7 904
<> 144:ef7eb2e8f9f7 905 /* Re-enable interrupts */
<> 144:ef7eb2e8f9f7 906 if(was_enabled != 0) {
<> 144:ef7eb2e8f9f7 907 obj->serial.periph.uart->IFC = USART_IFC_TXC;
<> 144:ef7eb2e8f9f7 908 obj->serial.periph.uart->IEN = enabled_interrupts;
<> 144:ef7eb2e8f9f7 909 }
<> 144:ef7eb2e8f9f7 910 }
<> 144:ef7eb2e8f9f7 911 }
<> 144:ef7eb2e8f9f7 912
<> 144:ef7eb2e8f9f7 913 /******************************************************************************
<> 144:ef7eb2e8f9f7 914 * INTERRUPTS *
<> 144:ef7eb2e8f9f7 915 ******************************************************************************/
<> 144:ef7eb2e8f9f7 916 uint8_t serial_tx_ready(serial_t *obj)
<> 144:ef7eb2e8f9f7 917 {
<> 144:ef7eb2e8f9f7 918 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 919 return (obj->serial.periph.leuart->STATUS & LEUART_STATUS_TXBL) ? true : false;
<> 144:ef7eb2e8f9f7 920 } else {
<> 144:ef7eb2e8f9f7 921 return (obj->serial.periph.uart->STATUS & USART_STATUS_TXBL) ? true : false;
<> 144:ef7eb2e8f9f7 922 }
<> 144:ef7eb2e8f9f7 923 }
<> 144:ef7eb2e8f9f7 924
<> 144:ef7eb2e8f9f7 925 uint8_t serial_rx_ready(serial_t *obj)
<> 144:ef7eb2e8f9f7 926 {
<> 144:ef7eb2e8f9f7 927 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 928 return (obj->serial.periph.leuart->STATUS & LEUART_STATUS_RXDATAV) ? true : false;
<> 144:ef7eb2e8f9f7 929 } else {
<> 144:ef7eb2e8f9f7 930 return (obj->serial.periph.uart->STATUS & USART_STATUS_RXDATAV) ? true : false;
<> 144:ef7eb2e8f9f7 931 }
<> 144:ef7eb2e8f9f7 932 }
<> 144:ef7eb2e8f9f7 933
<> 144:ef7eb2e8f9f7 934 void serial_write_asynch(serial_t *obj, int data)
<> 144:ef7eb2e8f9f7 935 {
<> 144:ef7eb2e8f9f7 936 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 937 obj->serial.periph.leuart->TXDATA = (uint32_t)data;
<> 144:ef7eb2e8f9f7 938 } else {
<> 144:ef7eb2e8f9f7 939 obj->serial.periph.uart->TXDATA = (uint32_t)data;
<> 144:ef7eb2e8f9f7 940 }
<> 144:ef7eb2e8f9f7 941 }
<> 144:ef7eb2e8f9f7 942
<> 144:ef7eb2e8f9f7 943 int serial_read_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 944 {
<> 144:ef7eb2e8f9f7 945 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 946 return (int)obj->serial.periph.leuart->RXDATA;
<> 144:ef7eb2e8f9f7 947 } else {
<> 144:ef7eb2e8f9f7 948 return (int)obj->serial.periph.uart->RXDATA;
<> 144:ef7eb2e8f9f7 949 }
<> 144:ef7eb2e8f9f7 950 }
<> 144:ef7eb2e8f9f7 951
<> 144:ef7eb2e8f9f7 952 uint8_t serial_tx_int_flag(serial_t *obj)
<> 144:ef7eb2e8f9f7 953 {
<> 144:ef7eb2e8f9f7 954 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 955 return (obj->serial.periph.leuart->IF & LEUART_IF_TXBL) ? true : false;
<> 144:ef7eb2e8f9f7 956 } else {
<> 144:ef7eb2e8f9f7 957 return (obj->serial.periph.uart->IF & USART_IF_TXBL) ? true : false;
<> 144:ef7eb2e8f9f7 958 }
<> 144:ef7eb2e8f9f7 959 }
<> 144:ef7eb2e8f9f7 960
<> 144:ef7eb2e8f9f7 961 uint8_t serial_rx_int_flag(serial_t *obj)
<> 144:ef7eb2e8f9f7 962 {
<> 144:ef7eb2e8f9f7 963 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 964 return (obj->serial.periph.leuart->IF & LEUART_IF_RXDATAV) ? true : false;
<> 144:ef7eb2e8f9f7 965 } else {
<> 144:ef7eb2e8f9f7 966 return (obj->serial.periph.uart->IF & USART_IF_RXDATAV) ? true : false;
<> 144:ef7eb2e8f9f7 967 }
<> 144:ef7eb2e8f9f7 968 }
<> 144:ef7eb2e8f9f7 969
<> 144:ef7eb2e8f9f7 970 void serial_read_asynch_complete(serial_t *obj)
<> 144:ef7eb2e8f9f7 971 {
<> 144:ef7eb2e8f9f7 972 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 973 obj->serial.periph.leuart->IFC |= LEUART_IFC_RXOF; // in case it got full
<> 144:ef7eb2e8f9f7 974 } else {
<> 144:ef7eb2e8f9f7 975 obj->serial.periph.uart->IFC |= USART_IFC_RXFULL; // in case it got full
<> 144:ef7eb2e8f9f7 976 }
<> 144:ef7eb2e8f9f7 977 }
<> 144:ef7eb2e8f9f7 978
<> 144:ef7eb2e8f9f7 979 void serial_write_asynch_complete(serial_t *obj)
<> 144:ef7eb2e8f9f7 980 {
<> 144:ef7eb2e8f9f7 981 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 982 obj->serial.periph.leuart->IFC |= LEUART_IFC_TXC;
<> 144:ef7eb2e8f9f7 983 } else {
<> 144:ef7eb2e8f9f7 984 obj->serial.periph.uart->IFC |= USART_IFC_TXC;
<> 144:ef7eb2e8f9f7 985 }
<> 144:ef7eb2e8f9f7 986 }
<> 144:ef7eb2e8f9f7 987
<> 144:ef7eb2e8f9f7 988 /** Enable and set the interrupt handler for write (TX)
<> 144:ef7eb2e8f9f7 989 *
<> 144:ef7eb2e8f9f7 990 * @param obj The serial object
<> 144:ef7eb2e8f9f7 991 * @param address The address of TX handler
<> 144:ef7eb2e8f9f7 992 * @param enable Set to non-zero to enable or zero to disable
<> 144:ef7eb2e8f9f7 993 */
<> 144:ef7eb2e8f9f7 994 void serial_write_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable)
<> 144:ef7eb2e8f9f7 995 {
<> 144:ef7eb2e8f9f7 996 NVIC_SetVector(serial_get_tx_irq_index(obj), address);
<> 144:ef7eb2e8f9f7 997 serial_irq_set(obj, (SerialIrq)1, enable);
<> 144:ef7eb2e8f9f7 998 }
<> 144:ef7eb2e8f9f7 999
<> 144:ef7eb2e8f9f7 1000 /** Enable and set the interrupt handler for read (RX)
<> 144:ef7eb2e8f9f7 1001 *
<> 144:ef7eb2e8f9f7 1002 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1003 * @param address The address of RX handler
<> 144:ef7eb2e8f9f7 1004 * @param enable Set to non-zero to enable or zero to disable
<> 144:ef7eb2e8f9f7 1005 */
<> 144:ef7eb2e8f9f7 1006 void serial_read_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable)
<> 144:ef7eb2e8f9f7 1007 {
<> 144:ef7eb2e8f9f7 1008 NVIC_SetVector(serial_get_rx_irq_index(obj), address);
<> 144:ef7eb2e8f9f7 1009 serial_irq_set(obj, (SerialIrq)0, enable);
<> 144:ef7eb2e8f9f7 1010 }
<> 144:ef7eb2e8f9f7 1011
<> 144:ef7eb2e8f9f7 1012 uint8_t serial_interrupt_enabled(serial_t *obj)
<> 144:ef7eb2e8f9f7 1013 {
<> 144:ef7eb2e8f9f7 1014 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1015 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV | LEUART_IEN_TXBL)) ? true : false;
<> 144:ef7eb2e8f9f7 1016 } else {
<> 144:ef7eb2e8f9f7 1017 return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV | USART_IEN_TXBL)) ? true : false;
<> 144:ef7eb2e8f9f7 1018 }
<> 144:ef7eb2e8f9f7 1019 }
<> 144:ef7eb2e8f9f7 1020
<> 144:ef7eb2e8f9f7 1021 /**
<> 144:ef7eb2e8f9f7 1022 * Set handler for all serial interrupts (is probably SerialBase::_handler())
<> 144:ef7eb2e8f9f7 1023 * and store IRQ ID to be returned to the handler upon interrupt. ID is
<> 144:ef7eb2e8f9f7 1024 * probably a pointer to the calling Serial object.
<> 144:ef7eb2e8f9f7 1025 */
<> 144:ef7eb2e8f9f7 1026 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
<> 144:ef7eb2e8f9f7 1027 {
<> 144:ef7eb2e8f9f7 1028 irq_handler = handler;
<> 144:ef7eb2e8f9f7 1029 serial_irq_ids[serial_get_index(obj)] = id;
<> 144:ef7eb2e8f9f7 1030 }
<> 144:ef7eb2e8f9f7 1031
<> 144:ef7eb2e8f9f7 1032 /**
<> 144:ef7eb2e8f9f7 1033 * Generic ISR for all UARTs, both TX and RX
<> 144:ef7eb2e8f9f7 1034 */
<> 144:ef7eb2e8f9f7 1035 static void uart_irq(UARTName name, SerialIrq irq)
<> 144:ef7eb2e8f9f7 1036 {
<> 144:ef7eb2e8f9f7 1037 uint8_t index = serial_pointer_get_index((uint32_t)name);
<> 144:ef7eb2e8f9f7 1038 if (serial_irq_ids[index] != 0) {
<> 144:ef7eb2e8f9f7 1039 /* Pass interrupt on to mbed common handler */
<> 144:ef7eb2e8f9f7 1040 irq_handler(serial_irq_ids[index], irq);
<> 144:ef7eb2e8f9f7 1041 /* Clearing interrupt not necessary */
<> 144:ef7eb2e8f9f7 1042 }
<> 144:ef7eb2e8f9f7 1043 }
<> 144:ef7eb2e8f9f7 1044
<> 144:ef7eb2e8f9f7 1045 /**
<> 144:ef7eb2e8f9f7 1046 * Set ISR for a given UART and interrupt event (TX or RX)
<> 144:ef7eb2e8f9f7 1047 */
<> 144:ef7eb2e8f9f7 1048 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
<> 144:ef7eb2e8f9f7 1049 {
<> 144:ef7eb2e8f9f7 1050 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1051 /* Enable or disable interrupt */
<> 144:ef7eb2e8f9f7 1052 if (enable) {
<> 144:ef7eb2e8f9f7 1053 if (irq == RxIrq) { /* RX */
<> 144:ef7eb2e8f9f7 1054 obj->serial.periph.leuart->IEN |= LEUART_IEN_RXDATAV;
<> 144:ef7eb2e8f9f7 1055 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1056 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1057 } else { /* TX */
<> 144:ef7eb2e8f9f7 1058 obj->serial.periph.leuart->IEN |= LEUART_IEN_TXC;
<> 144:ef7eb2e8f9f7 1059 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1060 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
<> 144:ef7eb2e8f9f7 1061 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1062 }
<> 144:ef7eb2e8f9f7 1063 } else {
<> 144:ef7eb2e8f9f7 1064 if (irq == RxIrq) { /* RX */
<> 144:ef7eb2e8f9f7 1065 obj->serial.periph.leuart->IEN &= ~LEUART_IEN_RXDATAV;
<> 144:ef7eb2e8f9f7 1066 NVIC_DisableIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1067 } else { /* TX */
<> 144:ef7eb2e8f9f7 1068 obj->serial.periph.leuart->IEN &= ~LEUART_IEN_TXC;
<> 144:ef7eb2e8f9f7 1069 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1070 }
<> 144:ef7eb2e8f9f7 1071 }
<> 144:ef7eb2e8f9f7 1072 } else {
<> 144:ef7eb2e8f9f7 1073 /* Enable or disable interrupt */
<> 144:ef7eb2e8f9f7 1074 if (enable) {
<> 144:ef7eb2e8f9f7 1075 if (irq == RxIrq) { /* RX */
<> 144:ef7eb2e8f9f7 1076 obj->serial.periph.uart->IEN |= USART_IEN_RXDATAV;
<> 144:ef7eb2e8f9f7 1077 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1078 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1079 } else { /* TX */
<> 144:ef7eb2e8f9f7 1080 obj->serial.periph.uart->IEN |= USART_IEN_TXC;
<> 144:ef7eb2e8f9f7 1081 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1082 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
<> 144:ef7eb2e8f9f7 1083 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1084 }
<> 144:ef7eb2e8f9f7 1085 } else {
<> 144:ef7eb2e8f9f7 1086 if (irq == RxIrq) { /* RX */
<> 144:ef7eb2e8f9f7 1087 obj->serial.periph.uart->IEN &= ~USART_IEN_RXDATAV;
<> 144:ef7eb2e8f9f7 1088 NVIC_DisableIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1089 } else { /* TX */
<> 144:ef7eb2e8f9f7 1090 obj->serial.periph.uart->IEN &= ~USART_IEN_TXC;
<> 144:ef7eb2e8f9f7 1091 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1092 }
<> 144:ef7eb2e8f9f7 1093 }
<> 144:ef7eb2e8f9f7 1094 }
<> 144:ef7eb2e8f9f7 1095 }
<> 144:ef7eb2e8f9f7 1096
<> 144:ef7eb2e8f9f7 1097 /******************************************************************************
<> 144:ef7eb2e8f9f7 1098 * READ/WRITE *
<> 144:ef7eb2e8f9f7 1099 ******************************************************************************/
<> 144:ef7eb2e8f9f7 1100
<> 144:ef7eb2e8f9f7 1101 /**
<> 144:ef7eb2e8f9f7 1102 * Get one char from serial link
<> 144:ef7eb2e8f9f7 1103 */
<> 144:ef7eb2e8f9f7 1104 int serial_getc(serial_t *obj)
<> 144:ef7eb2e8f9f7 1105 {
<> 144:ef7eb2e8f9f7 1106 /* Emlib USART_Rx blocks until data is available, so we don't need to use
<> 144:ef7eb2e8f9f7 1107 * serial_readable(). Use USART_RxDataGet() to read register directly. */
<> 144:ef7eb2e8f9f7 1108 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1109 return LEUART_Rx(obj->serial.periph.leuart);
<> 144:ef7eb2e8f9f7 1110 } else {
<> 144:ef7eb2e8f9f7 1111 return USART_Rx(obj->serial.periph.uart);
<> 144:ef7eb2e8f9f7 1112 }
<> 144:ef7eb2e8f9f7 1113 }
<> 144:ef7eb2e8f9f7 1114
<> 144:ef7eb2e8f9f7 1115 /*
<> 144:ef7eb2e8f9f7 1116 * Send one char over serial link
<> 144:ef7eb2e8f9f7 1117 */
<> 144:ef7eb2e8f9f7 1118 void serial_putc(serial_t *obj, int c)
<> 144:ef7eb2e8f9f7 1119 {
<> 144:ef7eb2e8f9f7 1120 /* Emlib USART_Tx blocks until buffer is writable (non-full), so we don't
<> 144:ef7eb2e8f9f7 1121 * need to use serial_writable(). */
<> 144:ef7eb2e8f9f7 1122 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1123 LEUART_Tx(obj->serial.periph.leuart, (uint8_t)(c));
<> 144:ef7eb2e8f9f7 1124 while (!(obj->serial.periph.leuart->STATUS & LEUART_STATUS_TXC));
<> 144:ef7eb2e8f9f7 1125 } else {
<> 144:ef7eb2e8f9f7 1126 USART_Tx(obj->serial.periph.uart, (uint8_t)(c));
<> 144:ef7eb2e8f9f7 1127 while (!(obj->serial.periph.uart->STATUS & USART_STATUS_TXC));
<> 144:ef7eb2e8f9f7 1128 }
<> 144:ef7eb2e8f9f7 1129 }
<> 144:ef7eb2e8f9f7 1130
<> 144:ef7eb2e8f9f7 1131 /**
<> 144:ef7eb2e8f9f7 1132 * Check if data is available in RX data vector
<> 144:ef7eb2e8f9f7 1133 */
<> 144:ef7eb2e8f9f7 1134 int serial_readable(serial_t *obj)
<> 144:ef7eb2e8f9f7 1135 {
<> 144:ef7eb2e8f9f7 1136 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1137 return obj->serial.periph.leuart->STATUS & LEUART_STATUS_RXDATAV;
<> 144:ef7eb2e8f9f7 1138 } else {
<> 144:ef7eb2e8f9f7 1139 return obj->serial.periph.uart->STATUS & USART_STATUS_RXDATAV;
<> 144:ef7eb2e8f9f7 1140 }
<> 144:ef7eb2e8f9f7 1141 }
<> 144:ef7eb2e8f9f7 1142
<> 144:ef7eb2e8f9f7 1143 /**
<> 144:ef7eb2e8f9f7 1144 * Check if TX buffer is empty
<> 144:ef7eb2e8f9f7 1145 */
<> 144:ef7eb2e8f9f7 1146 int serial_writable(serial_t *obj)
<> 144:ef7eb2e8f9f7 1147 {
<> 144:ef7eb2e8f9f7 1148 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1149 return obj->serial.periph.leuart->STATUS & LEUART_STATUS_TXBL;
<> 144:ef7eb2e8f9f7 1150 } else {
<> 144:ef7eb2e8f9f7 1151 return obj->serial.periph.uart->STATUS & USART_STATUS_TXBL;
<> 144:ef7eb2e8f9f7 1152 }
<> 144:ef7eb2e8f9f7 1153 }
<> 144:ef7eb2e8f9f7 1154
<> 144:ef7eb2e8f9f7 1155 /**
<> 144:ef7eb2e8f9f7 1156 * Clear UART interrupts
<> 144:ef7eb2e8f9f7 1157 */
<> 144:ef7eb2e8f9f7 1158 void serial_clear(serial_t *obj)
<> 144:ef7eb2e8f9f7 1159 {
<> 144:ef7eb2e8f9f7 1160 /* Interrupts automatically clear when condition is not met anymore */
<> 144:ef7eb2e8f9f7 1161 }
<> 144:ef7eb2e8f9f7 1162
<> 144:ef7eb2e8f9f7 1163 void serial_break_set(serial_t *obj)
<> 144:ef7eb2e8f9f7 1164 {
<> 144:ef7eb2e8f9f7 1165 /* Send transmission break */
<> 144:ef7eb2e8f9f7 1166 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1167 obj->serial.periph.leuart->TXDATAX = LEUART_TXDATAX_TXBREAK;
<> 144:ef7eb2e8f9f7 1168 } else {
<> 144:ef7eb2e8f9f7 1169 obj->serial.periph.uart->TXDATAX = USART_TXDATAX_TXBREAK;
<> 144:ef7eb2e8f9f7 1170 }
<> 144:ef7eb2e8f9f7 1171 }
<> 144:ef7eb2e8f9f7 1172
<> 144:ef7eb2e8f9f7 1173 void serial_break_clear(serial_t *obj)
<> 144:ef7eb2e8f9f7 1174 {
<> 144:ef7eb2e8f9f7 1175 /* No need to clear break, it is automatically cleared after one frame.
<> 144:ef7eb2e8f9f7 1176 * From the reference manual:
<> 144:ef7eb2e8f9f7 1177 *
<> 144:ef7eb2e8f9f7 1178 * By setting TXBREAK, the output will be held low during the stop-bit
<> 144:ef7eb2e8f9f7 1179 * period to generate a framing error. A receiver that supports break
<> 144:ef7eb2e8f9f7 1180 * detection detects this state, allowing it to be used e.g. for framing
<> 144:ef7eb2e8f9f7 1181 * of larger data packets. The line is driven high before the next frame
<> 144:ef7eb2e8f9f7 1182 * is transmitted so the next start condition can be identified correctly
<> 144:ef7eb2e8f9f7 1183 * by the recipient. Continuous breaks lasting longer than a USART frame
<> 144:ef7eb2e8f9f7 1184 * are thus not supported by the USART. GPIO can be used for this.
<> 144:ef7eb2e8f9f7 1185 */
<> 144:ef7eb2e8f9f7 1186 }
<> 144:ef7eb2e8f9f7 1187
<> 144:ef7eb2e8f9f7 1188 void serial_pinout_tx(PinName tx)
<> 144:ef7eb2e8f9f7 1189 {
<> 144:ef7eb2e8f9f7 1190 /* 0x10 sets DOUT high. Prevents false start. */
<> 144:ef7eb2e8f9f7 1191 pin_mode(tx, PushPull | 0x10);
<> 144:ef7eb2e8f9f7 1192 }
<> 144:ef7eb2e8f9f7 1193
<> 144:ef7eb2e8f9f7 1194 /************************************************************************************
<> 144:ef7eb2e8f9f7 1195 * DMA helper functions *
<> 144:ef7eb2e8f9f7 1196 ************************************************************************************/
<> 144:ef7eb2e8f9f7 1197 /******************************************
<> 144:ef7eb2e8f9f7 1198 * static void serial_dmaTransferComplete(uint channel, bool primary, void* user)
<> 144:ef7eb2e8f9f7 1199 *
<> 144:ef7eb2e8f9f7 1200 * Callback function which gets called upon DMA transfer completion
<> 144:ef7eb2e8f9f7 1201 * the user-defined pointer is pointing to the CPP-land thunk
<> 144:ef7eb2e8f9f7 1202 ******************************************/
<> 144:ef7eb2e8f9f7 1203 static void serial_dmaTransferComplete(unsigned int channel, bool primary, void *user)
<> 144:ef7eb2e8f9f7 1204 {
<> 144:ef7eb2e8f9f7 1205 /* Store information about which channel triggered because CPP doesn't take arguments */
<> 144:ef7eb2e8f9f7 1206 serial_dma_irq_fired[channel] = true;
<> 144:ef7eb2e8f9f7 1207
<> 144:ef7eb2e8f9f7 1208 /* User pointer should be a thunk to CPP land */
<> 144:ef7eb2e8f9f7 1209 if (user != NULL) {
<> 144:ef7eb2e8f9f7 1210 ((DMACallback)user)();
<> 144:ef7eb2e8f9f7 1211 }
<> 144:ef7eb2e8f9f7 1212 }
<> 144:ef7eb2e8f9f7 1213
<> 144:ef7eb2e8f9f7 1214 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 1215
<> 144:ef7eb2e8f9f7 1216 /******************************************
<> 144:ef7eb2e8f9f7 1217 * static void serial_setupDmaChannel(serial_t *obj, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1218 *
<> 144:ef7eb2e8f9f7 1219 * Sets up the DMA configuration block for the assigned channel
<> 144:ef7eb2e8f9f7 1220 * tx_nrx: true if configuring TX, false if configuring RX.
<> 144:ef7eb2e8f9f7 1221 ******************************************/
<> 144:ef7eb2e8f9f7 1222 static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1223 {
<> 144:ef7eb2e8f9f7 1224 DMA_CfgChannel_TypeDef channelConfig;
<> 144:ef7eb2e8f9f7 1225
<> 144:ef7eb2e8f9f7 1226 if(tx_nrx) {
<> 144:ef7eb2e8f9f7 1227 //setup TX channel
<> 144:ef7eb2e8f9f7 1228 channelConfig.highPri = false;
<> 144:ef7eb2e8f9f7 1229 channelConfig.enableInt = true;
<> 144:ef7eb2e8f9f7 1230 channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
<> 144:ef7eb2e8f9f7 1231
<> 144:ef7eb2e8f9f7 1232 switch((uint32_t)(obj->serial.periph.uart)) {
<> 144:ef7eb2e8f9f7 1233 #ifdef UART0
<> 144:ef7eb2e8f9f7 1234 case UART_0:
<> 144:ef7eb2e8f9f7 1235 channelConfig.select = DMAREQ_UART0_TXBL;
<> 144:ef7eb2e8f9f7 1236 break;
<> 144:ef7eb2e8f9f7 1237 #endif
<> 144:ef7eb2e8f9f7 1238 #ifdef UART1
<> 144:ef7eb2e8f9f7 1239 case UART_1:
<> 144:ef7eb2e8f9f7 1240 channelConfig.select = DMAREQ_UART1_TXBL;
<> 144:ef7eb2e8f9f7 1241 break;
<> 144:ef7eb2e8f9f7 1242 #endif
<> 144:ef7eb2e8f9f7 1243 #ifdef USART0
<> 144:ef7eb2e8f9f7 1244 case USART_0:
<> 144:ef7eb2e8f9f7 1245 channelConfig.select = DMAREQ_USART0_TXBL;
<> 144:ef7eb2e8f9f7 1246 break;
<> 144:ef7eb2e8f9f7 1247 #endif
<> 144:ef7eb2e8f9f7 1248 #ifdef USART1
<> 144:ef7eb2e8f9f7 1249 case USART_1:
<> 144:ef7eb2e8f9f7 1250 channelConfig.select = DMAREQ_USART1_TXBL;
<> 144:ef7eb2e8f9f7 1251 break;
<> 144:ef7eb2e8f9f7 1252 #endif
<> 144:ef7eb2e8f9f7 1253 #ifdef USART2
<> 144:ef7eb2e8f9f7 1254 case USART_2:
<> 144:ef7eb2e8f9f7 1255 channelConfig.select = DMAREQ_USART2_TXBL;
<> 144:ef7eb2e8f9f7 1256 break;
<> 144:ef7eb2e8f9f7 1257 #endif
AnnaBridge 179:b0033dcd6934 1258 #ifdef USART3
AnnaBridge 179:b0033dcd6934 1259 case USART_3:
AnnaBridge 179:b0033dcd6934 1260 channelConfig.select = DMAREQ_USART3_TXBL;
AnnaBridge 179:b0033dcd6934 1261 break;
AnnaBridge 179:b0033dcd6934 1262 #endif
AnnaBridge 179:b0033dcd6934 1263 #ifdef USART4
AnnaBridge 179:b0033dcd6934 1264 case USART_4:
AnnaBridge 179:b0033dcd6934 1265 channelConfig.select = DMAREQ_USART4_TXBL;
AnnaBridge 179:b0033dcd6934 1266 break;
AnnaBridge 179:b0033dcd6934 1267 #endif
AnnaBridge 179:b0033dcd6934 1268 #ifdef USART5
AnnaBridge 179:b0033dcd6934 1269 case USART_5:
AnnaBridge 179:b0033dcd6934 1270 channelConfig.select = DMAREQ_USART5_TXBL;
AnnaBridge 179:b0033dcd6934 1271 break;
AnnaBridge 179:b0033dcd6934 1272 #endif
<> 144:ef7eb2e8f9f7 1273 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 1274 case LEUART_0:
<> 144:ef7eb2e8f9f7 1275 channelConfig.select = DMAREQ_LEUART0_TXBL;
<> 144:ef7eb2e8f9f7 1276 break;
<> 144:ef7eb2e8f9f7 1277 #endif
<> 144:ef7eb2e8f9f7 1278 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 1279 case LEUART_1:
<> 144:ef7eb2e8f9f7 1280 channelConfig.select = DMAREQ_LEUART1_TXBL;
<> 144:ef7eb2e8f9f7 1281 break;
<> 144:ef7eb2e8f9f7 1282 #endif
<> 144:ef7eb2e8f9f7 1283 }
<> 144:ef7eb2e8f9f7 1284
<> 144:ef7eb2e8f9f7 1285 DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
<> 144:ef7eb2e8f9f7 1286 } else {
<> 144:ef7eb2e8f9f7 1287 //setup RX channel
<> 144:ef7eb2e8f9f7 1288 channelConfig.highPri = true;
<> 144:ef7eb2e8f9f7 1289 channelConfig.enableInt = true;
<> 144:ef7eb2e8f9f7 1290 channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
<> 144:ef7eb2e8f9f7 1291
<> 144:ef7eb2e8f9f7 1292 switch((uint32_t)(obj->serial.periph.uart)) {
<> 144:ef7eb2e8f9f7 1293 #ifdef UART0
<> 144:ef7eb2e8f9f7 1294 case UART_0:
<> 144:ef7eb2e8f9f7 1295 channelConfig.select = DMAREQ_UART0_RXDATAV;
<> 144:ef7eb2e8f9f7 1296 break;
<> 144:ef7eb2e8f9f7 1297 #endif
<> 144:ef7eb2e8f9f7 1298 #ifdef UART1
<> 144:ef7eb2e8f9f7 1299 case UART_1:
<> 144:ef7eb2e8f9f7 1300 channelConfig.select = DMAREQ_UART1_RXDATAV;
<> 144:ef7eb2e8f9f7 1301 break;
<> 144:ef7eb2e8f9f7 1302 #endif
<> 144:ef7eb2e8f9f7 1303 #ifdef USART0
<> 144:ef7eb2e8f9f7 1304 case USART_0:
<> 144:ef7eb2e8f9f7 1305 channelConfig.select = DMAREQ_USART0_RXDATAV;
<> 144:ef7eb2e8f9f7 1306 break;
<> 144:ef7eb2e8f9f7 1307 #endif
<> 144:ef7eb2e8f9f7 1308 #ifdef USART1
<> 144:ef7eb2e8f9f7 1309 case USART_1:
<> 144:ef7eb2e8f9f7 1310 channelConfig.select = DMAREQ_USART1_RXDATAV;
<> 144:ef7eb2e8f9f7 1311 break;
<> 144:ef7eb2e8f9f7 1312 #endif
<> 144:ef7eb2e8f9f7 1313 #ifdef USART2
<> 144:ef7eb2e8f9f7 1314 case USART_2:
<> 144:ef7eb2e8f9f7 1315 channelConfig.select = DMAREQ_USART2_RXDATAV;
<> 144:ef7eb2e8f9f7 1316 break;
<> 144:ef7eb2e8f9f7 1317 #endif
AnnaBridge 179:b0033dcd6934 1318 #ifdef USART3
AnnaBridge 179:b0033dcd6934 1319 case USART_3:
AnnaBridge 179:b0033dcd6934 1320 channelConfig.select = DMAREQ_USART3_RXDATAV;
AnnaBridge 179:b0033dcd6934 1321 break;
AnnaBridge 179:b0033dcd6934 1322 #endif
AnnaBridge 179:b0033dcd6934 1323 #ifdef USART4
AnnaBridge 179:b0033dcd6934 1324 case USART_4:
AnnaBridge 179:b0033dcd6934 1325 channelConfig.select = DMAREQ_USART4_RXDATAV;
AnnaBridge 179:b0033dcd6934 1326 break;
AnnaBridge 179:b0033dcd6934 1327 #endif
AnnaBridge 179:b0033dcd6934 1328 #ifdef USART5
AnnaBridge 179:b0033dcd6934 1329 case USART_5:
AnnaBridge 179:b0033dcd6934 1330 channelConfig.select = DMAREQ_USART5_RXDATAV;
AnnaBridge 179:b0033dcd6934 1331 break;
AnnaBridge 179:b0033dcd6934 1332 #endif
<> 144:ef7eb2e8f9f7 1333 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 1334 case LEUART_0:
<> 144:ef7eb2e8f9f7 1335 channelConfig.select = DMAREQ_LEUART0_RXDATAV;
<> 144:ef7eb2e8f9f7 1336 break;
<> 144:ef7eb2e8f9f7 1337 #endif
<> 144:ef7eb2e8f9f7 1338 #ifdef LEUART1
<> 144:ef7eb2e8f9f7 1339 case LEUART_1:
<> 144:ef7eb2e8f9f7 1340 channelConfig.select = DMAREQ_LEUART1_RXDATAV;
<> 144:ef7eb2e8f9f7 1341 break;
<> 144:ef7eb2e8f9f7 1342 #endif
<> 144:ef7eb2e8f9f7 1343 }
<> 144:ef7eb2e8f9f7 1344
<> 144:ef7eb2e8f9f7 1345 DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
<> 144:ef7eb2e8f9f7 1346 }
<> 144:ef7eb2e8f9f7 1347 }
<> 144:ef7eb2e8f9f7 1348
<> 144:ef7eb2e8f9f7 1349 #endif /* LDMA_PRESENT */
<> 144:ef7eb2e8f9f7 1350
<> 144:ef7eb2e8f9f7 1351 /******************************************
<> 144:ef7eb2e8f9f7 1352 * static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState)
<> 144:ef7eb2e8f9f7 1353 *
<> 144:ef7eb2e8f9f7 1354 * Tries to set the passed DMA state to the requested state.
<> 144:ef7eb2e8f9f7 1355 *
<> 144:ef7eb2e8f9f7 1356 * requested state possibilities:
<> 144:ef7eb2e8f9f7 1357 * * NEVER:
<> 144:ef7eb2e8f9f7 1358 * if the previous state was always, will deallocate the channel
<> 144:ef7eb2e8f9f7 1359 * * OPPORTUNISTIC:
<> 144:ef7eb2e8f9f7 1360 * If the previous state was always, will reuse that channel but free upon next completion.
<> 144:ef7eb2e8f9f7 1361 * If not, will try to acquire a channel.
<> 144:ef7eb2e8f9f7 1362 * When allocated, state changes to DMA_USAGE_TEMPORARY_ALLOCATED.
<> 144:ef7eb2e8f9f7 1363 * * ALWAYS:
<> 144:ef7eb2e8f9f7 1364 * Will try to allocate a channel and keep it.
<> 144:ef7eb2e8f9f7 1365 * If succesfully allocated, state changes to DMA_USAGE_ALLOCATED.
<> 144:ef7eb2e8f9f7 1366 ******************************************/
<> 144:ef7eb2e8f9f7 1367 static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, serial_t *serialPtr, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1368 {
<> 144:ef7eb2e8f9f7 1369 DMAUsage currentState = obj->dmaUsageState;
<> 144:ef7eb2e8f9f7 1370 int tempDMAChannel = -1;
<> 144:ef7eb2e8f9f7 1371
<> 144:ef7eb2e8f9f7 1372 if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
<> 144:ef7eb2e8f9f7 1373 /* Try to allocate channel */
<> 144:ef7eb2e8f9f7 1374 tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
<> 144:ef7eb2e8f9f7 1375 if(tempDMAChannel >= 0) {
<> 144:ef7eb2e8f9f7 1376 obj->dmaChannel = tempDMAChannel;
<> 144:ef7eb2e8f9f7 1377 obj->dmaUsageState = DMA_USAGE_ALLOCATED;
<> 144:ef7eb2e8f9f7 1378 dma_init();
<> 144:ef7eb2e8f9f7 1379 serial_dmaSetupChannel(serialPtr, tx_nrx);
<> 144:ef7eb2e8f9f7 1380 }
<> 144:ef7eb2e8f9f7 1381 } else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
<> 144:ef7eb2e8f9f7 1382 if (currentState == DMA_USAGE_ALLOCATED) {
<> 144:ef7eb2e8f9f7 1383 /* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
<> 144:ef7eb2e8f9f7 1384 obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
<> 144:ef7eb2e8f9f7 1385 } else {
<> 144:ef7eb2e8f9f7 1386 /* Try to allocate channel */
<> 144:ef7eb2e8f9f7 1387 tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
<> 144:ef7eb2e8f9f7 1388 if(tempDMAChannel >= 0) {
<> 144:ef7eb2e8f9f7 1389 obj->dmaChannel = tempDMAChannel;
<> 144:ef7eb2e8f9f7 1390 obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
<> 144:ef7eb2e8f9f7 1391 dma_init();
<> 144:ef7eb2e8f9f7 1392 serial_dmaSetupChannel(serialPtr, tx_nrx);
<> 144:ef7eb2e8f9f7 1393 }
<> 144:ef7eb2e8f9f7 1394 }
<> 144:ef7eb2e8f9f7 1395 } else if (requestedState == DMA_USAGE_NEVER) {
<> 144:ef7eb2e8f9f7 1396 /* If channel is allocated, get rid of it */
<> 144:ef7eb2e8f9f7 1397 dma_channel_free(obj->dmaChannel);
<> 144:ef7eb2e8f9f7 1398 obj->dmaChannel = -1;
<> 144:ef7eb2e8f9f7 1399 obj->dmaUsageState = DMA_USAGE_NEVER;
<> 144:ef7eb2e8f9f7 1400 }
<> 144:ef7eb2e8f9f7 1401 }
<> 144:ef7eb2e8f9f7 1402
<> 144:ef7eb2e8f9f7 1403 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 1404
<> 144:ef7eb2e8f9f7 1405 static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1406 {
<> 144:ef7eb2e8f9f7 1407 DMA_CfgDescr_TypeDef channelConfig;
<> 144:ef7eb2e8f9f7 1408
<> 144:ef7eb2e8f9f7 1409 if(tx_nrx) {
<> 144:ef7eb2e8f9f7 1410 // Set DMA callback
<> 144:ef7eb2e8f9f7 1411 obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
<> 144:ef7eb2e8f9f7 1412 obj->serial.dmaOptionsTX.dmaCallback.userPtr = NULL;
<> 144:ef7eb2e8f9f7 1413
<> 144:ef7eb2e8f9f7 1414 // Set up configuration structure
<> 144:ef7eb2e8f9f7 1415 channelConfig.dstInc = dmaDataIncNone;
<> 144:ef7eb2e8f9f7 1416 channelConfig.srcInc = dmaDataInc1;
<> 144:ef7eb2e8f9f7 1417 channelConfig.size = dmaDataSize1;
<> 144:ef7eb2e8f9f7 1418 channelConfig.arbRate = dmaArbitrate1;
<> 144:ef7eb2e8f9f7 1419 channelConfig.hprot = 0;
<> 144:ef7eb2e8f9f7 1420
<> 144:ef7eb2e8f9f7 1421 // Clear TXC
<> 144:ef7eb2e8f9f7 1422 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1423 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_TXC);
<> 144:ef7eb2e8f9f7 1424 } else {
<> 144:ef7eb2e8f9f7 1425 USART_IntClear(obj->serial.periph.uart, USART_IFC_TXC);
<> 144:ef7eb2e8f9f7 1426 }
<> 144:ef7eb2e8f9f7 1427
<> 144:ef7eb2e8f9f7 1428 // Set callback and enable TXC. This will fire once the
<> 144:ef7eb2e8f9f7 1429 // serial transfer finishes
<> 144:ef7eb2e8f9f7 1430 NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)cb);
<> 144:ef7eb2e8f9f7 1431 serial_irq_set(obj, TxIrq, true);
<> 144:ef7eb2e8f9f7 1432
<> 144:ef7eb2e8f9f7 1433 DMA_CfgDescr(obj->serial.dmaOptionsTX.dmaChannel, true, &channelConfig);
<> 144:ef7eb2e8f9f7 1434 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1435 // Activate TX and clear TX buffer (note that clear must be done
<> 144:ef7eb2e8f9f7 1436 // separately and before TXEN or DMA will die on some platforms)
<> 144:ef7eb2e8f9f7 1437 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1438 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN;
<> 144:ef7eb2e8f9f7 1439 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1440
<> 144:ef7eb2e8f9f7 1441 // Kick off TX DMA
<> 144:ef7eb2e8f9f7 1442 DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.leuart->TXDATA), buffer, length - 1);
<> 144:ef7eb2e8f9f7 1443 } else {
<> 144:ef7eb2e8f9f7 1444 // Activate TX amd clear TX buffer
<> 144:ef7eb2e8f9f7 1445 obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1446
<> 144:ef7eb2e8f9f7 1447 // Kick off TX DMA
<> 144:ef7eb2e8f9f7 1448 DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.uart->TXDATA), buffer, length - 1);
<> 144:ef7eb2e8f9f7 1449 }
<> 144:ef7eb2e8f9f7 1450
<> 144:ef7eb2e8f9f7 1451
<> 144:ef7eb2e8f9f7 1452 } else {
<> 144:ef7eb2e8f9f7 1453 // Set DMA callback
<> 144:ef7eb2e8f9f7 1454 obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
<> 144:ef7eb2e8f9f7 1455 obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
<> 144:ef7eb2e8f9f7 1456
<> 144:ef7eb2e8f9f7 1457 // Set up configuration structure
<> 144:ef7eb2e8f9f7 1458 channelConfig.dstInc = dmaDataInc1;
<> 144:ef7eb2e8f9f7 1459 channelConfig.srcInc = dmaDataIncNone;
<> 144:ef7eb2e8f9f7 1460 channelConfig.size = dmaDataSize1;
<> 144:ef7eb2e8f9f7 1461 channelConfig.arbRate = dmaArbitrate1;
<> 144:ef7eb2e8f9f7 1462 channelConfig.hprot = 0;
<> 144:ef7eb2e8f9f7 1463
<> 144:ef7eb2e8f9f7 1464 DMA_CfgDescr(obj->serial.dmaOptionsRX.dmaChannel, true, &channelConfig);
<> 144:ef7eb2e8f9f7 1465
<> 144:ef7eb2e8f9f7 1466 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1467 // Activate RX and clear RX buffer
<> 144:ef7eb2e8f9f7 1468 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1469 obj->serial.periph.leuart->CMD = LEUART_CMD_RXEN;
<> 144:ef7eb2e8f9f7 1470 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1471
<> 144:ef7eb2e8f9f7 1472 // Kick off RX DMA
<> 144:ef7eb2e8f9f7 1473 DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.leuart->RXDATA), length - 1);
<> 144:ef7eb2e8f9f7 1474 } else {
<> 144:ef7eb2e8f9f7 1475 // Activate RX and clear RX buffer
<> 144:ef7eb2e8f9f7 1476 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1477
<> 144:ef7eb2e8f9f7 1478 // Kick off RX DMA
<> 144:ef7eb2e8f9f7 1479 DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.uart->RXDATA), length - 1);
<> 144:ef7eb2e8f9f7 1480 }
<> 144:ef7eb2e8f9f7 1481 }
<> 144:ef7eb2e8f9f7 1482 }
<> 144:ef7eb2e8f9f7 1483
<> 144:ef7eb2e8f9f7 1484 #endif
<> 144:ef7eb2e8f9f7 1485
<> 144:ef7eb2e8f9f7 1486
<> 144:ef7eb2e8f9f7 1487 #ifdef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 1488
<> 144:ef7eb2e8f9f7 1489 static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1490 {
<> 144:ef7eb2e8f9f7 1491 }
<> 144:ef7eb2e8f9f7 1492
<> 144:ef7eb2e8f9f7 1493 static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
<> 144:ef7eb2e8f9f7 1494 {
<> 144:ef7eb2e8f9f7 1495 LDMA_PeripheralSignal_t dma_periph;
<> 144:ef7eb2e8f9f7 1496
<> 144:ef7eb2e8f9f7 1497 obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
<> 144:ef7eb2e8f9f7 1498
<> 144:ef7eb2e8f9f7 1499 if( tx_nrx ) {
<> 144:ef7eb2e8f9f7 1500 volatile void *target_addr;
<> 144:ef7eb2e8f9f7 1501
<> 144:ef7eb2e8f9f7 1502 // Clear TXC
<> 144:ef7eb2e8f9f7 1503 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1504 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_TXC);
<> 144:ef7eb2e8f9f7 1505 } else {
<> 144:ef7eb2e8f9f7 1506 USART_IntClear(obj->serial.periph.uart, USART_IFC_TXC);
<> 144:ef7eb2e8f9f7 1507 }
<> 144:ef7eb2e8f9f7 1508
<> 144:ef7eb2e8f9f7 1509 switch((uint32_t)(obj->serial.periph.uart)) {
<> 144:ef7eb2e8f9f7 1510 #ifdef USART0
<> 144:ef7eb2e8f9f7 1511 case USART_0:
<> 144:ef7eb2e8f9f7 1512 dma_periph = ldmaPeripheralSignal_USART0_TXBL;
<> 144:ef7eb2e8f9f7 1513 target_addr = &USART0->TXDATA;
<> 144:ef7eb2e8f9f7 1514 obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1515 break;
<> 144:ef7eb2e8f9f7 1516 #endif
<> 144:ef7eb2e8f9f7 1517 #ifdef USART1
<> 144:ef7eb2e8f9f7 1518 case USART_1:
<> 144:ef7eb2e8f9f7 1519 dma_periph = ldmaPeripheralSignal_USART1_TXBL;
<> 144:ef7eb2e8f9f7 1520 target_addr = &USART1->TXDATA;
<> 144:ef7eb2e8f9f7 1521 obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1522 break;
<> 144:ef7eb2e8f9f7 1523 #endif
<> 144:ef7eb2e8f9f7 1524 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 1525 case LEUART_0:
<> 144:ef7eb2e8f9f7 1526 dma_periph = ldmaPeripheralSignal_LEUART0_TXBL;
<> 144:ef7eb2e8f9f7 1527 target_addr = &LEUART0->TXDATA;
<> 144:ef7eb2e8f9f7 1528 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1529 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN;
<> 144:ef7eb2e8f9f7 1530 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1531 break;
<> 144:ef7eb2e8f9f7 1532 #endif
<> 144:ef7eb2e8f9f7 1533 default:
<> 144:ef7eb2e8f9f7 1534 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 1535 while(1);
<> 144:ef7eb2e8f9f7 1536 break;
<> 144:ef7eb2e8f9f7 1537 }
<> 144:ef7eb2e8f9f7 1538
<> 144:ef7eb2e8f9f7 1539 // Set callback and enable TXC. This will fire once the
<> 144:ef7eb2e8f9f7 1540 // serial transfer finishes
<> 144:ef7eb2e8f9f7 1541 NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)cb);
<> 144:ef7eb2e8f9f7 1542 serial_irq_set(obj, TxIrq, true);
<> 144:ef7eb2e8f9f7 1543
<> 144:ef7eb2e8f9f7 1544 // Start DMA transfer
<> 144:ef7eb2e8f9f7 1545 LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
<> 144:ef7eb2e8f9f7 1546 LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(buffer, target_addr, length);
<> 144:ef7eb2e8f9f7 1547 LDMAx_StartTransfer(obj->serial.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete, NULL);
<> 144:ef7eb2e8f9f7 1548
<> 144:ef7eb2e8f9f7 1549 } else {
<> 144:ef7eb2e8f9f7 1550 volatile const void *source_addr;
<> 144:ef7eb2e8f9f7 1551
<> 144:ef7eb2e8f9f7 1552 switch((uint32_t)(obj->serial.periph.uart)) {
<> 144:ef7eb2e8f9f7 1553 #ifdef USART0
<> 144:ef7eb2e8f9f7 1554 case USART_0:
<> 144:ef7eb2e8f9f7 1555 dma_periph = ldmaPeripheralSignal_USART0_RXDATAV;
<> 144:ef7eb2e8f9f7 1556 source_addr = &USART0->RXDATA;
<> 144:ef7eb2e8f9f7 1557 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1558 break;
<> 144:ef7eb2e8f9f7 1559 #endif
<> 144:ef7eb2e8f9f7 1560 #ifdef USART1
<> 144:ef7eb2e8f9f7 1561 case USART_1:
<> 144:ef7eb2e8f9f7 1562 dma_periph = ldmaPeripheralSignal_USART1_RXDATAV;
<> 144:ef7eb2e8f9f7 1563 source_addr = &USART1->RXDATA;
<> 144:ef7eb2e8f9f7 1564 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1565 break;
<> 144:ef7eb2e8f9f7 1566 #endif
AnnaBridge 179:b0033dcd6934 1567 #ifdef USART2
AnnaBridge 179:b0033dcd6934 1568 case USART_2:
AnnaBridge 179:b0033dcd6934 1569 dma_periph = ldmaPeripheralSignal_USART2_RXDATAV;
AnnaBridge 179:b0033dcd6934 1570 source_addr = &USART2->RXDATA;
AnnaBridge 179:b0033dcd6934 1571 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
AnnaBridge 179:b0033dcd6934 1572 break;
AnnaBridge 179:b0033dcd6934 1573 #endif
AnnaBridge 179:b0033dcd6934 1574 #ifdef USART3
AnnaBridge 179:b0033dcd6934 1575 case USART_3:
AnnaBridge 179:b0033dcd6934 1576 dma_periph = ldmaPeripheralSignal_USART3_RXDATAV;
AnnaBridge 179:b0033dcd6934 1577 source_addr = &USART3->RXDATA;
AnnaBridge 179:b0033dcd6934 1578 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
AnnaBridge 179:b0033dcd6934 1579 break;
AnnaBridge 179:b0033dcd6934 1580 #endif
AnnaBridge 179:b0033dcd6934 1581 #ifdef USART4
AnnaBridge 179:b0033dcd6934 1582 case USART_4:
AnnaBridge 179:b0033dcd6934 1583 dma_periph = ldmaPeripheralSignal_USART4_RXDATAV;
AnnaBridge 179:b0033dcd6934 1584 source_addr = &USART4->RXDATA;
AnnaBridge 179:b0033dcd6934 1585 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
AnnaBridge 179:b0033dcd6934 1586 break;
AnnaBridge 179:b0033dcd6934 1587 #endif
AnnaBridge 179:b0033dcd6934 1588 #ifdef USART5
AnnaBridge 179:b0033dcd6934 1589 case USART_5:
AnnaBridge 179:b0033dcd6934 1590 dma_periph = ldmaPeripheralSignal_USART5_RXDATAV;
AnnaBridge 179:b0033dcd6934 1591 source_addr = &USART5->RXDATA;
AnnaBridge 179:b0033dcd6934 1592 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
AnnaBridge 179:b0033dcd6934 1593 break;
AnnaBridge 179:b0033dcd6934 1594 #endif
<> 144:ef7eb2e8f9f7 1595 #ifdef LEUART0
<> 144:ef7eb2e8f9f7 1596 case LEUART_0:
<> 144:ef7eb2e8f9f7 1597 dma_periph = ldmaPeripheralSignal_LEUART0_RXDATAV;
<> 144:ef7eb2e8f9f7 1598 source_addr = &LEUART0->RXDATA;
<> 144:ef7eb2e8f9f7 1599 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1600 obj->serial.periph.leuart->CMD = LEUART_CMD_RXEN;
<> 144:ef7eb2e8f9f7 1601 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1602 break;
<> 144:ef7eb2e8f9f7 1603 #endif
<> 144:ef7eb2e8f9f7 1604 default:
<> 144:ef7eb2e8f9f7 1605 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 1606 while(1);
<> 144:ef7eb2e8f9f7 1607 break;
<> 144:ef7eb2e8f9f7 1608 }
<> 144:ef7eb2e8f9f7 1609
<> 144:ef7eb2e8f9f7 1610 LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
<> 144:ef7eb2e8f9f7 1611 LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(source_addr, buffer, length);
<> 144:ef7eb2e8f9f7 1612 LDMAx_StartTransfer(obj->serial.dmaOptionsRX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete, cb);
<> 144:ef7eb2e8f9f7 1613 }
<> 144:ef7eb2e8f9f7 1614 }
<> 144:ef7eb2e8f9f7 1615
<> 144:ef7eb2e8f9f7 1616 #endif /* LDMA_PRESENT */
<> 144:ef7eb2e8f9f7 1617
<> 144:ef7eb2e8f9f7 1618 /************************************************************************************
<> 144:ef7eb2e8f9f7 1619 * ASYNCHRONOUS HAL *
<> 144:ef7eb2e8f9f7 1620 ************************************************************************************/
<> 144:ef7eb2e8f9f7 1621
<> 144:ef7eb2e8f9f7 1622 #if DEVICE_SERIAL_ASYNCH
<> 144:ef7eb2e8f9f7 1623
<> 144:ef7eb2e8f9f7 1624 /************************************
<> 144:ef7eb2e8f9f7 1625 * HELPER FUNCTIONS *
<> 144:ef7eb2e8f9f7 1626 ***********************************/
<> 144:ef7eb2e8f9f7 1627
<> 144:ef7eb2e8f9f7 1628 /** Configure TX events
<> 144:ef7eb2e8f9f7 1629 *
<> 144:ef7eb2e8f9f7 1630 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1631 * @param event The logical OR of the TX events to configure
<> 144:ef7eb2e8f9f7 1632 * @param enable Set to non-zero to enable events, or zero to disable them
<> 144:ef7eb2e8f9f7 1633 */
<> 144:ef7eb2e8f9f7 1634 void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable)
<> 144:ef7eb2e8f9f7 1635 {
<> 144:ef7eb2e8f9f7 1636 // Shouldn't have to enable TX interrupt here, just need to keep track of the requested events.
<> 144:ef7eb2e8f9f7 1637 if(enable) obj->serial.events |= event;
<> 144:ef7eb2e8f9f7 1638 else obj->serial.events &= ~event;
<> 144:ef7eb2e8f9f7 1639 }
<> 144:ef7eb2e8f9f7 1640
<> 144:ef7eb2e8f9f7 1641 /**
<> 144:ef7eb2e8f9f7 1642 * @param obj The serial object.
<> 144:ef7eb2e8f9f7 1643 * @param event The logical OR of the RX events to configure
<> 144:ef7eb2e8f9f7 1644 * @param enable Set to non-zero to enable events, or zero to disable them
<> 144:ef7eb2e8f9f7 1645 */
<> 144:ef7eb2e8f9f7 1646 void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
<> 144:ef7eb2e8f9f7 1647 {
<> 144:ef7eb2e8f9f7 1648 if(enable) {
<> 144:ef7eb2e8f9f7 1649 obj->serial.events |= event;
<> 144:ef7eb2e8f9f7 1650 } else {
<> 144:ef7eb2e8f9f7 1651 obj->serial.events &= ~event;
<> 144:ef7eb2e8f9f7 1652 }
<> 144:ef7eb2e8f9f7 1653 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1654 if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
<> 144:ef7eb2e8f9f7 1655 //FERR interrupt source
<> 144:ef7eb2e8f9f7 1656 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_FERR;
<> 144:ef7eb2e8f9f7 1657 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_FERR;
<> 144:ef7eb2e8f9f7 1658 }
<> 144:ef7eb2e8f9f7 1659 if(event & SERIAL_EVENT_RX_PARITY_ERROR) {
<> 144:ef7eb2e8f9f7 1660 //PERR interrupt source
<> 144:ef7eb2e8f9f7 1661 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_PERR;
<> 144:ef7eb2e8f9f7 1662 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_PERR;
<> 144:ef7eb2e8f9f7 1663 }
<> 144:ef7eb2e8f9f7 1664 if(event & SERIAL_EVENT_RX_OVERFLOW) {
<> 144:ef7eb2e8f9f7 1665 //RXOF interrupt source
<> 144:ef7eb2e8f9f7 1666 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_RXOF;
<> 144:ef7eb2e8f9f7 1667 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_RXOF;
<> 144:ef7eb2e8f9f7 1668 }
<> 144:ef7eb2e8f9f7 1669 } else {
<> 144:ef7eb2e8f9f7 1670 if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
<> 144:ef7eb2e8f9f7 1671 //FERR interrupt source
<> 144:ef7eb2e8f9f7 1672 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_FERR;
<> 144:ef7eb2e8f9f7 1673 else obj->serial.periph.uart->IEN &= ~USART_IEN_FERR;
<> 144:ef7eb2e8f9f7 1674 }
<> 144:ef7eb2e8f9f7 1675 if(event & SERIAL_EVENT_RX_PARITY_ERROR) {
<> 144:ef7eb2e8f9f7 1676 //PERR interrupt source
<> 144:ef7eb2e8f9f7 1677 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_PERR;
<> 144:ef7eb2e8f9f7 1678 else obj->serial.periph.uart->IEN &= ~USART_IEN_PERR;
<> 144:ef7eb2e8f9f7 1679 }
<> 144:ef7eb2e8f9f7 1680 if(event & SERIAL_EVENT_RX_OVERFLOW) {
<> 144:ef7eb2e8f9f7 1681 //RXOF interrupt source
<> 144:ef7eb2e8f9f7 1682 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_RXOF;
<> 144:ef7eb2e8f9f7 1683 else obj->serial.periph.uart->IEN &= ~USART_IEN_RXOF;
<> 144:ef7eb2e8f9f7 1684 }
<> 144:ef7eb2e8f9f7 1685 }
<> 144:ef7eb2e8f9f7 1686 }
<> 144:ef7eb2e8f9f7 1687
<> 144:ef7eb2e8f9f7 1688 /** Configure the TX buffer for an asynchronous write serial transaction
<> 144:ef7eb2e8f9f7 1689 *
<> 144:ef7eb2e8f9f7 1690 * @param obj The serial object.
<> 144:ef7eb2e8f9f7 1691 * @param tx The buffer for sending.
<> 144:ef7eb2e8f9f7 1692 * @param tx_length The number of words to transmit.
<> 144:ef7eb2e8f9f7 1693 */
<> 144:ef7eb2e8f9f7 1694 void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
<> 144:ef7eb2e8f9f7 1695 {
<> 144:ef7eb2e8f9f7 1696 // We only support byte buffers for now
<> 144:ef7eb2e8f9f7 1697 MBED_ASSERT(width == 8);
<> 144:ef7eb2e8f9f7 1698
<> 144:ef7eb2e8f9f7 1699 if(serial_tx_active(obj)) return;
<> 144:ef7eb2e8f9f7 1700
<> 144:ef7eb2e8f9f7 1701 obj->tx_buff.buffer = tx;
<> 144:ef7eb2e8f9f7 1702 obj->tx_buff.length = tx_length;
<> 144:ef7eb2e8f9f7 1703 obj->tx_buff.pos = 0;
<> 144:ef7eb2e8f9f7 1704
<> 144:ef7eb2e8f9f7 1705 return;
<> 144:ef7eb2e8f9f7 1706 }
<> 144:ef7eb2e8f9f7 1707
<> 144:ef7eb2e8f9f7 1708 /** Configure the TX buffer for an asynchronous read serial transaction
<> 144:ef7eb2e8f9f7 1709 *
<> 144:ef7eb2e8f9f7 1710 * @param obj The serial object.
<> 144:ef7eb2e8f9f7 1711 * @param rx The buffer for receiving.
<> 144:ef7eb2e8f9f7 1712 * @param rx_length The number of words to read.
<> 144:ef7eb2e8f9f7 1713 */
<> 144:ef7eb2e8f9f7 1714 void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
<> 144:ef7eb2e8f9f7 1715 {
<> 144:ef7eb2e8f9f7 1716 // We only support byte buffers for now
<> 144:ef7eb2e8f9f7 1717 MBED_ASSERT(width == 8);
<> 144:ef7eb2e8f9f7 1718
<> 144:ef7eb2e8f9f7 1719 if(serial_rx_active(obj)) return;
<> 144:ef7eb2e8f9f7 1720
<> 144:ef7eb2e8f9f7 1721 obj->rx_buff.buffer = rx;
<> 144:ef7eb2e8f9f7 1722 obj->rx_buff.length = rx_length;
<> 144:ef7eb2e8f9f7 1723 obj->rx_buff.pos = 0;
<> 144:ef7eb2e8f9f7 1724
<> 144:ef7eb2e8f9f7 1725 return;
<> 144:ef7eb2e8f9f7 1726 }
<> 144:ef7eb2e8f9f7 1727
<> 144:ef7eb2e8f9f7 1728 /************************************
<> 144:ef7eb2e8f9f7 1729 * TRANSFER FUNCTIONS *
<> 144:ef7eb2e8f9f7 1730 ***********************************/
<> 144:ef7eb2e8f9f7 1731
<> 144:ef7eb2e8f9f7 1732 /** Begin asynchronous TX transfer. The used buffer is specified in the serial object,
<> 144:ef7eb2e8f9f7 1733 * tx_buff
<> 144:ef7eb2e8f9f7 1734 *
<> 144:ef7eb2e8f9f7 1735 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1736 * @param cb The function to call when an event occurs
<> 144:ef7eb2e8f9f7 1737 * @param hint A suggestion for how to use DMA with this transfer
<> 144:ef7eb2e8f9f7 1738 * @return Returns number of data transfered, or 0 otherwise
<> 144:ef7eb2e8f9f7 1739 */
<> 144:ef7eb2e8f9f7 1740 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 1741 {
<> 144:ef7eb2e8f9f7 1742 // Check that a buffer has indeed been set up
<> 144:ef7eb2e8f9f7 1743 MBED_ASSERT(tx != (void*)0);
<> 144:ef7eb2e8f9f7 1744 if(tx_length == 0) return 0;
<> 144:ef7eb2e8f9f7 1745
<> 144:ef7eb2e8f9f7 1746 // Set up buffer
<> 144:ef7eb2e8f9f7 1747 serial_tx_buffer_set(obj, (void *)tx, tx_length, tx_width);
<> 144:ef7eb2e8f9f7 1748
<> 144:ef7eb2e8f9f7 1749 // Set up events
<> 144:ef7eb2e8f9f7 1750 serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
<> 144:ef7eb2e8f9f7 1751 serial_tx_enable_event(obj, event, true);
<> 144:ef7eb2e8f9f7 1752
<> 144:ef7eb2e8f9f7 1753 // Set up sleepmode
<> 144:ef7eb2e8f9f7 1754 serial_block_sleep(obj);
<> 144:ef7eb2e8f9f7 1755
<> 144:ef7eb2e8f9f7 1756 // Determine DMA strategy
<> 144:ef7eb2e8f9f7 1757 serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
<> 144:ef7eb2e8f9f7 1758
<> 144:ef7eb2e8f9f7 1759 // If DMA, kick off DMA transfer
<> 144:ef7eb2e8f9f7 1760 if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
<> 144:ef7eb2e8f9f7 1761 serial_dmaActivate(obj, (void*)handler, obj->tx_buff.buffer, obj->tx_buff.length, true);
<> 144:ef7eb2e8f9f7 1762 }
<> 144:ef7eb2e8f9f7 1763 // Else, activate interrupt. TXBL will take care of buffer filling through ISR.
<> 144:ef7eb2e8f9f7 1764 else {
<> 144:ef7eb2e8f9f7 1765 // Store callback
<> 144:ef7eb2e8f9f7 1766 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1767 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1768 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
<> 144:ef7eb2e8f9f7 1769 NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
<> 144:ef7eb2e8f9f7 1770 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1771
<> 144:ef7eb2e8f9f7 1772 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1773 // Activate TX and clear TX buffer
<> 144:ef7eb2e8f9f7 1774 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1775 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN;
<> 144:ef7eb2e8f9f7 1776 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1777
<> 144:ef7eb2e8f9f7 1778 // Enable interrupt
<> 144:ef7eb2e8f9f7 1779 LEUART_IntEnable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 1780 } else {
<> 144:ef7eb2e8f9f7 1781 // Activate TX and clear TX buffer
<> 144:ef7eb2e8f9f7 1782 obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_CLEARTX;
<> 144:ef7eb2e8f9f7 1783
<> 144:ef7eb2e8f9f7 1784 // Enable interrupt
<> 144:ef7eb2e8f9f7 1785 USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 1786 }
<> 144:ef7eb2e8f9f7 1787 }
<> 144:ef7eb2e8f9f7 1788
<> 144:ef7eb2e8f9f7 1789 return 0;
<> 144:ef7eb2e8f9f7 1790 }
<> 144:ef7eb2e8f9f7 1791
<> 144:ef7eb2e8f9f7 1792 /** Begin asynchronous RX transfer (enable interrupt for data collecting)
<> 144:ef7eb2e8f9f7 1793 * The used buffer is specified in the serial object - rx_buff
<> 144:ef7eb2e8f9f7 1794 *
<> 144:ef7eb2e8f9f7 1795 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1796 * @param cb The function to call when an event occurs
<> 144:ef7eb2e8f9f7 1797 * @param hint A suggestion for how to use DMA with this transfer
<> 144:ef7eb2e8f9f7 1798 */
<> 144:ef7eb2e8f9f7 1799 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 1800 {
<> 144:ef7eb2e8f9f7 1801 // Check that a buffer has indeed been set up
<> 144:ef7eb2e8f9f7 1802 MBED_ASSERT(rx != (void*)0);
<> 144:ef7eb2e8f9f7 1803 if(rx_length == 0) return;
<> 144:ef7eb2e8f9f7 1804
<> 144:ef7eb2e8f9f7 1805 // Set up buffer
<> 144:ef7eb2e8f9f7 1806 serial_rx_buffer_set(obj,(void*) rx, rx_length, rx_width);
<> 144:ef7eb2e8f9f7 1807
<> 144:ef7eb2e8f9f7 1808 //disable character match if no character is specified
<> 144:ef7eb2e8f9f7 1809 if(char_match == SERIAL_RESERVED_CHAR_MATCH){
<> 144:ef7eb2e8f9f7 1810 event &= ~SERIAL_EVENT_RX_CHARACTER_MATCH;
<> 144:ef7eb2e8f9f7 1811 }
<> 144:ef7eb2e8f9f7 1812
<> 144:ef7eb2e8f9f7 1813 /*clear all set interrupts*/
<> 144:ef7eb2e8f9f7 1814 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1815 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_PERR | LEUART_IFC_FERR | LEUART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 1816 }else{
<> 144:ef7eb2e8f9f7 1817 USART_IntClear(obj->serial.periph.uart, USART_IFC_PERR | USART_IFC_FERR | USART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 1818 }
<> 144:ef7eb2e8f9f7 1819
<> 144:ef7eb2e8f9f7 1820 // Set up events
<> 144:ef7eb2e8f9f7 1821 serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
<> 144:ef7eb2e8f9f7 1822 serial_rx_enable_event(obj, event, true);
<> 144:ef7eb2e8f9f7 1823 obj->char_match = char_match;
<> 144:ef7eb2e8f9f7 1824
<> 144:ef7eb2e8f9f7 1825 // Set up sleepmode
<> 144:ef7eb2e8f9f7 1826 serial_block_sleep(obj);
<> 144:ef7eb2e8f9f7 1827
<> 144:ef7eb2e8f9f7 1828 // Determine DMA strategy
<> 144:ef7eb2e8f9f7 1829 // If character match is enabled, we can't use DMA, sadly. We could when using LEUART though, but that support is not in here yet.
<> 144:ef7eb2e8f9f7 1830 // TODO: add DMA support for character matching with leuart
<> 144:ef7eb2e8f9f7 1831 if(!(event & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
<> 144:ef7eb2e8f9f7 1832 serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
<> 144:ef7eb2e8f9f7 1833 }else{
<> 144:ef7eb2e8f9f7 1834 serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), DMA_USAGE_NEVER, obj, false);
<> 144:ef7eb2e8f9f7 1835 }
<> 144:ef7eb2e8f9f7 1836
<> 144:ef7eb2e8f9f7 1837 // If DMA, kick off DMA
<> 144:ef7eb2e8f9f7 1838 if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
<> 144:ef7eb2e8f9f7 1839 serial_dmaActivate(obj, (void*)handler, obj->rx_buff.buffer, obj->rx_buff.length, false);
<> 144:ef7eb2e8f9f7 1840 }
<> 144:ef7eb2e8f9f7 1841 // Else, activate interrupt. RXDATAV is responsible for incoming data notification.
<> 144:ef7eb2e8f9f7 1842 else {
<> 144:ef7eb2e8f9f7 1843 // Store callback
<> 144:ef7eb2e8f9f7 1844 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1845 NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
<> 144:ef7eb2e8f9f7 1846 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
<> 144:ef7eb2e8f9f7 1847
<> 144:ef7eb2e8f9f7 1848 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1849 // Activate RX and clear RX buffer
<> 144:ef7eb2e8f9f7 1850 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1851 obj->serial.periph.leuart->CMD = LEUART_CMD_RXEN;
<> 144:ef7eb2e8f9f7 1852 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 1853
<> 144:ef7eb2e8f9f7 1854 // Enable interrupt
<> 144:ef7eb2e8f9f7 1855 LEUART_IntEnable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV);
<> 144:ef7eb2e8f9f7 1856 } else {
<> 144:ef7eb2e8f9f7 1857 // Activate RX and clear RX buffer
<> 144:ef7eb2e8f9f7 1858 obj->serial.periph.uart->CMD = USART_CMD_RXEN | USART_CMD_CLEARRX;
<> 144:ef7eb2e8f9f7 1859
<> 144:ef7eb2e8f9f7 1860 // Clear RXFULL
<> 144:ef7eb2e8f9f7 1861 USART_IntClear(obj->serial.periph.uart, USART_IFC_RXFULL);
<> 144:ef7eb2e8f9f7 1862
<> 144:ef7eb2e8f9f7 1863 // Enable interrupt
<> 144:ef7eb2e8f9f7 1864 USART_IntEnable(obj->serial.periph.uart, USART_IEN_RXDATAV);
<> 144:ef7eb2e8f9f7 1865 }
<> 144:ef7eb2e8f9f7 1866 }
<> 144:ef7eb2e8f9f7 1867
<> 144:ef7eb2e8f9f7 1868 return;
<> 144:ef7eb2e8f9f7 1869 }
<> 144:ef7eb2e8f9f7 1870
<> 144:ef7eb2e8f9f7 1871 /** Attempts to determine if the serial peripheral is already in use for TX
<> 144:ef7eb2e8f9f7 1872 *
<> 144:ef7eb2e8f9f7 1873 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1874 * @return Non-zero if the TX transaction is ongoing, 0 otherwise
<> 144:ef7eb2e8f9f7 1875 */
<> 144:ef7eb2e8f9f7 1876 uint8_t serial_tx_active(serial_t *obj)
<> 144:ef7eb2e8f9f7 1877 {
<> 144:ef7eb2e8f9f7 1878 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1879 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_TXBL|LEUART_IEN_TXC)) ? true : false;
<> 144:ef7eb2e8f9f7 1880 } else {
<> 144:ef7eb2e8f9f7 1881 return (obj->serial.periph.uart->IEN & (USART_IEN_TXBL|USART_IEN_TXC)) ? true : false;
<> 144:ef7eb2e8f9f7 1882 }
<> 144:ef7eb2e8f9f7 1883 }
<> 144:ef7eb2e8f9f7 1884
<> 144:ef7eb2e8f9f7 1885 /** Attempts to determine if the serial peripheral is already in use for RX
<> 144:ef7eb2e8f9f7 1886 *
<> 144:ef7eb2e8f9f7 1887 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1888 * @return Non-zero if the RX transaction is ongoing, 0 otherwise
<> 144:ef7eb2e8f9f7 1889 */
<> 144:ef7eb2e8f9f7 1890 uint8_t serial_rx_active(serial_t *obj)
<> 144:ef7eb2e8f9f7 1891 {
<> 144:ef7eb2e8f9f7 1892 switch(obj->serial.dmaOptionsRX.dmaUsageState) {
<> 144:ef7eb2e8f9f7 1893 case DMA_USAGE_TEMPORARY_ALLOCATED:
<> 144:ef7eb2e8f9f7 1894 /* Temporary allocation always means its active, as this state gets cleared afterwards */
<> 144:ef7eb2e8f9f7 1895 return 1;
<> 144:ef7eb2e8f9f7 1896 case DMA_USAGE_ALLOCATED:
<> 144:ef7eb2e8f9f7 1897 /* Check whether the allocated DMA channel is active by checking the DMA transfer */
<> 144:ef7eb2e8f9f7 1898 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 1899 return DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel);
<> 144:ef7eb2e8f9f7 1900 #else
<> 144:ef7eb2e8f9f7 1901 // LDMA_TransferDone does not work since the CHDONE bits get cleared,
<> 144:ef7eb2e8f9f7 1902 // so just check if the channel is enabled
<> 144:ef7eb2e8f9f7 1903 return LDMA->CHEN & (1 << obj->serial.dmaOptionsRX.dmaChannel);
<> 144:ef7eb2e8f9f7 1904 #endif
<> 144:ef7eb2e8f9f7 1905 default:
<> 144:ef7eb2e8f9f7 1906 /* Check whether interrupt for serial TX is enabled */
<> 144:ef7eb2e8f9f7 1907 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1908 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV)) ? true : false;
<> 144:ef7eb2e8f9f7 1909 } else {
<> 144:ef7eb2e8f9f7 1910 return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV)) ? true : false;
<> 144:ef7eb2e8f9f7 1911 }
<> 144:ef7eb2e8f9f7 1912 }
<> 144:ef7eb2e8f9f7 1913 }
<> 144:ef7eb2e8f9f7 1914
<> 144:ef7eb2e8f9f7 1915 /** The asynchronous TX handler. Writes to the TX FIFO and checks for events.
<> 144:ef7eb2e8f9f7 1916 * If any TX event has occured, the TX abort function is called.
<> 144:ef7eb2e8f9f7 1917 *
<> 144:ef7eb2e8f9f7 1918 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1919 * @return Returns event flags if a TX transfer termination condition was met or 0 otherwise
<> 144:ef7eb2e8f9f7 1920 */
<> 144:ef7eb2e8f9f7 1921 int serial_tx_irq_handler_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 1922 {
<> 144:ef7eb2e8f9f7 1923 /* This interrupt handler is called from USART irq */
<> 144:ef7eb2e8f9f7 1924 uint8_t *buf = obj->tx_buff.buffer;
<> 144:ef7eb2e8f9f7 1925
<> 144:ef7eb2e8f9f7 1926 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1927 if(obj->serial.periph.leuart->IEN & LEUART_IEN_TXBL){
<> 144:ef7eb2e8f9f7 1928 /* There is still data to send */
<> 144:ef7eb2e8f9f7 1929 while((LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_TXBL) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
<> 144:ef7eb2e8f9f7 1930 while (obj->serial.periph.leuart->SYNCBUSY);
<> 144:ef7eb2e8f9f7 1931 LEUART_Tx(obj->serial.periph.leuart, buf[obj->tx_buff.pos]);
<> 144:ef7eb2e8f9f7 1932 obj->tx_buff.pos++;
<> 144:ef7eb2e8f9f7 1933 }
<> 144:ef7eb2e8f9f7 1934 if(obj->tx_buff.pos >= obj->tx_buff.length){
<> 144:ef7eb2e8f9f7 1935 /* Last byte has been put in TX, set up TXC interrupt */
<> 144:ef7eb2e8f9f7 1936 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 1937 LEUART_IntEnable(obj->serial.periph.leuart, LEUART_IEN_TXC);
<> 144:ef7eb2e8f9f7 1938 while (obj->serial.periph.leuart->SYNCBUSY);
<> 144:ef7eb2e8f9f7 1939 }
<> 144:ef7eb2e8f9f7 1940 }else if (obj->serial.periph.leuart->IF & LEUART_IF_TXC){
<> 144:ef7eb2e8f9f7 1941 /* Last byte has been successfully transmitted. Stop the procedure */
<> 144:ef7eb2e8f9f7 1942 serial_tx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 1943 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 1944 }
<> 144:ef7eb2e8f9f7 1945 } else {
<> 144:ef7eb2e8f9f7 1946 if(obj->serial.periph.uart->IEN & USART_IEN_TXBL){
<> 144:ef7eb2e8f9f7 1947 /* There is still data to send */
<> 144:ef7eb2e8f9f7 1948 while((USART_StatusGet(obj->serial.periph.uart) & USART_STATUS_TXBL) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
<> 144:ef7eb2e8f9f7 1949 USART_Tx(obj->serial.periph.uart, buf[obj->tx_buff.pos]);
<> 144:ef7eb2e8f9f7 1950 obj->tx_buff.pos++;
<> 144:ef7eb2e8f9f7 1951 }
<> 144:ef7eb2e8f9f7 1952 if(obj->tx_buff.pos >= obj->tx_buff.length){
<> 144:ef7eb2e8f9f7 1953 /* Last byte has been put in TX, set up TXC interrupt */
<> 144:ef7eb2e8f9f7 1954 USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 1955 USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXC);
<> 144:ef7eb2e8f9f7 1956 }
<> 144:ef7eb2e8f9f7 1957 } else if (obj->serial.periph.uart->IF & USART_IF_TXC) {
<> 144:ef7eb2e8f9f7 1958 /* Last byte has been successfully transmitted. Stop the procedure */
<> 144:ef7eb2e8f9f7 1959 serial_tx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 1960 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 1961 }
<> 144:ef7eb2e8f9f7 1962 }
<> 144:ef7eb2e8f9f7 1963 return 0;
<> 144:ef7eb2e8f9f7 1964 }
<> 144:ef7eb2e8f9f7 1965
<> 144:ef7eb2e8f9f7 1966 /** The asynchronous RX handler. Reads from the RX FIFOF and checks for events.
<> 144:ef7eb2e8f9f7 1967 * If any RX event has occured, the RX abort function is called.
<> 144:ef7eb2e8f9f7 1968 *
<> 144:ef7eb2e8f9f7 1969 * @param obj The serial object
<> 144:ef7eb2e8f9f7 1970 * @return Returns event flags if a RX transfer termination condition was met or 0 otherwise
<> 144:ef7eb2e8f9f7 1971 */
<> 144:ef7eb2e8f9f7 1972 int serial_rx_irq_handler_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 1973 {
<> 144:ef7eb2e8f9f7 1974 int event = 0;
<> 144:ef7eb2e8f9f7 1975
<> 144:ef7eb2e8f9f7 1976 /* This interrupt handler is called from USART irq */
<> 144:ef7eb2e8f9f7 1977 uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
<> 144:ef7eb2e8f9f7 1978
<> 144:ef7eb2e8f9f7 1979 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 1980 /* Determine the source of the interrupt */
<> 144:ef7eb2e8f9f7 1981 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_PERR) {
<> 144:ef7eb2e8f9f7 1982 /* Parity error has occurred, and we are notifying. */
<> 144:ef7eb2e8f9f7 1983 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_PERR);
<> 144:ef7eb2e8f9f7 1984 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 1985 return SERIAL_EVENT_RX_PARITY_ERROR;
<> 144:ef7eb2e8f9f7 1986 }
<> 144:ef7eb2e8f9f7 1987
<> 144:ef7eb2e8f9f7 1988 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_FERR) {
<> 144:ef7eb2e8f9f7 1989 /* Framing error has occurred, and we are notifying */
<> 144:ef7eb2e8f9f7 1990 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_FERR);
<> 144:ef7eb2e8f9f7 1991 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 1992 return SERIAL_EVENT_RX_FRAMING_ERROR;
<> 144:ef7eb2e8f9f7 1993 }
<> 144:ef7eb2e8f9f7 1994
<> 144:ef7eb2e8f9f7 1995 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_RXOF) {
<> 144:ef7eb2e8f9f7 1996 /* RX buffer overflow has occurred, and we are notifying */
<> 144:ef7eb2e8f9f7 1997 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 1998 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 1999 return SERIAL_EVENT_RX_OVERFLOW;
<> 144:ef7eb2e8f9f7 2000 }
<> 144:ef7eb2e8f9f7 2001
<> 144:ef7eb2e8f9f7 2002 if((LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_RXDATAV) || (LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_RXDATAV)) {
<> 144:ef7eb2e8f9f7 2003 /* Valid data in buffer. Determine course of action: continue receiving or interrupt */
<> 144:ef7eb2e8f9f7 2004 if(obj->rx_buff.pos >= (obj->rx_buff.length - 1)) {
<> 144:ef7eb2e8f9f7 2005 /* Last char, transfer complete. Switch off interrupt and return event. */
<> 144:ef7eb2e8f9f7 2006 buf[obj->rx_buff.pos] = LEUART_RxDataGet(obj->serial.periph.leuart);
<> 144:ef7eb2e8f9f7 2007
<> 144:ef7eb2e8f9f7 2008 event |= SERIAL_EVENT_RX_COMPLETE;
<> 144:ef7eb2e8f9f7 2009
<> 144:ef7eb2e8f9f7 2010 if((buf[obj->rx_buff.pos] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
<> 144:ef7eb2e8f9f7 2011
<> 144:ef7eb2e8f9f7 2012 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2013 return event & obj->serial.events;
<> 144:ef7eb2e8f9f7 2014 } else {
<> 144:ef7eb2e8f9f7 2015 /* There's still space in the receive buffer */
<> 144:ef7eb2e8f9f7 2016 while((LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_RXDATAV) && (obj->rx_buff.pos <= (obj->rx_buff.length - 1))) {
<> 144:ef7eb2e8f9f7 2017 bool aborting = false;
<> 144:ef7eb2e8f9f7 2018 buf[obj->rx_buff.pos] = LEUART_RxDataGet(obj->serial.periph.leuart);
<> 144:ef7eb2e8f9f7 2019 obj->rx_buff.pos++;
<> 144:ef7eb2e8f9f7 2020
<> 144:ef7eb2e8f9f7 2021 /* Check for character match event */
<> 144:ef7eb2e8f9f7 2022 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
<> 144:ef7eb2e8f9f7 2023 aborting = true;
<> 144:ef7eb2e8f9f7 2024 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
<> 144:ef7eb2e8f9f7 2025 }
<> 144:ef7eb2e8f9f7 2026
<> 144:ef7eb2e8f9f7 2027 /* Check for final char event */
<> 144:ef7eb2e8f9f7 2028 if(obj->rx_buff.pos >= (obj->rx_buff.length)) {
<> 144:ef7eb2e8f9f7 2029 aborting = true;
<> 144:ef7eb2e8f9f7 2030 event |= SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 2031 }
<> 144:ef7eb2e8f9f7 2032
<> 144:ef7eb2e8f9f7 2033 if(aborting) {
<> 144:ef7eb2e8f9f7 2034 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2035 return event & obj->serial.events;
<> 144:ef7eb2e8f9f7 2036 }
<> 144:ef7eb2e8f9f7 2037 }
<> 144:ef7eb2e8f9f7 2038 }
<> 144:ef7eb2e8f9f7 2039 }
<> 144:ef7eb2e8f9f7 2040 } else {
<> 144:ef7eb2e8f9f7 2041 /* Determine the source of the interrupt */
<> 144:ef7eb2e8f9f7 2042 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_PERR) {
<> 144:ef7eb2e8f9f7 2043 /* Parity error has occurred, and we are notifying. */
<> 144:ef7eb2e8f9f7 2044 USART_IntClear(obj->serial.periph.uart, USART_IFC_PERR);
<> 144:ef7eb2e8f9f7 2045 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2046 return SERIAL_EVENT_RX_PARITY_ERROR;
<> 144:ef7eb2e8f9f7 2047 }
<> 144:ef7eb2e8f9f7 2048
<> 144:ef7eb2e8f9f7 2049 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_FERR) {
<> 144:ef7eb2e8f9f7 2050 /* Framing error has occurred, and we are notifying */
<> 144:ef7eb2e8f9f7 2051 USART_IntClear(obj->serial.periph.uart, USART_IFC_FERR);
<> 144:ef7eb2e8f9f7 2052 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2053 return SERIAL_EVENT_RX_FRAMING_ERROR;
<> 144:ef7eb2e8f9f7 2054 }
<> 144:ef7eb2e8f9f7 2055
<> 144:ef7eb2e8f9f7 2056 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_RXOF) {
<> 144:ef7eb2e8f9f7 2057 /* RX buffer overflow has occurred, and we are notifying */
<> 144:ef7eb2e8f9f7 2058 USART_IntClear(obj->serial.periph.uart, USART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 2059 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2060 return SERIAL_EVENT_RX_OVERFLOW;
<> 144:ef7eb2e8f9f7 2061 }
<> 144:ef7eb2e8f9f7 2062
<> 144:ef7eb2e8f9f7 2063 if((USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_RXDATAV) || (USART_StatusGet(obj->serial.periph.uart) & USART_STATUS_RXFULL)) {
<> 144:ef7eb2e8f9f7 2064 /* Valid data in buffer. Determine course of action: continue receiving or interrupt */
<> 144:ef7eb2e8f9f7 2065 if(obj->rx_buff.pos >= (obj->rx_buff.length - 1)) {
<> 144:ef7eb2e8f9f7 2066 /* Last char, transfer complete. Switch off interrupt and return event. */
<> 144:ef7eb2e8f9f7 2067 buf[obj->rx_buff.pos] = USART_RxDataGet(obj->serial.periph.uart);
<> 144:ef7eb2e8f9f7 2068
<> 144:ef7eb2e8f9f7 2069 event |= SERIAL_EVENT_RX_COMPLETE;
<> 144:ef7eb2e8f9f7 2070
<> 144:ef7eb2e8f9f7 2071 if((buf[obj->rx_buff.pos] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
<> 144:ef7eb2e8f9f7 2072
<> 144:ef7eb2e8f9f7 2073 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2074 return event & obj->serial.events;
<> 144:ef7eb2e8f9f7 2075 } else {
<> 144:ef7eb2e8f9f7 2076 /* There's still space in the receive buffer */
<> 144:ef7eb2e8f9f7 2077 while(((USART_StatusGet(obj->serial.periph.uart) & USART_STATUS_RXDATAV) || (USART_StatusGet(obj->serial.periph.uart) & USART_IF_RXFULL)) && (obj->rx_buff.pos <= (obj->rx_buff.length - 1))) {
<> 144:ef7eb2e8f9f7 2078 bool aborting = false;
<> 144:ef7eb2e8f9f7 2079 buf[obj->rx_buff.pos] = USART_RxDataGet(obj->serial.periph.uart);
<> 144:ef7eb2e8f9f7 2080 obj->rx_buff.pos++;
<> 144:ef7eb2e8f9f7 2081
<> 144:ef7eb2e8f9f7 2082 /* Check for character match event */
<> 144:ef7eb2e8f9f7 2083 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
<> 144:ef7eb2e8f9f7 2084 aborting = true;
<> 144:ef7eb2e8f9f7 2085 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
<> 144:ef7eb2e8f9f7 2086 }
<> 144:ef7eb2e8f9f7 2087
<> 144:ef7eb2e8f9f7 2088 /* Check for final char event */
<> 144:ef7eb2e8f9f7 2089 if(obj->rx_buff.pos >= (obj->rx_buff.length)) {
<> 144:ef7eb2e8f9f7 2090 aborting = true;
<> 144:ef7eb2e8f9f7 2091 event |= SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 2092 }
<> 144:ef7eb2e8f9f7 2093
<> 144:ef7eb2e8f9f7 2094 if(aborting) {
<> 144:ef7eb2e8f9f7 2095 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2096 return event & obj->serial.events;
<> 144:ef7eb2e8f9f7 2097 }
<> 144:ef7eb2e8f9f7 2098 }
<> 144:ef7eb2e8f9f7 2099 }
<> 144:ef7eb2e8f9f7 2100 }
<> 144:ef7eb2e8f9f7 2101 }
<> 144:ef7eb2e8f9f7 2102
<> 144:ef7eb2e8f9f7 2103 /* All events should have generated a return, if no return has happened, no event has been caught */
<> 144:ef7eb2e8f9f7 2104 return 0;
<> 144:ef7eb2e8f9f7 2105 }
<> 144:ef7eb2e8f9f7 2106
<> 144:ef7eb2e8f9f7 2107 /** Unified IRQ handler. Determines the appropriate handler to execute and returns the flags.
<> 144:ef7eb2e8f9f7 2108 *
<> 144:ef7eb2e8f9f7 2109 * WARNING: this code should be stateless, as re-entrancy is very possible in interrupt-based mode.
<> 144:ef7eb2e8f9f7 2110 */
<> 144:ef7eb2e8f9f7 2111 int serial_irq_handler_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 2112 {
<> 144:ef7eb2e8f9f7 2113 uint32_t txc_int;
<> 144:ef7eb2e8f9f7 2114
<> 144:ef7eb2e8f9f7 2115 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2116 txc_int = LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_TXC;
<> 144:ef7eb2e8f9f7 2117 } else {
<> 144:ef7eb2e8f9f7 2118 txc_int = USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_TXC;
<> 144:ef7eb2e8f9f7 2119 }
<> 144:ef7eb2e8f9f7 2120
<> 144:ef7eb2e8f9f7 2121 /* First, check if we're running in DMA mode */
<> 144:ef7eb2e8f9f7 2122 if( (obj->serial.dmaOptionsRX.dmaChannel != -1) &&
<> 144:ef7eb2e8f9f7 2123 serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel]) {
<> 144:ef7eb2e8f9f7 2124 /* Clean up */
<> 144:ef7eb2e8f9f7 2125 serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
<> 144:ef7eb2e8f9f7 2126 serial_rx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2127
<> 144:ef7eb2e8f9f7 2128 /* Notify CPP land of RX completion */
<> 144:ef7eb2e8f9f7 2129 return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 2130 } else if (txc_int && (obj->serial.dmaOptionsTX.dmaChannel != -1) &&
<> 144:ef7eb2e8f9f7 2131 serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
<> 144:ef7eb2e8f9f7 2132 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2133 /* Clean up */
<> 144:ef7eb2e8f9f7 2134 serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
<> 144:ef7eb2e8f9f7 2135 serial_tx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2136 /* Notify CPP land of completion */
<> 144:ef7eb2e8f9f7 2137 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 2138 }else{
<> 144:ef7eb2e8f9f7 2139 /* Clean up */
<> 144:ef7eb2e8f9f7 2140 serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
<> 144:ef7eb2e8f9f7 2141 serial_tx_abort_asynch_intern(obj, 1);
<> 144:ef7eb2e8f9f7 2142 /* Notify CPP land of completion */
<> 144:ef7eb2e8f9f7 2143 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
<> 144:ef7eb2e8f9f7 2144 }
<> 144:ef7eb2e8f9f7 2145 } else {
<> 144:ef7eb2e8f9f7 2146 /* Check the NVIC to see which interrupt we're running from
<> 144:ef7eb2e8f9f7 2147 * Also make sure to prioritize RX */
<> 144:ef7eb2e8f9f7 2148 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2149 //Different method of checking tx vs rx for LEUART
<> 144:ef7eb2e8f9f7 2150 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF)) {
<> 144:ef7eb2e8f9f7 2151 return serial_rx_irq_handler_asynch(obj);
<> 144:ef7eb2e8f9f7 2152 } else if(LEUART_StatusGet(obj->serial.periph.leuart) & (LEUART_STATUS_TXBL | LEUART_STATUS_TXC)) {
<> 144:ef7eb2e8f9f7 2153 return serial_tx_irq_handler_asynch(obj);
<> 144:ef7eb2e8f9f7 2154 }
<> 144:ef7eb2e8f9f7 2155 } else {
<> 144:ef7eb2e8f9f7 2156 if(USART_IntGetEnabled(obj->serial.periph.uart) & (USART_IF_RXDATAV | USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR)) {
<> 144:ef7eb2e8f9f7 2157 return serial_rx_irq_handler_asynch(obj);
<> 144:ef7eb2e8f9f7 2158 } else if(USART_StatusGet(obj->serial.periph.uart) & (USART_STATUS_TXBL | USART_STATUS_TXC)){
<> 144:ef7eb2e8f9f7 2159 return serial_tx_irq_handler_asynch(obj);
<> 144:ef7eb2e8f9f7 2160 }
<> 144:ef7eb2e8f9f7 2161 }
<> 144:ef7eb2e8f9f7 2162 }
<> 144:ef7eb2e8f9f7 2163
<> 144:ef7eb2e8f9f7 2164 // All should be done now
<> 144:ef7eb2e8f9f7 2165 return 0;
<> 144:ef7eb2e8f9f7 2166 }
<> 144:ef7eb2e8f9f7 2167
<> 144:ef7eb2e8f9f7 2168 /** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
<> 144:ef7eb2e8f9f7 2169 * flush TX hardware buffer if TX FIFO is used
<> 144:ef7eb2e8f9f7 2170 *
<> 144:ef7eb2e8f9f7 2171 * @param obj The serial object
<> 144:ef7eb2e8f9f7 2172 */
<> 144:ef7eb2e8f9f7 2173 void serial_tx_abort_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 2174 {
<> 144:ef7eb2e8f9f7 2175 serial_tx_abort_asynch_intern(obj, 0);
<> 144:ef7eb2e8f9f7 2176 }
<> 144:ef7eb2e8f9f7 2177
<> 144:ef7eb2e8f9f7 2178 static void serial_tx_abort_asynch_intern(serial_t *obj, int unblock_sleep)
<> 144:ef7eb2e8f9f7 2179 {
<> 144:ef7eb2e8f9f7 2180 // Transmitter should be disabled here but there are multiple issues
<> 144:ef7eb2e8f9f7 2181 // making that quite difficult.
<> 144:ef7eb2e8f9f7 2182 //
<> 144:ef7eb2e8f9f7 2183 // - Disabling the transmitter when using DMA on platforms prior to
<> 144:ef7eb2e8f9f7 2184 // Pearl can cause the UART to leave the line low, generating a break
<> 144:ef7eb2e8f9f7 2185 // condition until the next transmission begins.
<> 144:ef7eb2e8f9f7 2186 //
<> 144:ef7eb2e8f9f7 2187 // - On (at least) Pearl, once TXC interrupt has fired it will take some time
<> 144:ef7eb2e8f9f7 2188 // (some tens of microsec) for TXC to be set in STATUS. If we turn off
<> 144:ef7eb2e8f9f7 2189 // the transmitter before this, bad things will happen.
<> 144:ef7eb2e8f9f7 2190 //
<> 144:ef7eb2e8f9f7 2191 // - On (at least) Pearl, when using TX DMA it is possible for the USART
<> 144:ef7eb2e8f9f7 2192 // status to be: TXENS TXBL TXIDLE = 1, TXBUFCNT = 0, but TXC = 0.
<> 144:ef7eb2e8f9f7 2193 //
<> 144:ef7eb2e8f9f7 2194 // All in all, the logic was so fragile it's best to leave it out.
<> 144:ef7eb2e8f9f7 2195
<> 144:ef7eb2e8f9f7 2196 /* Clean up */
<> 144:ef7eb2e8f9f7 2197 switch(obj->serial.dmaOptionsTX.dmaUsageState) {
<> 144:ef7eb2e8f9f7 2198 case DMA_USAGE_ALLOCATED:
<> 144:ef7eb2e8f9f7 2199 /* stop DMA transfer */
<> 144:ef7eb2e8f9f7 2200 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 2201 DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
<> 144:ef7eb2e8f9f7 2202 #else
<> 144:ef7eb2e8f9f7 2203 LDMA_StopTransfer(obj->serial.dmaOptionsTX.dmaChannel);
<> 144:ef7eb2e8f9f7 2204 #endif
<> 144:ef7eb2e8f9f7 2205 break;
<> 144:ef7eb2e8f9f7 2206 case DMA_USAGE_TEMPORARY_ALLOCATED:
<> 144:ef7eb2e8f9f7 2207 /* stop DMA transfer and release channel */
<> 144:ef7eb2e8f9f7 2208 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 2209 DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
<> 144:ef7eb2e8f9f7 2210 #else
<> 144:ef7eb2e8f9f7 2211 LDMA_StopTransfer(obj->serial.dmaOptionsTX.dmaChannel);
<> 144:ef7eb2e8f9f7 2212 #endif
<> 144:ef7eb2e8f9f7 2213 dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
<> 144:ef7eb2e8f9f7 2214 obj->serial.dmaOptionsTX.dmaChannel = -1;
<> 144:ef7eb2e8f9f7 2215 obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
<> 144:ef7eb2e8f9f7 2216 break;
<> 144:ef7eb2e8f9f7 2217 default:
<> 144:ef7eb2e8f9f7 2218 break;
<> 144:ef7eb2e8f9f7 2219 }
<> 144:ef7eb2e8f9f7 2220
<> 144:ef7eb2e8f9f7 2221 /* stop interrupting */
<> 144:ef7eb2e8f9f7 2222 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2223 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 2224 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXC);
<> 144:ef7eb2e8f9f7 2225 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_TXC);
<> 144:ef7eb2e8f9f7 2226 } else {
<> 144:ef7eb2e8f9f7 2227 USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
<> 144:ef7eb2e8f9f7 2228 USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXC);
<> 144:ef7eb2e8f9f7 2229 USART_IntClear(obj->serial.periph.uart, USART_IFC_TXC);
<> 144:ef7eb2e8f9f7 2230 }
<> 144:ef7eb2e8f9f7 2231
<> 144:ef7eb2e8f9f7 2232 /* Say that we can stop using this emode */
<> 144:ef7eb2e8f9f7 2233 if(unblock_sleep)
<> 144:ef7eb2e8f9f7 2234 serial_unblock_sleep(obj);
<> 144:ef7eb2e8f9f7 2235 }
<> 144:ef7eb2e8f9f7 2236
<> 144:ef7eb2e8f9f7 2237
<> 144:ef7eb2e8f9f7 2238 static void serial_unblock_sleep(serial_t *obj)
<> 144:ef7eb2e8f9f7 2239 {
<> 144:ef7eb2e8f9f7 2240 if( obj->serial.sleep_blocked > 0 ) {
<> 144:ef7eb2e8f9f7 2241 #ifdef LEUART_USING_LFXO
<> 144:ef7eb2e8f9f7 2242 if(LEUART_REF_VALID(obj->serial.periph.leuart) && (LEUART_BaudrateGet(obj->serial.periph.leuart) <= (LEUART_LF_REF_FREQ/2))){
<> 144:ef7eb2e8f9f7 2243 unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART);
<> 144:ef7eb2e8f9f7 2244 }else{
<> 144:ef7eb2e8f9f7 2245 unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
<> 144:ef7eb2e8f9f7 2246 }
<> 144:ef7eb2e8f9f7 2247 #else
<> 144:ef7eb2e8f9f7 2248 unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
<> 144:ef7eb2e8f9f7 2249 #endif
<> 144:ef7eb2e8f9f7 2250 obj->serial.sleep_blocked--;
<> 144:ef7eb2e8f9f7 2251 }
<> 144:ef7eb2e8f9f7 2252 }
<> 144:ef7eb2e8f9f7 2253
<> 144:ef7eb2e8f9f7 2254 static void serial_block_sleep(serial_t *obj)
<> 144:ef7eb2e8f9f7 2255 {
<> 144:ef7eb2e8f9f7 2256 obj->serial.sleep_blocked++;
<> 144:ef7eb2e8f9f7 2257 #ifdef LEUART_USING_LFXO
<> 144:ef7eb2e8f9f7 2258 if(LEUART_REF_VALID(obj->serial.periph.leuart) && (LEUART_BaudrateGet(obj->serial.periph.leuart) <= (LEUART_LF_REF_FREQ/2))){
<> 144:ef7eb2e8f9f7 2259 blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART);
<> 144:ef7eb2e8f9f7 2260 }else{
<> 144:ef7eb2e8f9f7 2261 blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
<> 144:ef7eb2e8f9f7 2262 }
<> 144:ef7eb2e8f9f7 2263 #else
<> 144:ef7eb2e8f9f7 2264 blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
<> 144:ef7eb2e8f9f7 2265 #endif
<> 144:ef7eb2e8f9f7 2266 }
<> 144:ef7eb2e8f9f7 2267
<> 144:ef7eb2e8f9f7 2268 /** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
<> 144:ef7eb2e8f9f7 2269 * flush RX hardware buffer if RX FIFO is used
<> 144:ef7eb2e8f9f7 2270 *
<> 144:ef7eb2e8f9f7 2271 * @param obj The serial object
<> 144:ef7eb2e8f9f7 2272 */
<> 144:ef7eb2e8f9f7 2273 void serial_rx_abort_asynch(serial_t *obj)
<> 144:ef7eb2e8f9f7 2274 {
<> 144:ef7eb2e8f9f7 2275 serial_rx_abort_asynch_intern(obj, 0);
<> 144:ef7eb2e8f9f7 2276 }
<> 144:ef7eb2e8f9f7 2277
<> 144:ef7eb2e8f9f7 2278 static void serial_rx_abort_asynch_intern(serial_t *obj, int unblock_sleep)
<> 144:ef7eb2e8f9f7 2279 {
<> 144:ef7eb2e8f9f7 2280 /* Stop receiver */
<> 144:ef7eb2e8f9f7 2281 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2282 obj->serial.periph.leuart->CMD = LEUART_CMD_RXDIS;
<> 144:ef7eb2e8f9f7 2283 while(obj->serial.periph.leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
<> 144:ef7eb2e8f9f7 2284 } else {
<> 144:ef7eb2e8f9f7 2285 obj->serial.periph.uart->CMD = USART_CMD_RXDIS;
<> 144:ef7eb2e8f9f7 2286 }
<> 144:ef7eb2e8f9f7 2287
<> 144:ef7eb2e8f9f7 2288 /* Clean up */
<> 144:ef7eb2e8f9f7 2289 switch(obj->serial.dmaOptionsRX.dmaUsageState) {
<> 144:ef7eb2e8f9f7 2290 case DMA_USAGE_ALLOCATED:
<> 144:ef7eb2e8f9f7 2291 /* stop DMA transfer */
<> 144:ef7eb2e8f9f7 2292 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 2293 DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
<> 144:ef7eb2e8f9f7 2294 #else
<> 144:ef7eb2e8f9f7 2295 LDMA_StopTransfer(obj->serial.dmaOptionsRX.dmaChannel);
<> 144:ef7eb2e8f9f7 2296 #endif
<> 144:ef7eb2e8f9f7 2297 break;
<> 144:ef7eb2e8f9f7 2298 case DMA_USAGE_TEMPORARY_ALLOCATED:
<> 144:ef7eb2e8f9f7 2299 /* stop DMA transfer and release channel */
<> 144:ef7eb2e8f9f7 2300 #ifndef LDMA_PRESENT
<> 144:ef7eb2e8f9f7 2301 DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
<> 144:ef7eb2e8f9f7 2302 #else
<> 144:ef7eb2e8f9f7 2303 LDMA_StopTransfer(obj->serial.dmaOptionsRX.dmaChannel);
<> 144:ef7eb2e8f9f7 2304 #endif
<> 144:ef7eb2e8f9f7 2305 dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
<> 144:ef7eb2e8f9f7 2306 obj->serial.dmaOptionsRX.dmaChannel = -1;
<> 144:ef7eb2e8f9f7 2307 obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
<> 144:ef7eb2e8f9f7 2308 break;
<> 144:ef7eb2e8f9f7 2309 default:
<> 144:ef7eb2e8f9f7 2310 /* stop interrupting */
<> 144:ef7eb2e8f9f7 2311 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2312 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV | LEUART_IEN_PERR | LEUART_IEN_FERR | LEUART_IEN_RXOF);
<> 144:ef7eb2e8f9f7 2313 } else {
<> 144:ef7eb2e8f9f7 2314 USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
<> 144:ef7eb2e8f9f7 2315 }
<> 144:ef7eb2e8f9f7 2316 break;
<> 144:ef7eb2e8f9f7 2317 }
<> 144:ef7eb2e8f9f7 2318
<> 144:ef7eb2e8f9f7 2319 /*clear all set interrupts*/
<> 144:ef7eb2e8f9f7 2320 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
<> 144:ef7eb2e8f9f7 2321 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_PERR | LEUART_IFC_FERR | LEUART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 2322 }else{
<> 144:ef7eb2e8f9f7 2323 USART_IntClear(obj->serial.periph.uart, USART_IFC_PERR | USART_IFC_FERR | USART_IFC_RXOF);
<> 144:ef7eb2e8f9f7 2324 }
<> 144:ef7eb2e8f9f7 2325
<> 144:ef7eb2e8f9f7 2326 /* Say that we can stop using this emode */
<> 144:ef7eb2e8f9f7 2327 if( unblock_sleep )
<> 144:ef7eb2e8f9f7 2328 serial_unblock_sleep(obj);
<> 144:ef7eb2e8f9f7 2329 }
<> 144:ef7eb2e8f9f7 2330
<> 144:ef7eb2e8f9f7 2331 #endif //DEVICE_SERIAL_ASYNCH
<> 144:ef7eb2e8f9f7 2332 #endif //DEVICE_SERIAL