mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Apr 28 13:00:10 2015 +0100
Revision:
526:7c4bdfe6a168
Parent:
525:c320967f86b9
Child:
527:74d34ce5a2b5
Synchronized with git revision cdff09e6b6c486eb58fb5e968f3191c8480b0567

Full URL: https://github.com/mbedmicro/mbed/commit/cdff09e6b6c486eb58fb5e968f3191c8480b0567/

Silabs - Fix unblock/block declaration, implement gpio_is_connected

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 525:c320967f86b9 1 /* mbed Microcontroller Library
mbed_official 525:c320967f86b9 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 525:c320967f86b9 3 *
mbed_official 525:c320967f86b9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 525:c320967f86b9 5 * you may not use this file except in compliance with the License.
mbed_official 525:c320967f86b9 6 * You may obtain a copy of the License at
mbed_official 525:c320967f86b9 7 *
mbed_official 525:c320967f86b9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 525:c320967f86b9 9 *
mbed_official 525:c320967f86b9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 525:c320967f86b9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 525:c320967f86b9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 525:c320967f86b9 13 * See the License for the specific language governing permissions and
mbed_official 525:c320967f86b9 14 * limitations under the License.
mbed_official 525:c320967f86b9 15 */
mbed_official 525:c320967f86b9 16
mbed_official 525:c320967f86b9 17 #include "device.h"
mbed_official 525:c320967f86b9 18 #include "clocking.h"
mbed_official 525:c320967f86b9 19 #if DEVICE_SERIAL
mbed_official 525:c320967f86b9 20
mbed_official 525:c320967f86b9 21 #include "mbed_assert.h"
mbed_official 525:c320967f86b9 22 #include "serial_api.h"
mbed_official 525:c320967f86b9 23 #include <string.h>
mbed_official 525:c320967f86b9 24 #include <stdbool.h>
mbed_official 525:c320967f86b9 25
mbed_official 525:c320967f86b9 26 #include "pinmap.h"
mbed_official 525:c320967f86b9 27 #include "pinmap_function.h"
mbed_official 525:c320967f86b9 28 #include "PeripheralPins.h"
mbed_official 525:c320967f86b9 29 #include "PeripheralNames.h"
mbed_official 525:c320967f86b9 30
mbed_official 525:c320967f86b9 31 #include "em_usart.h"
mbed_official 525:c320967f86b9 32 #include "em_leuart.h"
mbed_official 525:c320967f86b9 33 #include "em_cmu.h"
mbed_official 525:c320967f86b9 34 #include "em_dma.h"
mbed_official 525:c320967f86b9 35 #include "dma_api_HAL.h"
mbed_official 525:c320967f86b9 36 #include "dma_api.h"
mbed_official 525:c320967f86b9 37 #include "sleep_api.h"
mbed_official 525:c320967f86b9 38 #include "buffer.h"
mbed_official 526:7c4bdfe6a168 39 #include "sleepmodes.h"
mbed_official 525:c320967f86b9 40
mbed_official 525:c320967f86b9 41 #define SERIAL_LEAST_ACTIVE_SLEEPMODE EM1
mbed_official 525:c320967f86b9 42 #define SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART EM2
mbed_official 525:c320967f86b9 43
mbed_official 525:c320967f86b9 44 /** Validation of LEUART register block pointer reference
mbed_official 525:c320967f86b9 45 * for assert statements. */
mbed_official 525:c320967f86b9 46 #if !defined(LEUART_COUNT)
mbed_official 525:c320967f86b9 47 #define LEUART_REF_VALID(ref) (0)
mbed_official 525:c320967f86b9 48 #elif (LEUART_COUNT == 1)
mbed_official 525:c320967f86b9 49 #define LEUART_REF_VALID(ref) ((ref) == LEUART0)
mbed_official 525:c320967f86b9 50 #elif (LEUART_COUNT == 2)
mbed_official 525:c320967f86b9 51 #define LEUART_REF_VALID(ref) (((ref) == LEUART0) || ((ref) == LEUART1))
mbed_official 525:c320967f86b9 52 #else
mbed_official 525:c320967f86b9 53 #error Undefined number of low energy UARTs (LEUART).
mbed_official 525:c320967f86b9 54 #endif
mbed_official 525:c320967f86b9 55
mbed_official 525:c320967f86b9 56 /* Store IRQ id for each UART */
mbed_official 525:c320967f86b9 57 static uint32_t serial_irq_ids[SERIAL_NUM_UARTS] = { 0 };
mbed_official 525:c320967f86b9 58 /* Interrupt handler from mbed common */
mbed_official 525:c320967f86b9 59 static uart_irq_handler irq_handler;
mbed_official 525:c320967f86b9 60 /* Keep track of incoming DMA IRQ's */
mbed_official 525:c320967f86b9 61 static bool serial_dma_irq_fired[DMACTRL_CH_CNT] = { false };
mbed_official 525:c320967f86b9 62
mbed_official 525:c320967f86b9 63 /* Serial interface on USBTX/USBRX retargets stdio */
mbed_official 525:c320967f86b9 64 int stdio_uart_inited = 0;
mbed_official 525:c320967f86b9 65 serial_t stdio_uart;
mbed_official 525:c320967f86b9 66
mbed_official 525:c320967f86b9 67 static void uart_irq(UARTName, int, SerialIrq);
mbed_official 525:c320967f86b9 68 uint8_t serial_get_index(serial_t *obj);
mbed_official 525:c320967f86b9 69 IRQn_Type serial_get_rx_irq_index(serial_t *obj);
mbed_official 525:c320967f86b9 70 IRQn_Type serial_get_tx_irq_index(serial_t *obj);
mbed_official 525:c320967f86b9 71 CMU_Clock_TypeDef serial_get_clock(serial_t *obj);
mbed_official 525:c320967f86b9 72
mbed_official 525:c320967f86b9 73 /* ISRs for RX and TX events */
mbed_official 525:c320967f86b9 74 #ifdef UART0
mbed_official 525:c320967f86b9 75 static void uart0_rx_irq() { uart_irq(UART_0, 0, RxIrq); }
mbed_official 525:c320967f86b9 76 static void uart0_tx_irq() { uart_irq(UART_0, 0, TxIrq); USART_IntClear((USART_TypeDef*)UART_0, USART_IFC_TXC);}
mbed_official 525:c320967f86b9 77 #endif
mbed_official 525:c320967f86b9 78 #ifdef UART1
mbed_official 525:c320967f86b9 79 static void uart1_rx_irq() { uart_irq(UART_1, 1, RxIrq); }
mbed_official 525:c320967f86b9 80 static void uart1_tx_irq() { uart_irq(UART_1, 1, TxIrq); USART_IntClear((USART_TypeDef*)UART_1, USART_IFC_TXC);}
mbed_official 525:c320967f86b9 81 #endif
mbed_official 525:c320967f86b9 82 #ifdef USART0
mbed_official 525:c320967f86b9 83 static void usart0_rx_irq() { uart_irq(USART_0, 2, RxIrq); }
mbed_official 525:c320967f86b9 84 static void usart0_tx_irq() { uart_irq(USART_0, 2, TxIrq); USART_IntClear((USART_TypeDef*)USART_0, USART_IFC_TXC);}
mbed_official 525:c320967f86b9 85 #endif
mbed_official 525:c320967f86b9 86 #ifdef USART1
mbed_official 525:c320967f86b9 87 static void usart1_rx_irq() { uart_irq(USART_1, 3, RxIrq); }
mbed_official 525:c320967f86b9 88 static void usart1_tx_irq() { uart_irq(USART_1, 3, TxIrq); USART_IntClear((USART_TypeDef*)USART_1, USART_IFC_TXC);}
mbed_official 525:c320967f86b9 89 #endif
mbed_official 525:c320967f86b9 90 #ifdef USART2
mbed_official 525:c320967f86b9 91 static void usart2_rx_irq() { uart_irq(USART_2, 4, RxIrq); }
mbed_official 525:c320967f86b9 92 static void usart2_tx_irq() { uart_irq(USART_2, 4, TxIrq); USART_IntClear((USART_TypeDef*)USART_2, USART_IFC_TXC);}
mbed_official 525:c320967f86b9 93 #endif
mbed_official 525:c320967f86b9 94 #ifdef LEUART0
mbed_official 525:c320967f86b9 95 static void leuart0_irq() {
mbed_official 525:c320967f86b9 96 if(LEUART_IntGetEnabled(LEUART0) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
mbed_official 525:c320967f86b9 97 uart_irq(LEUART_0, 5, RxIrq);
mbed_official 525:c320967f86b9 98 } else {
mbed_official 525:c320967f86b9 99 uart_irq(LEUART_0, 5, TxIrq);
mbed_official 525:c320967f86b9 100 }
mbed_official 525:c320967f86b9 101 }
mbed_official 525:c320967f86b9 102 #endif
mbed_official 525:c320967f86b9 103 #ifdef LEUART1
mbed_official 525:c320967f86b9 104 static void leuart1_irq() {
mbed_official 525:c320967f86b9 105 if(LEUART_IntGetEnabled(LEUART1) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
mbed_official 525:c320967f86b9 106 uart_irq(LEUART_1, 6, RxIrq);
mbed_official 525:c320967f86b9 107 } else {
mbed_official 525:c320967f86b9 108 uart_irq(LEUART_1, 6, TxIrq);
mbed_official 525:c320967f86b9 109 }
mbed_official 525:c320967f86b9 110 }
mbed_official 525:c320967f86b9 111 #endif
mbed_official 525:c320967f86b9 112
mbed_official 525:c320967f86b9 113 /**
mbed_official 525:c320967f86b9 114 * Initialize the UART using default settings, overridden by settings from serial object
mbed_official 525:c320967f86b9 115 *
mbed_official 525:c320967f86b9 116 * @param obj pointer to serial object
mbed_official 525:c320967f86b9 117 */
mbed_official 525:c320967f86b9 118 static void uart_init(serial_t *obj)
mbed_official 525:c320967f86b9 119 {
mbed_official 525:c320967f86b9 120 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 121 LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
mbed_official 525:c320967f86b9 122
mbed_official 525:c320967f86b9 123 init.enable = leuartDisable;
mbed_official 525:c320967f86b9 124 init.baudrate = 9600;
mbed_official 525:c320967f86b9 125 init.databits = leuartDatabits8;
mbed_official 525:c320967f86b9 126 init.parity = leuartNoParity;
mbed_official 525:c320967f86b9 127 init.stopbits = leuartStopbits1;
mbed_official 525:c320967f86b9 128
mbed_official 525:c320967f86b9 129 /* Determine the reference clock, because the correct clock is not set up at init time */
mbed_official 525:c320967f86b9 130 init.refFreq = LEUART_REF_FREQ;
mbed_official 525:c320967f86b9 131
mbed_official 525:c320967f86b9 132 LEUART_Init(obj->serial.periph.leuart, &init);
mbed_official 525:c320967f86b9 133 } else {
mbed_official 525:c320967f86b9 134 USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
mbed_official 525:c320967f86b9 135
mbed_official 525:c320967f86b9 136 init.enable = usartDisable;
mbed_official 525:c320967f86b9 137 init.baudrate = 9600;
mbed_official 525:c320967f86b9 138 init.oversampling = usartOVS16;
mbed_official 525:c320967f86b9 139 init.databits = usartDatabits8;
mbed_official 525:c320967f86b9 140 init.parity = usartNoParity;
mbed_official 525:c320967f86b9 141 init.stopbits = usartStopbits1;
mbed_official 525:c320967f86b9 142
mbed_official 525:c320967f86b9 143 /* Determine the reference clock, because the correct clock is not set up at init time */
mbed_official 525:c320967f86b9 144 init.refFreq = REFERENCE_FREQUENCY;
mbed_official 525:c320967f86b9 145
mbed_official 525:c320967f86b9 146 USART_InitAsync(obj->serial.periph.uart, &init);
mbed_official 525:c320967f86b9 147 }
mbed_official 525:c320967f86b9 148 }
mbed_official 525:c320967f86b9 149
mbed_official 525:c320967f86b9 150 /**
mbed_official 525:c320967f86b9 151 * Get index of serial object, relating it to the physical peripheral.
mbed_official 525:c320967f86b9 152 *
mbed_official 525:c320967f86b9 153 * @param obj pointer to serial object
mbed_official 525:c320967f86b9 154 * @return internal index of U(S)ART peripheral
mbed_official 525:c320967f86b9 155 */
mbed_official 525:c320967f86b9 156 inline uint8_t serial_get_index(serial_t *obj)
mbed_official 525:c320967f86b9 157 {
mbed_official 525:c320967f86b9 158 switch ((uint32_t)obj->serial.periph.uart) {
mbed_official 525:c320967f86b9 159 #ifdef UART0
mbed_official 525:c320967f86b9 160 case UART_0:
mbed_official 525:c320967f86b9 161 return 0;
mbed_official 525:c320967f86b9 162 #endif
mbed_official 525:c320967f86b9 163 #ifdef UART1
mbed_official 525:c320967f86b9 164 case UART_1:
mbed_official 525:c320967f86b9 165 return 1;
mbed_official 525:c320967f86b9 166 #endif
mbed_official 525:c320967f86b9 167 #ifdef USART0
mbed_official 525:c320967f86b9 168 case USART_0:
mbed_official 525:c320967f86b9 169 return 2;
mbed_official 525:c320967f86b9 170 #endif
mbed_official 525:c320967f86b9 171 #ifdef USART1
mbed_official 525:c320967f86b9 172 case USART_1:
mbed_official 525:c320967f86b9 173 return 3;
mbed_official 525:c320967f86b9 174 #endif
mbed_official 525:c320967f86b9 175 #ifdef USART2
mbed_official 525:c320967f86b9 176 case USART_2:
mbed_official 525:c320967f86b9 177 return 4;
mbed_official 525:c320967f86b9 178 #endif
mbed_official 525:c320967f86b9 179 #ifdef LEUART0
mbed_official 525:c320967f86b9 180 case LEUART_0:
mbed_official 525:c320967f86b9 181 return 5;
mbed_official 525:c320967f86b9 182 #endif
mbed_official 525:c320967f86b9 183 #ifdef LEUART1
mbed_official 525:c320967f86b9 184 case LEUART_1:
mbed_official 525:c320967f86b9 185 return 6;
mbed_official 525:c320967f86b9 186 #endif
mbed_official 525:c320967f86b9 187 }
mbed_official 525:c320967f86b9 188 return 0;
mbed_official 525:c320967f86b9 189 }
mbed_official 525:c320967f86b9 190
mbed_official 525:c320967f86b9 191 /**
mbed_official 525:c320967f86b9 192 * Get index of serial object RX IRQ, relating it to the physical peripheral.
mbed_official 525:c320967f86b9 193 *
mbed_official 525:c320967f86b9 194 * @param obj pointer to serial object
mbed_official 525:c320967f86b9 195 * @return internal NVIC RX IRQ index of U(S)ART peripheral
mbed_official 525:c320967f86b9 196 */
mbed_official 525:c320967f86b9 197 inline IRQn_Type serial_get_rx_irq_index(serial_t *obj)
mbed_official 525:c320967f86b9 198 {
mbed_official 525:c320967f86b9 199 switch ((uint32_t)obj->serial.periph.uart) {
mbed_official 525:c320967f86b9 200 #ifdef UART0
mbed_official 525:c320967f86b9 201 case UART_0:
mbed_official 525:c320967f86b9 202 return UART0_RX_IRQn;
mbed_official 525:c320967f86b9 203 #endif
mbed_official 525:c320967f86b9 204 #ifdef UART1
mbed_official 525:c320967f86b9 205 case UART_1:
mbed_official 525:c320967f86b9 206 return UART1_RX_IRQn;
mbed_official 525:c320967f86b9 207 #endif
mbed_official 525:c320967f86b9 208 #ifdef USART0
mbed_official 525:c320967f86b9 209 case USART_0:
mbed_official 525:c320967f86b9 210 return USART0_RX_IRQn;
mbed_official 525:c320967f86b9 211 #endif
mbed_official 525:c320967f86b9 212 #ifdef USART1
mbed_official 525:c320967f86b9 213 case USART_1:
mbed_official 525:c320967f86b9 214 return USART1_RX_IRQn;
mbed_official 525:c320967f86b9 215 #endif
mbed_official 525:c320967f86b9 216 #ifdef USART2
mbed_official 525:c320967f86b9 217 case USART_2:
mbed_official 525:c320967f86b9 218 return USART2_RX_IRQn;
mbed_official 525:c320967f86b9 219 #endif
mbed_official 525:c320967f86b9 220 #ifdef LEUART0
mbed_official 525:c320967f86b9 221 case LEUART_0:
mbed_official 525:c320967f86b9 222 return LEUART0_IRQn;
mbed_official 525:c320967f86b9 223 #endif
mbed_official 525:c320967f86b9 224 #ifdef LEUART1
mbed_official 525:c320967f86b9 225 case LEUART_1:
mbed_official 525:c320967f86b9 226 return LEUART1_IRQn;
mbed_official 525:c320967f86b9 227 #endif
mbed_official 525:c320967f86b9 228 default:
mbed_official 525:c320967f86b9 229 MBED_ASSERT(0);
mbed_official 525:c320967f86b9 230 }
mbed_official 526:7c4bdfe6a168 231 return (IRQn_Type)0;
mbed_official 525:c320967f86b9 232 }
mbed_official 525:c320967f86b9 233
mbed_official 525:c320967f86b9 234 /**
mbed_official 525:c320967f86b9 235 * Get index of serial object TX IRQ, relating it to the physical peripheral.
mbed_official 525:c320967f86b9 236 *
mbed_official 525:c320967f86b9 237 * @param obj pointer to serial object
mbed_official 525:c320967f86b9 238 * @return internal NVIC TX IRQ index of U(S)ART peripheral
mbed_official 525:c320967f86b9 239 */
mbed_official 525:c320967f86b9 240 inline IRQn_Type serial_get_tx_irq_index(serial_t *obj)
mbed_official 525:c320967f86b9 241 {
mbed_official 525:c320967f86b9 242 switch ((uint32_t)obj->serial.periph.uart) {
mbed_official 525:c320967f86b9 243 #ifdef UART0
mbed_official 525:c320967f86b9 244 case UART_0:
mbed_official 525:c320967f86b9 245 return UART0_TX_IRQn;
mbed_official 525:c320967f86b9 246 #endif
mbed_official 525:c320967f86b9 247 #ifdef UART1
mbed_official 525:c320967f86b9 248 case UART_1:
mbed_official 525:c320967f86b9 249 return UART1_TX_IRQn;
mbed_official 525:c320967f86b9 250 #endif
mbed_official 525:c320967f86b9 251 #ifdef USART0
mbed_official 525:c320967f86b9 252 case USART_0:
mbed_official 525:c320967f86b9 253 return USART0_TX_IRQn;
mbed_official 525:c320967f86b9 254 #endif
mbed_official 525:c320967f86b9 255 #ifdef USART1
mbed_official 525:c320967f86b9 256 case USART_1:
mbed_official 525:c320967f86b9 257 return USART1_TX_IRQn;
mbed_official 525:c320967f86b9 258 #endif
mbed_official 525:c320967f86b9 259 #ifdef USART2
mbed_official 525:c320967f86b9 260 case USART_2:
mbed_official 525:c320967f86b9 261 return USART2_TX_IRQn;
mbed_official 525:c320967f86b9 262 #endif
mbed_official 525:c320967f86b9 263 #ifdef LEUART0
mbed_official 525:c320967f86b9 264 case LEUART_0:
mbed_official 525:c320967f86b9 265 return LEUART0_IRQn;
mbed_official 525:c320967f86b9 266 #endif
mbed_official 525:c320967f86b9 267 #ifdef LEUART1
mbed_official 525:c320967f86b9 268 case LEUART_1:
mbed_official 525:c320967f86b9 269 return LEUART1_IRQn;
mbed_official 525:c320967f86b9 270 #endif
mbed_official 525:c320967f86b9 271 default:
mbed_official 525:c320967f86b9 272 MBED_ASSERT(0);
mbed_official 525:c320967f86b9 273 }
mbed_official 526:7c4bdfe6a168 274 return (IRQn_Type)0;
mbed_official 525:c320967f86b9 275 }
mbed_official 525:c320967f86b9 276
mbed_official 525:c320967f86b9 277 /**
mbed_official 525:c320967f86b9 278 * Get clock tree for serial peripheral pointed to by obj.
mbed_official 525:c320967f86b9 279 *
mbed_official 525:c320967f86b9 280 * @param obj pointer to serial object
mbed_official 525:c320967f86b9 281 * @return CMU_Clock_TypeDef for U(S)ART
mbed_official 525:c320967f86b9 282 */
mbed_official 525:c320967f86b9 283 inline CMU_Clock_TypeDef serial_get_clock(serial_t *obj)
mbed_official 525:c320967f86b9 284 {
mbed_official 525:c320967f86b9 285 switch ((uint32_t)obj->serial.periph.uart) {
mbed_official 525:c320967f86b9 286 #ifdef UART0
mbed_official 525:c320967f86b9 287 case UART_0:
mbed_official 525:c320967f86b9 288 return cmuClock_UART0;
mbed_official 525:c320967f86b9 289 #endif
mbed_official 525:c320967f86b9 290 #ifdef UART1
mbed_official 525:c320967f86b9 291 case UART_1:
mbed_official 525:c320967f86b9 292 return cmuClock_UART1;
mbed_official 525:c320967f86b9 293 #endif
mbed_official 525:c320967f86b9 294 #ifdef USART0
mbed_official 525:c320967f86b9 295 case USART_0:
mbed_official 525:c320967f86b9 296 return cmuClock_USART0;
mbed_official 525:c320967f86b9 297 #endif
mbed_official 525:c320967f86b9 298 #ifdef USART1
mbed_official 525:c320967f86b9 299 case USART_1:
mbed_official 525:c320967f86b9 300 return cmuClock_USART1;
mbed_official 525:c320967f86b9 301 #endif
mbed_official 525:c320967f86b9 302 #ifdef USART2
mbed_official 525:c320967f86b9 303 case USART_2:
mbed_official 525:c320967f86b9 304 return cmuClock_USART2;
mbed_official 525:c320967f86b9 305 #endif
mbed_official 525:c320967f86b9 306 #ifdef LEUART0
mbed_official 525:c320967f86b9 307 case LEUART_0:
mbed_official 525:c320967f86b9 308 return cmuClock_LEUART0;
mbed_official 525:c320967f86b9 309 #endif
mbed_official 525:c320967f86b9 310 #ifdef LEUART1
mbed_official 525:c320967f86b9 311 case LEUART_1:
mbed_official 525:c320967f86b9 312 return cmuClock_LEUART1;
mbed_official 525:c320967f86b9 313 #endif
mbed_official 525:c320967f86b9 314 default:
mbed_official 525:c320967f86b9 315 return cmuClock_HFPER;
mbed_official 525:c320967f86b9 316 }
mbed_official 525:c320967f86b9 317 }
mbed_official 525:c320967f86b9 318
mbed_official 525:c320967f86b9 319 void serial_preinit(serial_t *obj, PinName tx, PinName rx)
mbed_official 525:c320967f86b9 320 {
mbed_official 525:c320967f86b9 321 /* Get UART object connected to the given pins */
mbed_official 525:c320967f86b9 322 UARTName uart_tx = (UARTName) pinmap_peripheral(tx, PinMap_UART_TX);
mbed_official 525:c320967f86b9 323 UARTName uart_rx = (UARTName) pinmap_peripheral(rx, PinMap_UART_RX);
mbed_official 525:c320967f86b9 324 /* Check that pins are connected to same UART */
mbed_official 525:c320967f86b9 325 UARTName uart = (UARTName) pinmap_merge(uart_tx, uart_rx);
mbed_official 525:c320967f86b9 326 MBED_ASSERT((int) uart != NC);
mbed_official 525:c320967f86b9 327
mbed_official 525:c320967f86b9 328 obj->serial.periph.uart = (USART_TypeDef *) uart;
mbed_official 525:c320967f86b9 329
mbed_official 525:c320967f86b9 330 /* Get location */
mbed_official 525:c320967f86b9 331 uint32_t uart_tx_loc = pin_location(tx, PinMap_UART_TX);
mbed_official 525:c320967f86b9 332 uint32_t uart_rx_loc = pin_location(rx, PinMap_UART_RX);
mbed_official 525:c320967f86b9 333 /* Check that pins are used by same location for the given UART */
mbed_official 525:c320967f86b9 334 obj->serial.location = pinmap_merge(uart_tx_loc, uart_rx_loc);
mbed_official 525:c320967f86b9 335 MBED_ASSERT(obj->serial.location != (uint32_t)NC);
mbed_official 525:c320967f86b9 336
mbed_official 525:c320967f86b9 337 /* Store pins in object for easy disabling in serial_free() */
mbed_official 525:c320967f86b9 338 obj->serial.rx_pin = rx;
mbed_official 525:c320967f86b9 339 obj->serial.tx_pin = tx;
mbed_official 525:c320967f86b9 340
mbed_official 525:c320967f86b9 341 /* Select interrupt */
mbed_official 525:c320967f86b9 342 switch ((uint32_t)obj->serial.periph.uart) {
mbed_official 525:c320967f86b9 343 #ifdef UART0
mbed_official 525:c320967f86b9 344 case UART_0:
mbed_official 525:c320967f86b9 345 NVIC_SetVector(UART0_RX_IRQn, (uint32_t) &uart0_rx_irq);
mbed_official 525:c320967f86b9 346 NVIC_SetVector(UART0_TX_IRQn, (uint32_t) &uart0_tx_irq);
mbed_official 525:c320967f86b9 347 NVIC_SetPriority(UART0_TX_IRQn, 1);
mbed_official 525:c320967f86b9 348 break;
mbed_official 525:c320967f86b9 349 #endif
mbed_official 525:c320967f86b9 350 #ifdef UART1
mbed_official 525:c320967f86b9 351 case UART_1:
mbed_official 525:c320967f86b9 352 NVIC_SetVector(UART1_RX_IRQn, (uint32_t) &uart1_rx_irq);
mbed_official 525:c320967f86b9 353 NVIC_SetVector(UART1_TX_IRQn, (uint32_t) &uart1_tx_irq);
mbed_official 525:c320967f86b9 354 NVIC_SetPriority(UART1_TX_IRQn, 1);
mbed_official 525:c320967f86b9 355 break;
mbed_official 525:c320967f86b9 356 #endif
mbed_official 525:c320967f86b9 357 #ifdef USART0
mbed_official 525:c320967f86b9 358 case USART_0:
mbed_official 525:c320967f86b9 359 NVIC_SetVector(USART0_RX_IRQn, (uint32_t) &usart0_rx_irq);
mbed_official 525:c320967f86b9 360 NVIC_SetVector(USART0_TX_IRQn, (uint32_t) &usart0_tx_irq);
mbed_official 525:c320967f86b9 361 NVIC_SetPriority(USART0_TX_IRQn, 1);
mbed_official 525:c320967f86b9 362 break;
mbed_official 525:c320967f86b9 363 #endif
mbed_official 525:c320967f86b9 364 #ifdef USART1
mbed_official 525:c320967f86b9 365 case USART_1:
mbed_official 525:c320967f86b9 366 NVIC_SetVector(USART1_RX_IRQn, (uint32_t) &usart1_rx_irq);
mbed_official 525:c320967f86b9 367 NVIC_SetVector(USART1_TX_IRQn, (uint32_t) &usart1_tx_irq);
mbed_official 525:c320967f86b9 368 NVIC_SetPriority(USART1_TX_IRQn, 1);
mbed_official 525:c320967f86b9 369 break;
mbed_official 525:c320967f86b9 370 #endif
mbed_official 525:c320967f86b9 371 #ifdef USART2
mbed_official 525:c320967f86b9 372 case USART_2:
mbed_official 525:c320967f86b9 373 NVIC_SetVector(USART2_RX_IRQn, (uint32_t) &usart2_rx_irq);
mbed_official 525:c320967f86b9 374 NVIC_SetVector(USART2_TX_IRQn, (uint32_t) &usart2_tx_irq);
mbed_official 525:c320967f86b9 375 NVIC_SetPriority(USART2_TX_IRQn, 1);
mbed_official 525:c320967f86b9 376 break;
mbed_official 525:c320967f86b9 377 #endif
mbed_official 525:c320967f86b9 378 #ifdef LEUART0
mbed_official 525:c320967f86b9 379 case LEUART_0:
mbed_official 525:c320967f86b9 380 NVIC_SetVector(LEUART0_IRQn, (uint32_t) &leuart0_irq);
mbed_official 525:c320967f86b9 381 break;
mbed_official 525:c320967f86b9 382 #endif
mbed_official 525:c320967f86b9 383 #ifdef LEUART1
mbed_official 525:c320967f86b9 384 case LEUART_1:
mbed_official 525:c320967f86b9 385 NVIC_SetVector(LEUART1_IRQn, (uint32_t) &leuart1_irq);
mbed_official 525:c320967f86b9 386 break;
mbed_official 525:c320967f86b9 387 #endif
mbed_official 525:c320967f86b9 388 }
mbed_official 525:c320967f86b9 389 }
mbed_official 525:c320967f86b9 390
mbed_official 525:c320967f86b9 391 void serial_enable_pins(serial_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 392 {
mbed_official 525:c320967f86b9 393 if (enable) {
mbed_official 525:c320967f86b9 394 /* Configure GPIO pins*/
mbed_official 525:c320967f86b9 395 pin_mode(obj->serial.rx_pin, Input);
mbed_official 525:c320967f86b9 396 /* 0x10 sets DOUT. Prevents false start. */
mbed_official 525:c320967f86b9 397 pin_mode(obj->serial.tx_pin, PushPull | 0x10);
mbed_official 525:c320967f86b9 398 } else {
mbed_official 525:c320967f86b9 399 pin_mode(obj->serial.rx_pin, Disabled);
mbed_official 525:c320967f86b9 400 pin_mode(obj->serial.tx_pin, Disabled);
mbed_official 525:c320967f86b9 401 }
mbed_official 525:c320967f86b9 402 }
mbed_official 525:c320967f86b9 403
mbed_official 525:c320967f86b9 404 void serial_init(serial_t *obj, PinName tx, PinName rx)
mbed_official 525:c320967f86b9 405 {
mbed_official 525:c320967f86b9 406 serial_preinit(obj, tx, rx);
mbed_official 525:c320967f86b9 407
mbed_official 525:c320967f86b9 408 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 409 // Set up LEUART clock tree to use high-speed clock)
mbed_official 525:c320967f86b9 410 CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
mbed_official 525:c320967f86b9 411 CMU_ClockSelectSet(serial_get_clock(obj), cmuSelect_CORELEDIV2);
mbed_official 525:c320967f86b9 412 }
mbed_official 525:c320967f86b9 413
mbed_official 525:c320967f86b9 414 CMU_ClockEnable(serial_get_clock(obj), true);
mbed_official 525:c320967f86b9 415
mbed_official 525:c320967f86b9 416 /* Configure UART for async operation */
mbed_official 525:c320967f86b9 417 uart_init(obj);
mbed_official 525:c320967f86b9 418
mbed_official 525:c320967f86b9 419 /* Limitations of board controller: CDC port only supports 115kbaud */
mbed_official 525:c320967f86b9 420 if((tx == STDIO_UART_TX) && (rx == STDIO_UART_RX) && (obj->serial.periph.uart == (USART_TypeDef*)STDIO_UART )) {
mbed_official 525:c320967f86b9 421 serial_baud(obj, 115200);
mbed_official 525:c320967f86b9 422 }
mbed_official 525:c320967f86b9 423
mbed_official 525:c320967f86b9 424 /* Enable pins for UART at correct location */
mbed_official 525:c320967f86b9 425 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 426 obj->serial.periph.leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
mbed_official 525:c320967f86b9 427 obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
mbed_official 525:c320967f86b9 428 } else {
mbed_official 525:c320967f86b9 429 obj->serial.periph.uart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
mbed_official 525:c320967f86b9 430 obj->serial.periph.uart->IFC = USART_IFC_TXC;
mbed_official 525:c320967f86b9 431 }
mbed_official 525:c320967f86b9 432
mbed_official 525:c320967f86b9 433 /* If this is the UART to be used for stdio, copy it to the stdio_uart struct */
mbed_official 525:c320967f86b9 434 if (obj->serial.periph.uart == (USART_TypeDef*)STDIO_UART ) {
mbed_official 525:c320967f86b9 435 stdio_uart_inited = 1;
mbed_official 525:c320967f86b9 436 memcpy(&stdio_uart, obj, sizeof(serial_t));
mbed_official 525:c320967f86b9 437
mbed_official 525:c320967f86b9 438 /* enable TX and RX by default for STDIO */
mbed_official 525:c320967f86b9 439 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 440 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN | LEUART_CMD_RXEN;
mbed_official 525:c320967f86b9 441 } else {
mbed_official 525:c320967f86b9 442 obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_RXEN;
mbed_official 525:c320967f86b9 443 }
mbed_official 525:c320967f86b9 444 }
mbed_official 525:c320967f86b9 445
mbed_official 525:c320967f86b9 446 serial_enable_pins(obj, true);
mbed_official 525:c320967f86b9 447
mbed_official 525:c320967f86b9 448
mbed_official 525:c320967f86b9 449
mbed_official 525:c320967f86b9 450 obj->serial.dmaOptionsTX.dmaChannel = -1;
mbed_official 525:c320967f86b9 451 obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 452
mbed_official 525:c320967f86b9 453 obj->serial.dmaOptionsRX.dmaChannel = -1;
mbed_official 525:c320967f86b9 454 obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 455
mbed_official 525:c320967f86b9 456 }
mbed_official 525:c320967f86b9 457
mbed_official 525:c320967f86b9 458 void serial_enable(serial_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 459 {
mbed_official 525:c320967f86b9 460 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 461 if (enable) {
mbed_official 525:c320967f86b9 462 LEUART_Enable(obj->serial.periph.leuart, leuartEnable);
mbed_official 525:c320967f86b9 463 } else {
mbed_official 525:c320967f86b9 464 LEUART_Enable(obj->serial.periph.leuart, leuartDisable);
mbed_official 525:c320967f86b9 465 }
mbed_official 525:c320967f86b9 466 } else {
mbed_official 525:c320967f86b9 467 if (enable) {
mbed_official 525:c320967f86b9 468 USART_Enable(obj->serial.periph.uart, usartEnable);
mbed_official 525:c320967f86b9 469 } else {
mbed_official 525:c320967f86b9 470 USART_Enable(obj->serial.periph.uart, usartDisable);
mbed_official 525:c320967f86b9 471 }
mbed_official 525:c320967f86b9 472 }
mbed_official 525:c320967f86b9 473 serial_irq_ids[serial_get_index(obj)] = 0;
mbed_official 525:c320967f86b9 474 }
mbed_official 525:c320967f86b9 475
mbed_official 525:c320967f86b9 476 /**
mbed_official 525:c320967f86b9 477 * Set UART baud rate
mbed_official 525:c320967f86b9 478 */
mbed_official 525:c320967f86b9 479 void serial_baud(serial_t *obj, int baudrate)
mbed_official 525:c320967f86b9 480 {
mbed_official 525:c320967f86b9 481 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 482 LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_REF_FREQ, (uint32_t)baudrate);
mbed_official 525:c320967f86b9 483 } else {
mbed_official 525:c320967f86b9 484 USART_BaudrateAsyncSet(obj->serial.periph.uart, REFERENCE_FREQUENCY, (uint32_t)baudrate, usartOVS16);
mbed_official 525:c320967f86b9 485 }
mbed_official 525:c320967f86b9 486 }
mbed_official 525:c320967f86b9 487
mbed_official 525:c320967f86b9 488 /**
mbed_official 525:c320967f86b9 489 * Set UART format by re-initializing the peripheral.
mbed_official 525:c320967f86b9 490 */
mbed_official 525:c320967f86b9 491 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
mbed_official 525:c320967f86b9 492 {
mbed_official 525:c320967f86b9 493 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 494 /* Save the serial state */
mbed_official 525:c320967f86b9 495 uint8_t was_enabled = LEUART_StatusGet(obj->serial.periph.leuart) & (LEUART_STATUS_TXENS | LEUART_STATUS_RXENS);
mbed_official 525:c320967f86b9 496 uint32_t enabled_interrupts = obj->serial.periph.leuart->IEN;
mbed_official 525:c320967f86b9 497
mbed_official 525:c320967f86b9 498 LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
mbed_official 525:c320967f86b9 499
mbed_official 525:c320967f86b9 500 /* We support 8 data bits ONLY on LEUART*/
mbed_official 525:c320967f86b9 501 MBED_ASSERT(data_bits == 8);
mbed_official 525:c320967f86b9 502
mbed_official 525:c320967f86b9 503 /* Re-init the UART */
mbed_official 525:c320967f86b9 504 init.enable = (was_enabled == 0 ? leuartDisable : leuartEnable);
mbed_official 525:c320967f86b9 505 init.baudrate = LEUART_BaudrateGet(obj->serial.periph.leuart);
mbed_official 525:c320967f86b9 506 if (stop_bits == 2) {
mbed_official 525:c320967f86b9 507 init.stopbits = leuartStopbits2;
mbed_official 525:c320967f86b9 508 } else {
mbed_official 525:c320967f86b9 509 init.stopbits = leuartStopbits1;
mbed_official 525:c320967f86b9 510 }
mbed_official 525:c320967f86b9 511 switch (parity) {
mbed_official 525:c320967f86b9 512 case ParityOdd:
mbed_official 525:c320967f86b9 513 case ParityForced0:
mbed_official 525:c320967f86b9 514 init.parity = leuartOddParity;
mbed_official 525:c320967f86b9 515 break;
mbed_official 525:c320967f86b9 516 case ParityEven:
mbed_official 525:c320967f86b9 517 case ParityForced1:
mbed_official 525:c320967f86b9 518 init.parity = leuartEvenParity;
mbed_official 525:c320967f86b9 519 break;
mbed_official 525:c320967f86b9 520 default: /* ParityNone */
mbed_official 525:c320967f86b9 521 init.parity = leuartNoParity;
mbed_official 525:c320967f86b9 522 break;
mbed_official 525:c320967f86b9 523 }
mbed_official 525:c320967f86b9 524
mbed_official 525:c320967f86b9 525 LEUART_Init(obj->serial.periph.leuart, &init);
mbed_official 525:c320967f86b9 526
mbed_official 525:c320967f86b9 527 /* Re-enable pins for UART at correct location */
mbed_official 525:c320967f86b9 528 obj->serial.periph.leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
mbed_official 525:c320967f86b9 529
mbed_official 525:c320967f86b9 530 /* Re-enable interrupts */
mbed_official 525:c320967f86b9 531 if(was_enabled != 0) {
mbed_official 525:c320967f86b9 532 obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
mbed_official 525:c320967f86b9 533 obj->serial.periph.leuart->IEN = enabled_interrupts;
mbed_official 525:c320967f86b9 534 }
mbed_official 525:c320967f86b9 535 } else {
mbed_official 525:c320967f86b9 536 /* Save the serial state */
mbed_official 525:c320967f86b9 537 uint8_t was_enabled = USART_StatusGet(obj->serial.periph.uart) & (USART_STATUS_TXENS | USART_STATUS_RXENS);
mbed_official 525:c320967f86b9 538 uint32_t enabled_interrupts = obj->serial.periph.uart->IEN;
mbed_official 525:c320967f86b9 539
mbed_official 525:c320967f86b9 540
mbed_official 525:c320967f86b9 541 USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
mbed_official 525:c320967f86b9 542
mbed_official 525:c320967f86b9 543 /* We support 4 to 8 data bits */
mbed_official 525:c320967f86b9 544 MBED_ASSERT(data_bits >= 4 && data_bits <= 8);
mbed_official 525:c320967f86b9 545
mbed_official 525:c320967f86b9 546 /* Re-init the UART */
mbed_official 525:c320967f86b9 547 init.enable = (was_enabled == 0 ? usartDisable : usartEnable);
mbed_official 525:c320967f86b9 548 init.baudrate = USART_BaudrateGet(obj->serial.periph.uart);
mbed_official 525:c320967f86b9 549 init.oversampling = usartOVS16;
mbed_official 525:c320967f86b9 550 init.databits = (USART_Databits_TypeDef)((data_bits - 3) << _USART_FRAME_DATABITS_SHIFT);
mbed_official 525:c320967f86b9 551 if (stop_bits == 2) {
mbed_official 525:c320967f86b9 552 init.stopbits = usartStopbits2;
mbed_official 525:c320967f86b9 553 } else {
mbed_official 525:c320967f86b9 554 init.stopbits = usartStopbits1;
mbed_official 525:c320967f86b9 555 }
mbed_official 525:c320967f86b9 556 switch (parity) {
mbed_official 525:c320967f86b9 557 case ParityOdd:
mbed_official 525:c320967f86b9 558 case ParityForced0:
mbed_official 525:c320967f86b9 559 init.parity = usartOddParity;
mbed_official 525:c320967f86b9 560 break;
mbed_official 525:c320967f86b9 561 case ParityEven:
mbed_official 525:c320967f86b9 562 case ParityForced1:
mbed_official 525:c320967f86b9 563 init.parity = usartEvenParity;
mbed_official 525:c320967f86b9 564 break;
mbed_official 525:c320967f86b9 565 default: /* ParityNone */
mbed_official 525:c320967f86b9 566 init.parity = usartNoParity;
mbed_official 525:c320967f86b9 567 break;
mbed_official 525:c320967f86b9 568 }
mbed_official 525:c320967f86b9 569
mbed_official 525:c320967f86b9 570 USART_InitAsync(obj->serial.periph.uart, &init);
mbed_official 525:c320967f86b9 571
mbed_official 525:c320967f86b9 572 /* Re-enable pins for UART at correct location */
mbed_official 525:c320967f86b9 573 obj->serial.periph.uart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
mbed_official 525:c320967f86b9 574
mbed_official 525:c320967f86b9 575 /* Re-enable interrupts */
mbed_official 525:c320967f86b9 576 if(was_enabled != 0) {
mbed_official 525:c320967f86b9 577 obj->serial.periph.uart->IFC = USART_IFC_TXC;
mbed_official 525:c320967f86b9 578 obj->serial.periph.uart->IEN = enabled_interrupts;
mbed_official 525:c320967f86b9 579 }
mbed_official 525:c320967f86b9 580 }
mbed_official 525:c320967f86b9 581 }
mbed_official 525:c320967f86b9 582
mbed_official 525:c320967f86b9 583 /******************************************************************************
mbed_official 525:c320967f86b9 584 * INTERRUPTS *
mbed_official 525:c320967f86b9 585 ******************************************************************************/
mbed_official 525:c320967f86b9 586 uint8_t serial_tx_ready(serial_t *obj)
mbed_official 525:c320967f86b9 587 {
mbed_official 525:c320967f86b9 588 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 589 return (obj->serial.periph.leuart->STATUS & LEUART_STATUS_TXBL) ? true : false;
mbed_official 525:c320967f86b9 590 } else {
mbed_official 525:c320967f86b9 591 return (obj->serial.periph.uart->STATUS & USART_STATUS_TXBL) ? true : false;
mbed_official 525:c320967f86b9 592 }
mbed_official 525:c320967f86b9 593 }
mbed_official 525:c320967f86b9 594
mbed_official 525:c320967f86b9 595 uint8_t serial_rx_ready(serial_t *obj)
mbed_official 525:c320967f86b9 596 {
mbed_official 525:c320967f86b9 597 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 598 return (obj->serial.periph.leuart->STATUS & LEUART_STATUS_RXDATAV) ? true : false;
mbed_official 525:c320967f86b9 599 } else {
mbed_official 525:c320967f86b9 600 return (obj->serial.periph.uart->STATUS & USART_STATUS_RXDATAV) ? true : false;
mbed_official 525:c320967f86b9 601 }
mbed_official 525:c320967f86b9 602 }
mbed_official 525:c320967f86b9 603
mbed_official 525:c320967f86b9 604 void serial_write_asynch(serial_t *obj, int data)
mbed_official 525:c320967f86b9 605 {
mbed_official 525:c320967f86b9 606 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 607 obj->serial.periph.leuart->TXDATA = (uint32_t)data;
mbed_official 525:c320967f86b9 608 } else {
mbed_official 525:c320967f86b9 609 obj->serial.periph.uart->TXDATA = (uint32_t)data;
mbed_official 525:c320967f86b9 610 }
mbed_official 525:c320967f86b9 611 }
mbed_official 525:c320967f86b9 612
mbed_official 525:c320967f86b9 613 int serial_read_asynch(serial_t *obj)
mbed_official 525:c320967f86b9 614 {
mbed_official 525:c320967f86b9 615 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 616 return (int)obj->serial.periph.leuart->RXDATA;
mbed_official 525:c320967f86b9 617 } else {
mbed_official 525:c320967f86b9 618 return (int)obj->serial.periph.uart->RXDATA;
mbed_official 525:c320967f86b9 619 }
mbed_official 525:c320967f86b9 620 }
mbed_official 525:c320967f86b9 621
mbed_official 525:c320967f86b9 622 uint8_t serial_tx_int_flag(serial_t *obj)
mbed_official 525:c320967f86b9 623 {
mbed_official 525:c320967f86b9 624 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 625 return (obj->serial.periph.leuart->IF & LEUART_IF_TXBL) ? true : false;
mbed_official 525:c320967f86b9 626 } else {
mbed_official 525:c320967f86b9 627 return (obj->serial.periph.uart->IF & USART_IF_TXBL) ? true : false;
mbed_official 525:c320967f86b9 628 }
mbed_official 525:c320967f86b9 629 }
mbed_official 525:c320967f86b9 630
mbed_official 525:c320967f86b9 631 uint8_t serial_rx_int_flag(serial_t *obj)
mbed_official 525:c320967f86b9 632 {
mbed_official 525:c320967f86b9 633 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 634 return (obj->serial.periph.leuart->IF & LEUART_IF_RXDATAV) ? true : false;
mbed_official 525:c320967f86b9 635 } else {
mbed_official 525:c320967f86b9 636 return (obj->serial.periph.uart->IF & USART_IF_RXDATAV) ? true : false;
mbed_official 525:c320967f86b9 637 }
mbed_official 525:c320967f86b9 638 }
mbed_official 525:c320967f86b9 639
mbed_official 525:c320967f86b9 640 void serial_read_asynch_complete(serial_t *obj)
mbed_official 525:c320967f86b9 641 {
mbed_official 525:c320967f86b9 642 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 643 obj->serial.periph.leuart->IFC |= LEUART_IFC_RXOF; // in case it got full
mbed_official 525:c320967f86b9 644 } else {
mbed_official 525:c320967f86b9 645 obj->serial.periph.uart->IFC |= USART_IFC_RXFULL; // in case it got full
mbed_official 525:c320967f86b9 646 }
mbed_official 525:c320967f86b9 647 }
mbed_official 525:c320967f86b9 648
mbed_official 525:c320967f86b9 649 void serial_write_asynch_complete(serial_t *obj)
mbed_official 525:c320967f86b9 650 {
mbed_official 525:c320967f86b9 651 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 652 obj->serial.periph.leuart->IFC |= LEUART_IFC_TXC;
mbed_official 525:c320967f86b9 653 } else {
mbed_official 525:c320967f86b9 654 obj->serial.periph.uart->IFC |= USART_IFC_TXC;
mbed_official 525:c320967f86b9 655 }
mbed_official 525:c320967f86b9 656 }
mbed_official 525:c320967f86b9 657
mbed_official 525:c320967f86b9 658 /** Enable and set the interrupt handler for write (TX)
mbed_official 525:c320967f86b9 659 *
mbed_official 525:c320967f86b9 660 * @param obj The serial object
mbed_official 525:c320967f86b9 661 * @param address The address of TX handler
mbed_official 525:c320967f86b9 662 * @param enable Set to non-zero to enable or zero to disable
mbed_official 525:c320967f86b9 663 */
mbed_official 525:c320967f86b9 664 void serial_write_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable)
mbed_official 525:c320967f86b9 665 {
mbed_official 525:c320967f86b9 666 NVIC_SetVector(serial_get_tx_irq_index(obj), address);
mbed_official 525:c320967f86b9 667 serial_irq_set(obj, (SerialIrq)1, enable);
mbed_official 525:c320967f86b9 668 }
mbed_official 525:c320967f86b9 669
mbed_official 525:c320967f86b9 670 /** Enable and set the interrupt handler for read (RX)
mbed_official 525:c320967f86b9 671 *
mbed_official 525:c320967f86b9 672 * @param obj The serial object
mbed_official 525:c320967f86b9 673 * @param address The address of RX handler
mbed_official 525:c320967f86b9 674 * @param enable Set to non-zero to enable or zero to disable
mbed_official 525:c320967f86b9 675 */
mbed_official 525:c320967f86b9 676 void serial_read_enable_interrupt(serial_t *obj, uint32_t address, uint8_t enable)
mbed_official 525:c320967f86b9 677 {
mbed_official 525:c320967f86b9 678 NVIC_SetVector(serial_get_rx_irq_index(obj), address);
mbed_official 525:c320967f86b9 679 serial_irq_set(obj, (SerialIrq)0, enable);
mbed_official 525:c320967f86b9 680 }
mbed_official 525:c320967f86b9 681
mbed_official 525:c320967f86b9 682 uint8_t serial_interrupt_enabled(serial_t *obj)
mbed_official 525:c320967f86b9 683 {
mbed_official 525:c320967f86b9 684 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 685 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV | LEUART_IEN_TXBL)) ? true : false;
mbed_official 525:c320967f86b9 686 } else {
mbed_official 525:c320967f86b9 687 return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV | USART_IEN_TXBL)) ? true : false;
mbed_official 525:c320967f86b9 688 }
mbed_official 525:c320967f86b9 689 }
mbed_official 525:c320967f86b9 690
mbed_official 525:c320967f86b9 691 /**
mbed_official 525:c320967f86b9 692 * Set handler for all serial interrupts (is probably SerialBase::_handler())
mbed_official 525:c320967f86b9 693 * and store IRQ ID to be returned to the handler upon interrupt. ID is
mbed_official 525:c320967f86b9 694 * probably a pointer to the calling Serial object.
mbed_official 525:c320967f86b9 695 */
mbed_official 525:c320967f86b9 696 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
mbed_official 525:c320967f86b9 697 {
mbed_official 525:c320967f86b9 698 irq_handler = handler;
mbed_official 525:c320967f86b9 699 serial_irq_ids[serial_get_index(obj)] = id;
mbed_official 525:c320967f86b9 700 }
mbed_official 525:c320967f86b9 701
mbed_official 525:c320967f86b9 702 /**
mbed_official 525:c320967f86b9 703 * Generic ISR for all UARTs, both TX and RX
mbed_official 525:c320967f86b9 704 */
mbed_official 525:c320967f86b9 705 static void uart_irq(UARTName name, int index, SerialIrq irq)
mbed_official 525:c320967f86b9 706 {
mbed_official 525:c320967f86b9 707 if (serial_irq_ids[index] != 0) {
mbed_official 525:c320967f86b9 708 /* Pass interrupt on to mbed common handler */
mbed_official 525:c320967f86b9 709 irq_handler(serial_irq_ids[index], irq);
mbed_official 525:c320967f86b9 710 /* Clearing interrupt not necessary */
mbed_official 525:c320967f86b9 711 }
mbed_official 525:c320967f86b9 712 }
mbed_official 525:c320967f86b9 713
mbed_official 525:c320967f86b9 714 /**
mbed_official 525:c320967f86b9 715 * Set ISR for a given UART and interrupt event (TX or RX)
mbed_official 525:c320967f86b9 716 */
mbed_official 525:c320967f86b9 717 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
mbed_official 525:c320967f86b9 718 {
mbed_official 525:c320967f86b9 719 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 720 /* Enable or disable interrupt */
mbed_official 525:c320967f86b9 721 if (enable) {
mbed_official 525:c320967f86b9 722 if (irq == RxIrq) { /* RX */
mbed_official 525:c320967f86b9 723 obj->serial.periph.leuart->IEN |= LEUART_IEN_RXDATAV;
mbed_official 525:c320967f86b9 724 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 725 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 726 } else { /* TX */
mbed_official 525:c320967f86b9 727 obj->serial.periph.leuart->IEN |= LEUART_IEN_TXC;
mbed_official 525:c320967f86b9 728 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 729 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
mbed_official 525:c320967f86b9 730 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 731 }
mbed_official 525:c320967f86b9 732 } else {
mbed_official 525:c320967f86b9 733 if (irq == RxIrq) { /* RX */
mbed_official 525:c320967f86b9 734 obj->serial.periph.leuart->IEN &= ~LEUART_IEN_RXDATAV;
mbed_official 525:c320967f86b9 735 NVIC_DisableIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 736 } else { /* TX */
mbed_official 525:c320967f86b9 737 obj->serial.periph.leuart->IEN &= ~LEUART_IEN_TXC;
mbed_official 525:c320967f86b9 738 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 739 }
mbed_official 525:c320967f86b9 740 }
mbed_official 525:c320967f86b9 741 } else {
mbed_official 525:c320967f86b9 742 /* Enable or disable interrupt */
mbed_official 525:c320967f86b9 743 if (enable) {
mbed_official 525:c320967f86b9 744 if (irq == RxIrq) { /* RX */
mbed_official 525:c320967f86b9 745 obj->serial.periph.uart->IEN |= USART_IEN_RXDATAV;
mbed_official 525:c320967f86b9 746 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 747 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 748 } else { /* TX */
mbed_official 525:c320967f86b9 749 obj->serial.periph.uart->IEN |= USART_IEN_TXC;
mbed_official 525:c320967f86b9 750 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 751 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
mbed_official 525:c320967f86b9 752 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 753 }
mbed_official 525:c320967f86b9 754 } else {
mbed_official 525:c320967f86b9 755 if (irq == RxIrq) { /* RX */
mbed_official 525:c320967f86b9 756 obj->serial.periph.uart->IEN &= ~USART_IEN_RXDATAV;
mbed_official 525:c320967f86b9 757 NVIC_DisableIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 758 } else { /* TX */
mbed_official 525:c320967f86b9 759 obj->serial.periph.uart->IEN &= ~USART_IEN_TXC;
mbed_official 525:c320967f86b9 760 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 761 }
mbed_official 525:c320967f86b9 762 }
mbed_official 525:c320967f86b9 763 }
mbed_official 525:c320967f86b9 764 }
mbed_official 525:c320967f86b9 765
mbed_official 525:c320967f86b9 766 /******************************************************************************
mbed_official 525:c320967f86b9 767 * READ/WRITE *
mbed_official 525:c320967f86b9 768 ******************************************************************************/
mbed_official 525:c320967f86b9 769
mbed_official 525:c320967f86b9 770 /**
mbed_official 525:c320967f86b9 771 * Get one char from serial link
mbed_official 525:c320967f86b9 772 */
mbed_official 525:c320967f86b9 773 int serial_getc(serial_t *obj)
mbed_official 525:c320967f86b9 774 {
mbed_official 525:c320967f86b9 775 /* Emlib USART_Rx blocks until data is available, so we don't need to use
mbed_official 525:c320967f86b9 776 * serial_readable(). Use USART_RxDataGet() to read register directly. */
mbed_official 525:c320967f86b9 777 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 778 return LEUART_Rx(obj->serial.periph.leuart);
mbed_official 525:c320967f86b9 779 } else {
mbed_official 525:c320967f86b9 780 return USART_Rx(obj->serial.periph.uart);
mbed_official 525:c320967f86b9 781 }
mbed_official 525:c320967f86b9 782 }
mbed_official 525:c320967f86b9 783
mbed_official 525:c320967f86b9 784 /*
mbed_official 525:c320967f86b9 785 * Send one char over serial link
mbed_official 525:c320967f86b9 786 */
mbed_official 525:c320967f86b9 787 void serial_putc(serial_t *obj, int c)
mbed_official 525:c320967f86b9 788 {
mbed_official 525:c320967f86b9 789 /* Emlib USART_Tx blocks until buffer is writable (non-full), so we don't
mbed_official 525:c320967f86b9 790 * need to use serial_writable(). */
mbed_official 525:c320967f86b9 791 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 792 LEUART_Tx(obj->serial.periph.leuart, (uint8_t)(c));
mbed_official 525:c320967f86b9 793 } else {
mbed_official 525:c320967f86b9 794 USART_Tx(obj->serial.periph.uart, (uint8_t)(c));
mbed_official 525:c320967f86b9 795 }
mbed_official 525:c320967f86b9 796 }
mbed_official 525:c320967f86b9 797
mbed_official 525:c320967f86b9 798 /**
mbed_official 525:c320967f86b9 799 * Check if data is available in RX data vector
mbed_official 525:c320967f86b9 800 */
mbed_official 525:c320967f86b9 801 int serial_readable(serial_t *obj)
mbed_official 525:c320967f86b9 802 {
mbed_official 525:c320967f86b9 803 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 804 return obj->serial.periph.leuart->STATUS & LEUART_STATUS_RXDATAV;
mbed_official 525:c320967f86b9 805 } else {
mbed_official 525:c320967f86b9 806 return obj->serial.periph.uart->STATUS & USART_STATUS_RXDATAV;
mbed_official 525:c320967f86b9 807 }
mbed_official 525:c320967f86b9 808 }
mbed_official 525:c320967f86b9 809
mbed_official 525:c320967f86b9 810 /**
mbed_official 525:c320967f86b9 811 * Check if TX buffer is empty
mbed_official 525:c320967f86b9 812 */
mbed_official 525:c320967f86b9 813 int serial_writable(serial_t *obj)
mbed_official 525:c320967f86b9 814 {
mbed_official 525:c320967f86b9 815 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 816 return obj->serial.periph.leuart->STATUS & LEUART_STATUS_TXBL;
mbed_official 525:c320967f86b9 817 } else {
mbed_official 525:c320967f86b9 818 return obj->serial.periph.uart->STATUS & USART_STATUS_TXBL;
mbed_official 525:c320967f86b9 819 }
mbed_official 525:c320967f86b9 820 }
mbed_official 525:c320967f86b9 821
mbed_official 525:c320967f86b9 822 /**
mbed_official 525:c320967f86b9 823 * Clear UART interrupts
mbed_official 525:c320967f86b9 824 */
mbed_official 525:c320967f86b9 825 void serial_clear(serial_t *obj)
mbed_official 525:c320967f86b9 826 {
mbed_official 525:c320967f86b9 827 /* Interrupts automatically clear when condition is not met anymore */
mbed_official 525:c320967f86b9 828 }
mbed_official 525:c320967f86b9 829
mbed_official 525:c320967f86b9 830 void serial_break_set(serial_t *obj)
mbed_official 525:c320967f86b9 831 {
mbed_official 525:c320967f86b9 832 /* Send transmission break */
mbed_official 525:c320967f86b9 833 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 834 obj->serial.periph.leuart->TXDATAX = LEUART_TXDATAX_TXBREAK;
mbed_official 525:c320967f86b9 835 } else {
mbed_official 525:c320967f86b9 836 obj->serial.periph.uart->TXDATAX = USART_TXDATAX_TXBREAK;
mbed_official 525:c320967f86b9 837 }
mbed_official 525:c320967f86b9 838 }
mbed_official 525:c320967f86b9 839
mbed_official 525:c320967f86b9 840 void serial_break_clear(serial_t *obj)
mbed_official 525:c320967f86b9 841 {
mbed_official 525:c320967f86b9 842 /* No need to clear break, it is automatically cleared after one frame.
mbed_official 525:c320967f86b9 843 * From the reference manual:
mbed_official 525:c320967f86b9 844 *
mbed_official 525:c320967f86b9 845 * By setting TXBREAK, the output will be held low during the stop-bit
mbed_official 525:c320967f86b9 846 * period to generate a framing error. A receiver that supports break
mbed_official 525:c320967f86b9 847 * detection detects this state, allowing it to be used e.g. for framing
mbed_official 525:c320967f86b9 848 * of larger data packets. The line is driven high before the next frame
mbed_official 525:c320967f86b9 849 * is transmitted so the next start condition can be identified correctly
mbed_official 525:c320967f86b9 850 * by the recipient. Continuous breaks lasting longer than a USART frame
mbed_official 525:c320967f86b9 851 * are thus not supported by the USART. GPIO can be used for this.
mbed_official 525:c320967f86b9 852 */
mbed_official 525:c320967f86b9 853 }
mbed_official 525:c320967f86b9 854
mbed_official 525:c320967f86b9 855 void serial_pinout_tx(PinName tx)
mbed_official 525:c320967f86b9 856 {
mbed_official 525:c320967f86b9 857 /* 0x10 sets DOUT high. Prevents false start. */
mbed_official 525:c320967f86b9 858 pin_mode(tx, PushPull | 0x10);
mbed_official 525:c320967f86b9 859 }
mbed_official 525:c320967f86b9 860
mbed_official 525:c320967f86b9 861 /************************************************************************************
mbed_official 525:c320967f86b9 862 * DMA helper functions *
mbed_official 525:c320967f86b9 863 ************************************************************************************/
mbed_official 525:c320967f86b9 864 /******************************************
mbed_official 525:c320967f86b9 865 * static void serial_dmaTransferComplete(uint channel, bool primary, void* user)
mbed_official 525:c320967f86b9 866 *
mbed_official 525:c320967f86b9 867 * Callback function which gets called upon DMA transfer completion
mbed_official 525:c320967f86b9 868 * the user-defined pointer is pointing to the CPP-land thunk
mbed_official 525:c320967f86b9 869 ******************************************/
mbed_official 525:c320967f86b9 870 static void serial_dmaTransferComplete(unsigned int channel, bool primary, void *user)
mbed_official 525:c320967f86b9 871 {
mbed_official 525:c320967f86b9 872 /* Store information about which channel triggered because CPP doesn't take arguments */
mbed_official 525:c320967f86b9 873 serial_dma_irq_fired[channel] = true;
mbed_official 525:c320967f86b9 874
mbed_official 525:c320967f86b9 875 /* User pointer should be a thunk to CPP land */
mbed_official 525:c320967f86b9 876 if (user != NULL) {
mbed_official 525:c320967f86b9 877 ((DMACallback)user)();
mbed_official 525:c320967f86b9 878 }
mbed_official 525:c320967f86b9 879 }
mbed_official 525:c320967f86b9 880
mbed_official 525:c320967f86b9 881 /******************************************
mbed_official 525:c320967f86b9 882 * static void serial_setupDmaChannel(serial_t *obj, bool tx_nrx)
mbed_official 525:c320967f86b9 883 *
mbed_official 525:c320967f86b9 884 * Sets up the DMA configuration block for the assigned channel
mbed_official 525:c320967f86b9 885 * tx_nrx: true if configuring TX, false if configuring RX.
mbed_official 525:c320967f86b9 886 ******************************************/
mbed_official 525:c320967f86b9 887 static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx) {
mbed_official 525:c320967f86b9 888 DMA_CfgChannel_TypeDef channelConfig;
mbed_official 525:c320967f86b9 889
mbed_official 525:c320967f86b9 890 if(tx_nrx) {
mbed_official 525:c320967f86b9 891 //setup TX channel
mbed_official 525:c320967f86b9 892 channelConfig.highPri = false;
mbed_official 525:c320967f86b9 893 channelConfig.enableInt = true;
mbed_official 525:c320967f86b9 894 channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
mbed_official 525:c320967f86b9 895
mbed_official 525:c320967f86b9 896 switch((uint32_t)(obj->serial.periph.uart)) {
mbed_official 525:c320967f86b9 897 #ifdef UART0
mbed_official 525:c320967f86b9 898 case UART_0:
mbed_official 525:c320967f86b9 899 channelConfig.select = DMAREQ_UART0_TXBL;
mbed_official 525:c320967f86b9 900 break;
mbed_official 525:c320967f86b9 901 #endif
mbed_official 525:c320967f86b9 902 #ifdef UART1
mbed_official 525:c320967f86b9 903 case UART_1:
mbed_official 525:c320967f86b9 904 channelConfig.select = DMAREQ_UART1_TXBL;
mbed_official 525:c320967f86b9 905 break;
mbed_official 525:c320967f86b9 906 #endif
mbed_official 525:c320967f86b9 907 #ifdef USART0
mbed_official 525:c320967f86b9 908 case USART_0:
mbed_official 525:c320967f86b9 909 channelConfig.select = DMAREQ_USART0_TXBL;
mbed_official 525:c320967f86b9 910 break;
mbed_official 525:c320967f86b9 911 #endif
mbed_official 525:c320967f86b9 912 #ifdef USART1
mbed_official 525:c320967f86b9 913 case USART_1:
mbed_official 525:c320967f86b9 914 channelConfig.select = DMAREQ_USART1_TXBL;
mbed_official 525:c320967f86b9 915 break;
mbed_official 525:c320967f86b9 916 #endif
mbed_official 525:c320967f86b9 917 #ifdef USART2
mbed_official 525:c320967f86b9 918 case USART_2:
mbed_official 525:c320967f86b9 919 channelConfig.select = DMAREQ_USART2_TXBL;
mbed_official 525:c320967f86b9 920 break;
mbed_official 525:c320967f86b9 921 #endif
mbed_official 525:c320967f86b9 922 #ifdef LEUART0
mbed_official 525:c320967f86b9 923 case LEUART_0:
mbed_official 525:c320967f86b9 924 channelConfig.select = DMAREQ_LEUART0_TXBL;
mbed_official 525:c320967f86b9 925 break;
mbed_official 525:c320967f86b9 926 #endif
mbed_official 525:c320967f86b9 927 #ifdef LEUART1
mbed_official 525:c320967f86b9 928 case LEUART_1:
mbed_official 525:c320967f86b9 929 channelConfig.select = DMAREQ_LEUART1_TXBL;
mbed_official 525:c320967f86b9 930 break;
mbed_official 525:c320967f86b9 931 #endif
mbed_official 525:c320967f86b9 932 }
mbed_official 525:c320967f86b9 933
mbed_official 525:c320967f86b9 934 DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
mbed_official 525:c320967f86b9 935 } else {
mbed_official 525:c320967f86b9 936 //setup RX channel
mbed_official 525:c320967f86b9 937 channelConfig.highPri = true;
mbed_official 525:c320967f86b9 938 channelConfig.enableInt = true;
mbed_official 525:c320967f86b9 939 channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
mbed_official 525:c320967f86b9 940
mbed_official 525:c320967f86b9 941 switch((uint32_t)(obj->serial.periph.uart)) {
mbed_official 525:c320967f86b9 942 #ifdef UART0
mbed_official 525:c320967f86b9 943 case UART_0:
mbed_official 525:c320967f86b9 944 channelConfig.select = DMAREQ_UART0_RXDATAV;
mbed_official 525:c320967f86b9 945 break;
mbed_official 525:c320967f86b9 946 #endif
mbed_official 525:c320967f86b9 947 #ifdef UART1
mbed_official 525:c320967f86b9 948 case UART_1:
mbed_official 525:c320967f86b9 949 channelConfig.select = DMAREQ_UART1_RXDATAV;
mbed_official 525:c320967f86b9 950 break;
mbed_official 525:c320967f86b9 951 #endif
mbed_official 525:c320967f86b9 952 #ifdef USART0
mbed_official 525:c320967f86b9 953 case USART_0:
mbed_official 525:c320967f86b9 954 channelConfig.select = DMAREQ_USART0_RXDATAV;
mbed_official 525:c320967f86b9 955 break;
mbed_official 525:c320967f86b9 956 #endif
mbed_official 525:c320967f86b9 957 #ifdef USART1
mbed_official 525:c320967f86b9 958 case USART_1:
mbed_official 525:c320967f86b9 959 channelConfig.select = DMAREQ_USART1_RXDATAV;
mbed_official 525:c320967f86b9 960 break;
mbed_official 525:c320967f86b9 961 #endif
mbed_official 525:c320967f86b9 962 #ifdef USART2
mbed_official 525:c320967f86b9 963 case USART_2:
mbed_official 525:c320967f86b9 964 channelConfig.select = DMAREQ_USART2_RXDATAV;
mbed_official 525:c320967f86b9 965 break;
mbed_official 525:c320967f86b9 966 #endif
mbed_official 525:c320967f86b9 967 #ifdef LEUART0
mbed_official 525:c320967f86b9 968 case LEUART_0:
mbed_official 525:c320967f86b9 969 channelConfig.select = DMAREQ_LEUART0_RXDATAV;
mbed_official 525:c320967f86b9 970 break;
mbed_official 525:c320967f86b9 971 #endif
mbed_official 525:c320967f86b9 972 #ifdef LEUART1
mbed_official 525:c320967f86b9 973 case LEUART_1:
mbed_official 525:c320967f86b9 974 channelConfig.select = DMAREQ_LEUART1_RXDATAV;
mbed_official 525:c320967f86b9 975 break;
mbed_official 525:c320967f86b9 976 #endif
mbed_official 525:c320967f86b9 977 }
mbed_official 525:c320967f86b9 978
mbed_official 525:c320967f86b9 979 DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
mbed_official 525:c320967f86b9 980 }
mbed_official 525:c320967f86b9 981
mbed_official 525:c320967f86b9 982
mbed_official 525:c320967f86b9 983 }
mbed_official 525:c320967f86b9 984
mbed_official 525:c320967f86b9 985 /******************************************
mbed_official 525:c320967f86b9 986 * static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState)
mbed_official 525:c320967f86b9 987 *
mbed_official 525:c320967f86b9 988 * Tries to set the passed DMA state to the requested state.
mbed_official 525:c320967f86b9 989 *
mbed_official 525:c320967f86b9 990 * requested state possibilities:
mbed_official 525:c320967f86b9 991 * * NEVER:
mbed_official 525:c320967f86b9 992 * if the previous state was always, will deallocate the channel
mbed_official 525:c320967f86b9 993 * * OPPORTUNISTIC:
mbed_official 525:c320967f86b9 994 * If the previous state was always, will reuse that channel but free upon next completion.
mbed_official 525:c320967f86b9 995 * If not, will try to acquire a channel.
mbed_official 525:c320967f86b9 996 * When allocated, state changes to DMA_USAGE_TEMPORARY_ALLOCATED.
mbed_official 525:c320967f86b9 997 * * ALWAYS:
mbed_official 525:c320967f86b9 998 * Will try to allocate a channel and keep it.
mbed_official 525:c320967f86b9 999 * If succesfully allocated, state changes to DMA_USAGE_ALLOCATED.
mbed_official 525:c320967f86b9 1000 ******************************************/
mbed_official 525:c320967f86b9 1001 static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, serial_t *serialPtr, bool tx_nrx) {
mbed_official 525:c320967f86b9 1002 DMAUsage currentState = obj->dmaUsageState;
mbed_official 525:c320967f86b9 1003 int tempDMAChannel = -1;
mbed_official 525:c320967f86b9 1004
mbed_official 525:c320967f86b9 1005 if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
mbed_official 525:c320967f86b9 1006 /* Try to allocate channel */
mbed_official 525:c320967f86b9 1007 tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
mbed_official 525:c320967f86b9 1008 if(tempDMAChannel >= 0) {
mbed_official 525:c320967f86b9 1009 obj->dmaChannel = tempDMAChannel;
mbed_official 525:c320967f86b9 1010 obj->dmaUsageState = DMA_USAGE_ALLOCATED;
mbed_official 525:c320967f86b9 1011 dma_init();
mbed_official 525:c320967f86b9 1012 serial_dmaSetupChannel(serialPtr, tx_nrx);
mbed_official 525:c320967f86b9 1013 }
mbed_official 525:c320967f86b9 1014 } else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
mbed_official 525:c320967f86b9 1015 if (currentState == DMA_USAGE_ALLOCATED) {
mbed_official 525:c320967f86b9 1016 /* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
mbed_official 525:c320967f86b9 1017 obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
mbed_official 525:c320967f86b9 1018 } else {
mbed_official 525:c320967f86b9 1019 /* Try to allocate channel */
mbed_official 525:c320967f86b9 1020 tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
mbed_official 525:c320967f86b9 1021 if(tempDMAChannel >= 0) {
mbed_official 525:c320967f86b9 1022 obj->dmaChannel = tempDMAChannel;
mbed_official 525:c320967f86b9 1023 obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
mbed_official 525:c320967f86b9 1024 dma_init();
mbed_official 525:c320967f86b9 1025 serial_dmaSetupChannel(serialPtr, tx_nrx);
mbed_official 525:c320967f86b9 1026 }
mbed_official 525:c320967f86b9 1027 }
mbed_official 525:c320967f86b9 1028 } else if (requestedState == DMA_USAGE_NEVER) {
mbed_official 525:c320967f86b9 1029 /* If channel is allocated, get rid of it */
mbed_official 525:c320967f86b9 1030 dma_channel_free(obj->dmaChannel);
mbed_official 525:c320967f86b9 1031 obj->dmaChannel = -1;
mbed_official 525:c320967f86b9 1032 obj->dmaUsageState = DMA_USAGE_NEVER;
mbed_official 525:c320967f86b9 1033 }
mbed_official 525:c320967f86b9 1034 }
mbed_official 525:c320967f86b9 1035
mbed_official 525:c320967f86b9 1036 static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx) {
mbed_official 525:c320967f86b9 1037 DMA_CfgDescr_TypeDef channelConfig;
mbed_official 525:c320967f86b9 1038
mbed_official 525:c320967f86b9 1039 if(tx_nrx) {
mbed_official 525:c320967f86b9 1040 // Set DMA callback
mbed_official 525:c320967f86b9 1041 obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
mbed_official 525:c320967f86b9 1042 obj->serial.dmaOptionsTX.dmaCallback.userPtr = cb;
mbed_official 525:c320967f86b9 1043
mbed_official 525:c320967f86b9 1044 // Set up configuration structure
mbed_official 525:c320967f86b9 1045 channelConfig.dstInc = dmaDataIncNone;
mbed_official 525:c320967f86b9 1046 channelConfig.srcInc = dmaDataInc1;
mbed_official 525:c320967f86b9 1047 channelConfig.size = dmaDataSize1;
mbed_official 525:c320967f86b9 1048 channelConfig.arbRate = dmaArbitrate1;
mbed_official 525:c320967f86b9 1049 channelConfig.hprot = 0;
mbed_official 525:c320967f86b9 1050
mbed_official 525:c320967f86b9 1051 DMA_CfgDescr(obj->serial.dmaOptionsTX.dmaChannel, true, &channelConfig);
mbed_official 525:c320967f86b9 1052
mbed_official 525:c320967f86b9 1053 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1054 // Activate TX
mbed_official 525:c320967f86b9 1055 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN;
mbed_official 525:c320967f86b9 1056
mbed_official 525:c320967f86b9 1057 // Clear TX buffer
mbed_official 525:c320967f86b9 1058 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 1059
mbed_official 525:c320967f86b9 1060 // Kick off TX DMA
mbed_official 525:c320967f86b9 1061 DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.leuart->TXDATA), buffer, length - 1);
mbed_official 525:c320967f86b9 1062 } else {
mbed_official 525:c320967f86b9 1063 // Activate TX
mbed_official 525:c320967f86b9 1064 obj->serial.periph.uart->CMD = USART_CMD_TXEN;
mbed_official 525:c320967f86b9 1065
mbed_official 525:c320967f86b9 1066 // Clear TX buffer
mbed_official 525:c320967f86b9 1067 obj->serial.periph.uart->CMD = USART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 1068
mbed_official 525:c320967f86b9 1069 // Kick off TX DMA
mbed_official 525:c320967f86b9 1070 DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.uart->TXDATA), buffer, length - 1);
mbed_official 525:c320967f86b9 1071 }
mbed_official 525:c320967f86b9 1072 } else {
mbed_official 525:c320967f86b9 1073 // Set DMA callback
mbed_official 525:c320967f86b9 1074 obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
mbed_official 525:c320967f86b9 1075 obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
mbed_official 525:c320967f86b9 1076
mbed_official 525:c320967f86b9 1077 // Set up configuration structure
mbed_official 525:c320967f86b9 1078 channelConfig.dstInc = dmaDataInc1;
mbed_official 525:c320967f86b9 1079 channelConfig.srcInc = dmaDataIncNone;
mbed_official 525:c320967f86b9 1080 channelConfig.size = dmaDataSize1;
mbed_official 525:c320967f86b9 1081 channelConfig.arbRate = dmaArbitrate1;
mbed_official 525:c320967f86b9 1082 channelConfig.hprot = 0;
mbed_official 525:c320967f86b9 1083
mbed_official 525:c320967f86b9 1084 DMA_CfgDescr(obj->serial.dmaOptionsRX.dmaChannel, true, &channelConfig);
mbed_official 525:c320967f86b9 1085
mbed_official 525:c320967f86b9 1086 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1087 // Activate RX
mbed_official 525:c320967f86b9 1088 obj->serial.periph.leuart->CMD = LEUART_CMD_RXEN;
mbed_official 525:c320967f86b9 1089
mbed_official 525:c320967f86b9 1090 // Clear RX buffer
mbed_official 525:c320967f86b9 1091 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 1092
mbed_official 525:c320967f86b9 1093 // Kick off RX DMA
mbed_official 525:c320967f86b9 1094 DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.leuart->RXDATA), length - 1);
mbed_official 525:c320967f86b9 1095 } else {
mbed_official 525:c320967f86b9 1096 // Activate RX
mbed_official 525:c320967f86b9 1097 obj->serial.periph.uart->CMD = USART_CMD_RXEN;
mbed_official 525:c320967f86b9 1098
mbed_official 525:c320967f86b9 1099 // Clear RX buffer
mbed_official 525:c320967f86b9 1100 obj->serial.periph.uart->CMD = USART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 1101
mbed_official 525:c320967f86b9 1102 // Kick off RX DMA
mbed_official 525:c320967f86b9 1103 DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.uart->RXDATA), length - 1);
mbed_official 525:c320967f86b9 1104 }
mbed_official 525:c320967f86b9 1105 }
mbed_official 525:c320967f86b9 1106 }
mbed_official 525:c320967f86b9 1107
mbed_official 525:c320967f86b9 1108 /************************************************************************************
mbed_official 525:c320967f86b9 1109 * ASYNCHRONOUS HAL *
mbed_official 525:c320967f86b9 1110 ************************************************************************************/
mbed_official 525:c320967f86b9 1111
mbed_official 525:c320967f86b9 1112 #if DEVICE_SERIAL_ASYNCH
mbed_official 525:c320967f86b9 1113
mbed_official 525:c320967f86b9 1114 /************************************
mbed_official 525:c320967f86b9 1115 * HELPER FUNCTIONS *
mbed_official 525:c320967f86b9 1116 ***********************************/
mbed_official 525:c320967f86b9 1117
mbed_official 525:c320967f86b9 1118 /** Configure TX events
mbed_official 525:c320967f86b9 1119 *
mbed_official 525:c320967f86b9 1120 * @param obj The serial object
mbed_official 525:c320967f86b9 1121 * @param event The logical OR of the TX events to configure
mbed_official 525:c320967f86b9 1122 * @param enable Set to non-zero to enable events, or zero to disable them
mbed_official 525:c320967f86b9 1123 */
mbed_official 525:c320967f86b9 1124 void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable) {
mbed_official 525:c320967f86b9 1125 // Shouldn't have to enable TX interrupt here, just need to keep track of the requested events.
mbed_official 525:c320967f86b9 1126 if(enable) obj->serial.events |= event;
mbed_official 525:c320967f86b9 1127 else obj->serial.events &= ~event;
mbed_official 525:c320967f86b9 1128 }
mbed_official 525:c320967f86b9 1129
mbed_official 525:c320967f86b9 1130 /**
mbed_official 525:c320967f86b9 1131 * @param obj The serial object.
mbed_official 525:c320967f86b9 1132 * @param event The logical OR of the RX events to configure
mbed_official 525:c320967f86b9 1133 * @param enable Set to non-zero to enable events, or zero to disable them
mbed_official 525:c320967f86b9 1134 */
mbed_official 525:c320967f86b9 1135 void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) {
mbed_official 525:c320967f86b9 1136 if(enable) {
mbed_official 525:c320967f86b9 1137 obj->serial.events |= event;
mbed_official 525:c320967f86b9 1138 } else {
mbed_official 525:c320967f86b9 1139 obj->serial.events &= ~event;
mbed_official 525:c320967f86b9 1140 }
mbed_official 525:c320967f86b9 1141 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1142 if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
mbed_official 525:c320967f86b9 1143 //FERR interrupt source
mbed_official 525:c320967f86b9 1144 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_FERR;
mbed_official 525:c320967f86b9 1145 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_FERR;
mbed_official 525:c320967f86b9 1146 }
mbed_official 525:c320967f86b9 1147 if(event & SERIAL_EVENT_RX_PARITY_ERROR) {
mbed_official 525:c320967f86b9 1148 //PERR interrupt source
mbed_official 525:c320967f86b9 1149 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_PERR;
mbed_official 525:c320967f86b9 1150 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_PERR;
mbed_official 525:c320967f86b9 1151 }
mbed_official 525:c320967f86b9 1152 if(event & SERIAL_EVENT_RX_OVERFLOW) {
mbed_official 525:c320967f86b9 1153 //RXOF interrupt source
mbed_official 525:c320967f86b9 1154 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_RXOF;
mbed_official 525:c320967f86b9 1155 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_RXOF;
mbed_official 525:c320967f86b9 1156 }
mbed_official 525:c320967f86b9 1157 if(event & SERIAL_EVENT_RX_CHARACTER_MATCH) {
mbed_official 525:c320967f86b9 1158 /* This is only supported on LEUART in hardware. */
mbed_official 525:c320967f86b9 1159 if(enable) obj->serial.periph.leuart->IEN |= LEUART_IEN_SIGF;
mbed_official 525:c320967f86b9 1160 else obj->serial.periph.leuart->IEN &= ~LEUART_IEN_SIGF;
mbed_official 525:c320967f86b9 1161 }
mbed_official 525:c320967f86b9 1162 } else {
mbed_official 525:c320967f86b9 1163 if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
mbed_official 525:c320967f86b9 1164 //FERR interrupt source
mbed_official 525:c320967f86b9 1165 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_FERR;
mbed_official 525:c320967f86b9 1166 else obj->serial.periph.uart->IEN &= ~USART_IEN_FERR;
mbed_official 525:c320967f86b9 1167 }
mbed_official 525:c320967f86b9 1168 if(event & SERIAL_EVENT_RX_PARITY_ERROR) {
mbed_official 525:c320967f86b9 1169 //PERR interrupt source
mbed_official 525:c320967f86b9 1170 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_PERR;
mbed_official 525:c320967f86b9 1171 else obj->serial.periph.uart->IEN &= ~USART_IEN_PERR;
mbed_official 525:c320967f86b9 1172 }
mbed_official 525:c320967f86b9 1173 if(event & SERIAL_EVENT_RX_OVERFLOW) {
mbed_official 525:c320967f86b9 1174 //RXOF interrupt source
mbed_official 525:c320967f86b9 1175 if(enable) obj->serial.periph.uart->IEN |= USART_IEN_RXOF;
mbed_official 525:c320967f86b9 1176 else obj->serial.periph.uart->IEN &= ~USART_IEN_RXOF;
mbed_official 525:c320967f86b9 1177 }
mbed_official 525:c320967f86b9 1178 if(event & SERIAL_EVENT_RX_CHARACTER_MATCH) {
mbed_official 525:c320967f86b9 1179 /* This is currently unsupported in HW.
mbed_official 525:c320967f86b9 1180 * In order to support this, we will have to switch to interrupt-based operation and check every incoming character.
mbed_official 525:c320967f86b9 1181 */
mbed_official 525:c320967f86b9 1182
mbed_official 525:c320967f86b9 1183 //TODO: force interrupt-based operation when enabling character match.
mbed_official 525:c320967f86b9 1184 }
mbed_official 525:c320967f86b9 1185 }
mbed_official 525:c320967f86b9 1186 }
mbed_official 525:c320967f86b9 1187
mbed_official 525:c320967f86b9 1188 /** Configure the TX buffer for an asynchronous write serial transaction
mbed_official 525:c320967f86b9 1189 *
mbed_official 525:c320967f86b9 1190 * @param obj The serial object.
mbed_official 525:c320967f86b9 1191 * @param tx The buffer for sending.
mbed_official 525:c320967f86b9 1192 * @param tx_length The number of words to transmit.
mbed_official 525:c320967f86b9 1193 */
mbed_official 525:c320967f86b9 1194 void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width) {
mbed_official 525:c320967f86b9 1195 // We only support byte buffers for now
mbed_official 525:c320967f86b9 1196 MBED_ASSERT(width == 8);
mbed_official 525:c320967f86b9 1197
mbed_official 525:c320967f86b9 1198 if(serial_tx_active(obj)) return;
mbed_official 525:c320967f86b9 1199
mbed_official 525:c320967f86b9 1200 obj->tx_buff.buffer = tx;
mbed_official 525:c320967f86b9 1201 obj->tx_buff.length = tx_length;
mbed_official 525:c320967f86b9 1202 obj->tx_buff.pos = 0;
mbed_official 525:c320967f86b9 1203
mbed_official 525:c320967f86b9 1204 return;
mbed_official 525:c320967f86b9 1205 }
mbed_official 525:c320967f86b9 1206
mbed_official 525:c320967f86b9 1207 /** Configure the TX buffer for an asynchronous read serial transaction
mbed_official 525:c320967f86b9 1208 *
mbed_official 525:c320967f86b9 1209 * @param obj The serial object.
mbed_official 525:c320967f86b9 1210 * @param rx The buffer for receiving.
mbed_official 525:c320967f86b9 1211 * @param rx_length The number of words to read.
mbed_official 525:c320967f86b9 1212 */
mbed_official 525:c320967f86b9 1213 void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width) {
mbed_official 525:c320967f86b9 1214 // We only support byte buffers for now
mbed_official 525:c320967f86b9 1215 MBED_ASSERT(width == 8);
mbed_official 525:c320967f86b9 1216
mbed_official 525:c320967f86b9 1217 if(serial_rx_active(obj)) return;
mbed_official 525:c320967f86b9 1218
mbed_official 525:c320967f86b9 1219 obj->rx_buff.buffer = rx;
mbed_official 525:c320967f86b9 1220 obj->rx_buff.length = rx_length;
mbed_official 525:c320967f86b9 1221 obj->rx_buff.pos = 0;
mbed_official 525:c320967f86b9 1222
mbed_official 525:c320967f86b9 1223 return;
mbed_official 525:c320967f86b9 1224 }
mbed_official 525:c320967f86b9 1225
mbed_official 525:c320967f86b9 1226 /** Set character to be matched. If an event is enabled, and received character
mbed_official 525:c320967f86b9 1227 * matches the defined char_match, the receiving process is stopped and MATCH event
mbed_official 525:c320967f86b9 1228 * is invoked
mbed_official 525:c320967f86b9 1229 *
mbed_official 525:c320967f86b9 1230 * @param obj The serial object
mbed_official 525:c320967f86b9 1231 * @param char_match A character in range 0-254
mbed_official 525:c320967f86b9 1232 */
mbed_official 525:c320967f86b9 1233 void serial_set_char_match(serial_t *obj, uint8_t char_match) {
mbed_official 525:c320967f86b9 1234 // We only have hardware support for this in LEUART.
mbed_official 525:c320967f86b9 1235 // When in USART/UART, we can set up a check in the receiving ISR, but not when using DMA.
mbed_official 525:c320967f86b9 1236 if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
mbed_official 525:c320967f86b9 1237 obj->char_match = char_match;
mbed_official 525:c320967f86b9 1238
mbed_official 525:c320967f86b9 1239 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1240 obj->serial.periph.leuart->SIGFRAME = char_match & 0x000000FF;
mbed_official 525:c320967f86b9 1241 }
mbed_official 525:c320967f86b9 1242 }
mbed_official 525:c320967f86b9 1243
mbed_official 525:c320967f86b9 1244 return;
mbed_official 525:c320967f86b9 1245 }
mbed_official 525:c320967f86b9 1246
mbed_official 525:c320967f86b9 1247 /************************************
mbed_official 525:c320967f86b9 1248 * TRANSFER FUNCTIONS *
mbed_official 525:c320967f86b9 1249 ***********************************/
mbed_official 525:c320967f86b9 1250
mbed_official 525:c320967f86b9 1251 /** Begin asynchronous TX transfer. The used buffer is specified in the serial object,
mbed_official 525:c320967f86b9 1252 * tx_buff
mbed_official 525:c320967f86b9 1253 *
mbed_official 525:c320967f86b9 1254 * @param obj The serial object
mbed_official 525:c320967f86b9 1255 * @param cb The function to call when an event occurs
mbed_official 525:c320967f86b9 1256 * @param hint A suggestion for how to use DMA with this transfer
mbed_official 525:c320967f86b9 1257 * @return Returns number of data transfered, or 0 otherwise
mbed_official 525:c320967f86b9 1258 */
mbed_official 525:c320967f86b9 1259 int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint) {
mbed_official 525:c320967f86b9 1260 // Check that a buffer has indeed been set up
mbed_official 525:c320967f86b9 1261 MBED_ASSERT(tx != (void*)0);
mbed_official 525:c320967f86b9 1262 if(tx_length == 0) return 0;
mbed_official 525:c320967f86b9 1263
mbed_official 525:c320967f86b9 1264 // Set up buffer
mbed_official 525:c320967f86b9 1265 serial_tx_buffer_set(obj, tx, tx_length, tx_width);
mbed_official 525:c320967f86b9 1266
mbed_official 525:c320967f86b9 1267 // Set up events
mbed_official 525:c320967f86b9 1268 serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
mbed_official 525:c320967f86b9 1269 serial_tx_enable_event(obj, event, true);
mbed_official 525:c320967f86b9 1270
mbed_official 525:c320967f86b9 1271 // Set up sleepmode
mbed_official 525:c320967f86b9 1272 blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1273
mbed_official 525:c320967f86b9 1274 // Determine DMA strategy
mbed_official 525:c320967f86b9 1275 serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
mbed_official 525:c320967f86b9 1276
mbed_official 525:c320967f86b9 1277 // If DMA, kick off DMA transfer
mbed_official 525:c320967f86b9 1278 if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
mbed_official 525:c320967f86b9 1279 serial_dmaActivate(obj, (void*)handler, obj->tx_buff.buffer, obj->tx_buff.length, true);
mbed_official 525:c320967f86b9 1280 }
mbed_official 525:c320967f86b9 1281 // Else, activate interrupt. TXBL will take care of buffer filling through ISR.
mbed_official 525:c320967f86b9 1282 else {
mbed_official 525:c320967f86b9 1283 // Store callback
mbed_official 525:c320967f86b9 1284 NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 1285 NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 1286 NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
mbed_official 525:c320967f86b9 1287 NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
mbed_official 525:c320967f86b9 1288 NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
mbed_official 525:c320967f86b9 1289
mbed_official 525:c320967f86b9 1290 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1291 // Activate TX and return
mbed_official 525:c320967f86b9 1292 obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN;
mbed_official 525:c320967f86b9 1293
mbed_official 525:c320967f86b9 1294 // Clear TX buffer
mbed_official 525:c320967f86b9 1295 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 1296
mbed_official 525:c320967f86b9 1297 // Enable interrupt
mbed_official 525:c320967f86b9 1298 LEUART_IntEnable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
mbed_official 525:c320967f86b9 1299 } else {
mbed_official 525:c320967f86b9 1300 // Activate TX and return
mbed_official 525:c320967f86b9 1301 obj->serial.periph.uart->CMD = USART_CMD_TXEN;
mbed_official 525:c320967f86b9 1302
mbed_official 525:c320967f86b9 1303 // Clear TX buffer
mbed_official 525:c320967f86b9 1304 obj->serial.periph.uart->CMD = USART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 1305
mbed_official 525:c320967f86b9 1306 // Enable interrupt
mbed_official 525:c320967f86b9 1307 USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXBL);
mbed_official 525:c320967f86b9 1308 }
mbed_official 525:c320967f86b9 1309 }
mbed_official 525:c320967f86b9 1310
mbed_official 525:c320967f86b9 1311 return 0;
mbed_official 525:c320967f86b9 1312 }
mbed_official 525:c320967f86b9 1313
mbed_official 525:c320967f86b9 1314 /** Begin asynchronous RX transfer (enable interrupt for data collecting)
mbed_official 525:c320967f86b9 1315 * The used buffer is specified in the serial object - rx_buff
mbed_official 525:c320967f86b9 1316 *
mbed_official 525:c320967f86b9 1317 * @param obj The serial object
mbed_official 525:c320967f86b9 1318 * @param cb The function to call when an event occurs
mbed_official 525:c320967f86b9 1319 * @param hint A suggestion for how to use DMA with this transfer
mbed_official 525:c320967f86b9 1320 */
mbed_official 525:c320967f86b9 1321 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) {
mbed_official 525:c320967f86b9 1322 // Check that a buffer has indeed been set up
mbed_official 525:c320967f86b9 1323 MBED_ASSERT(rx != (void*)0);
mbed_official 525:c320967f86b9 1324 if(rx_length == 0) return;
mbed_official 525:c320967f86b9 1325
mbed_official 525:c320967f86b9 1326 // Set up buffer
mbed_official 525:c320967f86b9 1327 serial_rx_buffer_set(obj, rx, rx_length, rx_width);
mbed_official 525:c320967f86b9 1328
mbed_official 525:c320967f86b9 1329 // Set up events
mbed_official 525:c320967f86b9 1330 serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
mbed_official 525:c320967f86b9 1331 serial_rx_enable_event(obj, event, true);
mbed_official 525:c320967f86b9 1332 serial_set_char_match(obj, char_match);
mbed_official 525:c320967f86b9 1333
mbed_official 525:c320967f86b9 1334 // Set up sleepmode
mbed_official 525:c320967f86b9 1335 blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1336
mbed_official 525:c320967f86b9 1337 // Determine DMA strategy
mbed_official 525:c320967f86b9 1338 // 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.
mbed_official 525:c320967f86b9 1339 if(!(event & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
mbed_official 525:c320967f86b9 1340 serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
mbed_official 525:c320967f86b9 1341 }
mbed_official 525:c320967f86b9 1342
mbed_official 525:c320967f86b9 1343 // If DMA, kick off DMA
mbed_official 525:c320967f86b9 1344 if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
mbed_official 525:c320967f86b9 1345 serial_dmaActivate(obj, (void*)handler, obj->rx_buff.buffer, obj->rx_buff.length, false);
mbed_official 525:c320967f86b9 1346 }
mbed_official 525:c320967f86b9 1347 // Else, activate interrupt. RXDATAV is responsible for incoming data notification.
mbed_official 525:c320967f86b9 1348 else {
mbed_official 525:c320967f86b9 1349 // Store callback
mbed_official 525:c320967f86b9 1350 NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 1351 NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
mbed_official 525:c320967f86b9 1352 NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
mbed_official 525:c320967f86b9 1353
mbed_official 525:c320967f86b9 1354 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1355 // Activate RX
mbed_official 525:c320967f86b9 1356 obj->serial.periph.leuart->CMD = LEUART_CMD_RXEN;
mbed_official 525:c320967f86b9 1357
mbed_official 525:c320967f86b9 1358 // Clear RX buffer
mbed_official 525:c320967f86b9 1359 obj->serial.periph.leuart->CMD = LEUART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 1360
mbed_official 525:c320967f86b9 1361 // Enable interrupt
mbed_official 525:c320967f86b9 1362 LEUART_IntEnable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV);
mbed_official 525:c320967f86b9 1363 } else {
mbed_official 525:c320967f86b9 1364 // Activate RX
mbed_official 525:c320967f86b9 1365 obj->serial.periph.uart->CMD = USART_CMD_RXEN;
mbed_official 525:c320967f86b9 1366
mbed_official 525:c320967f86b9 1367 // Clear RX buffer
mbed_official 525:c320967f86b9 1368 obj->serial.periph.uart->CMD = USART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 1369
mbed_official 525:c320967f86b9 1370 // Clear RXFULL
mbed_official 525:c320967f86b9 1371 USART_IntClear(obj->serial.periph.uart, USART_IFC_RXFULL);
mbed_official 525:c320967f86b9 1372
mbed_official 525:c320967f86b9 1373 // Enable interrupt
mbed_official 525:c320967f86b9 1374 USART_IntEnable(obj->serial.periph.uart, USART_IEN_RXDATAV);
mbed_official 525:c320967f86b9 1375 }
mbed_official 525:c320967f86b9 1376 }
mbed_official 525:c320967f86b9 1377
mbed_official 525:c320967f86b9 1378 return;
mbed_official 525:c320967f86b9 1379 }
mbed_official 525:c320967f86b9 1380
mbed_official 525:c320967f86b9 1381 /** Attempts to determine if the serial peripheral is already in use for TX
mbed_official 525:c320967f86b9 1382 *
mbed_official 525:c320967f86b9 1383 * @param obj The serial object
mbed_official 525:c320967f86b9 1384 * @return Non-zero if the TX transaction is ongoing, 0 otherwise
mbed_official 525:c320967f86b9 1385 */
mbed_official 525:c320967f86b9 1386 uint8_t serial_tx_active(serial_t *obj) {
mbed_official 525:c320967f86b9 1387 switch(obj->serial.dmaOptionsTX.dmaUsageState) {
mbed_official 525:c320967f86b9 1388 case DMA_USAGE_TEMPORARY_ALLOCATED:
mbed_official 525:c320967f86b9 1389 /* Temporary allocation always means its active, as this state gets cleared afterwards */
mbed_official 525:c320967f86b9 1390 return 1;
mbed_official 525:c320967f86b9 1391 case DMA_USAGE_ALLOCATED:
mbed_official 525:c320967f86b9 1392 /* Check whether the allocated DMA channel is active by checking the DMA transfer */
mbed_official 525:c320967f86b9 1393 return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
mbed_official 525:c320967f86b9 1394 default:
mbed_official 525:c320967f86b9 1395 /* Check whether interrupt for serial TX is enabled */
mbed_official 525:c320967f86b9 1396 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1397 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_TXBL)) ? true : false;
mbed_official 525:c320967f86b9 1398 } else {
mbed_official 525:c320967f86b9 1399 return (obj->serial.periph.uart->IEN & (USART_IEN_TXBL)) ? true : false;
mbed_official 525:c320967f86b9 1400 }
mbed_official 525:c320967f86b9 1401 }
mbed_official 525:c320967f86b9 1402 }
mbed_official 525:c320967f86b9 1403
mbed_official 525:c320967f86b9 1404 /** Attempts to determine if the serial peripheral is already in use for RX
mbed_official 525:c320967f86b9 1405 *
mbed_official 525:c320967f86b9 1406 * @param obj The serial object
mbed_official 525:c320967f86b9 1407 * @return Non-zero if the RX transaction is ongoing, 0 otherwise
mbed_official 525:c320967f86b9 1408 */
mbed_official 525:c320967f86b9 1409 uint8_t serial_rx_active(serial_t *obj) {
mbed_official 525:c320967f86b9 1410 switch(obj->serial.dmaOptionsRX.dmaUsageState) {
mbed_official 525:c320967f86b9 1411 case DMA_USAGE_TEMPORARY_ALLOCATED:
mbed_official 525:c320967f86b9 1412 /* Temporary allocation always means its active, as this state gets cleared afterwards */
mbed_official 525:c320967f86b9 1413 return 1;
mbed_official 525:c320967f86b9 1414 case DMA_USAGE_ALLOCATED:
mbed_official 525:c320967f86b9 1415 /* Check whether the allocated DMA channel is active by checking the DMA transfer */
mbed_official 525:c320967f86b9 1416 return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
mbed_official 525:c320967f86b9 1417 default:
mbed_official 525:c320967f86b9 1418 /* Check whether interrupt for serial TX is enabled */
mbed_official 525:c320967f86b9 1419 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1420 return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV)) ? true : false;
mbed_official 525:c320967f86b9 1421 } else {
mbed_official 525:c320967f86b9 1422 return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV)) ? true : false;
mbed_official 525:c320967f86b9 1423 }
mbed_official 525:c320967f86b9 1424 }
mbed_official 525:c320967f86b9 1425 }
mbed_official 525:c320967f86b9 1426
mbed_official 525:c320967f86b9 1427 /** The asynchronous TX handler. Writes to the TX FIFO and checks for events.
mbed_official 525:c320967f86b9 1428 * If any TX event has occured, the TX abort function is called.
mbed_official 525:c320967f86b9 1429 *
mbed_official 525:c320967f86b9 1430 * @param obj The serial object
mbed_official 525:c320967f86b9 1431 * @return Returns event flags if a TX transfer termination condition was met or 0 otherwise
mbed_official 525:c320967f86b9 1432 */
mbed_official 525:c320967f86b9 1433 int serial_tx_irq_handler_asynch(serial_t *obj) {
mbed_official 525:c320967f86b9 1434 /* This interrupt handler is called from USART irq */
mbed_official 525:c320967f86b9 1435 uint8_t *buf = obj->tx_buff.buffer;
mbed_official 525:c320967f86b9 1436
mbed_official 525:c320967f86b9 1437 /* Interrupt has another TX source */
mbed_official 525:c320967f86b9 1438 if(obj->tx_buff.pos >= obj->tx_buff.length) {
mbed_official 525:c320967f86b9 1439 /* Transfer complete. Switch off interrupt and return event. */
mbed_official 525:c320967f86b9 1440 serial_tx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1441 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
mbed_official 525:c320967f86b9 1442 } else {
mbed_official 525:c320967f86b9 1443 /* There's still data in the buffer that needs to be sent */
mbed_official 525:c320967f86b9 1444 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1445 while((LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_TXBL) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
mbed_official 525:c320967f86b9 1446 LEUART_Tx(obj->serial.periph.leuart, buf[obj->tx_buff.pos]);
mbed_official 525:c320967f86b9 1447 obj->tx_buff.pos++;
mbed_official 525:c320967f86b9 1448 }
mbed_official 525:c320967f86b9 1449 } else {
mbed_official 525:c320967f86b9 1450 while((USART_StatusGet(obj->serial.periph.uart) & USART_STATUS_TXBL) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
mbed_official 525:c320967f86b9 1451 USART_Tx(obj->serial.periph.uart, buf[obj->tx_buff.pos]);
mbed_official 525:c320967f86b9 1452 obj->tx_buff.pos++;
mbed_official 525:c320967f86b9 1453 }
mbed_official 525:c320967f86b9 1454 }
mbed_official 525:c320967f86b9 1455 }
mbed_official 525:c320967f86b9 1456 return 0;
mbed_official 525:c320967f86b9 1457 }
mbed_official 525:c320967f86b9 1458
mbed_official 525:c320967f86b9 1459 /** The asynchronous RX handler. Reads from the RX FIFOF and checks for events.
mbed_official 525:c320967f86b9 1460 * If any RX event has occured, the RX abort function is called.
mbed_official 525:c320967f86b9 1461 *
mbed_official 525:c320967f86b9 1462 * @param obj The serial object
mbed_official 525:c320967f86b9 1463 * @return Returns event flags if a RX transfer termination condition was met or 0 otherwise
mbed_official 525:c320967f86b9 1464 */
mbed_official 525:c320967f86b9 1465 int serial_rx_irq_handler_asynch(serial_t *obj) {
mbed_official 525:c320967f86b9 1466 int event = 0;
mbed_official 525:c320967f86b9 1467
mbed_official 525:c320967f86b9 1468 /* This interrupt handler is called from USART irq */
mbed_official 525:c320967f86b9 1469 uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
mbed_official 525:c320967f86b9 1470
mbed_official 525:c320967f86b9 1471 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1472 /* Determine the source of the interrupt */
mbed_official 525:c320967f86b9 1473 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_PERR) {
mbed_official 525:c320967f86b9 1474 /* Parity error has occurred, and we are notifying. */
mbed_official 525:c320967f86b9 1475 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_PERR);
mbed_official 525:c320967f86b9 1476 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1477 return SERIAL_EVENT_RX_PARITY_ERROR;
mbed_official 525:c320967f86b9 1478 }
mbed_official 525:c320967f86b9 1479
mbed_official 525:c320967f86b9 1480 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_FERR) {
mbed_official 525:c320967f86b9 1481 /* Framing error has occurred, and we are notifying */
mbed_official 525:c320967f86b9 1482 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_FERR);
mbed_official 525:c320967f86b9 1483 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1484 return SERIAL_EVENT_RX_FRAMING_ERROR;
mbed_official 525:c320967f86b9 1485 }
mbed_official 525:c320967f86b9 1486
mbed_official 525:c320967f86b9 1487 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_RXOF) {
mbed_official 525:c320967f86b9 1488 /* RX buffer overflow has occurred, and we are notifying */
mbed_official 525:c320967f86b9 1489 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_RXOF);
mbed_official 525:c320967f86b9 1490 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1491 return SERIAL_EVENT_RX_OVERFLOW;
mbed_official 525:c320967f86b9 1492 }
mbed_official 525:c320967f86b9 1493
mbed_official 525:c320967f86b9 1494 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_SIGF) {
mbed_official 525:c320967f86b9 1495 /* Char match has occurred, stop RX and return */
mbed_official 525:c320967f86b9 1496 LEUART_IntClear(obj->serial.periph.leuart, LEUART_IFC_SIGF);
mbed_official 525:c320967f86b9 1497 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1498 return SERIAL_EVENT_RX_CHARACTER_MATCH;
mbed_official 525:c320967f86b9 1499 }
mbed_official 525:c320967f86b9 1500
mbed_official 525:c320967f86b9 1501 if((LEUART_IntGetEnabled(obj->serial.periph.leuart) & LEUART_IF_RXDATAV) || (LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_RXDATAV)) {
mbed_official 525:c320967f86b9 1502 /* Valid data in buffer. Determine course of action: continue receiving or interrupt */
mbed_official 525:c320967f86b9 1503 if(obj->rx_buff.pos >= (obj->rx_buff.length - 1)) {
mbed_official 525:c320967f86b9 1504 /* Last char, transfer complete. Switch off interrupt and return event. */
mbed_official 525:c320967f86b9 1505 buf[obj->rx_buff.pos] = LEUART_RxDataGet(obj->serial.periph.leuart);
mbed_official 525:c320967f86b9 1506
mbed_official 525:c320967f86b9 1507 event |= SERIAL_EVENT_RX_COMPLETE;
mbed_official 525:c320967f86b9 1508
mbed_official 525:c320967f86b9 1509 if((buf[obj->rx_buff.pos] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
mbed_official 525:c320967f86b9 1510
mbed_official 525:c320967f86b9 1511 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1512 return event & obj->serial.events;
mbed_official 525:c320967f86b9 1513 } else {
mbed_official 525:c320967f86b9 1514 /* There's still space in the receive buffer */
mbed_official 525:c320967f86b9 1515 while((LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_RXDATAV) && (obj->rx_buff.pos <= (obj->rx_buff.length - 1))) {
mbed_official 525:c320967f86b9 1516
mbed_official 525:c320967f86b9 1517 buf[obj->rx_buff.pos] = LEUART_RxDataGet(obj->serial.periph.leuart);
mbed_official 525:c320967f86b9 1518 obj->rx_buff.pos++;
mbed_official 525:c320967f86b9 1519
mbed_official 525:c320967f86b9 1520 /* Check for character match event */
mbed_official 525:c320967f86b9 1521 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
mbed_official 525:c320967f86b9 1522 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
mbed_official 525:c320967f86b9 1523 }
mbed_official 525:c320967f86b9 1524
mbed_official 525:c320967f86b9 1525 /* Check for final char event */
mbed_official 525:c320967f86b9 1526 if(obj->rx_buff.pos >= (obj->rx_buff.length)) {
mbed_official 525:c320967f86b9 1527 event |= SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
mbed_official 525:c320967f86b9 1528 }
mbed_official 525:c320967f86b9 1529
mbed_official 525:c320967f86b9 1530 if(event != 0) {
mbed_official 525:c320967f86b9 1531 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1532 return event & obj->serial.events;
mbed_official 525:c320967f86b9 1533 }
mbed_official 525:c320967f86b9 1534 }
mbed_official 525:c320967f86b9 1535 }
mbed_official 525:c320967f86b9 1536 }
mbed_official 525:c320967f86b9 1537 } else {
mbed_official 525:c320967f86b9 1538 /* Determine the source of the interrupt */
mbed_official 525:c320967f86b9 1539 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_PERR) {
mbed_official 525:c320967f86b9 1540 /* Parity error has occurred, and we are notifying. */
mbed_official 525:c320967f86b9 1541 USART_IntClear(obj->serial.periph.uart, USART_IFC_PERR);
mbed_official 525:c320967f86b9 1542 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1543 return SERIAL_EVENT_RX_PARITY_ERROR;
mbed_official 525:c320967f86b9 1544 }
mbed_official 525:c320967f86b9 1545
mbed_official 525:c320967f86b9 1546 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_FERR) {
mbed_official 525:c320967f86b9 1547 /* Framing error has occurred, and we are notifying */
mbed_official 525:c320967f86b9 1548 USART_IntClear(obj->serial.periph.uart, USART_IFC_FERR);
mbed_official 525:c320967f86b9 1549 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1550 return SERIAL_EVENT_RX_FRAMING_ERROR;
mbed_official 525:c320967f86b9 1551 }
mbed_official 525:c320967f86b9 1552
mbed_official 525:c320967f86b9 1553 if(USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_RXOF) {
mbed_official 525:c320967f86b9 1554 /* RX buffer overflow has occurred, and we are notifying */
mbed_official 525:c320967f86b9 1555 USART_IntClear(obj->serial.periph.uart, USART_IFC_RXOF);
mbed_official 525:c320967f86b9 1556 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1557 return SERIAL_EVENT_RX_OVERFLOW;
mbed_official 525:c320967f86b9 1558 }
mbed_official 525:c320967f86b9 1559
mbed_official 525:c320967f86b9 1560 if((USART_IntGetEnabled(obj->serial.periph.uart) & USART_IF_RXDATAV) || (USART_StatusGet(obj->serial.periph.uart) & USART_STATUS_RXFULL)) {
mbed_official 525:c320967f86b9 1561 /* Valid data in buffer. Determine course of action: continue receiving or interrupt */
mbed_official 525:c320967f86b9 1562 if(obj->rx_buff.pos >= (obj->rx_buff.length - 1)) {
mbed_official 525:c320967f86b9 1563 /* Last char, transfer complete. Switch off interrupt and return event. */
mbed_official 525:c320967f86b9 1564 buf[obj->rx_buff.pos] = USART_RxDataGet(obj->serial.periph.uart);
mbed_official 525:c320967f86b9 1565
mbed_official 525:c320967f86b9 1566 event |= SERIAL_EVENT_RX_COMPLETE;
mbed_official 525:c320967f86b9 1567
mbed_official 525:c320967f86b9 1568 if((buf[obj->rx_buff.pos] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
mbed_official 525:c320967f86b9 1569
mbed_official 525:c320967f86b9 1570 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1571 return event & obj->serial.events;
mbed_official 525:c320967f86b9 1572 } else {
mbed_official 525:c320967f86b9 1573 /* There's still space in the receive buffer */
mbed_official 525:c320967f86b9 1574 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))) {
mbed_official 525:c320967f86b9 1575
mbed_official 525:c320967f86b9 1576 buf[obj->rx_buff.pos] = USART_RxDataGet(obj->serial.periph.uart);
mbed_official 525:c320967f86b9 1577 obj->rx_buff.pos++;
mbed_official 525:c320967f86b9 1578
mbed_official 525:c320967f86b9 1579 /* Check for character match event */
mbed_official 525:c320967f86b9 1580 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
mbed_official 525:c320967f86b9 1581 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
mbed_official 525:c320967f86b9 1582 }
mbed_official 525:c320967f86b9 1583
mbed_official 525:c320967f86b9 1584 /* Check for final char event */
mbed_official 525:c320967f86b9 1585 if(obj->rx_buff.pos >= (obj->rx_buff.length)) {
mbed_official 525:c320967f86b9 1586 event |= SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
mbed_official 525:c320967f86b9 1587 }
mbed_official 525:c320967f86b9 1588
mbed_official 525:c320967f86b9 1589 if(event != 0) {
mbed_official 525:c320967f86b9 1590 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1591 return event & obj->serial.events;
mbed_official 525:c320967f86b9 1592 }
mbed_official 525:c320967f86b9 1593 }
mbed_official 525:c320967f86b9 1594 }
mbed_official 525:c320967f86b9 1595 }
mbed_official 525:c320967f86b9 1596 }
mbed_official 525:c320967f86b9 1597
mbed_official 525:c320967f86b9 1598 /* All events should have generated a return, if no return has happened, no event has been caught */
mbed_official 525:c320967f86b9 1599 return 0;
mbed_official 525:c320967f86b9 1600 }
mbed_official 525:c320967f86b9 1601
mbed_official 525:c320967f86b9 1602 /** Unified IRQ handler. Determines the appropriate handler to execute and returns the flags.
mbed_official 525:c320967f86b9 1603 *
mbed_official 525:c320967f86b9 1604 * WARNING: this code should be stateless, as re-entrancy is very possible in interrupt-based mode.
mbed_official 525:c320967f86b9 1605 */
mbed_official 525:c320967f86b9 1606 int serial_irq_handler_asynch(serial_t *obj) {
mbed_official 525:c320967f86b9 1607 /* First, check if we're running in DMA mode */
mbed_official 525:c320967f86b9 1608 if(serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel]) {
mbed_official 525:c320967f86b9 1609 /* Clean up */
mbed_official 525:c320967f86b9 1610 serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
mbed_official 525:c320967f86b9 1611 serial_rx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1612
mbed_official 525:c320967f86b9 1613 /* Notify CPP land of RX completion */
mbed_official 525:c320967f86b9 1614 return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
mbed_official 525:c320967f86b9 1615 } else if (serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
mbed_official 525:c320967f86b9 1616 /* Clean up */
mbed_official 525:c320967f86b9 1617 serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
mbed_official 525:c320967f86b9 1618 serial_tx_abort_asynch(obj);
mbed_official 525:c320967f86b9 1619
mbed_official 525:c320967f86b9 1620 /* Notify CPP land of completion */
mbed_official 525:c320967f86b9 1621 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
mbed_official 525:c320967f86b9 1622 } else {
mbed_official 525:c320967f86b9 1623 /* Check the NVIC to see which interrupt we're running from
mbed_official 525:c320967f86b9 1624 * Also make sure to prioritize RX */
mbed_official 525:c320967f86b9 1625 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1626 //Different method of checking tx vs rx for LEUART
mbed_official 525:c320967f86b9 1627 if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF | LEUART_IF_SIGF)) {
mbed_official 525:c320967f86b9 1628 return serial_rx_irq_handler_asynch(obj);
mbed_official 525:c320967f86b9 1629 } else if(LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_TXBL) {
mbed_official 525:c320967f86b9 1630 return serial_tx_irq_handler_asynch(obj);
mbed_official 525:c320967f86b9 1631 }
mbed_official 525:c320967f86b9 1632 } else {
mbed_official 525:c320967f86b9 1633 if(USART_IntGetEnabled(obj->serial.periph.uart) & (USART_IF_RXDATAV | USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR)) {
mbed_official 525:c320967f86b9 1634 return serial_rx_irq_handler_asynch(obj);
mbed_official 525:c320967f86b9 1635 } else {
mbed_official 525:c320967f86b9 1636 return serial_tx_irq_handler_asynch(obj);
mbed_official 525:c320967f86b9 1637 }
mbed_official 525:c320967f86b9 1638 }
mbed_official 525:c320967f86b9 1639 }
mbed_official 525:c320967f86b9 1640
mbed_official 525:c320967f86b9 1641 // All should be done now
mbed_official 525:c320967f86b9 1642 return 0;
mbed_official 525:c320967f86b9 1643 }
mbed_official 525:c320967f86b9 1644
mbed_official 525:c320967f86b9 1645 /** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
mbed_official 525:c320967f86b9 1646 * flush TX hardware buffer if TX FIFO is used
mbed_official 525:c320967f86b9 1647 *
mbed_official 525:c320967f86b9 1648 * @param obj The serial object
mbed_official 525:c320967f86b9 1649 */
mbed_official 525:c320967f86b9 1650 void serial_tx_abort_asynch(serial_t *obj) {
mbed_official 525:c320967f86b9 1651 /* Stop transmitter */
mbed_official 525:c320967f86b9 1652 //obj->serial.periph.uart->CMD |= USART_CMD_TXDIS;
mbed_official 525:c320967f86b9 1653
mbed_official 525:c320967f86b9 1654 /* Clean up */
mbed_official 525:c320967f86b9 1655 switch(obj->serial.dmaOptionsTX.dmaUsageState) {
mbed_official 525:c320967f86b9 1656 case DMA_USAGE_ALLOCATED:
mbed_official 525:c320967f86b9 1657 /* stop DMA transfer */
mbed_official 525:c320967f86b9 1658 DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
mbed_official 525:c320967f86b9 1659 break;
mbed_official 525:c320967f86b9 1660 case DMA_USAGE_TEMPORARY_ALLOCATED:
mbed_official 525:c320967f86b9 1661 /* stop DMA transfer and release channel */
mbed_official 525:c320967f86b9 1662 DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
mbed_official 525:c320967f86b9 1663 dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
mbed_official 525:c320967f86b9 1664 obj->serial.dmaOptionsTX.dmaChannel = -1;
mbed_official 525:c320967f86b9 1665 obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 1666 break;
mbed_official 525:c320967f86b9 1667 default:
mbed_official 525:c320967f86b9 1668 /* stop interrupting */
mbed_official 525:c320967f86b9 1669 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1670 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
mbed_official 525:c320967f86b9 1671 } else {
mbed_official 525:c320967f86b9 1672 USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
mbed_official 525:c320967f86b9 1673 }
mbed_official 525:c320967f86b9 1674 break;
mbed_official 525:c320967f86b9 1675 }
mbed_official 525:c320967f86b9 1676
mbed_official 525:c320967f86b9 1677 /* Unblock EM2 and below */
mbed_official 525:c320967f86b9 1678 unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1679 }
mbed_official 525:c320967f86b9 1680
mbed_official 525:c320967f86b9 1681 /** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
mbed_official 525:c320967f86b9 1682 * flush RX hardware buffer if RX FIFO is used
mbed_official 525:c320967f86b9 1683 *
mbed_official 525:c320967f86b9 1684 * @param obj The serial object
mbed_official 525:c320967f86b9 1685 */
mbed_official 525:c320967f86b9 1686 void serial_rx_abort_asynch(serial_t *obj) {
mbed_official 525:c320967f86b9 1687 /* Stop receiver */
mbed_official 525:c320967f86b9 1688 obj->serial.periph.uart->CMD |= USART_CMD_RXDIS;
mbed_official 525:c320967f86b9 1689
mbed_official 525:c320967f86b9 1690 /* Clean up */
mbed_official 525:c320967f86b9 1691 switch(obj->serial.dmaOptionsRX.dmaUsageState) {
mbed_official 525:c320967f86b9 1692 case DMA_USAGE_ALLOCATED:
mbed_official 525:c320967f86b9 1693 /* stop DMA transfer */
mbed_official 525:c320967f86b9 1694 DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
mbed_official 525:c320967f86b9 1695 break;
mbed_official 525:c320967f86b9 1696 case DMA_USAGE_TEMPORARY_ALLOCATED:
mbed_official 525:c320967f86b9 1697 /* stop DMA transfer and release channel */
mbed_official 525:c320967f86b9 1698 DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
mbed_official 525:c320967f86b9 1699 dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
mbed_official 525:c320967f86b9 1700 obj->serial.dmaOptionsRX.dmaChannel = -1;
mbed_official 525:c320967f86b9 1701 obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 1702 break;
mbed_official 525:c320967f86b9 1703 default:
mbed_official 525:c320967f86b9 1704 /* stop interrupting */
mbed_official 525:c320967f86b9 1705 if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
mbed_official 525:c320967f86b9 1706 LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV | LEUART_IEN_PERR | LEUART_IEN_FERR | LEUART_IEN_RXOF | LEUART_IEN_SIGF);
mbed_official 525:c320967f86b9 1707 } else {
mbed_official 525:c320967f86b9 1708 USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
mbed_official 525:c320967f86b9 1709 }
mbed_official 525:c320967f86b9 1710 break;
mbed_official 525:c320967f86b9 1711 }
mbed_official 525:c320967f86b9 1712
mbed_official 525:c320967f86b9 1713 /* Say that we can stop using this emode */
mbed_official 525:c320967f86b9 1714 unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1715 }
mbed_official 525:c320967f86b9 1716
mbed_official 525:c320967f86b9 1717 #endif //DEVICE_SERIAL_ASYNCH
mbed_official 525:c320967f86b9 1718 #endif //DEVICE_SERIAL