Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

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