mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Apr 28 22:45:18 2015 +0100
Revision:
527:74d34ce5a2b5
Parent:
526:7c4bdfe6a168
Child:
547:88c982c8f758
Synchronized with git revision 55891732d461662a2320cd6f0918ba66e7864ae9

Full URL: https://github.com/mbedmicro/mbed/commit/55891732d461662a2320cd6f0918ba66e7864ae9/

[Silicon Labs] Fix a bug preventing LEUART from being clocked correctly

Who changed what in which revision?

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