added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /***************************************************************************//**
<> 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