mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 188:bcfe06ba3d64 1 /*
AnnaBridge 188:bcfe06ba3d64 2 * mbed Microcontroller Library
AnnaBridge 188:bcfe06ba3d64 3 * Copyright (c) 2017-2018 Future Electronics
AnnaBridge 189:f392fc9709a3 4 * Copyright (c) 2018-2019 Cypress Semiconductor Corporation
AnnaBridge 189:f392fc9709a3 5 * SPDX-License-Identifier: Apache-2.0
AnnaBridge 188:bcfe06ba3d64 6 *
AnnaBridge 188:bcfe06ba3d64 7 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 188:bcfe06ba3d64 8 * you may not use this file except in compliance with the License.
AnnaBridge 188:bcfe06ba3d64 9 * You may obtain a copy of the License at
AnnaBridge 188:bcfe06ba3d64 10 *
AnnaBridge 188:bcfe06ba3d64 11 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 188:bcfe06ba3d64 12 *
AnnaBridge 188:bcfe06ba3d64 13 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 188:bcfe06ba3d64 14 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 188:bcfe06ba3d64 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 188:bcfe06ba3d64 16 * See the License for the specific language governing permissions and
AnnaBridge 188:bcfe06ba3d64 17 * limitations under the License.
AnnaBridge 188:bcfe06ba3d64 18 */
AnnaBridge 188:bcfe06ba3d64 19
AnnaBridge 188:bcfe06ba3d64 20 #if DEVICE_SERIAL
AnnaBridge 188:bcfe06ba3d64 21
AnnaBridge 188:bcfe06ba3d64 22 #include <string.h>
AnnaBridge 188:bcfe06ba3d64 23
AnnaBridge 188:bcfe06ba3d64 24 #include "cmsis.h"
AnnaBridge 188:bcfe06ba3d64 25 #include "mbed_assert.h"
AnnaBridge 188:bcfe06ba3d64 26 #include "mbed_error.h"
AnnaBridge 188:bcfe06ba3d64 27 #include "PeripheralPins.h"
AnnaBridge 188:bcfe06ba3d64 28 #include "pinmap.h"
AnnaBridge 188:bcfe06ba3d64 29 #include "serial_api.h"
AnnaBridge 188:bcfe06ba3d64 30 #include "psoc6_utils.h"
AnnaBridge 188:bcfe06ba3d64 31
AnnaBridge 189:f392fc9709a3 32 #include "cy_sysclk.h"
AnnaBridge 189:f392fc9709a3 33 #include "cy_gpio.h"
AnnaBridge 189:f392fc9709a3 34 #include "cy_scb_uart.h"
AnnaBridge 189:f392fc9709a3 35 #include "cy_sysint.h"
AnnaBridge 188:bcfe06ba3d64 36
AnnaBridge 188:bcfe06ba3d64 37 #define UART_OVERSAMPLE 12
AnnaBridge 188:bcfe06ba3d64 38 #define UART_DEFAULT_BAUDRATE 115200
AnnaBridge 188:bcfe06ba3d64 39 #define NUM_SERIAL_PORTS 8
AnnaBridge 188:bcfe06ba3d64 40 #define SERIAL_DEFAULT_IRQ_PRIORITY 3
AnnaBridge 188:bcfe06ba3d64 41
AnnaBridge 189:f392fc9709a3 42 #define UART_RX_INTR_MASK (CY_SCB_UART_RX_TRIGGER | CY_SCB_UART_RX_OVERFLOW | \
AnnaBridge 189:f392fc9709a3 43 CY_SCB_UART_RX_ERR_FRAME | CY_SCB_UART_RX_ERR_PARITY)
AnnaBridge 189:f392fc9709a3 44
AnnaBridge 188:bcfe06ba3d64 45 typedef struct serial_s serial_obj_t;
AnnaBridge 188:bcfe06ba3d64 46 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 188:bcfe06ba3d64 47 #define OBJ_P(in) (&(in->serial))
AnnaBridge 188:bcfe06ba3d64 48 #else
AnnaBridge 188:bcfe06ba3d64 49 #define OBJ_P(in) (in)
AnnaBridge 188:bcfe06ba3d64 50 #endif
AnnaBridge 188:bcfe06ba3d64 51
AnnaBridge 188:bcfe06ba3d64 52 /*
AnnaBridge 188:bcfe06ba3d64 53 * NOTE: Cypress PDL high level API implementation of USART doe not
AnnaBridge 188:bcfe06ba3d64 54 * align well with Mbed interface for interrupt-driven serial I/O.
AnnaBridge 188:bcfe06ba3d64 55 * For this reason only low level PDL API is used here.
AnnaBridge 188:bcfe06ba3d64 56 */
AnnaBridge 188:bcfe06ba3d64 57
AnnaBridge 189:f392fc9709a3 58 /* Default UART configuration */
AnnaBridge 188:bcfe06ba3d64 59 static const cy_stc_scb_uart_config_t default_uart_config = {
AnnaBridge 188:bcfe06ba3d64 60 .uartMode = CY_SCB_UART_STANDARD,
AnnaBridge 188:bcfe06ba3d64 61 .enableMutliProcessorMode = false,
AnnaBridge 188:bcfe06ba3d64 62 .smartCardRetryOnNack = false,
AnnaBridge 188:bcfe06ba3d64 63 .irdaInvertRx = false,
AnnaBridge 188:bcfe06ba3d64 64 .irdaEnableLowPowerReceiver = false,
AnnaBridge 188:bcfe06ba3d64 65
AnnaBridge 188:bcfe06ba3d64 66 .oversample = UART_OVERSAMPLE,
AnnaBridge 188:bcfe06ba3d64 67
AnnaBridge 188:bcfe06ba3d64 68 .enableMsbFirst = false,
AnnaBridge 188:bcfe06ba3d64 69 .dataWidth = 8UL,
AnnaBridge 188:bcfe06ba3d64 70 .parity = CY_SCB_UART_PARITY_NONE,
AnnaBridge 188:bcfe06ba3d64 71 .stopBits = CY_SCB_UART_STOP_BITS_1,
AnnaBridge 188:bcfe06ba3d64 72 .enableInputFilter = false,
AnnaBridge 188:bcfe06ba3d64 73 .breakWidth = 11UL,
AnnaBridge 188:bcfe06ba3d64 74 .dropOnFrameError = false,
AnnaBridge 188:bcfe06ba3d64 75 .dropOnParityError = false,
AnnaBridge 188:bcfe06ba3d64 76
AnnaBridge 188:bcfe06ba3d64 77 .receiverAddress = 0x0UL,
AnnaBridge 188:bcfe06ba3d64 78 .receiverAddressMask = 0x0UL,
AnnaBridge 188:bcfe06ba3d64 79 .acceptAddrInFifo = false,
AnnaBridge 188:bcfe06ba3d64 80
AnnaBridge 188:bcfe06ba3d64 81 .enableCts = false,
AnnaBridge 188:bcfe06ba3d64 82 .ctsPolarity = CY_SCB_UART_ACTIVE_LOW,
AnnaBridge 188:bcfe06ba3d64 83 .rtsRxFifoLevel = 20UL,
AnnaBridge 188:bcfe06ba3d64 84 .rtsPolarity = CY_SCB_UART_ACTIVE_LOW,
AnnaBridge 188:bcfe06ba3d64 85
AnnaBridge 189:f392fc9709a3 86 .rxFifoTriggerLevel = 0UL, /* Level triggers when at least one element is in FIFO */
AnnaBridge 188:bcfe06ba3d64 87 .rxFifoIntEnableMask = 0x0UL,
AnnaBridge 188:bcfe06ba3d64 88
AnnaBridge 189:f392fc9709a3 89 .txFifoTriggerLevel = 63UL, /* Level triggers when half-fifo is half empty */
AnnaBridge 188:bcfe06ba3d64 90 .txFifoIntEnableMask = 0x0UL
AnnaBridge 188:bcfe06ba3d64 91 };
AnnaBridge 188:bcfe06ba3d64 92
AnnaBridge 189:f392fc9709a3 93 /* STDIO serial information */
AnnaBridge 189:f392fc9709a3 94 bool stdio_uart_inited = false;
AnnaBridge 188:bcfe06ba3d64 95 serial_t stdio_uart;
AnnaBridge 188:bcfe06ba3d64 96
AnnaBridge 189:f392fc9709a3 97 int bt_uart_inited = false;
AnnaBridge 189:f392fc9709a3 98 serial_t bt_uart;
AnnaBridge 189:f392fc9709a3 99
AnnaBridge 188:bcfe06ba3d64 100 typedef struct irq_info_s {
AnnaBridge 188:bcfe06ba3d64 101 serial_obj_t *serial_obj;
AnnaBridge 188:bcfe06ba3d64 102 uart_irq_handler handler;
AnnaBridge 188:bcfe06ba3d64 103 uint32_t id_arg;
AnnaBridge 188:bcfe06ba3d64 104 IRQn_Type irqn;
AnnaBridge 188:bcfe06ba3d64 105 #if defined (TARGET_MCU_PSOC6_M0)
AnnaBridge 188:bcfe06ba3d64 106 cy_en_intr_t cm0p_irq_src;
AnnaBridge 188:bcfe06ba3d64 107 #endif
AnnaBridge 188:bcfe06ba3d64 108 } irq_info_t;
AnnaBridge 188:bcfe06ba3d64 109
AnnaBridge 189:f392fc9709a3 110
AnnaBridge 189:f392fc9709a3 111 /* Allocate interrupt information table */
AnnaBridge 188:bcfe06ba3d64 112 static irq_info_t irq_info[NUM_SERIAL_PORTS] = {
AnnaBridge 188:bcfe06ba3d64 113 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 114 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 115 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 116 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 117 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 118 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 119 {NULL, NULL, 0, unconnected_IRQn},
AnnaBridge 188:bcfe06ba3d64 120 {NULL, NULL, 0, unconnected_IRQn}
AnnaBridge 188:bcfe06ba3d64 121 };
AnnaBridge 188:bcfe06ba3d64 122
AnnaBridge 188:bcfe06ba3d64 123
AnnaBridge 189:f392fc9709a3 124 /** Routes interrupt to proper SCB block.
AnnaBridge 189:f392fc9709a3 125 *
AnnaBridge 189:f392fc9709a3 126 * @param serial_id The ID of serial object
AnnaBridge 189:f392fc9709a3 127 */
AnnaBridge 188:bcfe06ba3d64 128 static void serial_irq_dispatcher(uint32_t serial_id)
AnnaBridge 188:bcfe06ba3d64 129 {
AnnaBridge 188:bcfe06ba3d64 130 MBED_ASSERT(serial_id < NUM_SERIAL_PORTS);
AnnaBridge 189:f392fc9709a3 131
AnnaBridge 188:bcfe06ba3d64 132 irq_info_t *info = &irq_info[serial_id];
AnnaBridge 188:bcfe06ba3d64 133 serial_obj_t *obj = info->serial_obj;
AnnaBridge 188:bcfe06ba3d64 134 MBED_ASSERT(obj);
AnnaBridge 188:bcfe06ba3d64 135
AnnaBridge 188:bcfe06ba3d64 136 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 188:bcfe06ba3d64 137 if (obj->async_handler) {
AnnaBridge 188:bcfe06ba3d64 138 obj->async_handler();
AnnaBridge 188:bcfe06ba3d64 139 return;
AnnaBridge 188:bcfe06ba3d64 140 }
AnnaBridge 188:bcfe06ba3d64 141 #endif
AnnaBridge 189:f392fc9709a3 142
AnnaBridge 188:bcfe06ba3d64 143 if (Cy_SCB_GetRxInterruptStatusMasked(obj->base) & CY_SCB_RX_INTR_NOT_EMPTY) {
AnnaBridge 188:bcfe06ba3d64 144 info->handler(info->id_arg, RxIrq);
AnnaBridge 188:bcfe06ba3d64 145 Cy_SCB_ClearRxInterrupt(obj->base, CY_SCB_RX_INTR_NOT_EMPTY);
AnnaBridge 188:bcfe06ba3d64 146 }
AnnaBridge 188:bcfe06ba3d64 147
AnnaBridge 189:f392fc9709a3 148 if (Cy_SCB_GetTxInterruptStatusMasked(obj->base) & CY_SCB_UART_TX_EMPTY) {
AnnaBridge 188:bcfe06ba3d64 149 info->handler(info->id_arg, TxIrq);
AnnaBridge 189:f392fc9709a3 150 Cy_SCB_ClearTxInterrupt(obj->base, CY_SCB_UART_TX_EMPTY);
AnnaBridge 188:bcfe06ba3d64 151 }
AnnaBridge 188:bcfe06ba3d64 152 }
AnnaBridge 188:bcfe06ba3d64 153
AnnaBridge 188:bcfe06ba3d64 154 static void serial_irq_dispatcher_uart0(void)
AnnaBridge 188:bcfe06ba3d64 155 {
AnnaBridge 188:bcfe06ba3d64 156 serial_irq_dispatcher(0);
AnnaBridge 188:bcfe06ba3d64 157 }
AnnaBridge 188:bcfe06ba3d64 158
AnnaBridge 188:bcfe06ba3d64 159 static void serial_irq_dispatcher_uart1(void)
AnnaBridge 188:bcfe06ba3d64 160 {
AnnaBridge 188:bcfe06ba3d64 161 serial_irq_dispatcher(1);
AnnaBridge 188:bcfe06ba3d64 162 }
AnnaBridge 188:bcfe06ba3d64 163
AnnaBridge 188:bcfe06ba3d64 164 static void serial_irq_dispatcher_uart2(void)
AnnaBridge 188:bcfe06ba3d64 165 {
AnnaBridge 188:bcfe06ba3d64 166 serial_irq_dispatcher(2);
AnnaBridge 188:bcfe06ba3d64 167 }
AnnaBridge 188:bcfe06ba3d64 168
AnnaBridge 188:bcfe06ba3d64 169 static void serial_irq_dispatcher_uart3(void)
AnnaBridge 188:bcfe06ba3d64 170 {
AnnaBridge 188:bcfe06ba3d64 171 serial_irq_dispatcher(3);
AnnaBridge 188:bcfe06ba3d64 172 }
AnnaBridge 188:bcfe06ba3d64 173
AnnaBridge 188:bcfe06ba3d64 174 static void serial_irq_dispatcher_uart4(void)
AnnaBridge 188:bcfe06ba3d64 175 {
AnnaBridge 188:bcfe06ba3d64 176 serial_irq_dispatcher(4);
AnnaBridge 188:bcfe06ba3d64 177 }
AnnaBridge 188:bcfe06ba3d64 178
AnnaBridge 188:bcfe06ba3d64 179 static void serial_irq_dispatcher_uart5(void)
AnnaBridge 188:bcfe06ba3d64 180 {
AnnaBridge 188:bcfe06ba3d64 181 serial_irq_dispatcher(5);
AnnaBridge 188:bcfe06ba3d64 182 }
AnnaBridge 188:bcfe06ba3d64 183
AnnaBridge 188:bcfe06ba3d64 184 void serial_irq_dispatcher_uart6(void)
AnnaBridge 188:bcfe06ba3d64 185 {
AnnaBridge 188:bcfe06ba3d64 186 serial_irq_dispatcher(6);
AnnaBridge 188:bcfe06ba3d64 187 }
AnnaBridge 188:bcfe06ba3d64 188
AnnaBridge 188:bcfe06ba3d64 189 static void serial_irq_dispatcher_uart7(void)
AnnaBridge 188:bcfe06ba3d64 190 {
AnnaBridge 188:bcfe06ba3d64 191 serial_irq_dispatcher(7);
AnnaBridge 188:bcfe06ba3d64 192 }
AnnaBridge 188:bcfe06ba3d64 193
AnnaBridge 189:f392fc9709a3 194 /* Interrupts table */
AnnaBridge 188:bcfe06ba3d64 195 static void (*irq_dispatcher_table[])(void) = {
AnnaBridge 188:bcfe06ba3d64 196 serial_irq_dispatcher_uart0,
AnnaBridge 188:bcfe06ba3d64 197 serial_irq_dispatcher_uart1,
AnnaBridge 188:bcfe06ba3d64 198 serial_irq_dispatcher_uart2,
AnnaBridge 188:bcfe06ba3d64 199 serial_irq_dispatcher_uart3,
AnnaBridge 188:bcfe06ba3d64 200 serial_irq_dispatcher_uart4,
AnnaBridge 188:bcfe06ba3d64 201 serial_irq_dispatcher_uart5,
AnnaBridge 188:bcfe06ba3d64 202 serial_irq_dispatcher_uart6,
AnnaBridge 188:bcfe06ba3d64 203 serial_irq_dispatcher_uart7
AnnaBridge 188:bcfe06ba3d64 204 };
AnnaBridge 188:bcfe06ba3d64 205
AnnaBridge 188:bcfe06ba3d64 206
AnnaBridge 188:bcfe06ba3d64 207 static IRQn_Type serial_irq_allocate_channel(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 208 {
AnnaBridge 188:bcfe06ba3d64 209 #if defined (TARGET_MCU_PSOC6_M0)
AnnaBridge 188:bcfe06ba3d64 210 irq_info[obj->serial_id].cm0p_irq_src = scb_0_interrupt_IRQn + obj->serial_id;
AnnaBridge 188:bcfe06ba3d64 211 return cy_m0_nvic_allocate_channel(CY_SERIAL_IRQN_ID + obj->serial_id);
AnnaBridge 188:bcfe06ba3d64 212 #else
AnnaBridge 188:bcfe06ba3d64 213 return (IRQn_Type)(scb_0_interrupt_IRQn + obj->serial_id);
AnnaBridge 189:f392fc9709a3 214 #endif /* (TARGET_MCU_PSOC6_M0) */
AnnaBridge 188:bcfe06ba3d64 215 }
AnnaBridge 188:bcfe06ba3d64 216
AnnaBridge 188:bcfe06ba3d64 217
AnnaBridge 188:bcfe06ba3d64 218 static int serial_irq_setup_channel(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 219 {
AnnaBridge 188:bcfe06ba3d64 220 cy_stc_sysint_t irq_config;
AnnaBridge 188:bcfe06ba3d64 221 irq_info_t *info = &irq_info[obj->serial_id];
AnnaBridge 188:bcfe06ba3d64 222
AnnaBridge 188:bcfe06ba3d64 223 if (info->irqn == unconnected_IRQn) {
AnnaBridge 188:bcfe06ba3d64 224 IRQn_Type irqn = serial_irq_allocate_channel(obj);
AnnaBridge 188:bcfe06ba3d64 225 if (irqn < 0) {
AnnaBridge 188:bcfe06ba3d64 226 return (-1);
AnnaBridge 188:bcfe06ba3d64 227 }
AnnaBridge 189:f392fc9709a3 228
AnnaBridge 189:f392fc9709a3 229 /* Configure NVIC */
AnnaBridge 188:bcfe06ba3d64 230 irq_config.intrPriority = SERIAL_DEFAULT_IRQ_PRIORITY;
AnnaBridge 188:bcfe06ba3d64 231 irq_config.intrSrc = irqn;
AnnaBridge 188:bcfe06ba3d64 232 #if defined (TARGET_MCU_PSOC6_M0)
AnnaBridge 188:bcfe06ba3d64 233 irq_config.cm0pSrc = info->cm0p_irq_src;
AnnaBridge 188:bcfe06ba3d64 234 #endif
AnnaBridge 188:bcfe06ba3d64 235 if (Cy_SysInt_Init(&irq_config, irq_dispatcher_table[obj->serial_id]) != CY_SYSINT_SUCCESS) {
AnnaBridge 189:f392fc9709a3 236 return (-1);
AnnaBridge 188:bcfe06ba3d64 237 }
AnnaBridge 188:bcfe06ba3d64 238
AnnaBridge 188:bcfe06ba3d64 239 info->irqn = irqn;
AnnaBridge 188:bcfe06ba3d64 240 info->serial_obj = obj;
AnnaBridge 188:bcfe06ba3d64 241 }
AnnaBridge 189:f392fc9709a3 242
AnnaBridge 189:f392fc9709a3 243 /* Enable interrupt after successful setup */
AnnaBridge 189:f392fc9709a3 244 NVIC_EnableIRQ(info->irqn);
AnnaBridge 189:f392fc9709a3 245
AnnaBridge 188:bcfe06ba3d64 246 return 0;
AnnaBridge 188:bcfe06ba3d64 247 }
AnnaBridge 188:bcfe06ba3d64 248
AnnaBridge 189:f392fc9709a3 249
AnnaBridge 189:f392fc9709a3 250 /** Calculates fractional divider value.
AnnaBridge 189:f392fc9709a3 251 *
AnnaBridge 189:f392fc9709a3 252 * @param frequency The desired frequency of UART clock
AnnaBridge 189:f392fc9709a3 253 * @param frac_bits The number of fractional bits in the divider
AnnaBridge 189:f392fc9709a3 254 * @return The divider value
AnnaBridge 188:bcfe06ba3d64 255 */
AnnaBridge 188:bcfe06ba3d64 256 static uint32_t divider_value(uint32_t frequency, uint32_t frac_bits)
AnnaBridge 188:bcfe06ba3d64 257 {
AnnaBridge 188:bcfe06ba3d64 258 /* UARTs use peripheral clock */
AnnaBridge 189:f392fc9709a3 259 return ((cy_PeriClkFreqHz * (1 << frac_bits)) + (frequency / 2)) / frequency;
AnnaBridge 188:bcfe06ba3d64 260 }
AnnaBridge 188:bcfe06ba3d64 261
AnnaBridge 189:f392fc9709a3 262
AnnaBridge 189:f392fc9709a3 263 #define FRACT_DIV_INT(divider) (((divider) >> 5U) - 1U)
AnnaBridge 189:f392fc9709a3 264 #define FRACT_DIV_FARCT(divider) ((divider) & 0x1FU)
AnnaBridge 189:f392fc9709a3 265
AnnaBridge 189:f392fc9709a3 266 /** Finds clock divider, configures it and connects to SCB block.
AnnaBridge 189:f392fc9709a3 267 *
AnnaBridge 189:f392fc9709a3 268 * @param obj The serial object
AnnaBridge 189:f392fc9709a3 269 * @param baudrate The desired UART baud rate
AnnaBridge 189:f392fc9709a3 270 * @return CY_SYSCLK_SUCCESS if operation successful and CY_SYSCLK_BAD_PARAM otherwise
AnnaBridge 189:f392fc9709a3 271 */
AnnaBridge 188:bcfe06ba3d64 272 static cy_en_sysclk_status_t serial_init_clock(serial_obj_t *obj, uint32_t baudrate)
AnnaBridge 188:bcfe06ba3d64 273 {
AnnaBridge 188:bcfe06ba3d64 274 cy_en_sysclk_status_t status = CY_SYSCLK_BAD_PARAM;
AnnaBridge 188:bcfe06ba3d64 275
AnnaBridge 188:bcfe06ba3d64 276 if (obj->div_num == CY_INVALID_DIVIDER) {
AnnaBridge 188:bcfe06ba3d64 277 uint32_t divider_num = cy_clk_allocate_divider(CY_SYSCLK_DIV_16_5_BIT);
AnnaBridge 188:bcfe06ba3d64 278
AnnaBridge 188:bcfe06ba3d64 279 if (divider_num < PERI_DIV_16_5_NR) {
AnnaBridge 189:f392fc9709a3 280 /* Assign fractional divider */
AnnaBridge 188:bcfe06ba3d64 281 status = Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_16_5_BIT, divider_num);
AnnaBridge 188:bcfe06ba3d64 282 if (status == CY_SYSCLK_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 283 obj->div_type = CY_SYSCLK_DIV_16_5_BIT;
AnnaBridge 189:f392fc9709a3 284 obj->div_num = divider_num;
AnnaBridge 188:bcfe06ba3d64 285 }
AnnaBridge 188:bcfe06ba3d64 286 } else {
AnnaBridge 188:bcfe06ba3d64 287 // Try 16-bit divider.
AnnaBridge 188:bcfe06ba3d64 288 divider_num = cy_clk_allocate_divider(CY_SYSCLK_DIV_16_BIT);
AnnaBridge 188:bcfe06ba3d64 289 if (divider_num < PERI_DIV_16_NR) {
AnnaBridge 189:f392fc9709a3 290 /* Assign 16-bit divider */
AnnaBridge 188:bcfe06ba3d64 291 status = Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_16_BIT, divider_num);
AnnaBridge 188:bcfe06ba3d64 292 if (status == CY_SYSCLK_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 293 obj->div_type = CY_SYSCLK_DIV_16_BIT;
AnnaBridge 189:f392fc9709a3 294 obj->div_num = divider_num;
AnnaBridge 188:bcfe06ba3d64 295 }
AnnaBridge 188:bcfe06ba3d64 296 } else {
AnnaBridge 188:bcfe06ba3d64 297 error("Serial: cannot assign clock divider.");
AnnaBridge 188:bcfe06ba3d64 298 }
AnnaBridge 188:bcfe06ba3d64 299 }
AnnaBridge 188:bcfe06ba3d64 300 } else {
AnnaBridge 188:bcfe06ba3d64 301 status = CY_SYSCLK_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 302 }
AnnaBridge 188:bcfe06ba3d64 303
AnnaBridge 188:bcfe06ba3d64 304 if (status == CY_SYSCLK_SUCCESS) {
AnnaBridge 189:f392fc9709a3 305 Cy_SysClk_PeriphDisableDivider(obj->div_type, obj->div_num);
AnnaBridge 189:f392fc9709a3 306
AnnaBridge 188:bcfe06ba3d64 307 /* Set baud rate */
AnnaBridge 188:bcfe06ba3d64 308 if (obj->div_type == CY_SYSCLK_DIV_16_5_BIT) {
AnnaBridge 189:f392fc9709a3 309 /* Get fractional divider */
AnnaBridge 189:f392fc9709a3 310 uint32_t divider = divider_value(baudrate * UART_OVERSAMPLE, 5U);
AnnaBridge 189:f392fc9709a3 311
AnnaBridge 188:bcfe06ba3d64 312 status = Cy_SysClk_PeriphSetFracDivider(CY_SYSCLK_DIV_16_5_BIT,
AnnaBridge 188:bcfe06ba3d64 313 obj->div_num,
AnnaBridge 189:f392fc9709a3 314 FRACT_DIV_INT(divider),
AnnaBridge 189:f392fc9709a3 315 FRACT_DIV_FARCT(divider));
AnnaBridge 189:f392fc9709a3 316 } else {
AnnaBridge 189:f392fc9709a3 317 /* Get integer divider */
AnnaBridge 188:bcfe06ba3d64 318 status = Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_16_BIT,
AnnaBridge 188:bcfe06ba3d64 319 obj->div_num,
AnnaBridge 188:bcfe06ba3d64 320 divider_value(baudrate * UART_OVERSAMPLE, 0));
AnnaBridge 188:bcfe06ba3d64 321 }
AnnaBridge 189:f392fc9709a3 322
AnnaBridge 189:f392fc9709a3 323 Cy_SysClk_PeriphEnableDivider(obj->div_type, obj->div_num);
AnnaBridge 188:bcfe06ba3d64 324 }
AnnaBridge 189:f392fc9709a3 325
AnnaBridge 188:bcfe06ba3d64 326 return status;
AnnaBridge 188:bcfe06ba3d64 327 }
AnnaBridge 188:bcfe06ba3d64 328
AnnaBridge 189:f392fc9709a3 329
AnnaBridge 189:f392fc9709a3 330 /** Initializes i/o pins for UART tx/rx.
AnnaBridge 189:f392fc9709a3 331 *
AnnaBridge 189:f392fc9709a3 332 * @param obj The serial object
AnnaBridge 188:bcfe06ba3d64 333 */
AnnaBridge 188:bcfe06ba3d64 334 static void serial_init_pins(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 335 {
AnnaBridge 189:f392fc9709a3 336 if ((cy_reserve_io_pin(obj->pin_tx) || cy_reserve_io_pin(obj->pin_rx))
AnnaBridge 189:f392fc9709a3 337 && !obj->already_reserved) {
AnnaBridge 188:bcfe06ba3d64 338 error("Serial TX/RX pin reservation conflict.");
AnnaBridge 188:bcfe06ba3d64 339 }
AnnaBridge 189:f392fc9709a3 340
AnnaBridge 189:f392fc9709a3 341 pin_function(obj->pin_tx, pinmap_function(obj->pin_tx, PinMap_UART_TX));
AnnaBridge 189:f392fc9709a3 342 pin_function(obj->pin_rx, pinmap_function(obj->pin_rx, PinMap_UART_RX));
AnnaBridge 188:bcfe06ba3d64 343 }
AnnaBridge 188:bcfe06ba3d64 344
AnnaBridge 189:f392fc9709a3 345
AnnaBridge 189:f392fc9709a3 346 /** Initializes i/o pins for UART flow control
AnnaBridge 189:f392fc9709a3 347 *
AnnaBridge 189:f392fc9709a3 348 * @param obj The serial object
AnnaBridge 188:bcfe06ba3d64 349 */
AnnaBridge 188:bcfe06ba3d64 350 static void serial_init_flow_pins(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 351 {
AnnaBridge 188:bcfe06ba3d64 352 if (obj->pin_rts != NC) {
AnnaBridge 189:f392fc9709a3 353 if ((0 != cy_reserve_io_pin(obj->pin_rts)) && !obj->already_reserved) {
AnnaBridge 188:bcfe06ba3d64 354 error("Serial RTS pin reservation conflict.");
AnnaBridge 188:bcfe06ba3d64 355 }
AnnaBridge 189:f392fc9709a3 356 pin_function(obj->pin_rts, pinmap_function(obj->pin_rts, PinMap_UART_RTS));
AnnaBridge 188:bcfe06ba3d64 357 }
AnnaBridge 188:bcfe06ba3d64 358
AnnaBridge 188:bcfe06ba3d64 359 if (obj->pin_cts != NC) {
AnnaBridge 189:f392fc9709a3 360 if ((0 != cy_reserve_io_pin(obj->pin_cts)) && !obj->already_reserved) {
AnnaBridge 188:bcfe06ba3d64 361 error("Serial CTS pin reservation conflict.");
AnnaBridge 188:bcfe06ba3d64 362 }
AnnaBridge 189:f392fc9709a3 363 pin_function(obj->pin_cts, pinmap_function(obj->pin_cts, PinMap_UART_CTS));
AnnaBridge 188:bcfe06ba3d64 364 }
AnnaBridge 188:bcfe06ba3d64 365 }
AnnaBridge 188:bcfe06ba3d64 366
AnnaBridge 188:bcfe06ba3d64 367
AnnaBridge 189:f392fc9709a3 368 /** Initializes and enables UART/SCB.
AnnaBridge 189:f392fc9709a3 369 *
AnnaBridge 189:f392fc9709a3 370 * @param obj The serial object
AnnaBridge 188:bcfe06ba3d64 371 */
AnnaBridge 188:bcfe06ba3d64 372 static void serial_init_peripheral(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 373 {
AnnaBridge 188:bcfe06ba3d64 374 cy_stc_scb_uart_config_t uart_config = default_uart_config;
AnnaBridge 188:bcfe06ba3d64 375
AnnaBridge 189:f392fc9709a3 376 uart_config.dataWidth = obj->data_width;
AnnaBridge 189:f392fc9709a3 377 uart_config.parity = obj->parity;
AnnaBridge 189:f392fc9709a3 378 uart_config.stopBits = obj->stop_bits;
AnnaBridge 189:f392fc9709a3 379 uart_config.enableCts = (obj->pin_cts != NC);
AnnaBridge 188:bcfe06ba3d64 380
AnnaBridge 188:bcfe06ba3d64 381 Cy_SCB_UART_Init(obj->base, &uart_config, NULL);
AnnaBridge 188:bcfe06ba3d64 382 Cy_SCB_UART_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 383 }
AnnaBridge 188:bcfe06ba3d64 384
AnnaBridge 189:f392fc9709a3 385
AnnaBridge 189:f392fc9709a3 386 #if DEVICE_SLEEP && DEVICE_LPTICKER && SERIAL_PM_CALLBACK_ENABLED
AnnaBridge 188:bcfe06ba3d64 387 static cy_en_syspm_status_t serial_pm_callback(cy_stc_syspm_callback_params_t *params)
AnnaBridge 188:bcfe06ba3d64 388 {
AnnaBridge 188:bcfe06ba3d64 389 serial_obj_t *obj = (serial_obj_t *)params->context;
AnnaBridge 188:bcfe06ba3d64 390 cy_en_syspm_status_t status = CY_SYSPM_FAIL;
AnnaBridge 188:bcfe06ba3d64 391
AnnaBridge 188:bcfe06ba3d64 392 switch (params->mode) {
AnnaBridge 188:bcfe06ba3d64 393 case CY_SYSPM_CHECK_READY:
AnnaBridge 188:bcfe06ba3d64 394 /* If all data elements are transmitted from the TX FIFO and
AnnaBridge 188:bcfe06ba3d64 395 * shifter and the RX FIFO is empty: the UART is ready to enter
AnnaBridge 188:bcfe06ba3d64 396 * Deep Sleep mode.
AnnaBridge 188:bcfe06ba3d64 397 */
AnnaBridge 188:bcfe06ba3d64 398 if (Cy_SCB_UART_IsTxComplete(obj->base)) {
AnnaBridge 189:f392fc9709a3 399 if (0 == Cy_SCB_UART_GetNumInRxFifo(obj->base)) {
AnnaBridge 188:bcfe06ba3d64 400 /* Disable the UART. The transmitter stops driving the
AnnaBridge 188:bcfe06ba3d64 401 * lines and the receiver stops receiving data until
AnnaBridge 188:bcfe06ba3d64 402 * the UART is enabled.
AnnaBridge 188:bcfe06ba3d64 403 * This happens when the device failed to enter Deep
AnnaBridge 188:bcfe06ba3d64 404 * Sleep or it is awaken from Deep Sleep mode.
AnnaBridge 188:bcfe06ba3d64 405 */
AnnaBridge 188:bcfe06ba3d64 406 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 188:bcfe06ba3d64 407 status = CY_SYSPM_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 408 }
AnnaBridge 188:bcfe06ba3d64 409 }
AnnaBridge 188:bcfe06ba3d64 410 break;
AnnaBridge 188:bcfe06ba3d64 411
AnnaBridge 188:bcfe06ba3d64 412
AnnaBridge 188:bcfe06ba3d64 413 case CY_SYSPM_CHECK_FAIL:
AnnaBridge 188:bcfe06ba3d64 414 /* Enable the UART to operate */
AnnaBridge 188:bcfe06ba3d64 415 Cy_SCB_UART_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 416 status = CY_SYSPM_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 417 break;
AnnaBridge 188:bcfe06ba3d64 418
AnnaBridge 188:bcfe06ba3d64 419 case CY_SYSPM_BEFORE_TRANSITION:
AnnaBridge 188:bcfe06ba3d64 420 status = CY_SYSPM_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 421 break;
AnnaBridge 188:bcfe06ba3d64 422
AnnaBridge 188:bcfe06ba3d64 423 case CY_SYSPM_AFTER_TRANSITION:
AnnaBridge 188:bcfe06ba3d64 424 /* Enable the UART to operate */
AnnaBridge 188:bcfe06ba3d64 425 Cy_SCB_UART_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 426 status = CY_SYSPM_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 427 break;
AnnaBridge 188:bcfe06ba3d64 428
AnnaBridge 188:bcfe06ba3d64 429 default:
AnnaBridge 188:bcfe06ba3d64 430 break;
AnnaBridge 188:bcfe06ba3d64 431 }
AnnaBridge 189:f392fc9709a3 432
AnnaBridge 188:bcfe06ba3d64 433 return status;
AnnaBridge 188:bcfe06ba3d64 434 }
AnnaBridge 189:f392fc9709a3 435 #endif /* (DEVICE_SLEEP && DEVICE_LPTICKER && SERIAL_PM_CALLBACK_ENABLED) */
AnnaBridge 189:f392fc9709a3 436
AnnaBridge 188:bcfe06ba3d64 437
AnnaBridge 188:bcfe06ba3d64 438 void serial_init(serial_t *obj_in, PinName tx, PinName rx)
AnnaBridge 188:bcfe06ba3d64 439 {
AnnaBridge 188:bcfe06ba3d64 440 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 441 bool is_stdio = (tx == CY_STDIO_UART_TX) || (rx == CY_STDIO_UART_RX);
AnnaBridge 189:f392fc9709a3 442 #if !defined(TARGET_CY8CKIT_062_BLE)
AnnaBridge 189:f392fc9709a3 443 bool is_bt = (tx == CY_BT_UART_TX) || (rx == CY_BT_UART_RX);
AnnaBridge 189:f392fc9709a3 444 #else
AnnaBridge 189:f392fc9709a3 445 bool is_bt = false;
AnnaBridge 189:f392fc9709a3 446 #endif
AnnaBridge 188:bcfe06ba3d64 447
AnnaBridge 188:bcfe06ba3d64 448 if (is_stdio && stdio_uart_inited) {
AnnaBridge 188:bcfe06ba3d64 449 memcpy(obj_in, &stdio_uart, sizeof(serial_t));
AnnaBridge 188:bcfe06ba3d64 450 return;
AnnaBridge 189:f392fc9709a3 451 } else if (is_bt && bt_uart_inited) {
AnnaBridge 189:f392fc9709a3 452 memcpy(obj_in, &bt_uart, sizeof(serial_t));
AnnaBridge 189:f392fc9709a3 453 return;
AnnaBridge 189:f392fc9709a3 454 } else {
AnnaBridge 188:bcfe06ba3d64 455 uint32_t uart = pinmap_peripheral(tx, PinMap_UART_TX);
AnnaBridge 188:bcfe06ba3d64 456 uart = pinmap_merge(uart, pinmap_peripheral(rx, PinMap_UART_RX));
AnnaBridge 189:f392fc9709a3 457
AnnaBridge 188:bcfe06ba3d64 458 if (uart != (uint32_t)NC) {
AnnaBridge 189:f392fc9709a3 459 uint32_t serial_id = ((UARTName)uart - UART_0) / (UART_1 - UART_0);
AnnaBridge 189:f392fc9709a3 460
AnnaBridge 189:f392fc9709a3 461 /* Initialize configuration */
AnnaBridge 189:f392fc9709a3 462 obj->base = (CySCB_Type *)uart;
AnnaBridge 189:f392fc9709a3 463 obj->serial_id = serial_id;
AnnaBridge 189:f392fc9709a3 464 obj->clock = CY_PIN_CLOCK(pinmap_function(tx, PinMap_UART_TX));
AnnaBridge 189:f392fc9709a3 465 obj->div_num = CY_INVALID_DIVIDER;
AnnaBridge 189:f392fc9709a3 466 obj->already_reserved = (0 != cy_reserve_scb(obj->serial_id));
AnnaBridge 189:f392fc9709a3 467
AnnaBridge 189:f392fc9709a3 468 obj->pin_tx = tx;
AnnaBridge 189:f392fc9709a3 469 obj->pin_rx = rx;
AnnaBridge 189:f392fc9709a3 470 obj->pin_rts = NC;
AnnaBridge 189:f392fc9709a3 471 obj->pin_cts = NC;
AnnaBridge 189:f392fc9709a3 472
AnnaBridge 188:bcfe06ba3d64 473 obj->data_width = 8;
AnnaBridge 189:f392fc9709a3 474 obj->stop_bits = CY_SCB_UART_STOP_BITS_1;
AnnaBridge 189:f392fc9709a3 475 obj->parity = CY_SCB_UART_PARITY_NONE;
AnnaBridge 189:f392fc9709a3 476
AnnaBridge 189:f392fc9709a3 477 /* Check if resource severed */
AnnaBridge 189:f392fc9709a3 478 if (obj->already_reserved) {
AnnaBridge 189:f392fc9709a3 479 uint32_t map;
AnnaBridge 189:f392fc9709a3 480
AnnaBridge 189:f392fc9709a3 481 /* SCB pins and clocks are connected */
AnnaBridge 189:f392fc9709a3 482
AnnaBridge 189:f392fc9709a3 483 /* Disable block and get it into the default state */
AnnaBridge 189:f392fc9709a3 484 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 189:f392fc9709a3 485 Cy_SCB_UART_DeInit(obj->base);
AnnaBridge 188:bcfe06ba3d64 486
AnnaBridge 189:f392fc9709a3 487 /* Get connected clock */
AnnaBridge 189:f392fc9709a3 488 map = Cy_SysClk_PeriphGetAssignedDivider(obj->clock);
AnnaBridge 189:f392fc9709a3 489 obj->div_num = _FLD2VAL(CY_PERI_CLOCK_CTL_DIV_SEL, map);
AnnaBridge 189:f392fc9709a3 490 obj->div_type = (cy_en_divider_types_t) _FLD2VAL(CY_PERI_CLOCK_CTL_TYPE_SEL, map);
AnnaBridge 189:f392fc9709a3 491 } else {
AnnaBridge 189:f392fc9709a3 492 #if DEVICE_SLEEP && DEVICE_LPTICKER && SERIAL_PM_CALLBACK_ENABLED
AnnaBridge 189:f392fc9709a3 493 /* Register callback once */
AnnaBridge 189:f392fc9709a3 494 obj->pm_callback_handler.callback = serial_pm_callback;
AnnaBridge 189:f392fc9709a3 495 obj->pm_callback_handler.type = CY_SYSPM_DEEPSLEEP;
AnnaBridge 189:f392fc9709a3 496 obj->pm_callback_handler.skipMode = 0;
AnnaBridge 189:f392fc9709a3 497 obj->pm_callback_handler.callbackParams = &obj->pm_callback_params;
AnnaBridge 189:f392fc9709a3 498 obj->pm_callback_params.base = obj->base;
AnnaBridge 189:f392fc9709a3 499 obj->pm_callback_params.context = obj;
AnnaBridge 189:f392fc9709a3 500
AnnaBridge 189:f392fc9709a3 501 if (!Cy_SysPm_RegisterCallback(&obj->pm_callback_handler)) {
AnnaBridge 189:f392fc9709a3 502 error("PM callback registration failed!");
AnnaBridge 189:f392fc9709a3 503 }
AnnaBridge 189:f392fc9709a3 504 #endif /* (DEVICE_SLEEP && DEVICE_LPTICKER && SERIAL_PM_CALLBACK_ENABLED) */
AnnaBridge 189:f392fc9709a3 505 }
AnnaBridge 189:f392fc9709a3 506
AnnaBridge 189:f392fc9709a3 507 /* Configure hardware resources */
AnnaBridge 188:bcfe06ba3d64 508 serial_init_clock(obj, UART_DEFAULT_BAUDRATE);
AnnaBridge 189:f392fc9709a3 509 serial_init_pins(obj);
AnnaBridge 188:bcfe06ba3d64 510 serial_init_peripheral(obj);
AnnaBridge 189:f392fc9709a3 511
AnnaBridge 188:bcfe06ba3d64 512 if (is_stdio) {
AnnaBridge 188:bcfe06ba3d64 513 memcpy(&stdio_uart, obj_in, sizeof(serial_t));
AnnaBridge 188:bcfe06ba3d64 514 stdio_uart_inited = true;
AnnaBridge 189:f392fc9709a3 515 } else if (is_bt) {
AnnaBridge 189:f392fc9709a3 516 memcpy(&bt_uart, obj_in, sizeof(serial_t));
AnnaBridge 189:f392fc9709a3 517 bt_uart_inited = true;
AnnaBridge 188:bcfe06ba3d64 518 }
AnnaBridge 188:bcfe06ba3d64 519 } else {
AnnaBridge 188:bcfe06ba3d64 520 error("Serial pinout mismatch. Requested pins Rx and Tx can't be used for the same Serial communication.");
AnnaBridge 188:bcfe06ba3d64 521 }
AnnaBridge 188:bcfe06ba3d64 522 }
AnnaBridge 188:bcfe06ba3d64 523 }
AnnaBridge 188:bcfe06ba3d64 524
AnnaBridge 189:f392fc9709a3 525
AnnaBridge 189:f392fc9709a3 526 void serial_free(serial_t *obj)
AnnaBridge 189:f392fc9709a3 527 {
AnnaBridge 189:f392fc9709a3 528 error("This function is not supported.");
AnnaBridge 189:f392fc9709a3 529 }
AnnaBridge 189:f392fc9709a3 530
AnnaBridge 189:f392fc9709a3 531
AnnaBridge 188:bcfe06ba3d64 532 void serial_baud(serial_t *obj_in, int baudrate)
AnnaBridge 188:bcfe06ba3d64 533 {
AnnaBridge 188:bcfe06ba3d64 534 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 535
AnnaBridge 188:bcfe06ba3d64 536 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 188:bcfe06ba3d64 537 serial_init_clock(obj, baudrate);
AnnaBridge 188:bcfe06ba3d64 538 Cy_SCB_UART_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 539 }
AnnaBridge 188:bcfe06ba3d64 540
AnnaBridge 189:f392fc9709a3 541
AnnaBridge 188:bcfe06ba3d64 542 void serial_format(serial_t *obj_in, int data_bits, SerialParity parity, int stop_bits)
AnnaBridge 188:bcfe06ba3d64 543 {
AnnaBridge 188:bcfe06ba3d64 544 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 545
AnnaBridge 188:bcfe06ba3d64 546 if ((data_bits >= 5) && (data_bits <= 9)) {
AnnaBridge 188:bcfe06ba3d64 547 obj->data_width = data_bits;
AnnaBridge 188:bcfe06ba3d64 548 }
AnnaBridge 188:bcfe06ba3d64 549
AnnaBridge 188:bcfe06ba3d64 550 switch (parity) {
AnnaBridge 188:bcfe06ba3d64 551 case ParityNone:
AnnaBridge 188:bcfe06ba3d64 552 obj->parity = CY_SCB_UART_PARITY_NONE;
AnnaBridge 188:bcfe06ba3d64 553 break;
AnnaBridge 188:bcfe06ba3d64 554 case ParityOdd:
AnnaBridge 188:bcfe06ba3d64 555 obj->parity = CY_SCB_UART_PARITY_ODD;
AnnaBridge 188:bcfe06ba3d64 556 break;
AnnaBridge 188:bcfe06ba3d64 557 case ParityEven:
AnnaBridge 188:bcfe06ba3d64 558 obj->parity = CY_SCB_UART_PARITY_EVEN;
AnnaBridge 188:bcfe06ba3d64 559 break;
AnnaBridge 188:bcfe06ba3d64 560 case ParityForced1:
AnnaBridge 188:bcfe06ba3d64 561 case ParityForced0:
AnnaBridge 189:f392fc9709a3 562 error("Serial parity mode not supported!");
AnnaBridge 188:bcfe06ba3d64 563 break;
AnnaBridge 188:bcfe06ba3d64 564 }
AnnaBridge 188:bcfe06ba3d64 565
AnnaBridge 188:bcfe06ba3d64 566 switch (stop_bits) {
AnnaBridge 188:bcfe06ba3d64 567 case 1:
AnnaBridge 188:bcfe06ba3d64 568 obj->stop_bits = CY_SCB_UART_STOP_BITS_1;
AnnaBridge 188:bcfe06ba3d64 569 break;
AnnaBridge 188:bcfe06ba3d64 570 case 2:
AnnaBridge 188:bcfe06ba3d64 571 obj->stop_bits = CY_SCB_UART_STOP_BITS_2;
AnnaBridge 188:bcfe06ba3d64 572 break;
AnnaBridge 188:bcfe06ba3d64 573 case 3:
AnnaBridge 188:bcfe06ba3d64 574 obj->stop_bits = CY_SCB_UART_STOP_BITS_3;
AnnaBridge 188:bcfe06ba3d64 575 break;
AnnaBridge 188:bcfe06ba3d64 576 case 4:
AnnaBridge 188:bcfe06ba3d64 577 obj->stop_bits = CY_SCB_UART_STOP_BITS_4;
AnnaBridge 188:bcfe06ba3d64 578 break;
AnnaBridge 188:bcfe06ba3d64 579 }
AnnaBridge 188:bcfe06ba3d64 580
AnnaBridge 188:bcfe06ba3d64 581 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 188:bcfe06ba3d64 582 serial_init_peripheral(obj);
AnnaBridge 189:f392fc9709a3 583 /* SCB is enabled at the and of serial_init_peripheral() call */
AnnaBridge 188:bcfe06ba3d64 584 }
AnnaBridge 188:bcfe06ba3d64 585
AnnaBridge 189:f392fc9709a3 586
AnnaBridge 188:bcfe06ba3d64 587 void serial_putc(serial_t *obj_in, int c)
AnnaBridge 188:bcfe06ba3d64 588 {
AnnaBridge 188:bcfe06ba3d64 589 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 590
AnnaBridge 189:f392fc9709a3 591 while (0 == serial_writable(obj_in)) {
AnnaBridge 189:f392fc9709a3 592 /* There is an entry to be written */
AnnaBridge 188:bcfe06ba3d64 593 }
AnnaBridge 189:f392fc9709a3 594
AnnaBridge 189:f392fc9709a3 595 Cy_SCB_WriteTxFifo(obj->base, (uint32_t) c);
AnnaBridge 188:bcfe06ba3d64 596 }
AnnaBridge 188:bcfe06ba3d64 597
AnnaBridge 188:bcfe06ba3d64 598 int serial_getc(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 599 {
AnnaBridge 188:bcfe06ba3d64 600 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 601
AnnaBridge 189:f392fc9709a3 602 while (0 == serial_readable(obj_in)) {
AnnaBridge 189:f392fc9709a3 603 /* There is an item to be read */
AnnaBridge 188:bcfe06ba3d64 604 }
AnnaBridge 189:f392fc9709a3 605
AnnaBridge 188:bcfe06ba3d64 606 return Cy_SCB_UART_Get(obj->base);
AnnaBridge 188:bcfe06ba3d64 607 }
AnnaBridge 188:bcfe06ba3d64 608
AnnaBridge 189:f392fc9709a3 609
AnnaBridge 188:bcfe06ba3d64 610 int serial_readable(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 611 {
AnnaBridge 188:bcfe06ba3d64 612 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 613 return Cy_SCB_GetNumInRxFifo(obj->base);
AnnaBridge 188:bcfe06ba3d64 614 }
AnnaBridge 188:bcfe06ba3d64 615
AnnaBridge 189:f392fc9709a3 616
AnnaBridge 188:bcfe06ba3d64 617 int serial_writable(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 618 {
AnnaBridge 188:bcfe06ba3d64 619 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 620 return (Cy_SCB_GetFifoSize(obj->base) != Cy_SCB_GetNumInTxFifo(obj->base));
AnnaBridge 188:bcfe06ba3d64 621 }
AnnaBridge 188:bcfe06ba3d64 622
AnnaBridge 189:f392fc9709a3 623
AnnaBridge 188:bcfe06ba3d64 624 void serial_clear(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 625 {
AnnaBridge 188:bcfe06ba3d64 626 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 627
AnnaBridge 189:f392fc9709a3 628 /* The hardware FIFOs and statuses are cleared when SCB is disabled */
AnnaBridge 188:bcfe06ba3d64 629 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 188:bcfe06ba3d64 630 serial_init_peripheral(obj);
AnnaBridge 189:f392fc9709a3 631 /* SCB is enabled at the and of serial_init_peripheral() call */
AnnaBridge 188:bcfe06ba3d64 632 }
AnnaBridge 188:bcfe06ba3d64 633
AnnaBridge 189:f392fc9709a3 634
AnnaBridge 188:bcfe06ba3d64 635 void serial_break_set(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 636 {
AnnaBridge 188:bcfe06ba3d64 637 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 638
AnnaBridge 188:bcfe06ba3d64 639 /* Cypress SCB does not support transmitting break directly.
AnnaBridge 188:bcfe06ba3d64 640 * We emulate functionality by switching TX pin to GPIO mode.
AnnaBridge 188:bcfe06ba3d64 641 */
AnnaBridge 188:bcfe06ba3d64 642 GPIO_PRT_Type *port_tx = Cy_GPIO_PortToAddr(CY_PORT(obj->pin_tx));
AnnaBridge 188:bcfe06ba3d64 643 Cy_GPIO_Pin_FastInit(port_tx, CY_PIN(obj->pin_tx), CY_GPIO_DM_STRONG_IN_OFF, 0, HSIOM_SEL_GPIO);
AnnaBridge 188:bcfe06ba3d64 644 Cy_GPIO_Write(port_tx, CY_PIN(obj->pin_tx), 0);
AnnaBridge 188:bcfe06ba3d64 645 }
AnnaBridge 188:bcfe06ba3d64 646
AnnaBridge 189:f392fc9709a3 647
AnnaBridge 188:bcfe06ba3d64 648 void serial_break_clear(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 649 {
AnnaBridge 188:bcfe06ba3d64 650 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 651
AnnaBridge 188:bcfe06ba3d64 652 /* Connect TX pin back to SCB, see a comment in serial_break_set() above */
AnnaBridge 188:bcfe06ba3d64 653 GPIO_PRT_Type *port_tx = Cy_GPIO_PortToAddr(CY_PORT(obj->pin_tx));
AnnaBridge 188:bcfe06ba3d64 654 int tx_function = pinmap_function(obj->pin_tx, PinMap_UART_TX);
AnnaBridge 188:bcfe06ba3d64 655 Cy_GPIO_Pin_FastInit(port_tx, CY_PIN(obj->pin_tx), CY_GPIO_DM_STRONG_IN_OFF, 0, CY_PIN_HSIOM(tx_function));
AnnaBridge 188:bcfe06ba3d64 656 }
AnnaBridge 188:bcfe06ba3d64 657
AnnaBridge 189:f392fc9709a3 658
AnnaBridge 189:f392fc9709a3 659 void serial_pinout_tx(PinName tx)
AnnaBridge 189:f392fc9709a3 660 {
AnnaBridge 189:f392fc9709a3 661 error("This function is not supported.");
AnnaBridge 189:f392fc9709a3 662 }
AnnaBridge 189:f392fc9709a3 663
AnnaBridge 189:f392fc9709a3 664
AnnaBridge 188:bcfe06ba3d64 665 void serial_set_flow_control(serial_t *obj_in, FlowControl type, PinName rxflow, PinName txflow)
AnnaBridge 188:bcfe06ba3d64 666 {
AnnaBridge 188:bcfe06ba3d64 667 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 668
AnnaBridge 189:f392fc9709a3 669 /* Do not perform pins reservation second time for the same pins */
AnnaBridge 189:f392fc9709a3 670 if ((obj->pin_rts == rxflow) && (obj->pin_cts == txflow))
AnnaBridge 189:f392fc9709a3 671 return;
AnnaBridge 189:f392fc9709a3 672
AnnaBridge 188:bcfe06ba3d64 673 Cy_SCB_UART_Disable(obj->base, NULL);
AnnaBridge 188:bcfe06ba3d64 674
AnnaBridge 188:bcfe06ba3d64 675 switch (type) {
AnnaBridge 188:bcfe06ba3d64 676 case FlowControlNone:
AnnaBridge 188:bcfe06ba3d64 677 obj->pin_rts = NC;
AnnaBridge 188:bcfe06ba3d64 678 obj->pin_cts = NC;
AnnaBridge 188:bcfe06ba3d64 679 break;
AnnaBridge 188:bcfe06ba3d64 680 case FlowControlRTS:
AnnaBridge 188:bcfe06ba3d64 681 obj->pin_rts = rxflow;
AnnaBridge 188:bcfe06ba3d64 682 obj->pin_cts = NC;
AnnaBridge 188:bcfe06ba3d64 683 break;
AnnaBridge 188:bcfe06ba3d64 684 case FlowControlCTS:
AnnaBridge 188:bcfe06ba3d64 685 obj->pin_rts = NC;
AnnaBridge 188:bcfe06ba3d64 686 obj->pin_cts = txflow;
AnnaBridge 188:bcfe06ba3d64 687 break;
AnnaBridge 188:bcfe06ba3d64 688 case FlowControlRTSCTS:
AnnaBridge 188:bcfe06ba3d64 689 obj->pin_rts = rxflow;
AnnaBridge 188:bcfe06ba3d64 690 obj->pin_cts = txflow;
AnnaBridge 188:bcfe06ba3d64 691 break;
AnnaBridge 188:bcfe06ba3d64 692 }
AnnaBridge 188:bcfe06ba3d64 693
AnnaBridge 189:f392fc9709a3 694 serial_init_flow_pins(obj);
AnnaBridge 188:bcfe06ba3d64 695 serial_init_peripheral(obj);
AnnaBridge 188:bcfe06ba3d64 696 }
AnnaBridge 188:bcfe06ba3d64 697
AnnaBridge 189:f392fc9709a3 698
AnnaBridge 188:bcfe06ba3d64 699 #if DEVICE_SERIAL_ASYNCH
AnnaBridge 188:bcfe06ba3d64 700
AnnaBridge 188:bcfe06ba3d64 701 void serial_irq_handler(serial_t *obj_in, uart_irq_handler handler, uint32_t id)
AnnaBridge 188:bcfe06ba3d64 702 {
AnnaBridge 188:bcfe06ba3d64 703 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 704 irq_info_t *info = &irq_info[obj->serial_id];
AnnaBridge 188:bcfe06ba3d64 705
AnnaBridge 188:bcfe06ba3d64 706 if (info->irqn != unconnected_IRQn) {
AnnaBridge 189:f392fc9709a3 707 /* Seccessful serial_irq_setup_channel enables interrupt in NVIC */
AnnaBridge 188:bcfe06ba3d64 708 NVIC_DisableIRQ(info->irqn);
AnnaBridge 188:bcfe06ba3d64 709 }
AnnaBridge 189:f392fc9709a3 710
AnnaBridge 188:bcfe06ba3d64 711 info->handler = handler;
AnnaBridge 188:bcfe06ba3d64 712 info->id_arg = id;
AnnaBridge 189:f392fc9709a3 713
AnnaBridge 189:f392fc9709a3 714 if (0 != serial_irq_setup_channel(obj)) {
AnnaBridge 189:f392fc9709a3 715 error("Interrupt setup failed.");
AnnaBridge 189:f392fc9709a3 716 }
AnnaBridge 188:bcfe06ba3d64 717 }
AnnaBridge 188:bcfe06ba3d64 718
AnnaBridge 189:f392fc9709a3 719
AnnaBridge 188:bcfe06ba3d64 720 void serial_irq_set(serial_t *obj_in, SerialIrq irq, uint32_t enable)
AnnaBridge 188:bcfe06ba3d64 721 {
AnnaBridge 188:bcfe06ba3d64 722 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 723
AnnaBridge 188:bcfe06ba3d64 724 switch (irq) {
AnnaBridge 189:f392fc9709a3 725 case RxIrq: /* RxIrq for receive (buffer is not empty) */
AnnaBridge 189:f392fc9709a3 726 Cy_SCB_SetRxInterruptMask(obj->base, (0 != enable) ? CY_SCB_RX_INTR_NOT_EMPTY : 0);
AnnaBridge 188:bcfe06ba3d64 727 break;
AnnaBridge 189:f392fc9709a3 728
AnnaBridge 189:f392fc9709a3 729 case TxIrq: /* TxIrq for transmit (buffer is empty) */
AnnaBridge 189:f392fc9709a3 730 Cy_SCB_SetTxInterruptMask(obj->base, (0 != enable) ? CY_SCB_UART_TX_EMPTY : 0);
AnnaBridge 188:bcfe06ba3d64 731 break;
AnnaBridge 188:bcfe06ba3d64 732 }
AnnaBridge 188:bcfe06ba3d64 733 }
AnnaBridge 188:bcfe06ba3d64 734
AnnaBridge 189:f392fc9709a3 735
AnnaBridge 189:f392fc9709a3 736 int serial_tx_asynch(serial_t *obj_in, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
AnnaBridge 189:f392fc9709a3 737 {
AnnaBridge 189:f392fc9709a3 738 (void) tx_width; /* Deprecated argument */
AnnaBridge 189:f392fc9709a3 739 (void) hint; /* At the moment we do not support DMA transfers, so this parameter gets ignored. */
AnnaBridge 189:f392fc9709a3 740
AnnaBridge 189:f392fc9709a3 741 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 742 const uint8_t *p_buf = tx;
AnnaBridge 189:f392fc9709a3 743
AnnaBridge 189:f392fc9709a3 744 if (obj->tx_pending || (tx_length == 0)) {
AnnaBridge 189:f392fc9709a3 745 return 0;
AnnaBridge 189:f392fc9709a3 746 }
AnnaBridge 189:f392fc9709a3 747
AnnaBridge 189:f392fc9709a3 748 /* Configure interrupt handler */
AnnaBridge 189:f392fc9709a3 749 obj->async_handler = (cy_israddress)handler;
AnnaBridge 189:f392fc9709a3 750 if (serial_irq_setup_channel(obj) < 0) {
AnnaBridge 189:f392fc9709a3 751 return 0;
AnnaBridge 189:f392fc9709a3 752 }
AnnaBridge 189:f392fc9709a3 753
AnnaBridge 189:f392fc9709a3 754 /* Clear TX_DONE interrupt it might remain set from previous call */
AnnaBridge 189:f392fc9709a3 755 Cy_SCB_ClearTxInterrupt(obj->base, CY_SCB_UART_TX_DONE | CY_SCB_TX_INTR_LEVEL);
AnnaBridge 189:f392fc9709a3 756
AnnaBridge 189:f392fc9709a3 757 /* Write as much as possible into the FIFO first */
AnnaBridge 189:f392fc9709a3 758 while ((tx_length > 0) && (0 != Cy_SCB_UART_Put(obj->base, *p_buf))) {
AnnaBridge 189:f392fc9709a3 759 ++p_buf;
AnnaBridge 189:f392fc9709a3 760 --tx_length;
AnnaBridge 189:f392fc9709a3 761 }
AnnaBridge 189:f392fc9709a3 762
AnnaBridge 189:f392fc9709a3 763 if (tx_length > 0) {
AnnaBridge 189:f392fc9709a3 764 obj->tx_pending = true;
AnnaBridge 189:f392fc9709a3 765 obj->tx_events = event;
AnnaBridge 189:f392fc9709a3 766 obj_in->tx_buff.pos = 0;
AnnaBridge 189:f392fc9709a3 767 obj_in->tx_buff.buffer = (void *)p_buf;
AnnaBridge 189:f392fc9709a3 768 obj_in->tx_buff.length = tx_length;
AnnaBridge 189:f392fc9709a3 769
AnnaBridge 189:f392fc9709a3 770 /* Enable LEVEL interrupt to complete transmission */
AnnaBridge 189:f392fc9709a3 771 Cy_SCB_SetTxInterruptMask(obj->base, CY_SCB_TX_INTR_LEVEL);
AnnaBridge 189:f392fc9709a3 772 } else {
AnnaBridge 189:f392fc9709a3 773 /* Enable DONE interrupt to signal completing of the transmission */
AnnaBridge 189:f392fc9709a3 774 Cy_SCB_SetTxInterruptMask(obj->base, CY_SCB_UART_TX_DONE);
AnnaBridge 189:f392fc9709a3 775 }
AnnaBridge 189:f392fc9709a3 776
AnnaBridge 189:f392fc9709a3 777 return tx_length;
AnnaBridge 189:f392fc9709a3 778 }
AnnaBridge 189:f392fc9709a3 779
AnnaBridge 189:f392fc9709a3 780
AnnaBridge 189:f392fc9709a3 781 void serial_rx_asynch(serial_t *obj_in, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
AnnaBridge 189:f392fc9709a3 782 {
AnnaBridge 189:f392fc9709a3 783 (void) rx_width; /* Deprecated argument */
AnnaBridge 189:f392fc9709a3 784 (void) hint; /* At the moment we do not support DMA transfers, so this parameter gets ignored. */
AnnaBridge 189:f392fc9709a3 785
AnnaBridge 189:f392fc9709a3 786 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 787
AnnaBridge 189:f392fc9709a3 788 if (obj->rx_pending || (rx_length == 0)) {
AnnaBridge 189:f392fc9709a3 789 return;
AnnaBridge 189:f392fc9709a3 790 }
AnnaBridge 189:f392fc9709a3 791
AnnaBridge 189:f392fc9709a3 792 /* Configure interrupt handler */
AnnaBridge 189:f392fc9709a3 793 obj->async_handler = (cy_israddress)handler;
AnnaBridge 189:f392fc9709a3 794 if (serial_irq_setup_channel(obj) < 0) {
AnnaBridge 189:f392fc9709a3 795 return;
AnnaBridge 189:f392fc9709a3 796 }
AnnaBridge 189:f392fc9709a3 797
AnnaBridge 189:f392fc9709a3 798 obj->rx_pending = true;
AnnaBridge 189:f392fc9709a3 799 obj->rx_events = event;
AnnaBridge 189:f392fc9709a3 800 obj_in->char_match = char_match;
AnnaBridge 189:f392fc9709a3 801 obj_in->char_found = false;
AnnaBridge 189:f392fc9709a3 802 obj_in->rx_buff.pos = 0;
AnnaBridge 189:f392fc9709a3 803 obj_in->rx_buff.buffer = rx;
AnnaBridge 189:f392fc9709a3 804 obj_in->rx_buff.length = rx_length;
AnnaBridge 189:f392fc9709a3 805
AnnaBridge 189:f392fc9709a3 806 /* Enable interrupts to start receiving */
AnnaBridge 189:f392fc9709a3 807 Cy_SCB_SetRxInterruptMask(obj->base, UART_RX_INTR_MASK);
AnnaBridge 189:f392fc9709a3 808 }
AnnaBridge 189:f392fc9709a3 809
AnnaBridge 189:f392fc9709a3 810
AnnaBridge 189:f392fc9709a3 811 uint8_t serial_tx_active(serial_t *obj)
AnnaBridge 189:f392fc9709a3 812 {
AnnaBridge 189:f392fc9709a3 813 return obj->serial.tx_pending;
AnnaBridge 189:f392fc9709a3 814 }
AnnaBridge 189:f392fc9709a3 815
AnnaBridge 189:f392fc9709a3 816
AnnaBridge 189:f392fc9709a3 817 uint8_t serial_rx_active(serial_t *obj)
AnnaBridge 189:f392fc9709a3 818 {
AnnaBridge 189:f392fc9709a3 819 return obj->serial.rx_pending;
AnnaBridge 189:f392fc9709a3 820 }
AnnaBridge 189:f392fc9709a3 821
AnnaBridge 189:f392fc9709a3 822
AnnaBridge 189:f392fc9709a3 823 /** Finishes TX asynchronous transfer: disable TX interrupts and clear
AnnaBridge 189:f392fc9709a3 824 * pending state.
AnnaBridge 189:f392fc9709a3 825 *
AnnaBridge 189:f392fc9709a3 826 * @param obj The serial object
AnnaBridge 189:f392fc9709a3 827 */
AnnaBridge 188:bcfe06ba3d64 828 static void serial_finish_tx_asynch(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 829 {
AnnaBridge 188:bcfe06ba3d64 830 Cy_SCB_SetTxInterruptMask(obj->base, 0);
AnnaBridge 188:bcfe06ba3d64 831 obj->tx_pending = false;
AnnaBridge 188:bcfe06ba3d64 832 }
AnnaBridge 188:bcfe06ba3d64 833
AnnaBridge 189:f392fc9709a3 834
AnnaBridge 189:f392fc9709a3 835 /** Finishes TX asynchronous transfer: disable TX interrupts and clear
AnnaBridge 189:f392fc9709a3 836 * pending state.
AnnaBridge 189:f392fc9709a3 837 *
AnnaBridge 189:f392fc9709a3 838 * @param obj The serial object
AnnaBridge 189:f392fc9709a3 839 */
AnnaBridge 188:bcfe06ba3d64 840 static void serial_finish_rx_asynch(serial_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 841 {
AnnaBridge 188:bcfe06ba3d64 842 Cy_SCB_SetRxInterruptMask(obj->base, 0);
AnnaBridge 188:bcfe06ba3d64 843 obj->rx_pending = false;
AnnaBridge 188:bcfe06ba3d64 844 }
AnnaBridge 188:bcfe06ba3d64 845
AnnaBridge 188:bcfe06ba3d64 846
AnnaBridge 188:bcfe06ba3d64 847 int serial_irq_handler_asynch(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 848 {
AnnaBridge 188:bcfe06ba3d64 849 uint32_t cur_events = 0;
AnnaBridge 188:bcfe06ba3d64 850 uint32_t tx_status;
AnnaBridge 188:bcfe06ba3d64 851 uint32_t rx_status;
AnnaBridge 188:bcfe06ba3d64 852
AnnaBridge 188:bcfe06ba3d64 853 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 854
AnnaBridge 189:f392fc9709a3 855 /* Interrupt cause is TX */
AnnaBridge 189:f392fc9709a3 856 if (0 != (CY_SCB_TX_INTR & Cy_SCB_GetInterruptCause(obj->base))) {
AnnaBridge 188:bcfe06ba3d64 857
AnnaBridge 189:f392fc9709a3 858 /* Get interrupt sources and clear them */
AnnaBridge 189:f392fc9709a3 859 tx_status = Cy_SCB_GetTxInterruptStatusMasked(obj->base);
AnnaBridge 189:f392fc9709a3 860 Cy_SCB_ClearTxInterrupt(obj->base, tx_status);
AnnaBridge 188:bcfe06ba3d64 861
AnnaBridge 189:f392fc9709a3 862 if (0 != (tx_status & CY_SCB_TX_INTR_LEVEL)) {
AnnaBridge 189:f392fc9709a3 863
AnnaBridge 189:f392fc9709a3 864 /* Get current buffer position */
AnnaBridge 189:f392fc9709a3 865 uint8_t *ptr = obj_in->tx_buff.buffer;
AnnaBridge 189:f392fc9709a3 866 ptr += obj_in->tx_buff.pos;
AnnaBridge 188:bcfe06ba3d64 867
AnnaBridge 189:f392fc9709a3 868 /* FIFO has space available for more TX */
AnnaBridge 189:f392fc9709a3 869 while ((obj_in->tx_buff.pos < obj_in->tx_buff.length) &&
AnnaBridge 189:f392fc9709a3 870 (0 != Cy_SCB_UART_Put(obj->base, *ptr))) {
AnnaBridge 189:f392fc9709a3 871 ++ptr;
AnnaBridge 189:f392fc9709a3 872 ++(obj_in->tx_buff.pos);
AnnaBridge 189:f392fc9709a3 873 }
AnnaBridge 189:f392fc9709a3 874
AnnaBridge 189:f392fc9709a3 875 if (obj_in->tx_buff.pos == obj_in->tx_buff.length) {
AnnaBridge 189:f392fc9709a3 876 /* No more bytes to follow; check to see if we need to signal completion */
AnnaBridge 189:f392fc9709a3 877 if (0 != (obj->tx_events & SERIAL_EVENT_TX_COMPLETE)) {
AnnaBridge 189:f392fc9709a3 878 /* Disable TX_LEVEL and enable TX_DONE to get completion event */
AnnaBridge 189:f392fc9709a3 879 Cy_SCB_SetTxInterruptMask(obj->base, CY_SCB_UART_TX_DONE);
AnnaBridge 189:f392fc9709a3 880 } else {
AnnaBridge 189:f392fc9709a3 881 /* Nothing more to do, mark end of transmission */
AnnaBridge 189:f392fc9709a3 882 serial_finish_tx_asynch(obj);
AnnaBridge 189:f392fc9709a3 883 }
AnnaBridge 189:f392fc9709a3 884 }
AnnaBridge 188:bcfe06ba3d64 885 }
AnnaBridge 189:f392fc9709a3 886
AnnaBridge 189:f392fc9709a3 887 if (0 != (tx_status & CY_SCB_TX_INTR_UART_DONE)) {
AnnaBridge 189:f392fc9709a3 888 /* Mark end of the transmission */
AnnaBridge 189:f392fc9709a3 889 serial_finish_tx_asynch(obj);
AnnaBridge 189:f392fc9709a3 890 cur_events |= SERIAL_EVENT_TX_COMPLETE;
AnnaBridge 188:bcfe06ba3d64 891 }
AnnaBridge 188:bcfe06ba3d64 892 }
AnnaBridge 188:bcfe06ba3d64 893
AnnaBridge 189:f392fc9709a3 894 /* Interrupt cause is RX */
AnnaBridge 189:f392fc9709a3 895 if (0 != (CY_SCB_RX_INTR & Cy_SCB_GetInterruptCause(obj->base))) {
AnnaBridge 188:bcfe06ba3d64 896
AnnaBridge 189:f392fc9709a3 897 /* Get interrupt sources and clear them */
AnnaBridge 189:f392fc9709a3 898 rx_status = Cy_SCB_GetRxInterruptStatusMasked(obj->base);
AnnaBridge 189:f392fc9709a3 899 Cy_SCB_ClearRxInterrupt(obj->base, rx_status);
AnnaBridge 188:bcfe06ba3d64 900
AnnaBridge 189:f392fc9709a3 901 if (0 != (rx_status & CY_SCB_RX_INTR_OVERFLOW)) {
AnnaBridge 189:f392fc9709a3 902 cur_events |= SERIAL_EVENT_RX_OVERRUN_ERROR;
AnnaBridge 189:f392fc9709a3 903 }
AnnaBridge 188:bcfe06ba3d64 904
AnnaBridge 189:f392fc9709a3 905 if (0 != (rx_status & CY_SCB_RX_INTR_UART_FRAME_ERROR)) {
AnnaBridge 189:f392fc9709a3 906 cur_events |= SERIAL_EVENT_RX_FRAMING_ERROR;
AnnaBridge 189:f392fc9709a3 907 }
AnnaBridge 189:f392fc9709a3 908
AnnaBridge 189:f392fc9709a3 909 if (0 != (rx_status & CY_SCB_RX_INTR_UART_PARITY_ERROR)) {
AnnaBridge 189:f392fc9709a3 910 cur_events |= SERIAL_EVENT_RX_PARITY_ERROR;
AnnaBridge 189:f392fc9709a3 911 }
AnnaBridge 189:f392fc9709a3 912
AnnaBridge 189:f392fc9709a3 913 if (0 != (rx_status & CY_SCB_RX_INTR_LEVEL)) {
AnnaBridge 188:bcfe06ba3d64 914
AnnaBridge 189:f392fc9709a3 915 /* Get current buffer position */
AnnaBridge 189:f392fc9709a3 916 uint8_t *ptr = obj_in->rx_buff.buffer;
AnnaBridge 189:f392fc9709a3 917 ptr += obj_in->rx_buff.pos;
AnnaBridge 189:f392fc9709a3 918
AnnaBridge 189:f392fc9709a3 919 /* Get data from the RX FIFO */
AnnaBridge 189:f392fc9709a3 920 while (obj_in->rx_buff.pos < obj_in->rx_buff.length) {
AnnaBridge 189:f392fc9709a3 921 uint32_t c = Cy_SCB_UART_Get(obj->base);
AnnaBridge 189:f392fc9709a3 922
AnnaBridge 189:f392fc9709a3 923 if (c == CY_SCB_UART_RX_NO_DATA) {
AnnaBridge 189:f392fc9709a3 924 break;
AnnaBridge 189:f392fc9709a3 925 }
AnnaBridge 188:bcfe06ba3d64 926
AnnaBridge 189:f392fc9709a3 927 *ptr++ = (uint8_t) c;
AnnaBridge 189:f392fc9709a3 928 ++(obj_in->rx_buff.pos);
AnnaBridge 189:f392fc9709a3 929
AnnaBridge 189:f392fc9709a3 930 /* Check for character match condition */
AnnaBridge 189:f392fc9709a3 931 if (obj_in->char_match != SERIAL_RESERVED_CHAR_MATCH) {
AnnaBridge 189:f392fc9709a3 932 if (c == obj_in->char_match) {
AnnaBridge 189:f392fc9709a3 933 obj_in->char_found = true;
AnnaBridge 189:f392fc9709a3 934 cur_events |= SERIAL_EVENT_RX_CHARACTER_MATCH;
AnnaBridge 189:f392fc9709a3 935
AnnaBridge 189:f392fc9709a3 936 /* Clamp RX buffer */
AnnaBridge 189:f392fc9709a3 937 obj_in->rx_buff.length = obj_in->rx_buff.pos;
AnnaBridge 189:f392fc9709a3 938 break;
AnnaBridge 189:f392fc9709a3 939 }
AnnaBridge 188:bcfe06ba3d64 940 }
AnnaBridge 188:bcfe06ba3d64 941 }
AnnaBridge 188:bcfe06ba3d64 942 }
AnnaBridge 189:f392fc9709a3 943
AnnaBridge 189:f392fc9709a3 944 if (obj_in->rx_buff.pos == obj_in->rx_buff.length) {
AnnaBridge 189:f392fc9709a3 945 serial_finish_rx_asynch(obj);
AnnaBridge 189:f392fc9709a3 946 cur_events |= SERIAL_EVENT_RX_COMPLETE;
AnnaBridge 189:f392fc9709a3 947 }
AnnaBridge 188:bcfe06ba3d64 948 }
AnnaBridge 188:bcfe06ba3d64 949
AnnaBridge 189:f392fc9709a3 950 return (cur_events & (obj->tx_events | obj->rx_events));
AnnaBridge 189:f392fc9709a3 951 }
AnnaBridge 188:bcfe06ba3d64 952
AnnaBridge 188:bcfe06ba3d64 953
AnnaBridge 188:bcfe06ba3d64 954 void serial_tx_abort_asynch(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 955 {
AnnaBridge 188:bcfe06ba3d64 956 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 957
AnnaBridge 188:bcfe06ba3d64 958 serial_finish_tx_asynch(obj);
AnnaBridge 188:bcfe06ba3d64 959 Cy_SCB_UART_ClearTxFifo(obj->base);
AnnaBridge 188:bcfe06ba3d64 960 }
AnnaBridge 188:bcfe06ba3d64 961
AnnaBridge 188:bcfe06ba3d64 962 void serial_rx_abort_asynch(serial_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 963 {
AnnaBridge 188:bcfe06ba3d64 964 serial_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 965
AnnaBridge 188:bcfe06ba3d64 966 serial_finish_rx_asynch(obj);
AnnaBridge 188:bcfe06ba3d64 967 Cy_SCB_UART_ClearRxFifo(obj->base);
AnnaBridge 189:f392fc9709a3 968 Cy_SCB_ClearRxInterrupt(obj->base, CY_SCB_UART_RX_INTR_MASK);
AnnaBridge 188:bcfe06ba3d64 969 }
AnnaBridge 188:bcfe06ba3d64 970
AnnaBridge 189:f392fc9709a3 971 #endif /* DEVICE_SERIAL_ASYNCH */
AnnaBridge 188:bcfe06ba3d64 972
AnnaBridge 189:f392fc9709a3 973 #endif /* DEVICE_SERIAL */