added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Sep 02 15:07:44 2016 +0100
Revision:
144:ef7eb2e8f9f7
Parent:
52:4ce9155acc4d
This updates the lib to the mbed lib v125

Who changed what in which revision?

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