mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Apr 28 11:45:12 2015 +0100
Revision:
525:c320967f86b9
Child:
526:7c4bdfe6a168
Synchronized with git revision 299385b8331142b9dc524da7a986536f60b14553

Full URL: https://github.com/mbedmicro/mbed/commit/299385b8331142b9dc524da7a986536f60b14553/

Add in Silicon Labs targets with asynchronous API support

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