test

Committer:
elijahsj
Date:
Mon Nov 09 00:33:19 2020 -0500
Revision:
2:4364577b5ad8
Parent:
1:8a094db1347f
copied mbed library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elijahsj 1:8a094db1347f 1 /* mbed Microcontroller Library
elijahsj 1:8a094db1347f 2 *******************************************************************************
elijahsj 1:8a094db1347f 3 * Copyright (c) 2014, STMicroelectronics
elijahsj 1:8a094db1347f 4 * All rights reserved.
elijahsj 1:8a094db1347f 5 *
elijahsj 1:8a094db1347f 6 * Redistribution and use in source and binary forms, with or without
elijahsj 1:8a094db1347f 7 * modification, are permitted provided that the following conditions are met:
elijahsj 1:8a094db1347f 8 *
elijahsj 1:8a094db1347f 9 * 1. Redistributions of source code must retain the above copyright notice,
elijahsj 1:8a094db1347f 10 * this list of conditions and the following disclaimer.
elijahsj 1:8a094db1347f 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
elijahsj 1:8a094db1347f 12 * this list of conditions and the following disclaimer in the documentation
elijahsj 1:8a094db1347f 13 * and/or other materials provided with the distribution.
elijahsj 1:8a094db1347f 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
elijahsj 1:8a094db1347f 15 * may be used to endorse or promote products derived from this software
elijahsj 1:8a094db1347f 16 * without specific prior written permission.
elijahsj 1:8a094db1347f 17 *
elijahsj 1:8a094db1347f 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
elijahsj 1:8a094db1347f 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
elijahsj 1:8a094db1347f 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
elijahsj 1:8a094db1347f 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
elijahsj 1:8a094db1347f 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
elijahsj 1:8a094db1347f 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
elijahsj 1:8a094db1347f 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
elijahsj 1:8a094db1347f 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
elijahsj 1:8a094db1347f 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
elijahsj 1:8a094db1347f 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
elijahsj 1:8a094db1347f 28 *******************************************************************************
elijahsj 1:8a094db1347f 29 */
elijahsj 1:8a094db1347f 30 #include "mbed_assert.h"
elijahsj 1:8a094db1347f 31 #include "serial_api.h"
elijahsj 1:8a094db1347f 32 #include "serial_api_hal.h"
elijahsj 1:8a094db1347f 33
elijahsj 1:8a094db1347f 34 #if DEVICE_SERIAL
elijahsj 1:8a094db1347f 35
elijahsj 1:8a094db1347f 36 #include "cmsis.h"
elijahsj 1:8a094db1347f 37 #include "pinmap.h"
elijahsj 1:8a094db1347f 38 #include "mbed_error.h"
elijahsj 1:8a094db1347f 39 #include <string.h>
elijahsj 1:8a094db1347f 40 #include "PeripheralPins.h"
elijahsj 1:8a094db1347f 41
elijahsj 1:8a094db1347f 42 #define UART_NUM (3)
elijahsj 1:8a094db1347f 43
elijahsj 1:8a094db1347f 44 static uint32_t serial_irq_ids[UART_NUM] = {0};
elijahsj 1:8a094db1347f 45 UART_HandleTypeDef uart_handlers[UART_NUM];
elijahsj 1:8a094db1347f 46
elijahsj 1:8a094db1347f 47 static uart_irq_handler irq_handler;
elijahsj 1:8a094db1347f 48
elijahsj 1:8a094db1347f 49 int stdio_uart_inited = 0;
elijahsj 1:8a094db1347f 50 serial_t stdio_uart;
elijahsj 1:8a094db1347f 51
elijahsj 1:8a094db1347f 52 void serial_init(serial_t *obj, PinName tx, PinName rx)
elijahsj 1:8a094db1347f 53 {
elijahsj 1:8a094db1347f 54 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 55
elijahsj 1:8a094db1347f 56 // Determine the UART to use (UART_1, UART_2, ...)
elijahsj 1:8a094db1347f 57 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
elijahsj 1:8a094db1347f 58 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
elijahsj 1:8a094db1347f 59
elijahsj 1:8a094db1347f 60 // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
elijahsj 1:8a094db1347f 61 obj_s->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
elijahsj 1:8a094db1347f 62 MBED_ASSERT(obj_s->uart != (UARTName)NC);
elijahsj 1:8a094db1347f 63
elijahsj 1:8a094db1347f 64 // Enable USART clock
elijahsj 1:8a094db1347f 65 if (obj_s->uart == UART_1) {
elijahsj 1:8a094db1347f 66 __HAL_RCC_USART1_FORCE_RESET();
elijahsj 1:8a094db1347f 67 __HAL_RCC_USART1_RELEASE_RESET();
elijahsj 1:8a094db1347f 68 __HAL_RCC_USART1_CLK_ENABLE();
elijahsj 1:8a094db1347f 69 obj_s->index = 0;
elijahsj 1:8a094db1347f 70 }
elijahsj 1:8a094db1347f 71 if (obj_s->uart == UART_2) {
elijahsj 1:8a094db1347f 72 __HAL_RCC_USART2_FORCE_RESET();
elijahsj 1:8a094db1347f 73 __HAL_RCC_USART2_RELEASE_RESET();
elijahsj 1:8a094db1347f 74 __HAL_RCC_USART2_CLK_ENABLE();
elijahsj 1:8a094db1347f 75 obj_s->index = 1;
elijahsj 1:8a094db1347f 76 }
elijahsj 1:8a094db1347f 77 if (obj_s->uart == UART_3) {
elijahsj 1:8a094db1347f 78 __HAL_RCC_USART3_FORCE_RESET();
elijahsj 1:8a094db1347f 79 __HAL_RCC_USART3_RELEASE_RESET();
elijahsj 1:8a094db1347f 80 __HAL_RCC_USART3_CLK_ENABLE();
elijahsj 1:8a094db1347f 81 obj_s->index = 2;
elijahsj 1:8a094db1347f 82 }
elijahsj 1:8a094db1347f 83
elijahsj 1:8a094db1347f 84 // Configure UART pins
elijahsj 1:8a094db1347f 85 pinmap_pinout(tx, PinMap_UART_TX);
elijahsj 1:8a094db1347f 86 pinmap_pinout(rx, PinMap_UART_RX);
elijahsj 1:8a094db1347f 87
elijahsj 1:8a094db1347f 88 if (tx != NC) {
elijahsj 1:8a094db1347f 89 pin_mode(tx, PullUp);
elijahsj 1:8a094db1347f 90 }
elijahsj 1:8a094db1347f 91 if (rx != NC) {
elijahsj 1:8a094db1347f 92 pin_mode(rx, PullUp);
elijahsj 1:8a094db1347f 93 }
elijahsj 1:8a094db1347f 94
elijahsj 1:8a094db1347f 95 // Configure UART
elijahsj 1:8a094db1347f 96 obj_s->baudrate = 9600;
elijahsj 1:8a094db1347f 97 obj_s->databits = UART_WORDLENGTH_8B;
elijahsj 1:8a094db1347f 98 obj_s->stopbits = UART_STOPBITS_1;
elijahsj 1:8a094db1347f 99 obj_s->parity = UART_PARITY_NONE;
elijahsj 1:8a094db1347f 100
elijahsj 1:8a094db1347f 101 #if DEVICE_SERIAL_FC
elijahsj 1:8a094db1347f 102 obj_s->hw_flow_ctl = UART_HWCONTROL_NONE;
elijahsj 1:8a094db1347f 103 #endif
elijahsj 1:8a094db1347f 104
elijahsj 1:8a094db1347f 105 obj_s->pin_tx = tx;
elijahsj 1:8a094db1347f 106 obj_s->pin_rx = rx;
elijahsj 1:8a094db1347f 107
elijahsj 1:8a094db1347f 108 init_uart(obj);
elijahsj 1:8a094db1347f 109
elijahsj 1:8a094db1347f 110 // For stdio management
elijahsj 1:8a094db1347f 111 if (obj_s->uart == STDIO_UART) {
elijahsj 1:8a094db1347f 112 stdio_uart_inited = 1;
elijahsj 1:8a094db1347f 113 memcpy(&stdio_uart, obj, sizeof(serial_t));
elijahsj 1:8a094db1347f 114 }
elijahsj 1:8a094db1347f 115 }
elijahsj 1:8a094db1347f 116
elijahsj 1:8a094db1347f 117 void serial_free(serial_t *obj)
elijahsj 1:8a094db1347f 118 {
elijahsj 1:8a094db1347f 119 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 120
elijahsj 1:8a094db1347f 121 // Reset UART and disable clock
elijahsj 1:8a094db1347f 122 if (obj_s->uart == UART_1) {
elijahsj 1:8a094db1347f 123 __HAL_RCC_USART1_FORCE_RESET();
elijahsj 1:8a094db1347f 124 __HAL_RCC_USART1_RELEASE_RESET();
elijahsj 1:8a094db1347f 125 __HAL_RCC_USART1_CLK_DISABLE();
elijahsj 1:8a094db1347f 126 }
elijahsj 1:8a094db1347f 127 if (obj_s->uart == UART_2) {
elijahsj 1:8a094db1347f 128 __HAL_RCC_USART2_FORCE_RESET();
elijahsj 1:8a094db1347f 129 __HAL_RCC_USART2_RELEASE_RESET();
elijahsj 1:8a094db1347f 130 __HAL_RCC_USART2_CLK_DISABLE();
elijahsj 1:8a094db1347f 131 }
elijahsj 1:8a094db1347f 132 if (obj_s->uart == UART_3) {
elijahsj 1:8a094db1347f 133 __HAL_RCC_USART3_FORCE_RESET();
elijahsj 1:8a094db1347f 134 __HAL_RCC_USART3_RELEASE_RESET();
elijahsj 1:8a094db1347f 135 __HAL_RCC_USART3_CLK_DISABLE();
elijahsj 1:8a094db1347f 136 }
elijahsj 1:8a094db1347f 137
elijahsj 1:8a094db1347f 138 // Configure GPIOs
elijahsj 1:8a094db1347f 139 pin_function(obj_s->pin_tx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
elijahsj 1:8a094db1347f 140 pin_function(obj_s->pin_rx, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
elijahsj 1:8a094db1347f 141
elijahsj 1:8a094db1347f 142 serial_irq_ids[obj_s->index] = 0;
elijahsj 1:8a094db1347f 143 }
elijahsj 1:8a094db1347f 144
elijahsj 1:8a094db1347f 145 void serial_baud(serial_t *obj, int baudrate)
elijahsj 1:8a094db1347f 146 {
elijahsj 1:8a094db1347f 147 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 148
elijahsj 1:8a094db1347f 149 obj_s->baudrate = baudrate;
elijahsj 1:8a094db1347f 150 init_uart(obj);
elijahsj 1:8a094db1347f 151 }
elijahsj 1:8a094db1347f 152
elijahsj 1:8a094db1347f 153 /******************************************************************************
elijahsj 1:8a094db1347f 154 * INTERRUPTS HANDLING
elijahsj 1:8a094db1347f 155 ******************************************************************************/
elijahsj 1:8a094db1347f 156
elijahsj 1:8a094db1347f 157 static void uart_irq(int id)
elijahsj 1:8a094db1347f 158 {
elijahsj 1:8a094db1347f 159 UART_HandleTypeDef * huart = &uart_handlers[id];
elijahsj 1:8a094db1347f 160
elijahsj 1:8a094db1347f 161 if (serial_irq_ids[id] != 0) {
elijahsj 1:8a094db1347f 162 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) != RESET) {
elijahsj 1:8a094db1347f 163 if (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET) {
elijahsj 1:8a094db1347f 164 irq_handler(serial_irq_ids[id], TxIrq);
elijahsj 1:8a094db1347f 165 }
elijahsj 1:8a094db1347f 166 }
elijahsj 1:8a094db1347f 167 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE) != RESET) {
elijahsj 1:8a094db1347f 168 if (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET) {
elijahsj 1:8a094db1347f 169 irq_handler(serial_irq_ids[id], RxIrq);
elijahsj 1:8a094db1347f 170 /* Flag has been cleared when reading the content */
elijahsj 1:8a094db1347f 171 }
elijahsj 1:8a094db1347f 172 }
elijahsj 1:8a094db1347f 173 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
elijahsj 1:8a094db1347f 174 if (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET) {
elijahsj 1:8a094db1347f 175 volatile uint32_t tmpval = huart->Instance->DR; // Clear ORE flag
elijahsj 1:8a094db1347f 176 }
elijahsj 1:8a094db1347f 177 }
elijahsj 1:8a094db1347f 178 }
elijahsj 1:8a094db1347f 179 }
elijahsj 1:8a094db1347f 180
elijahsj 1:8a094db1347f 181 static void uart1_irq(void)
elijahsj 1:8a094db1347f 182 {
elijahsj 1:8a094db1347f 183 uart_irq(0);
elijahsj 1:8a094db1347f 184 }
elijahsj 1:8a094db1347f 185
elijahsj 1:8a094db1347f 186 static void uart2_irq(void)
elijahsj 1:8a094db1347f 187 {
elijahsj 1:8a094db1347f 188 uart_irq(1);
elijahsj 1:8a094db1347f 189 }
elijahsj 1:8a094db1347f 190
elijahsj 1:8a094db1347f 191 static void uart3_irq(void)
elijahsj 1:8a094db1347f 192 {
elijahsj 1:8a094db1347f 193 uart_irq(2);
elijahsj 1:8a094db1347f 194 }
elijahsj 1:8a094db1347f 195
elijahsj 1:8a094db1347f 196 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
elijahsj 1:8a094db1347f 197 {
elijahsj 1:8a094db1347f 198 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 199
elijahsj 1:8a094db1347f 200 irq_handler = handler;
elijahsj 1:8a094db1347f 201 serial_irq_ids[obj_s->index] = id;
elijahsj 1:8a094db1347f 202 }
elijahsj 1:8a094db1347f 203
elijahsj 1:8a094db1347f 204 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
elijahsj 1:8a094db1347f 205 {
elijahsj 1:8a094db1347f 206 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 207 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 208 IRQn_Type irq_n = (IRQn_Type)0;
elijahsj 1:8a094db1347f 209 uint32_t vector = 0;
elijahsj 1:8a094db1347f 210
elijahsj 1:8a094db1347f 211 if (obj_s->uart == UART_1) {
elijahsj 1:8a094db1347f 212 irq_n = USART1_IRQn;
elijahsj 1:8a094db1347f 213 vector = (uint32_t)&uart1_irq;
elijahsj 1:8a094db1347f 214 }
elijahsj 1:8a094db1347f 215
elijahsj 1:8a094db1347f 216 if (obj_s->uart == UART_2) {
elijahsj 1:8a094db1347f 217 irq_n = USART2_IRQn;
elijahsj 1:8a094db1347f 218 vector = (uint32_t)&uart2_irq;
elijahsj 1:8a094db1347f 219 }
elijahsj 1:8a094db1347f 220
elijahsj 1:8a094db1347f 221 if (obj_s->uart == UART_3) {
elijahsj 1:8a094db1347f 222 irq_n = USART3_IRQn;
elijahsj 1:8a094db1347f 223 vector = (uint32_t)&uart3_irq;
elijahsj 1:8a094db1347f 224 }
elijahsj 1:8a094db1347f 225
elijahsj 1:8a094db1347f 226 if (enable) {
elijahsj 1:8a094db1347f 227 if (irq == RxIrq) {
elijahsj 1:8a094db1347f 228 __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
elijahsj 1:8a094db1347f 229 } else { // TxIrq
elijahsj 1:8a094db1347f 230 __HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
elijahsj 1:8a094db1347f 231 }
elijahsj 1:8a094db1347f 232 NVIC_SetVector(irq_n, vector);
elijahsj 1:8a094db1347f 233 NVIC_EnableIRQ(irq_n);
elijahsj 1:8a094db1347f 234
elijahsj 1:8a094db1347f 235 } else { // disable
elijahsj 1:8a094db1347f 236 int all_disabled = 0;
elijahsj 1:8a094db1347f 237 if (irq == RxIrq) {
elijahsj 1:8a094db1347f 238 __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
elijahsj 1:8a094db1347f 239 // Check if TxIrq is disabled too
elijahsj 1:8a094db1347f 240 if ((huart->Instance->CR1 & USART_CR1_TXEIE) == 0) {
elijahsj 1:8a094db1347f 241 all_disabled = 1;
elijahsj 1:8a094db1347f 242 }
elijahsj 1:8a094db1347f 243 } else { // TxIrq
elijahsj 1:8a094db1347f 244 __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
elijahsj 1:8a094db1347f 245 // Check if RxIrq is disabled too
elijahsj 1:8a094db1347f 246 if ((huart->Instance->CR1 & USART_CR1_RXNEIE) == 0) {
elijahsj 1:8a094db1347f 247 all_disabled = 1;
elijahsj 1:8a094db1347f 248 }
elijahsj 1:8a094db1347f 249 }
elijahsj 1:8a094db1347f 250
elijahsj 1:8a094db1347f 251 if (all_disabled) {
elijahsj 1:8a094db1347f 252 NVIC_DisableIRQ(irq_n);
elijahsj 1:8a094db1347f 253 }
elijahsj 1:8a094db1347f 254 }
elijahsj 1:8a094db1347f 255 }
elijahsj 1:8a094db1347f 256
elijahsj 1:8a094db1347f 257 /******************************************************************************
elijahsj 1:8a094db1347f 258 * READ/WRITE
elijahsj 1:8a094db1347f 259 ******************************************************************************/
elijahsj 1:8a094db1347f 260
elijahsj 1:8a094db1347f 261 int serial_getc(serial_t *obj)
elijahsj 1:8a094db1347f 262 {
elijahsj 1:8a094db1347f 263 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 264 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 265
elijahsj 1:8a094db1347f 266 while (!serial_readable(obj));
elijahsj 1:8a094db1347f 267 if (obj_s->databits == UART_WORDLENGTH_8B) {
elijahsj 1:8a094db1347f 268 return (int)(huart->Instance->DR & (uint8_t)0xFF);
elijahsj 1:8a094db1347f 269 } else {
elijahsj 1:8a094db1347f 270 return (int)(huart->Instance->DR & (uint16_t)0x1FF);
elijahsj 1:8a094db1347f 271 }
elijahsj 1:8a094db1347f 272 }
elijahsj 1:8a094db1347f 273
elijahsj 1:8a094db1347f 274 void serial_putc(serial_t *obj, int c)
elijahsj 1:8a094db1347f 275 {
elijahsj 1:8a094db1347f 276 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 277 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 278
elijahsj 1:8a094db1347f 279 while (!serial_writable(obj));
elijahsj 1:8a094db1347f 280 if (obj_s->databits == UART_WORDLENGTH_8B) {
elijahsj 1:8a094db1347f 281 huart->Instance->DR = (uint8_t)(c & (uint8_t)0xFF);
elijahsj 1:8a094db1347f 282 } else {
elijahsj 1:8a094db1347f 283 huart->Instance->DR = (uint16_t)(c & (uint16_t)0x1FF);
elijahsj 1:8a094db1347f 284 }
elijahsj 1:8a094db1347f 285 }
elijahsj 1:8a094db1347f 286
elijahsj 1:8a094db1347f 287 void serial_clear(serial_t *obj)
elijahsj 1:8a094db1347f 288 {
elijahsj 1:8a094db1347f 289 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 290 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 291
elijahsj 1:8a094db1347f 292 huart->TxXferCount = 0;
elijahsj 1:8a094db1347f 293 huart->RxXferCount = 0;
elijahsj 1:8a094db1347f 294 }
elijahsj 1:8a094db1347f 295
elijahsj 1:8a094db1347f 296 void serial_break_set(serial_t *obj)
elijahsj 1:8a094db1347f 297 {
elijahsj 1:8a094db1347f 298 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 299 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 300
elijahsj 1:8a094db1347f 301 HAL_LIN_SendBreak(huart);
elijahsj 1:8a094db1347f 302 }
elijahsj 1:8a094db1347f 303
elijahsj 1:8a094db1347f 304 #if DEVICE_SERIAL_ASYNCH
elijahsj 1:8a094db1347f 305
elijahsj 1:8a094db1347f 306 /******************************************************************************
elijahsj 1:8a094db1347f 307 * LOCAL HELPER FUNCTIONS
elijahsj 1:8a094db1347f 308 ******************************************************************************/
elijahsj 1:8a094db1347f 309
elijahsj 1:8a094db1347f 310 /**
elijahsj 1:8a094db1347f 311 * Configure the TX buffer for an asynchronous write serial transaction
elijahsj 1:8a094db1347f 312 *
elijahsj 1:8a094db1347f 313 * @param obj The serial object.
elijahsj 1:8a094db1347f 314 * @param tx The buffer for sending.
elijahsj 1:8a094db1347f 315 * @param tx_length The number of words to transmit.
elijahsj 1:8a094db1347f 316 */
elijahsj 1:8a094db1347f 317 static void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
elijahsj 1:8a094db1347f 318 {
elijahsj 1:8a094db1347f 319 (void)width;
elijahsj 1:8a094db1347f 320
elijahsj 1:8a094db1347f 321 // Exit if a transmit is already on-going
elijahsj 1:8a094db1347f 322 if (serial_tx_active(obj)) {
elijahsj 1:8a094db1347f 323 return;
elijahsj 1:8a094db1347f 324 }
elijahsj 1:8a094db1347f 325
elijahsj 1:8a094db1347f 326 obj->tx_buff.buffer = tx;
elijahsj 1:8a094db1347f 327 obj->tx_buff.length = tx_length;
elijahsj 1:8a094db1347f 328 obj->tx_buff.pos = 0;
elijahsj 1:8a094db1347f 329 }
elijahsj 1:8a094db1347f 330
elijahsj 1:8a094db1347f 331 /**
elijahsj 1:8a094db1347f 332 * Configure the RX buffer for an asynchronous write serial transaction
elijahsj 1:8a094db1347f 333 *
elijahsj 1:8a094db1347f 334 * @param obj The serial object.
elijahsj 1:8a094db1347f 335 * @param tx The buffer for sending.
elijahsj 1:8a094db1347f 336 * @param tx_length The number of words to transmit.
elijahsj 1:8a094db1347f 337 */
elijahsj 1:8a094db1347f 338 static void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
elijahsj 1:8a094db1347f 339 {
elijahsj 1:8a094db1347f 340 (void)width;
elijahsj 1:8a094db1347f 341
elijahsj 1:8a094db1347f 342 // Exit if a reception is already on-going
elijahsj 1:8a094db1347f 343 if (serial_rx_active(obj)) {
elijahsj 1:8a094db1347f 344 return;
elijahsj 1:8a094db1347f 345 }
elijahsj 1:8a094db1347f 346
elijahsj 1:8a094db1347f 347 obj->rx_buff.buffer = rx;
elijahsj 1:8a094db1347f 348 obj->rx_buff.length = rx_length;
elijahsj 1:8a094db1347f 349 obj->rx_buff.pos = 0;
elijahsj 1:8a094db1347f 350 }
elijahsj 1:8a094db1347f 351
elijahsj 1:8a094db1347f 352 /**
elijahsj 1:8a094db1347f 353 * Configure events
elijahsj 1:8a094db1347f 354 *
elijahsj 1:8a094db1347f 355 * @param obj The serial object
elijahsj 1:8a094db1347f 356 * @param event The logical OR of the events to configure
elijahsj 1:8a094db1347f 357 * @param enable Set to non-zero to enable events, or zero to disable them
elijahsj 1:8a094db1347f 358 */
elijahsj 1:8a094db1347f 359 static void serial_enable_event(serial_t *obj, int event, uint8_t enable)
elijahsj 1:8a094db1347f 360 {
elijahsj 1:8a094db1347f 361 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 362
elijahsj 1:8a094db1347f 363 // Shouldn't have to enable interrupt here, just need to keep track of the requested events.
elijahsj 1:8a094db1347f 364 if (enable) {
elijahsj 1:8a094db1347f 365 obj_s->events |= event;
elijahsj 1:8a094db1347f 366 } else {
elijahsj 1:8a094db1347f 367 obj_s->events &= ~event;
elijahsj 1:8a094db1347f 368 }
elijahsj 1:8a094db1347f 369 }
elijahsj 1:8a094db1347f 370
elijahsj 1:8a094db1347f 371
elijahsj 1:8a094db1347f 372 /**
elijahsj 1:8a094db1347f 373 * Get index of serial object TX IRQ, relating it to the physical peripheral.
elijahsj 1:8a094db1347f 374 *
elijahsj 1:8a094db1347f 375 * @param obj pointer to serial object
elijahsj 1:8a094db1347f 376 * @return internal NVIC TX IRQ index of U(S)ART peripheral
elijahsj 1:8a094db1347f 377 */
elijahsj 1:8a094db1347f 378 static IRQn_Type serial_get_irq_n(serial_t *obj)
elijahsj 1:8a094db1347f 379 {
elijahsj 1:8a094db1347f 380 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 381 IRQn_Type irq_n;
elijahsj 1:8a094db1347f 382
elijahsj 1:8a094db1347f 383 switch (obj_s->index) {
elijahsj 1:8a094db1347f 384 case 0:
elijahsj 1:8a094db1347f 385 irq_n = USART1_IRQn;
elijahsj 1:8a094db1347f 386 break;
elijahsj 1:8a094db1347f 387
elijahsj 1:8a094db1347f 388 case 1:
elijahsj 1:8a094db1347f 389 irq_n = USART2_IRQn;
elijahsj 1:8a094db1347f 390 break;
elijahsj 1:8a094db1347f 391
elijahsj 1:8a094db1347f 392 case 2:
elijahsj 1:8a094db1347f 393 irq_n = USART3_IRQn;
elijahsj 1:8a094db1347f 394 break;
elijahsj 1:8a094db1347f 395
elijahsj 1:8a094db1347f 396 default:
elijahsj 1:8a094db1347f 397 irq_n = (IRQn_Type)0;
elijahsj 1:8a094db1347f 398 }
elijahsj 1:8a094db1347f 399
elijahsj 1:8a094db1347f 400 return irq_n;
elijahsj 1:8a094db1347f 401 }
elijahsj 1:8a094db1347f 402
elijahsj 1:8a094db1347f 403 /******************************************************************************
elijahsj 1:8a094db1347f 404 * MBED API FUNCTIONS
elijahsj 1:8a094db1347f 405 ******************************************************************************/
elijahsj 1:8a094db1347f 406
elijahsj 1:8a094db1347f 407 /**
elijahsj 1:8a094db1347f 408 * Begin asynchronous TX transfer. The used buffer is specified in the serial
elijahsj 1:8a094db1347f 409 * object, tx_buff
elijahsj 1:8a094db1347f 410 *
elijahsj 1:8a094db1347f 411 * @param obj The serial object
elijahsj 1:8a094db1347f 412 * @param tx The buffer for sending
elijahsj 1:8a094db1347f 413 * @param tx_length The number of words to transmit
elijahsj 1:8a094db1347f 414 * @param tx_width The bit width of buffer word
elijahsj 1:8a094db1347f 415 * @param handler The serial handler
elijahsj 1:8a094db1347f 416 * @param event The logical OR of events to be registered
elijahsj 1:8a094db1347f 417 * @param hint A suggestion for how to use DMA with this transfer
elijahsj 1:8a094db1347f 418 * @return Returns number of data transfered, or 0 otherwise
elijahsj 1:8a094db1347f 419 */
elijahsj 1:8a094db1347f 420 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
elijahsj 1:8a094db1347f 421 {
elijahsj 1:8a094db1347f 422 // TODO: DMA usage is currently ignored
elijahsj 1:8a094db1347f 423 (void) hint;
elijahsj 1:8a094db1347f 424
elijahsj 1:8a094db1347f 425 // Check buffer is ok
elijahsj 1:8a094db1347f 426 MBED_ASSERT(tx != (void*)0);
elijahsj 1:8a094db1347f 427 MBED_ASSERT(tx_width == 8); // support only 8b width
elijahsj 1:8a094db1347f 428
elijahsj 1:8a094db1347f 429 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 430 UART_HandleTypeDef * huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 431
elijahsj 1:8a094db1347f 432 if (tx_length == 0) {
elijahsj 1:8a094db1347f 433 return 0;
elijahsj 1:8a094db1347f 434 }
elijahsj 1:8a094db1347f 435
elijahsj 1:8a094db1347f 436 // Set up buffer
elijahsj 1:8a094db1347f 437 serial_tx_buffer_set(obj, (void *)tx, tx_length, tx_width);
elijahsj 1:8a094db1347f 438
elijahsj 1:8a094db1347f 439 // Set up events
elijahsj 1:8a094db1347f 440 serial_enable_event(obj, SERIAL_EVENT_TX_ALL, 0); // Clear all events
elijahsj 1:8a094db1347f 441 serial_enable_event(obj, event, 1); // Set only the wanted events
elijahsj 1:8a094db1347f 442
elijahsj 1:8a094db1347f 443 // Enable interrupt
elijahsj 1:8a094db1347f 444 IRQn_Type irq_n = serial_get_irq_n(obj);
elijahsj 1:8a094db1347f 445 NVIC_ClearPendingIRQ(irq_n);
elijahsj 1:8a094db1347f 446 NVIC_DisableIRQ(irq_n);
elijahsj 1:8a094db1347f 447 NVIC_SetPriority(irq_n, 1);
elijahsj 1:8a094db1347f 448 NVIC_SetVector(irq_n, (uint32_t)handler);
elijahsj 1:8a094db1347f 449 NVIC_EnableIRQ(irq_n);
elijahsj 1:8a094db1347f 450
elijahsj 1:8a094db1347f 451 // the following function will enable UART_IT_TXE and error interrupts
elijahsj 1:8a094db1347f 452 if (HAL_UART_Transmit_IT(huart, (uint8_t*)tx, tx_length) != HAL_OK) {
elijahsj 1:8a094db1347f 453 return 0;
elijahsj 1:8a094db1347f 454 }
elijahsj 1:8a094db1347f 455
elijahsj 1:8a094db1347f 456 return tx_length;
elijahsj 1:8a094db1347f 457 }
elijahsj 1:8a094db1347f 458
elijahsj 1:8a094db1347f 459 /**
elijahsj 1:8a094db1347f 460 * Begin asynchronous RX transfer (enable interrupt for data collecting)
elijahsj 1:8a094db1347f 461 * The used buffer is specified in the serial object, rx_buff
elijahsj 1:8a094db1347f 462 *
elijahsj 1:8a094db1347f 463 * @param obj The serial object
elijahsj 1:8a094db1347f 464 * @param rx The buffer for sending
elijahsj 1:8a094db1347f 465 * @param rx_length The number of words to transmit
elijahsj 1:8a094db1347f 466 * @param rx_width The bit width of buffer word
elijahsj 1:8a094db1347f 467 * @param handler The serial handler
elijahsj 1:8a094db1347f 468 * @param event The logical OR of events to be registered
elijahsj 1:8a094db1347f 469 * @param handler The serial handler
elijahsj 1:8a094db1347f 470 * @param char_match A character in range 0-254 to be matched
elijahsj 1:8a094db1347f 471 * @param hint A suggestion for how to use DMA with this transfer
elijahsj 1:8a094db1347f 472 */
elijahsj 1:8a094db1347f 473 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)
elijahsj 1:8a094db1347f 474 {
elijahsj 1:8a094db1347f 475 // TODO: DMA usage is currently ignored
elijahsj 1:8a094db1347f 476 (void) hint;
elijahsj 1:8a094db1347f 477
elijahsj 1:8a094db1347f 478 /* Sanity check arguments */
elijahsj 1:8a094db1347f 479 MBED_ASSERT(obj);
elijahsj 1:8a094db1347f 480 MBED_ASSERT(rx != (void*)0);
elijahsj 1:8a094db1347f 481 MBED_ASSERT(rx_width == 8); // support only 8b width
elijahsj 1:8a094db1347f 482
elijahsj 1:8a094db1347f 483 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 484 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 485
elijahsj 1:8a094db1347f 486 serial_enable_event(obj, SERIAL_EVENT_RX_ALL, 0);
elijahsj 1:8a094db1347f 487 serial_enable_event(obj, event, 1);
elijahsj 1:8a094db1347f 488
elijahsj 1:8a094db1347f 489 // set CharMatch
elijahsj 1:8a094db1347f 490 obj->char_match = char_match;
elijahsj 1:8a094db1347f 491
elijahsj 1:8a094db1347f 492 serial_rx_buffer_set(obj, rx, rx_length, rx_width);
elijahsj 1:8a094db1347f 493
elijahsj 1:8a094db1347f 494 IRQn_Type irq_n = serial_get_irq_n(obj);
elijahsj 1:8a094db1347f 495 NVIC_ClearPendingIRQ(irq_n);
elijahsj 1:8a094db1347f 496 NVIC_DisableIRQ(irq_n);
elijahsj 1:8a094db1347f 497 NVIC_SetPriority(irq_n, 0);
elijahsj 1:8a094db1347f 498 NVIC_SetVector(irq_n, (uint32_t)handler);
elijahsj 1:8a094db1347f 499 NVIC_EnableIRQ(irq_n);
elijahsj 1:8a094db1347f 500
elijahsj 1:8a094db1347f 501 // following HAL function will enable the RXNE interrupt + error interrupts
elijahsj 1:8a094db1347f 502 HAL_UART_Receive_IT(huart, (uint8_t*)rx, rx_length);
elijahsj 1:8a094db1347f 503 }
elijahsj 1:8a094db1347f 504
elijahsj 1:8a094db1347f 505 /**
elijahsj 1:8a094db1347f 506 * Attempts to determine if the serial peripheral is already in use for TX
elijahsj 1:8a094db1347f 507 *
elijahsj 1:8a094db1347f 508 * @param obj The serial object
elijahsj 1:8a094db1347f 509 * @return Non-zero if the TX transaction is ongoing, 0 otherwise
elijahsj 1:8a094db1347f 510 */
elijahsj 1:8a094db1347f 511 uint8_t serial_tx_active(serial_t *obj)
elijahsj 1:8a094db1347f 512 {
elijahsj 1:8a094db1347f 513 MBED_ASSERT(obj);
elijahsj 1:8a094db1347f 514
elijahsj 1:8a094db1347f 515 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 516 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 517
elijahsj 1:8a094db1347f 518 return ((HAL_UART_GetState(huart) == HAL_UART_STATE_BUSY_TX) ? 1 : 0);
elijahsj 1:8a094db1347f 519 }
elijahsj 1:8a094db1347f 520
elijahsj 1:8a094db1347f 521 /**
elijahsj 1:8a094db1347f 522 * Attempts to determine if the serial peripheral is already in use for RX
elijahsj 1:8a094db1347f 523 *
elijahsj 1:8a094db1347f 524 * @param obj The serial object
elijahsj 1:8a094db1347f 525 * @return Non-zero if the RX transaction is ongoing, 0 otherwise
elijahsj 1:8a094db1347f 526 */
elijahsj 1:8a094db1347f 527 uint8_t serial_rx_active(serial_t *obj)
elijahsj 1:8a094db1347f 528 {
elijahsj 1:8a094db1347f 529 MBED_ASSERT(obj);
elijahsj 1:8a094db1347f 530
elijahsj 1:8a094db1347f 531 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 532 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 533
elijahsj 1:8a094db1347f 534 return ((HAL_UART_GetState(huart) == HAL_UART_STATE_BUSY_RX) ? 1 : 0);
elijahsj 1:8a094db1347f 535 }
elijahsj 1:8a094db1347f 536
elijahsj 1:8a094db1347f 537 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
elijahsj 1:8a094db1347f 538 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_TC) != RESET) {
elijahsj 1:8a094db1347f 539 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
elijahsj 1:8a094db1347f 540 }
elijahsj 1:8a094db1347f 541 }
elijahsj 1:8a094db1347f 542
elijahsj 1:8a094db1347f 543 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
elijahsj 1:8a094db1347f 544 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) {
elijahsj 1:8a094db1347f 545 volatile uint32_t tmpval = huart->Instance->DR; // Clear PE flag
elijahsj 1:8a094db1347f 546 } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) {
elijahsj 1:8a094db1347f 547 volatile uint32_t tmpval = huart->Instance->DR; // Clear FE flag
elijahsj 1:8a094db1347f 548 } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_NE) != RESET) {
elijahsj 1:8a094db1347f 549 volatile uint32_t tmpval = huart->Instance->DR; // Clear NE flag
elijahsj 1:8a094db1347f 550 } else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
elijahsj 1:8a094db1347f 551 volatile uint32_t tmpval = huart->Instance->DR; // Clear ORE flag
elijahsj 1:8a094db1347f 552 }
elijahsj 1:8a094db1347f 553 }
elijahsj 1:8a094db1347f 554
elijahsj 1:8a094db1347f 555 /**
elijahsj 1:8a094db1347f 556 * The asynchronous TX and RX handler.
elijahsj 1:8a094db1347f 557 *
elijahsj 1:8a094db1347f 558 * @param obj The serial object
elijahsj 1:8a094db1347f 559 * @return Returns event flags if a TX/RX transfer termination condition was met or 0 otherwise
elijahsj 1:8a094db1347f 560 */
elijahsj 1:8a094db1347f 561 int serial_irq_handler_asynch(serial_t *obj)
elijahsj 1:8a094db1347f 562 {
elijahsj 1:8a094db1347f 563 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 564 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 565
elijahsj 1:8a094db1347f 566 volatile int return_event = 0;
elijahsj 1:8a094db1347f 567 uint8_t *buf = (uint8_t*)(obj->rx_buff.buffer);
elijahsj 1:8a094db1347f 568 uint8_t i = 0;
elijahsj 1:8a094db1347f 569
elijahsj 1:8a094db1347f 570 // TX PART:
elijahsj 1:8a094db1347f 571 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_TC) != RESET) {
elijahsj 1:8a094db1347f 572 if (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET) {
elijahsj 1:8a094db1347f 573 // Return event SERIAL_EVENT_TX_COMPLETE if requested
elijahsj 1:8a094db1347f 574 if ((obj_s->events & SERIAL_EVENT_TX_COMPLETE ) != 0) {
elijahsj 1:8a094db1347f 575 return_event |= (SERIAL_EVENT_TX_COMPLETE & obj_s->events);
elijahsj 1:8a094db1347f 576 }
elijahsj 1:8a094db1347f 577 }
elijahsj 1:8a094db1347f 578 }
elijahsj 1:8a094db1347f 579
elijahsj 1:8a094db1347f 580 // Handle error events
elijahsj 1:8a094db1347f 581 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) {
elijahsj 1:8a094db1347f 582 if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
elijahsj 1:8a094db1347f 583 return_event |= (SERIAL_EVENT_RX_PARITY_ERROR & obj_s->events);
elijahsj 1:8a094db1347f 584 }
elijahsj 1:8a094db1347f 585 }
elijahsj 1:8a094db1347f 586
elijahsj 1:8a094db1347f 587 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) {
elijahsj 1:8a094db1347f 588 if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
elijahsj 1:8a094db1347f 589 return_event |= (SERIAL_EVENT_RX_FRAMING_ERROR & obj_s->events);
elijahsj 1:8a094db1347f 590 }
elijahsj 1:8a094db1347f 591 }
elijahsj 1:8a094db1347f 592
elijahsj 1:8a094db1347f 593 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
elijahsj 1:8a094db1347f 594 if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
elijahsj 1:8a094db1347f 595 return_event |= (SERIAL_EVENT_RX_OVERRUN_ERROR & obj_s->events);
elijahsj 1:8a094db1347f 596 }
elijahsj 1:8a094db1347f 597 }
elijahsj 1:8a094db1347f 598
elijahsj 1:8a094db1347f 599 HAL_UART_IRQHandler(huart);
elijahsj 1:8a094db1347f 600
elijahsj 1:8a094db1347f 601 // Abort if an error occurs
elijahsj 1:8a094db1347f 602 if (return_event & SERIAL_EVENT_RX_PARITY_ERROR ||
elijahsj 1:8a094db1347f 603 return_event & SERIAL_EVENT_RX_FRAMING_ERROR ||
elijahsj 1:8a094db1347f 604 return_event & SERIAL_EVENT_RX_OVERRUN_ERROR) {
elijahsj 1:8a094db1347f 605 return return_event;
elijahsj 1:8a094db1347f 606 }
elijahsj 1:8a094db1347f 607
elijahsj 1:8a094db1347f 608 //RX PART
elijahsj 1:8a094db1347f 609 if (huart->RxXferSize != 0) {
elijahsj 1:8a094db1347f 610 obj->rx_buff.pos = huart->RxXferSize - huart->RxXferCount;
elijahsj 1:8a094db1347f 611 }
elijahsj 1:8a094db1347f 612 if ((huart->RxXferCount == 0) && (obj->rx_buff.pos >= (obj->rx_buff.length - 1))) {
elijahsj 1:8a094db1347f 613 return_event |= (SERIAL_EVENT_RX_COMPLETE & obj_s->events);
elijahsj 1:8a094db1347f 614 }
elijahsj 1:8a094db1347f 615
elijahsj 1:8a094db1347f 616 // Check if char_match is present
elijahsj 1:8a094db1347f 617 if (obj_s->events & SERIAL_EVENT_RX_CHARACTER_MATCH) {
elijahsj 1:8a094db1347f 618 if (buf != NULL) {
elijahsj 1:8a094db1347f 619 for (i = 0; i < obj->rx_buff.pos; i++) {
elijahsj 1:8a094db1347f 620 if (buf[i] == obj->char_match) {
elijahsj 1:8a094db1347f 621 obj->rx_buff.pos = i;
elijahsj 1:8a094db1347f 622 return_event |= (SERIAL_EVENT_RX_CHARACTER_MATCH & obj_s->events);
elijahsj 1:8a094db1347f 623 serial_rx_abort_asynch(obj);
elijahsj 1:8a094db1347f 624 break;
elijahsj 1:8a094db1347f 625 }
elijahsj 1:8a094db1347f 626 }
elijahsj 1:8a094db1347f 627 }
elijahsj 1:8a094db1347f 628 }
elijahsj 1:8a094db1347f 629
elijahsj 1:8a094db1347f 630 return return_event;
elijahsj 1:8a094db1347f 631 }
elijahsj 1:8a094db1347f 632
elijahsj 1:8a094db1347f 633 /**
elijahsj 1:8a094db1347f 634 * Abort the ongoing TX transaction. It disables the enabled interupt for TX and
elijahsj 1:8a094db1347f 635 * flush TX hardware buffer if TX FIFO is used
elijahsj 1:8a094db1347f 636 *
elijahsj 1:8a094db1347f 637 * @param obj The serial object
elijahsj 1:8a094db1347f 638 */
elijahsj 1:8a094db1347f 639 void serial_tx_abort_asynch(serial_t *obj)
elijahsj 1:8a094db1347f 640 {
elijahsj 1:8a094db1347f 641 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 642 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 643
elijahsj 1:8a094db1347f 644 __HAL_UART_DISABLE_IT(huart, UART_IT_TC);
elijahsj 1:8a094db1347f 645 __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
elijahsj 1:8a094db1347f 646
elijahsj 1:8a094db1347f 647 // clear flags
elijahsj 1:8a094db1347f 648 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
elijahsj 1:8a094db1347f 649
elijahsj 1:8a094db1347f 650 // reset states
elijahsj 1:8a094db1347f 651 huart->TxXferCount = 0;
elijahsj 1:8a094db1347f 652 // update handle state
elijahsj 1:8a094db1347f 653 if(huart->gState == HAL_UART_STATE_BUSY_TX_RX) {
elijahsj 1:8a094db1347f 654 huart->gState = HAL_UART_STATE_BUSY_RX;
elijahsj 1:8a094db1347f 655 } else {
elijahsj 1:8a094db1347f 656 huart->gState = HAL_UART_STATE_READY;
elijahsj 1:8a094db1347f 657 }
elijahsj 1:8a094db1347f 658 }
elijahsj 1:8a094db1347f 659
elijahsj 1:8a094db1347f 660 /**
elijahsj 1:8a094db1347f 661 * Abort the ongoing RX transaction It disables the enabled interrupt for RX and
elijahsj 1:8a094db1347f 662 * flush RX hardware buffer if RX FIFO is used
elijahsj 1:8a094db1347f 663 *
elijahsj 1:8a094db1347f 664 * @param obj The serial object
elijahsj 1:8a094db1347f 665 */
elijahsj 1:8a094db1347f 666 void serial_rx_abort_asynch(serial_t *obj)
elijahsj 1:8a094db1347f 667 {
elijahsj 1:8a094db1347f 668 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 669 UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
elijahsj 1:8a094db1347f 670
elijahsj 1:8a094db1347f 671 // disable interrupts
elijahsj 1:8a094db1347f 672 __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
elijahsj 1:8a094db1347f 673 __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
elijahsj 1:8a094db1347f 674 __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
elijahsj 1:8a094db1347f 675
elijahsj 1:8a094db1347f 676 // clear flags
elijahsj 1:8a094db1347f 677 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_RXNE);
elijahsj 1:8a094db1347f 678 volatile uint32_t tmpval = huart->Instance->DR; // Clear errors flag
elijahsj 1:8a094db1347f 679
elijahsj 1:8a094db1347f 680 // reset states
elijahsj 1:8a094db1347f 681 huart->RxXferCount = 0;
elijahsj 1:8a094db1347f 682 // update handle state
elijahsj 1:8a094db1347f 683 if(huart->RxState == HAL_UART_STATE_BUSY_TX_RX) {
elijahsj 1:8a094db1347f 684 huart->RxState = HAL_UART_STATE_BUSY_TX;
elijahsj 1:8a094db1347f 685 } else {
elijahsj 1:8a094db1347f 686 huart->RxState = HAL_UART_STATE_READY;
elijahsj 1:8a094db1347f 687 }
elijahsj 1:8a094db1347f 688 }
elijahsj 1:8a094db1347f 689
elijahsj 1:8a094db1347f 690 #endif
elijahsj 1:8a094db1347f 691
elijahsj 1:8a094db1347f 692 #if DEVICE_SERIAL_FC
elijahsj 1:8a094db1347f 693
elijahsj 1:8a094db1347f 694 /**
elijahsj 1:8a094db1347f 695 * Set HW Control Flow
elijahsj 1:8a094db1347f 696 * @param obj The serial object
elijahsj 1:8a094db1347f 697 * @param type The Control Flow type (FlowControlNone, FlowControlRTS, FlowControlCTS, FlowControlRTSCTS)
elijahsj 1:8a094db1347f 698 * @param rxflow Pin for the rxflow
elijahsj 1:8a094db1347f 699 * @param txflow Pin for the txflow
elijahsj 1:8a094db1347f 700 */
elijahsj 1:8a094db1347f 701 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
elijahsj 1:8a094db1347f 702 {
elijahsj 1:8a094db1347f 703 struct serial_s *obj_s = SERIAL_S(obj);
elijahsj 1:8a094db1347f 704
elijahsj 1:8a094db1347f 705 // Determine the UART to use (UART_1, UART_2, ...)
elijahsj 1:8a094db1347f 706 UARTName uart_rts = (UARTName)pinmap_peripheral(rxflow, PinMap_UART_RTS);
elijahsj 1:8a094db1347f 707 UARTName uart_cts = (UARTName)pinmap_peripheral(txflow, PinMap_UART_CTS);
elijahsj 1:8a094db1347f 708
elijahsj 1:8a094db1347f 709 // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
elijahsj 1:8a094db1347f 710 obj_s->uart = (UARTName)pinmap_merge(uart_cts, uart_rts);
elijahsj 1:8a094db1347f 711 MBED_ASSERT(obj_s->uart != (UARTName)NC);
elijahsj 1:8a094db1347f 712
elijahsj 1:8a094db1347f 713 if(type == FlowControlNone) {
elijahsj 1:8a094db1347f 714 // Disable hardware flow control
elijahsj 1:8a094db1347f 715 obj_s->hw_flow_ctl = UART_HWCONTROL_NONE;
elijahsj 1:8a094db1347f 716 }
elijahsj 1:8a094db1347f 717 if (type == FlowControlRTS) {
elijahsj 1:8a094db1347f 718 // Enable RTS
elijahsj 1:8a094db1347f 719 MBED_ASSERT(uart_rts != (UARTName)NC);
elijahsj 1:8a094db1347f 720 obj_s->hw_flow_ctl = UART_HWCONTROL_RTS;
elijahsj 1:8a094db1347f 721 obj_s->pin_rts = rxflow;
elijahsj 1:8a094db1347f 722 // Enable the pin for RTS function
elijahsj 1:8a094db1347f 723 pinmap_pinout(rxflow, PinMap_UART_RTS);
elijahsj 1:8a094db1347f 724 }
elijahsj 1:8a094db1347f 725 if (type == FlowControlCTS) {
elijahsj 1:8a094db1347f 726 // Enable CTS
elijahsj 1:8a094db1347f 727 MBED_ASSERT(uart_cts != (UARTName)NC);
elijahsj 1:8a094db1347f 728 obj_s->hw_flow_ctl = UART_HWCONTROL_CTS;
elijahsj 1:8a094db1347f 729 obj_s->pin_cts = txflow;
elijahsj 1:8a094db1347f 730 // Enable the pin for CTS function
elijahsj 1:8a094db1347f 731 pinmap_pinout(txflow, PinMap_UART_CTS);
elijahsj 1:8a094db1347f 732 }
elijahsj 1:8a094db1347f 733 if (type == FlowControlRTSCTS) {
elijahsj 1:8a094db1347f 734 // Enable CTS & RTS
elijahsj 1:8a094db1347f 735 MBED_ASSERT(uart_rts != (UARTName)NC);
elijahsj 1:8a094db1347f 736 MBED_ASSERT(uart_cts != (UARTName)NC);
elijahsj 1:8a094db1347f 737 obj_s->hw_flow_ctl = UART_HWCONTROL_RTS_CTS;
elijahsj 1:8a094db1347f 738 obj_s->pin_rts = rxflow;
elijahsj 1:8a094db1347f 739 obj_s->pin_cts = txflow;
elijahsj 1:8a094db1347f 740 // Enable the pin for CTS function
elijahsj 1:8a094db1347f 741 pinmap_pinout(txflow, PinMap_UART_CTS);
elijahsj 1:8a094db1347f 742 // Enable the pin for RTS function
elijahsj 1:8a094db1347f 743 pinmap_pinout(rxflow, PinMap_UART_RTS);
elijahsj 1:8a094db1347f 744 }
elijahsj 1:8a094db1347f 745
elijahsj 1:8a094db1347f 746 init_uart(obj);
elijahsj 1:8a094db1347f 747 }
elijahsj 1:8a094db1347f 748
elijahsj 1:8a094db1347f 749 #endif
elijahsj 1:8a094db1347f 750
elijahsj 1:8a094db1347f 751 #endif