1 /***************************************************************************//**
2 * \file cy_scb_uart.c
3 * \version 3.20
4 *
5 * Provides UART API implementation of the SCB driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2021 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB))
28 
29 #include "cy_scb_uart.h"
30 
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34 
35 /* Static functions */
36 static void HandleDataReceive (CySCB_Type *base, cy_stc_scb_uart_context_t *context);
37 static void HandleRingBuffer  (CySCB_Type *base, cy_stc_scb_uart_context_t *context);
38 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *context);
39 static uint32_t SelectRxFifoLevel(CySCB_Type const *base);
40 
41 /*******************************************************************************
42 * Function Name: Cy_SCB_UART_SetOverSample
43 ****************************************************************************//**
44 *
45 * Sets oversample bits of UART.
46 *
47 * \param base
48 * The pointer to the UART SCB instance.
49 *
50 * \param overSample
51 * Value of oversample to be set.
52 *
53 * \param context
54 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
55 * by the user. The structure is used during the UART operation for internal
56 * configuration and data retention. The user must not modify anything
57 * in this structure.
58 * User should not pass NULL as pointer to context.
59 *
60 * \return
61 * \ref cy_en_scb_uart_status_t
62 *
63 * \note
64 * Ensure that the SCB block is disabled before calling this function.
65 *
66 * \snippet scb/uart_snippet/main.c UART_SET_OVS
67 *
68 *******************************************************************************/
Cy_SCB_UART_SetOverSample(CySCB_Type * base,uint32_t overSample,cy_stc_scb_uart_context_t * context)69 cy_en_scb_uart_status_t Cy_SCB_UART_SetOverSample(CySCB_Type *base, uint32_t overSample, cy_stc_scb_uart_context_t *context)
70 {
71     CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 10.8', 1, \
72     'Intentional typecast to cy_en_scb_uart_mode_t enum to validate arguments.')
73     if((NULL == base) || (NULL == context) ||
74        ((CY_SCB_UART_IS_OVERSAMPLE_VALID(overSample, ((cy_en_scb_uart_mode_t)_FLD2VAL(SCB_UART_CTRL_MODE,SCB_UART_CTRL(base))), context->irdaEnableLowPowerReceiver)) == false))
75     {
76         return CY_SCB_UART_BAD_PARAM;
77     }
78     CY_MISRA_BLOCK_END('MISRA C-2012 Rule 10.8')
79 
80     uint32_t ovs;
81 
82     if (((uint32_t)CY_SCB_UART_IRDA == _FLD2VAL(SCB_UART_CTRL_MODE,SCB_UART_CTRL(base))) && (!context->irdaEnableLowPowerReceiver))
83     {
84         /* For Normal IrDA mode oversampling is always zero */
85         ovs = 0UL;
86     }
87     else
88     {
89         ovs = overSample - 1UL;
90     }
91 
92     /* Set oversample bits */
93     CY_REG32_CLR_SET(SCB_CTRL(base), SCB_CTRL_OVS, ovs);
94 
95     return CY_SCB_UART_SUCCESS;
96 }
97 
98 /*******************************************************************************
99 * Function Name: Cy_SCB_UART_SetDataWidth
100 ****************************************************************************//**
101 *
102 * Sets datawidth for UART transaction.
103 *
104 * \param base
105 * The pointer to the UART SCB instance.
106 *
107 * \param dataWidth
108 * The width of UART data in the UART transaction.
109 *
110 * \note
111 * Ensure that the SCB block is disabled before calling this function.
112 *
113 * \snippet scb/uart_snippet/main.c UART_SET_DATA_WIDTH
114 *
115 *******************************************************************************/
Cy_SCB_UART_SetDataWidth(CySCB_Type * base,uint32_t dataWidth)116 void Cy_SCB_UART_SetDataWidth(CySCB_Type *base, uint32_t dataWidth)
117 {
118     CY_ASSERT_L2(CY_SCB_UART_IS_DATA_WIDTH_VALID (dataWidth));
119 
120     /* Configure the memory width */
121     Cy_SCB_SetByteMode(base, (dataWidth <= CY_SCB_BYTE_WIDTH));
122 
123     CY_REG32_CLR_SET(SCB_RX_CTRL(base), SCB_RX_CTRL_DATA_WIDTH, (dataWidth - 1UL));
124 
125     CY_REG32_CLR_SET(SCB_TX_CTRL(base), SCB_TX_CTRL_DATA_WIDTH, (dataWidth - 1UL));
126 }
127 
128 /*******************************************************************************
129 * Function Name: Cy_SCB_UART_SetParity
130 ****************************************************************************//**
131 *
132 * Sets parity for UART transaction.
133 *
134 * \param base
135 * The pointer to the UART SCB instance.
136 *
137 * \param parity
138 * The UART parity bit in the UART transaction.
139 *
140 * \note
141 * Ensure that the SCB block is disabled before calling this function.
142 *
143 * \snippet scb/uart_snippet/main.c UART_SET_PARITY
144 *
145 *******************************************************************************/
Cy_SCB_UART_SetParity(CySCB_Type * base,cy_en_scb_uart_parity_t parity)146 void Cy_SCB_UART_SetParity(CySCB_Type *base, cy_en_scb_uart_parity_t parity)
147 {
148     CY_ASSERT_L3(CY_SCB_UART_IS_PARITY_VALID (parity));
149 
150     /* Configure the RX direction with given parameters */
151     CY_REG32_CLR_SET(SCB_UART_RX_CTRL(base), CY_SCB_UART_RX_CTRL_SET_PARITY, (uint32_t) parity);
152 
153     /* Configure the TX direction with given parameters*/
154     CY_REG32_CLR_SET(SCB_UART_TX_CTRL(base), CY_SCB_UART_TX_CTRL_SET_PARITY, (uint32_t) parity);
155 }
156 
157 /*******************************************************************************
158 * Function Name: Cy_SCB_UART_SetStopBits
159 ****************************************************************************//**
160 *
161 * Sets stop bits for UART transaction.
162 *
163 * \param base
164 * The pointer to the UART SCB instance.
165 *
166 * \param stopBits
167 * The number of stop bits in the UART transaction.
168 *
169 * \note
170 * Ensure that the SCB block is disabled before calling this function.
171 *
172 * \snippet scb/uart_snippet/main.c UART_SET_STOP_BITS
173 *
174 *******************************************************************************/
Cy_SCB_UART_SetStopBits(CySCB_Type * base,cy_en_scb_uart_stop_bits_t stopBits)175 void Cy_SCB_UART_SetStopBits(CySCB_Type *base, cy_en_scb_uart_stop_bits_t stopBits)
176 {
177     CY_ASSERT_L3(CY_SCB_UART_IS_STOP_BITS_VALID (stopBits));
178 
179     /* Configure the RX direction with given parameters */
180     CY_REG32_CLR_SET(SCB_UART_RX_CTRL(base), SCB_UART_RX_CTRL_STOP_BITS, ((uint32_t) stopBits) - 1UL);
181 
182     /* Configure the TX direction with given parameters*/
183     CY_REG32_CLR_SET(SCB_UART_TX_CTRL(base), SCB_UART_TX_CTRL_STOP_BITS, ((uint32_t) stopBits) - 1UL);
184 }
185 
186 /*******************************************************************************
187 * Function Name: Cy_SCB_UART_SetDropOnParityError
188 ****************************************************************************//**
189 *
190 * Sets SetDropOnParityError for UART transaction.
191 *
192 * \param base
193 * The pointer to the UART SCB instance.
194 *
195 * \param dropOnParityError
196 * To enable the hardware to drop data in the RX FIFO when a parity error is
197 * detected in the UART transaction.
198 *
199 * \note
200 * Ensure that the SCB block is disabled before calling this function.
201 *
202 * \snippet scb/uart_snippet/main.c UART_SET_DROP_ON_PARITY_ERROR
203 *
204 *******************************************************************************/
Cy_SCB_UART_SetDropOnParityError(CySCB_Type * base,bool dropOnParityError)205 void Cy_SCB_UART_SetDropOnParityError(CySCB_Type *base, bool dropOnParityError)
206 {
207     /* Configure the RX direction with given parameters */
208     CY_REG32_CLR_SET(SCB_UART_RX_CTRL(base), SCB_UART_RX_CTRL_DROP_ON_PARITY_ERROR, dropOnParityError);
209 }
210 
211 /*******************************************************************************
212 * Function Name: Cy_SCB_UART_SetEnableMsbFirst
213 ****************************************************************************//**
214 *
215 * Sets enableMsbFirst for UART transaction.
216 *
217 * \param base
218 * The pointer to the UART SCB instance.
219 *
220 * \param enableMsbFirst
221 * Enables the hardware to shift out data element MSB first;
222 * otherwise, LSB first in the UART transaction.
223 *
224 * \note
225 * Ensure that the SCB block is disabled before calling this function.
226 *
227 * \snippet scb/uart_snippet/main.c UART_SET_ENABLE_MSB_FIRST
228 *
229 *******************************************************************************/
Cy_SCB_UART_SetEnableMsbFirst(CySCB_Type * base,bool enableMsbFirst)230 void Cy_SCB_UART_SetEnableMsbFirst(CySCB_Type *base, bool enableMsbFirst)
231 {
232     /* Configure the RX direction with given parameters */
233     CY_REG32_CLR_SET(SCB_RX_CTRL(base), SCB_RX_CTRL_MSB_FIRST, enableMsbFirst);
234 
235     /* Configure the TX direction with given parameters*/
236     CY_REG32_CLR_SET(SCB_TX_CTRL(base), SCB_TX_CTRL_MSB_FIRST, enableMsbFirst);
237 }
238 
239 /*******************************************************************************
240 * Function Name: Cy_SCB_UART_Init
241 ****************************************************************************//**
242 *
243 * Initializes the SCB for UART operation.
244 *
245 * \param base
246 * The pointer to the UART SCB instance.
247 *
248 * \param config
249 * The pointer to configuration structure \ref cy_stc_scb_uart_config_t.
250 *
251 * \param context
252 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
253 * by the user. The structure is used during the UART operation for internal
254 * configuration and data retention. The user must not modify anything
255 * in this structure.
256 * If only UART \ref group_scb_uart_ll will be used pass NULL as pointer to
257 * context.
258 *
259 * \return
260 * \ref cy_en_scb_uart_status_t
261 *
262 * \note
263 * Ensure that the SCB block is disabled before calling this function.
264 *
265 *******************************************************************************/
Cy_SCB_UART_Init(CySCB_Type * base,cy_stc_scb_uart_config_t const * config,cy_stc_scb_uart_context_t * context)266 cy_en_scb_uart_status_t Cy_SCB_UART_Init(CySCB_Type *base, cy_stc_scb_uart_config_t const *config, cy_stc_scb_uart_context_t *context)
267 {
268     if ((NULL == base) || (NULL == config))
269     {
270         return CY_SCB_UART_BAD_PARAM;
271     }
272 
273     CY_ASSERT_L3(CY_SCB_UART_IS_MODE_VALID     (config->uartMode));
274     CY_ASSERT_L3(CY_SCB_UART_IS_STOP_BITS_VALID(config->stopBits));
275     CY_ASSERT_L3(CY_SCB_UART_IS_PARITY_VALID   (config->parity));
276     CY_ASSERT_L3(CY_SCB_UART_IS_POLARITY_VALID (config->ctsPolarity));
277     CY_ASSERT_L3(CY_SCB_UART_IS_POLARITY_VALID (config->rtsPolarity));
278 
279     CY_ASSERT_L2(CY_SCB_UART_IS_OVERSAMPLE_VALID  (config->oversample, config->uartMode, config->irdaEnableLowPowerReceiver));
280     CY_ASSERT_L2(CY_SCB_UART_IS_DATA_WIDTH_VALID  (config->dataWidth));
281     CY_ASSERT_L2(CY_SCB_UART_IS_ADDRESS_VALID     (config->receiverAddress));
282     CY_ASSERT_L2(CY_SCB_UART_IS_ADDRESS_MASK_VALID(config->receiverAddressMask));
283 
284     CY_ASSERT_L2(CY_SCB_UART_IS_MUTLI_PROC_VALID  (config->enableMutliProcessorMode, config->uartMode, config->dataWidth, config->parity));
285 
286     CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->rxFifoIntEnableMask, CY_SCB_UART_RX_INTR_MASK));
287     CY_ASSERT_L2(CY_SCB_IS_INTR_VALID(config->txFifoIntEnableMask, CY_SCB_UART_TX_INTR_MASK));
288 
289     uint32_t ovs;
290 
291     if ((CY_SCB_UART_IRDA == config->uartMode) && (!config->irdaEnableLowPowerReceiver))
292     {
293         /* For Normal IrDA mode oversampling is always zero */
294         ovs = 0UL;
295     }
296     else
297     {
298         ovs = (config->oversample - 1UL);
299     }
300 
301     /* Configure the UART interface */
302 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
303     SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, config->acceptAddrInFifo)                      |
304                  _VAL2FLD(SCB_CTRL_MEM_WIDTH, ((config->dataWidth <= CY_SCB_BYTE_WIDTH)? 0UL:1UL))  |
305                  _VAL2FLD(SCB_CTRL_OVS, ovs)                                                        |
306                  _VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_UART);
307 #elif((defined (CY_IP_MXSCB_VERSION) && CY_IP_MXSCB_VERSION==1))
308     SCB_CTRL(base) = _BOOL2FLD(SCB_CTRL_ADDR_ACCEPT, config->acceptAddrInFifo)               |
309                  _BOOL2FLD(SCB_CTRL_BYTE_MODE, (config->dataWidth <= CY_SCB_BYTE_WIDTH)) |
310                  _VAL2FLD(SCB_CTRL_OVS, ovs)                                             |
311                  _VAL2FLD(SCB_CTRL_MODE, CY_SCB_CTRL_MODE_UART);
312 #endif /* CY_IP_MXSCB_VERSION */
313     /* Configure SCB_CTRL.BYTE_MODE then verify levels */
314     CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rxFifoTriggerLevel));
315     CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->txFifoTriggerLevel));
316     CY_ASSERT_L2(CY_SCB_IS_TRIGGER_LEVEL_VALID(base, config->rtsRxFifoLevel));
317 
318     SCB_UART_CTRL(base) = _VAL2FLD(SCB_UART_CTRL_MODE, (uint32_t) config->uartMode);
319 
320     /* Configure the RX direction */
321     SCB_UART_RX_CTRL(base) = _BOOL2FLD(SCB_UART_RX_CTRL_POLARITY, config->irdaInvertRx)                  |
322                          _BOOL2FLD(SCB_UART_RX_CTRL_MP_MODE, config->enableMutliProcessorMode)       |
323                          _BOOL2FLD(SCB_UART_RX_CTRL_DROP_ON_PARITY_ERROR, config->dropOnParityError) |
324                          _BOOL2FLD(SCB_UART_RX_CTRL_DROP_ON_FRAME_ERROR, config->dropOnFrameError)   |
325                          _VAL2FLD(SCB_UART_RX_CTRL_BREAK_WIDTH, (config->breakWidth - 1UL))          |
326                          _VAL2FLD(SCB_UART_RX_CTRL_STOP_BITS,   ((uint32_t) config->stopBits) - 1UL) |
327                          _VAL2FLD(CY_SCB_UART_RX_CTRL_SET_PARITY, (uint32_t) config->parity);
328 #if((defined (CY_IP_MXSCB_VERSION) && (CY_IP_MXSCB_VERSION>=2)) || defined (CY_IP_MXS22SCB))
329     SCB_UART_RX_CTRL(base)|=_BOOL2FLD(SCB_UART_RX_CTRL_BREAK_LEVEL, config->breaklevel);
330 #endif /* CY_IP_MXSCB_VERSION */
331 
332 #if ((defined(CY_IP_MXSCB_VERSION)) && (CY_IP_MXSCB_VERSION >= 4))
333     SCB_UART_RX_CTRL(base)|=_BOOL2FLD(SCB_UART_RX_CTRL_HDRXEN, config->halfDuplexMode);
334 #endif /* ((defined(CY_IP_MXSCB_VERSION)) && (CY_IP_MXSCB_VERSION >= 4)) */
335 
336     SCB_RX_CTRL(base) = _BOOL2FLD(SCB_RX_CTRL_MSB_FIRST, config->enableMsbFirst)          |
337                     _BOOL2FLD(SCB_RX_CTRL_MEDIAN, ((config->enableInputFilter) || \
338                                              (config->uartMode == CY_SCB_UART_IRDA))) |
339                     _VAL2FLD(SCB_RX_CTRL_DATA_WIDTH, (config->dataWidth - 1UL));
340 
341     SCB_RX_MATCH(base) = _VAL2FLD(SCB_RX_MATCH_ADDR, config->receiverAddress) |
342                      _VAL2FLD(SCB_RX_MATCH_MASK, config->receiverAddressMask);
343 
344     /* Configure SCB_CTRL.RX_CTRL then verify break width */
345     CY_ASSERT_L2(CY_SCB_UART_IS_RX_BREAK_WIDTH_VALID(base, config->breakWidth));
346 
347     /* Configure the TX direction */
348     SCB_UART_TX_CTRL(base) = _BOOL2FLD(SCB_UART_TX_CTRL_RETRY_ON_NACK, ((config->smartCardRetryOnNack) && \
349                                                               (config->uartMode == CY_SCB_UART_SMARTCARD))) |
350                          _VAL2FLD(SCB_UART_TX_CTRL_STOP_BITS, ((uint32_t) config->stopBits) - 1UL)          |
351                          _VAL2FLD(CY_SCB_UART_TX_CTRL_SET_PARITY, (uint32_t) config->parity);
352 
353     SCB_TX_CTRL(base)  = _BOOL2FLD(SCB_TX_CTRL_MSB_FIRST,  config->enableMsbFirst)    |
354                      _VAL2FLD(SCB_TX_CTRL_DATA_WIDTH,  (config->dataWidth - 1UL)) |
355                      _BOOL2FLD(SCB_TX_CTRL_OPEN_DRAIN, (config->uartMode == CY_SCB_UART_SMARTCARD));
356 
357     SCB_RX_FIFO_CTRL(base) = _VAL2FLD(SCB_RX_FIFO_CTRL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
358 
359     /* Configure the flow control */
360     SCB_UART_FLOW_CTRL(base) = _BOOL2FLD(SCB_UART_FLOW_CTRL_CTS_ENABLED, config->enableCts) |
361                            _BOOL2FLD(SCB_UART_FLOW_CTRL_CTS_POLARITY, (CY_SCB_UART_ACTIVE_HIGH == config->ctsPolarity)) |
362                            _BOOL2FLD(SCB_UART_FLOW_CTRL_RTS_POLARITY, (CY_SCB_UART_ACTIVE_HIGH == config->rtsPolarity)) |
363                            _VAL2FLD(SCB_UART_FLOW_CTRL_TRIGGER_LEVEL, config->rtsRxFifoLevel);
364 
365     SCB_TX_FIFO_CTRL(base) = _VAL2FLD(SCB_TX_FIFO_CTRL_TRIGGER_LEVEL, config->txFifoTriggerLevel);
366 
367     /* Set up interrupt sources */
368     SCB_INTR_RX_MASK(base) = (config->rxFifoIntEnableMask & CY_SCB_UART_RX_INTR_MASK);
369     SCB_INTR_TX_MASK(base) = (config->txFifoIntEnableMask & CY_SCB_UART_TX_INTR_MASK);
370 
371     /* Initialize context */
372     if (NULL != context)
373     {
374         context->rxStatus  = 0UL;
375         context->txStatus  = 0UL;
376 
377         context->rxRingBuf = NULL;
378         context->rxRingBufSize = 0UL;
379 
380         context->rxBufIdx  = 0UL;
381         context->txLeftToTransmit = 0UL;
382 
383         context->cbEvents = NULL;
384         context->irdaEnableLowPowerReceiver = config->irdaEnableLowPowerReceiver;
385 
386     #if !defined(NDEBUG)
387         /* Put an initialization key into the initKey variable to verify
388         * context initialization in the transfer API.
389         */
390         context->initKey = CY_SCB_UART_INIT_KEY;
391     #endif /* !(NDEBUG) */
392     }
393 
394     return CY_SCB_UART_SUCCESS;
395 }
396 
397 
398 /*******************************************************************************
399 * Function Name: Cy_SCB_UART_DeInit
400 ****************************************************************************//**
401 *
402 * De-initializes the SCB block. Returns the register values to default.
403 *
404 * \param base
405 * The pointer to the UART SCB instance.
406 *
407 * \note
408 * Ensure that the SCB block is disabled before calling this function.
409 *
410 *******************************************************************************/
Cy_SCB_UART_DeInit(CySCB_Type * base)411 void Cy_SCB_UART_DeInit(CySCB_Type *base)
412 {
413     /* De-initialize the UART interface */
414     SCB_CTRL(base)      = CY_SCB_CTRL_DEF_VAL;
415     SCB_UART_CTRL(base) = CY_SCB_UART_CTRL_DEF_VAL;
416 
417     /* De-initialize the RX direction */
418     SCB_UART_RX_CTRL(base) = 0UL;
419     SCB_RX_CTRL(base)      = CY_SCB_RX_CTRL_DEF_VAL;
420     SCB_RX_FIFO_CTRL(base) = 0UL;
421     SCB_RX_MATCH(base)     = 0UL;
422 
423     /* De-initialize the TX direction */
424     SCB_UART_TX_CTRL(base) = 0UL;
425     SCB_TX_CTRL(base)      = CY_SCB_TX_CTRL_DEF_VAL;
426     SCB_TX_FIFO_CTRL(base) = 0UL;
427 
428     /* De-initialize the flow control */
429     SCB_UART_FLOW_CTRL(base) = 0UL;
430 
431     /* De-initialize the interrupt sources */
432     SCB_INTR_SPI_EC_MASK(base) = 0UL;
433     SCB_INTR_I2C_EC_MASK(base) = 0UL;
434     SCB_INTR_RX_MASK(base)     = 0UL;
435     SCB_INTR_TX_MASK(base)     = 0UL;
436     SCB_INTR_M_MASK(base)      = 0UL;
437     SCB_INTR_S_MASK(base)      = 0UL;
438 }
439 
440 
441 /*******************************************************************************
442 * Function Name: Cy_SCB_UART_Disable
443 ****************************************************************************//**
444 *
445 * Disables the SCB block and clears context statuses.
446 * Note that after the block is disabled, the TX and RX FIFOs and
447 * hardware statuses are cleared. Also, the hardware stops driving the
448 * output and ignores the input. Refer to section \ref group_scb_uart_lp for more
449 * information about UART pins when SCB disabled.
450 
451 * \param base
452 * The pointer to the UART SCB instance.
453 *
454 * \param context
455 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
456 * by the user. The structure is used during the UART operation for internal
457 * configuration and data retention. The user must not modify anything
458 * in this structure.
459 * If only UART functions that do not require context will be used to pass NULL
460 * as pointer to context.
461 *
462 * \note
463 * Calling this function when the UART is busy (transmitter preforms data
464 * transfer or receiver is in the middle of data reception) may result transfer
465 * corruption because the hardware stops driving the outputs and ignores
466 * the inputs.
467 * Ensure that the UART is not busy before calling this function.
468 *
469 *******************************************************************************/
Cy_SCB_UART_Disable(CySCB_Type * base,cy_stc_scb_uart_context_t * context)470 void Cy_SCB_UART_Disable(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
471 {
472     SCB_CTRL(base) &= (uint32_t) ~SCB_CTRL_ENABLED_Msk;
473 
474     if (NULL != context)
475     {
476         context->rxStatus  = 0UL;
477         context->txStatus  = 0UL;
478 
479         context->rxBufIdx  = 0UL;
480         context->txLeftToTransmit = 0UL;
481     }
482 }
483 
484 
485 /*******************************************************************************
486 * Function Name: Cy_SCB_UART_DeepSleepCallback
487 ****************************************************************************//**
488 *
489 * This function handles the transition of the SCB UART into and out of
490 * Deep Sleep mode. It prevents the device from entering Deep Sleep
491 * mode if the UART is transmitting data or has any data in the RX FIFO. If the
492 * UART is ready to enter Deep Sleep mode, it is disabled. The UART is enabled
493 * when the device fails to enter Deep Sleep mode or it is awakened from
494 * Deep Sleep mode. While the UART is disabled, it stops driving the outputs
495 * and ignores the inputs. Any incoming data is ignored. Refer to section
496 * \ref group_scb_uart_lp for more information about UART pins when SCB disabled.
497 *
498 * This function must be called during execution of \ref Cy_SysPm_CpuEnterDeepSleep,
499 * to do it, register this function as a callback before calling
500 * \ref Cy_SysPm_CpuEnterDeepSleep : specify \ref CY_SYSPM_DEEPSLEEP as the callback
501 * type and call \ref Cy_SysPm_RegisterCallback.
502 *
503 * \param callbackParams
504 * The pointer to the callback parameters structure
505 * \ref cy_stc_syspm_callback_params_t.
506 *
507 * \param mode
508 * Callback mode, see \ref cy_en_syspm_callback_mode_t
509 *
510 * \return
511 * \ref cy_en_syspm_status_t
512 *
513 *******************************************************************************/
Cy_SCB_UART_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)514 cy_en_syspm_status_t Cy_SCB_UART_DeepSleepCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
515 {
516     cy_en_syspm_status_t retStatus = CY_SYSPM_FAIL;
517 
518     CySCB_Type *locBase = (CySCB_Type *) callbackParams->base;
519     cy_stc_scb_uart_context_t *locContext = (cy_stc_scb_uart_context_t *) callbackParams->context;
520 
521     switch(mode)
522     {
523         case CY_SYSPM_CHECK_READY:
524         {
525             /* Check whether the High-level API is not busy executing the transmit
526             * or receive operation.
527             */
528             if ((0UL == (CY_SCB_UART_TRANSMIT_ACTIVE & Cy_SCB_UART_GetTransmitStatus(locBase, locContext))) &&
529                 (0UL == (CY_SCB_UART_RECEIVE_ACTIVE  & Cy_SCB_UART_GetReceiveStatus (locBase, locContext))))
530             {
531                 /* If all data elements are transmitted from the TX FIFO and
532                 * shifter and the RX FIFO is empty: the UART is ready to enter
533                 * Deep Sleep mode.
534                 */
535                 if (Cy_SCB_UART_IsTxComplete(locBase))
536                 {
537                     if (0UL == Cy_SCB_UART_GetNumInRxFifo(locBase))
538                     {
539                         /* Disable the UART. The transmitter stops driving the
540                         * lines and the receiver stops receiving data until
541                         * the UART is enabled.
542                         * This happens when the device failed to enter Deep
543                         * Sleep or it is awaken from Deep Sleep mode.
544                         */
545                         Cy_SCB_UART_Disable(locBase, locContext);
546 
547                         retStatus = CY_SYSPM_SUCCESS;
548                     }
549                 }
550             }
551         }
552         break;
553 
554         case CY_SYSPM_CHECK_FAIL:
555         {
556             /* The other driver is not ready for Deep Sleep mode. Restore the
557             * Active mode configuration.
558             */
559 
560             /* Enable the UART to operate */
561             Cy_SCB_UART_Enable(locBase);
562 
563             retStatus = CY_SYSPM_SUCCESS;
564         }
565         break;
566 
567         case CY_SYSPM_BEFORE_TRANSITION:
568             /* Do noting: the UART is not capable of waking up from
569             * Deep Sleep mode.
570             */
571         break;
572 
573         case CY_SYSPM_AFTER_TRANSITION:
574         {
575             /* Enable the UART to operate */
576             Cy_SCB_UART_Enable(locBase);
577 
578             retStatus = CY_SYSPM_SUCCESS;
579         }
580         break;
581 
582         default:
583             /* Unknown state */
584             break;
585     }
586 
587     return (retStatus);
588 }
589 
590 
591 /*******************************************************************************
592 * Function Name: Cy_SCB_UART_HibernateCallback
593 ****************************************************************************//**
594 *
595 * This function handles the transition of the SCB UART into Hibernate mode.
596 * It prevents the device from entering Hibernate mode if the UART is
597 * transmitting data or has any data in the RX FIFO. If the UART is ready
598 * to enter Hibernate mode, it is disabled. If the device fails to enter
599 * Hibernate mode, the UART is enabled. While the UART is disabled, it stops
600 * driving the outputs and ignores the inputs. Any incoming data is ignored.
601 * Refer to section \ref group_scb_uart_lp for more information about UART pins
602 * when SCB disabled.
603 *
604 * This function must be called during execution of \ref Cy_SysPm_SystemEnterHibernate.
605 * To do it, register this function as a callback before calling
606 * \ref Cy_SysPm_SystemEnterHibernate : specify \ref CY_SYSPM_HIBERNATE as the callback type
607 * and call \ref Cy_SysPm_RegisterCallback.
608 *
609 * \param callbackParams
610 * The pointer to the callback parameters structure
611 * \ref cy_stc_syspm_callback_params_t.
612 *
613 * \param mode
614 * Callback mode, see \ref cy_en_syspm_callback_mode_t
615 *
616 * \return
617 * \ref cy_en_syspm_status_t
618 *
619 *******************************************************************************/
Cy_SCB_UART_HibernateCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)620 cy_en_syspm_status_t Cy_SCB_UART_HibernateCallback(cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
621 {
622     return Cy_SCB_UART_DeepSleepCallback(callbackParams, mode);
623 }
624 
625 
626 /************************* High-Level Functions ********************************
627 * The following functions are considered high-level. They provide the layer of
628 * intelligence to the SCB. These functions require interrupts.
629 * Low-level and high-level functions must not be mixed because low-level API
630 * can adversely affect the operation of high-level functions.
631 *******************************************************************************/
632 
633 
634 /*******************************************************************************
635 * Function Name: Cy_SCB_UART_StartRingBuffer
636 ****************************************************************************//**
637 *
638 * Starts the receive ring buffer operation.
639 * The RX interrupt source is configured to get data from the RX
640 * FIFO and put into the ring buffer.
641 *
642 * \param base
643 * The pointer to the UART SCB instance.
644 *
645 * \param buffer
646 * Pointer to the user defined ring buffer.
647 * The element size is defined by the data type, which depends on the configured
648 * data width.
649 *
650 * \param size
651 * The size of the receive ring buffer.
652 * Note that one data element is used for internal use, so if the size is 32,
653 * then only 31 data elements are used for data storage.
654 *
655 * \param context
656 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
657 * by the user. The structure is used during the UART operation for internal
658 * configuration and data retention. The user must not modify anything
659 * in this structure.
660 *
661 * \note
662 * * The buffer must not be modified and stay allocated while the ring buffer
663 *   operates.
664 * * This function overrides the RX interrupt sources and changes the
665 *   RX FIFO level.
666 *
667 *******************************************************************************/
Cy_SCB_UART_StartRingBuffer(CySCB_Type * base,void * buffer,uint32_t size,cy_stc_scb_uart_context_t * context)668 void Cy_SCB_UART_StartRingBuffer(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
669 {
670     CY_ASSERT_L1(NULL != context);
671     #if !defined(NDEBUG)
672     CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
673     #endif
674     CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
675 
676     if ((NULL != buffer) && (size > 0UL))
677     {
678         uint32_t irqRxLevel =  SelectRxFifoLevel(base);
679 
680         context->rxRingBuf     = buffer;
681         context->rxRingBufSize = size;
682         context->rxRingBufHead = 0UL;
683         context->rxRingBufTail = 0UL;
684 
685         /* Set up an RX interrupt to handle the ring buffer */
686         Cy_SCB_SetRxFifoLevel(base, (size >= irqRxLevel) ? (irqRxLevel - 1UL) : (size - 1UL));
687 
688         Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
689     }
690 }
691 
692 
693 /*******************************************************************************
694 * Function Name: SelectRxFifoLevel
695 ****************************************************************************//**
696 * Select RX FIFO level as RTS level if it is valid (>0) or half of RX FIFO size
697 * in other case.
698 *
699 * \return
700 * The RX FIFO level.
701 *
702 *******************************************************************************/
SelectRxFifoLevel(CySCB_Type const * base)703 static uint32_t SelectRxFifoLevel(CySCB_Type const *base)
704 {
705     uint32_t halfFifoSize = Cy_SCB_GetFifoSize(base) / 2UL;
706     uint32_t rtsFifoLevel = Cy_SCB_UART_GetRtsFifoLevel(base);
707 
708     return ((rtsFifoLevel != 0UL ) ? (rtsFifoLevel) : (halfFifoSize));
709 }
710 
711 
712 /*******************************************************************************
713 * Function Name: Cy_SCB_UART_StopRingBuffer
714 ****************************************************************************//**
715 *
716 * Stops receiving data into the ring buffer and clears the ring buffer.
717 *
718 * \param base
719 * The pointer to the UART SCB instance.
720 *
721 * \param context
722 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
723 * by the user. The structure is used during the UART operation for internal
724 * configuration and data retention. The user must not modify anything
725 * in this structure.
726 *
727 *******************************************************************************/
Cy_SCB_UART_StopRingBuffer(CySCB_Type * base,cy_stc_scb_uart_context_t * context)728 void Cy_SCB_UART_StopRingBuffer(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
729 {
730     Cy_SCB_SetRxInterruptMask  (base, CY_SCB_CLEAR_ALL_INTR_SRC);
731     Cy_SCB_UART_ClearRingBuffer(base, context);
732 
733     context->rxRingBuf     = NULL;
734     context->rxRingBufSize = 0UL;
735 }
736 
737 
738 /*******************************************************************************
739 * Function Name: Cy_SCB_UART_GetNumInRingBuffer
740 ****************************************************************************//**
741 *
742 * Returns the number of data elements in the ring buffer.
743 *
744 * \param base
745 * The pointer to the UART SCB instance.
746 *
747 * \param context
748 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
749 * by the user. The structure is used during the UART operation for internal
750 * configuration and data retention. The user must not modify anything
751 * in this structure.
752 *
753 * \return
754 * The number of data elements in the receive ring buffer.
755 *
756 * \note
757 * One data element is used for internal use, so when the buffer is full,
758 * this function returns (Ring Buffer size - 1).
759 *
760 *******************************************************************************/
Cy_SCB_UART_GetNumInRingBuffer(CySCB_Type const * base,cy_stc_scb_uart_context_t const * context)761 uint32_t Cy_SCB_UART_GetNumInRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_context_t const *context)
762 {
763     uint32_t size;
764     uint32_t locHead = context->rxRingBufHead;
765 
766     /* Suppress a compiler warning about unused variables */
767     (void) base;
768 
769     if (locHead >= context->rxRingBufTail)
770     {
771         size = (locHead - context->rxRingBufTail);
772     }
773     else
774     {
775         size = (locHead + (context->rxRingBufSize - context->rxRingBufTail));
776     }
777 
778     return (size);
779 }
780 
781 
782 /*******************************************************************************
783 * Function Name: Cy_SCB_UART_ClearRingBuffer
784 ****************************************************************************//**
785 *
786 * Clears the ring buffer.
787 *
788 * \param base
789 * The pointer to the UART SCB instance.
790 *
791 * \param context
792 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
793 * by the user. The structure is used during the UART operation for internal
794 * configuration and data retention. The user must not modify anything
795 * in this structure.
796 *
797 *******************************************************************************/
Cy_SCB_UART_ClearRingBuffer(CySCB_Type const * base,cy_stc_scb_uart_context_t * context)798 void Cy_SCB_UART_ClearRingBuffer(CySCB_Type const *base, cy_stc_scb_uart_context_t *context)
799 {
800     /* Suppress a compiler warning about unused variables */
801     (void) base;
802 
803     context->rxRingBufHead = context->rxRingBufTail;
804 }
805 
806 
807 /*******************************************************************************
808 * Function Name: Cy_SCB_UART_Receive
809 ****************************************************************************//**
810 *
811 * This function starts a UART receive operation.
812 * It configures the receive interrupt sources to get data available in the
813 * receive FIFO and returns. The \ref Cy_SCB_UART_Interrupt manages the further
814 * data transfer.
815 *
816 * If the ring buffer is enabled, this function first reads data from the ring
817 * buffer. If there is more data to receive, it configures the receive interrupt
818 * sources to copy the remaining bytes from the RX FIFO when they arrive.
819 *
820 * When the receive operation is completed (requested number of data elements
821 * received) the \ref CY_SCB_UART_RECEIVE_ACTIVE status is cleared and
822 * the \ref CY_SCB_UART_RECEIVE_DONE_EVENT event is generated.
823 *
824 * \param base
825 * The pointer to the UART SCB instance.
826 *
827 * \param buffer
828 * Pointer to buffer to store received data.
829 * The element size is defined by the data type, which depends on the configured
830 * data width.
831 *
832 * \param size
833 * The number of data elements to receive.
834 *
835 * \param context
836 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
837 * by the user. The structure is used during the UART operation for internal
838 * configuration and data retention. The user must not modify anything
839 * in this structure.
840 *
841 * \return
842 * \ref cy_en_scb_uart_status_t
843 *
844 * \note
845 * * The buffer must not be modified and stay allocated until end of the
846 *   receive operation.
847 * * This function overrides the RX interrupt sources and changes the
848 *   RX FIFO level.
849 *
850 *******************************************************************************/
Cy_SCB_UART_Receive(CySCB_Type * base,void * buffer,uint32_t size,cy_stc_scb_uart_context_t * context)851 cy_en_scb_uart_status_t Cy_SCB_UART_Receive(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
852 {
853     CY_ASSERT_L1(NULL != context);
854     #if !defined(NDEBUG)
855     CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
856     #endif
857     CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
858 
859     cy_en_scb_uart_status_t retStatus = CY_SCB_UART_RECEIVE_BUSY;
860 
861     /* check whether there are no active transfer requests */
862     if (0UL == (context->rxStatus & CY_SCB_UART_RECEIVE_ACTIVE))
863     {
864         uint8_t  *tmpBuf = (uint8_t *) buffer;
865         uint32_t numToCopy = 0UL;
866 
867         /* Disable the RX interrupt source to stop the ring buffer update */
868         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
869 
870         if (NULL != context->rxRingBuf)
871         {
872             /* Get the items available in the ring buffer */
873             numToCopy = Cy_SCB_UART_GetNumInRingBuffer(base, context);
874 
875             if (numToCopy > 0UL)
876             {
877                 uint32_t idx;
878                 uint32_t locTail = context->rxRingBufTail;
879                 bool     byteMode = Cy_SCB_IsRxDataWidthByte(base);
880 
881                 /* Adjust the number of items to be read */
882                 if (numToCopy > size)
883                 {
884                     numToCopy = size;
885                 }
886 
887                 /* Copy the data elements from the ring buffer */
888                 for (idx = 0UL; idx < numToCopy; ++idx)
889                 {
890                     ++locTail;
891 
892                     if (locTail == context->rxRingBufSize)
893                     {
894                         locTail = 0UL;
895                     }
896 
897                     if (byteMode)
898                     {
899                         uint8_t *buf = (uint8_t *) buffer;
900                         buf[idx] = ((uint8_t *) context->rxRingBuf)[locTail];
901                     }
902                     else
903                     {
904                         uint16_t *buf = (uint16_t *) buffer;
905                         buf[idx] = ((uint16_t *) context->rxRingBuf)[locTail];
906                     }
907                 }
908 
909                 /* Update the ring buffer tail after data has been copied */
910                 context->rxRingBufTail = locTail;
911 
912                 /* Update with the copied bytes */
913                 size -= numToCopy;
914                 context->rxBufIdx = numToCopy;
915 
916                 /* Check whether all requested data has been read from the ring buffer */
917                 if (0UL == size)
918                 {
919                     /* Enable the RX-error interrupt sources to update the error status */
920                     Cy_SCB_SetRxInterruptMask(base, CY_SCB_UART_RECEIVE_ERR);
921 
922                     /* Call a completion callback if there was no abort receive called
923                     * in the interrupt. The abort clears the number of the received bytes.
924                     */
925                     if (context->rxBufIdx > 0UL)
926                     {
927                         if (NULL != context->cbEvents)
928                         {
929                             context->cbEvents(CY_SCB_UART_RECEIVE_DONE_EVENT);
930                         }
931                     }
932 
933                     /* Continue receiving data in the ring buffer */
934                     Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
935                 }
936                 else
937                 {
938                     tmpBuf = &tmpBuf[(byteMode) ? (numToCopy) : (2UL * numToCopy)];
939                 }
940             }
941         }
942 
943         /* Set up a direct RX FIFO receive */
944         if (size > 0UL)
945         {
946             uint32_t irqRxLevel = SelectRxFifoLevel(base);
947 
948             /* Set up context */
949             context->rxStatus  = CY_SCB_UART_RECEIVE_ACTIVE;
950 
951             context->rxBuf     = (void *) tmpBuf;
952             context->rxBufSize = size;
953             context->rxBufIdx =  numToCopy;
954 
955             /* Set the RX FIFO level to the trigger interrupt */
956             Cy_SCB_SetRxFifoLevel(base, (size > irqRxLevel) ? (irqRxLevel - 1UL) : (size - 1UL));
957 
958             /* Enable the RX interrupt sources to continue data reading */
959             Cy_SCB_SetRxInterruptMask(base, CY_SCB_UART_RX_INTR);
960         }
961 
962         retStatus = CY_SCB_UART_SUCCESS;
963     }
964 
965     return (retStatus);
966 }
967 
968 
969 /*******************************************************************************
970 * Function Name: Cy_SCB_UART_AbortReceive
971 ****************************************************************************//**
972 *
973 * Abort the current receive operation by clearing the receive status.
974 * * If the ring buffer is disabled, the receive interrupt sources are disabled.
975 * * If the ring buffer is enabled, the receive interrupt source is configured
976 *   to get data from the receive FIFO and put it into the ring buffer.
977 *
978 * \param base
979 * The pointer to the UART SCB instance.
980 *
981 * \param context
982 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
983 * by the user. The structure is used during the UART operation for internal
984 * configuration and data retention. The user must not modify anything
985 * in this structure.
986 *
987 * \note
988 * * The RX FIFO and ring buffer are not cleared after abort of receive
989 *   operation.
990 * * If after the abort of the receive operation the transmitter continues
991 *   sending data, it gets into the RX FIFO. To drop this data, the RX FIFO
992 *   and ring buffer (if enabled) must be cleared when the transmitter
993 *   stops sending data. Otherwise, received data will be kept and copied
994 *   to the buffer when \ref Cy_SCB_UART_Receive is called.
995 *
996 *******************************************************************************/
Cy_SCB_UART_AbortReceive(CySCB_Type * base,cy_stc_scb_uart_context_t * context)997 void Cy_SCB_UART_AbortReceive(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
998 {
999     if (NULL == context->rxRingBuf)
1000     {
1001         Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1002     }
1003 
1004     context->rxBufSize = 0UL;
1005     context->rxBufIdx  = 0UL;
1006 
1007     context->rxStatus  = 0UL;
1008 }
1009 
1010 
1011 /*******************************************************************************
1012 * Function Name: Cy_SCB_UART_GetNumReceived
1013 ****************************************************************************//**
1014 *
1015 * Returns the number of data elements received since the last call to \ref
1016 * Cy_SCB_UART_Receive.
1017 *
1018 * \param base
1019 * The pointer to the UART SCB instance.
1020 *
1021 * \param context
1022 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1023 * by the user. The structure is used during the UART operation for internal
1024 * configuration and data retention. The user must not modify anything
1025 * in this structure.
1026 *
1027 * \return
1028 * The number of data elements received.
1029 *
1030 *******************************************************************************/
Cy_SCB_UART_GetNumReceived(CySCB_Type const * base,cy_stc_scb_uart_context_t const * context)1031 uint32_t Cy_SCB_UART_GetNumReceived(CySCB_Type const *base, cy_stc_scb_uart_context_t const *context)
1032 {
1033     /* Suppress a compiler warning about unused variables */
1034     (void) base;
1035 
1036     return (context->rxBufIdx);
1037 }
1038 
1039 
1040 /*******************************************************************************
1041 * Function Name: Cy_SCB_UART_GetReceiveStatus
1042 ****************************************************************************//**
1043 *
1044 * Returns the status of the receive operation.
1045 * This status is a bit mask and the value returned may have multiple bits set.
1046 *
1047 * \param base
1048 * The pointer to the UART SCB instance.
1049 *
1050 * \param context
1051 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1052 * by the user. The structure is used during the UART operation for internal
1053 * configuration and data retention. The user must not modify anything
1054 * in this structure.
1055 *
1056 * \return
1057 * \ref group_scb_uart_macros_receive_status.
1058 *
1059 * \note
1060 * The status is only cleared by calling \ref Cy_SCB_UART_Receive again.
1061 *
1062 *******************************************************************************/
Cy_SCB_UART_GetReceiveStatus(CySCB_Type const * base,cy_stc_scb_uart_context_t const * context)1063 uint32_t Cy_SCB_UART_GetReceiveStatus(CySCB_Type const *base, cy_stc_scb_uart_context_t const *context)
1064 {
1065     /* Suppress a compiler warning about unused variables */
1066     (void) base;
1067 
1068     return (context->rxStatus);
1069 }
1070 
1071 
1072 /*******************************************************************************
1073 * Function Name: Cy_SCB_UART_Transmit
1074 ****************************************************************************//**
1075 *
1076 * This function starts a UART transmit operation.
1077 * It configures the transmit interrupt sources and returns.
1078 * The \ref Cy_SCB_UART_Interrupt manages the further data transfer.
1079 *
1080 * When the transmit operation is completed (requested number of data elements
1081 * sent on the bus), the \ref CY_SCB_UART_TRANSMIT_ACTIVE status is cleared and
1082 * the \ref CY_SCB_UART_TRANSMIT_DONE_EVENT event is generated.
1083 *
1084 * \param base
1085 * The pointer to the UART SCB instance.
1086 *
1087 * \param buffer
1088 * Pointer to user data to place in transmit buffer.
1089 * The element size is defined by the data type, which depends on the configured
1090 * data width.
1091 *
1092 * \param size
1093 * The number of data elements to transmit.
1094 *
1095 * \param context
1096 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1097 * by the user. The structure is used during the UART operation for internal
1098 * configuration and data retention. The user must not modify anything
1099 * in this structure.
1100 *
1101 * \return
1102 * \ref cy_en_scb_uart_status_t
1103 *
1104 * \note
1105 * * The buffer must not be modified and must stay allocated until its content is
1106 *   copied into the TX FIFO.
1107 * * This function overrides the TX FIFO interrupt sources and changes the
1108 *   TX FIFO level.
1109 *
1110 *******************************************************************************/
Cy_SCB_UART_Transmit(CySCB_Type * base,void * buffer,uint32_t size,cy_stc_scb_uart_context_t * context)1111 cy_en_scb_uart_status_t Cy_SCB_UART_Transmit(CySCB_Type *base, void *buffer, uint32_t size, cy_stc_scb_uart_context_t *context)
1112 {
1113     CY_ASSERT_L1(NULL != context);
1114     #if !defined(NDEBUG)
1115     CY_ASSERT_L1(CY_SCB_UART_INIT_KEY == context->initKey);
1116     #endif
1117     CY_ASSERT_L1(CY_SCB_IS_BUFFER_VALID(buffer, size));
1118 
1119     cy_en_scb_uart_status_t retStatus = CY_SCB_UART_TRANSMIT_BUSY;
1120 
1121     /* Check whether there are no active transfer requests */
1122     if (0UL == (CY_SCB_UART_TRANSMIT_ACTIVE & context->txStatus))
1123     {
1124         /* Set up context */
1125         context->txStatus  = CY_SCB_UART_TRANSMIT_ACTIVE;
1126 
1127         context->txBuf     = buffer;
1128         context->txBufSize = size;
1129 
1130         /* Set the level in TX FIFO to start a transfer */
1131         Cy_SCB_SetTxFifoLevel(base, (Cy_SCB_GetFifoSize(base) / 2UL));
1132 
1133         /* Enable the interrupt sources */
1134         if (((uint32_t) CY_SCB_UART_SMARTCARD) == _FLD2VAL(SCB_UART_CTRL_MODE, SCB_UART_CTRL(base)))
1135         {
1136             /* Transfer data into TX FIFO and track SmartCard-specific errors */
1137             Cy_SCB_SetTxInterruptMask(base, CY_SCB_UART_TX_INTR);
1138         }
1139         else
1140         {
1141             /* Transfer data into TX FIFO */
1142             Cy_SCB_SetTxInterruptMask(base, CY_SCB_TX_INTR_LEVEL);
1143         }
1144 
1145         retStatus = CY_SCB_UART_SUCCESS;
1146     }
1147 
1148     return (retStatus);
1149 }
1150 
1151 
1152 /*******************************************************************************
1153 * Function Name: Cy_SCB_UART_AbortTransmit
1154 ****************************************************************************//**
1155 *
1156 * Aborts the current transmit operation.
1157 * It disables the transmit interrupt sources and clears the transmit FIFO
1158 * and status.
1159 *
1160 * \param base
1161 * The pointer to the UART SCB instance.
1162 *
1163 * \param context
1164 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1165 * by the user. The structure is used during the UART operation for internal
1166 * configuration and data retention. The user must not modify anything
1167 * in this structure.
1168 *
1169 * \sideeffect
1170 * The transmit FIFO clear operation also clears the shift register, so that
1171 * the shifter can be cleared in the middle of a data element transfer,
1172 * corrupting it. The data element corruption means that all bits that have
1173 * not been transmitted are transmitted as "ones" on the bus.
1174 *
1175 *******************************************************************************/
Cy_SCB_UART_AbortTransmit(CySCB_Type * base,cy_stc_scb_uart_context_t * context)1176 void Cy_SCB_UART_AbortTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
1177 {
1178     Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1179 
1180     Cy_SCB_UART_ClearTxFifo(base);
1181 
1182     context->txBufSize = 0UL;
1183     context->txLeftToTransmit = 0UL;
1184 
1185     context->txStatus  = 0UL;
1186 }
1187 
1188 
1189 /*******************************************************************************
1190 * Function Name: Cy_SCB_UART_GetNumLeftToTransmit
1191 ****************************************************************************//**
1192 *
1193 * Returns the number of data elements left to transmit since the last call to
1194 * \ref Cy_SCB_UART_Transmit.
1195 *
1196 * \param base
1197 * The pointer to the UART SCB instance.
1198 *
1199 * \param context
1200 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1201 * by the user. The structure is used during the UART operation for internal
1202 * configuration and data retention. The user must not modify anything
1203 * in this structure.
1204 *
1205 * \return
1206 * The number of data elements left to transmit.
1207 *
1208 *******************************************************************************/
Cy_SCB_UART_GetNumLeftToTransmit(CySCB_Type const * base,cy_stc_scb_uart_context_t const * context)1209 uint32_t Cy_SCB_UART_GetNumLeftToTransmit(CySCB_Type const *base, cy_stc_scb_uart_context_t const *context)
1210 {
1211     /* Suppress a compiler warning about unused variables */
1212     (void) base;
1213 
1214     return (context->txLeftToTransmit);
1215 }
1216 
1217 
1218 /*******************************************************************************
1219 * Function Name: Cy_SCB_UART_GetTransmitStatus
1220 ****************************************************************************//**
1221 *
1222 * Returns the status of the transmit operation.
1223 * This status is a bit mask and the value returned may have multiple bits set.
1224 *
1225 * \param base
1226 * The pointer to the UART SCB instance.
1227 *
1228 * \param context
1229 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1230 * by the user. The structure is used during the UART operation for internal
1231 * configuration and data retention. The user must not modify anything
1232 * in this structure.
1233 *
1234 * \return
1235 * \ref group_scb_uart_macros_transmit_status.
1236 *
1237 * \note
1238 * The status is only cleared by calling \ref Cy_SCB_UART_Transmit or
1239 * \ref Cy_SCB_UART_AbortTransmit.
1240 *
1241 *******************************************************************************/
Cy_SCB_UART_GetTransmitStatus(CySCB_Type const * base,cy_stc_scb_uart_context_t const * context)1242 uint32_t Cy_SCB_UART_GetTransmitStatus(CySCB_Type const *base, cy_stc_scb_uart_context_t const *context)
1243 {
1244     /* Suppress a compiler warning about unused variables */
1245     (void) base;
1246 
1247     return (context->txStatus);
1248 }
1249 
1250 
1251 /*******************************************************************************
1252 * Function Name: Cy_SCB_UART_SendBreakBlocking
1253 ****************************************************************************//**
1254 *
1255 * Sends a break condition (logic low) of specified width on UART TX line.
1256 * Blocks until break is completed. Only call this function when UART TX FIFO
1257 * and shifter are empty.
1258 *
1259 * \param base
1260 * The pointer to the UART SCB instance.
1261 *
1262 * \param breakWidth
1263 * Width of break condition. Valid range is the TX data width (4 to 16 bits)
1264 *
1265 * \note
1266 * Before sending break all UART TX interrupt sources are disabled. The state
1267 * of UART TX interrupt sources is restored before function returns.
1268 *
1269 * \sideeffect
1270 * If this function is called while there is data in the TX FIFO or shifter that
1271 * data will be shifted out in packets the size of breakWidth.
1272 *
1273 *******************************************************************************/
Cy_SCB_UART_SendBreakBlocking(CySCB_Type * base,uint32_t breakWidth)1274 void Cy_SCB_UART_SendBreakBlocking(CySCB_Type *base, uint32_t breakWidth)
1275 {
1276     uint32_t txCtrlReg;
1277     uint32_t txIntrReg;
1278 
1279     CY_ASSERT_L2(CY_SCB_UART_IS_TX_BREAK_WIDTH_VALID(breakWidth));
1280 
1281     /* Disable all UART TX interrupt sources and clear UART TX Done history */
1282     txIntrReg = Cy_SCB_GetTxInterruptMask(base);
1283     Cy_SCB_SetTxInterruptMask(base, 0UL);
1284     Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UART_DONE);
1285 
1286     /* Store TX_CTRL configuration */
1287     txCtrlReg = SCB_TX_CTRL(base);
1288 
1289     /* Set break width: start bit adds one 0 bit */
1290     CY_REG32_CLR_SET(SCB_TX_CTRL(base), SCB_TX_CTRL_DATA_WIDTH, (breakWidth - 1UL));
1291 
1292     /* Generate break */
1293     Cy_SCB_WriteTxFifo(base, 0UL);
1294 
1295     /* Wait for break completion */
1296     while (0UL == (Cy_SCB_GetTxInterruptStatus(base) & CY_SCB_TX_INTR_UART_DONE))
1297     {
1298     }
1299 
1300     /* Clear all UART TX interrupt sources */
1301     Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_MASK);
1302 
1303     /* Restore TX data width and interrupt sources */
1304     SCB_TX_CTRL(base) = txCtrlReg;
1305     Cy_SCB_SetTxInterruptMask(base, txIntrReg);
1306 }
1307 
1308 
1309 /*******************************************************************************
1310 * Function Name: Cy_SCB_UART_Interrupt
1311 ****************************************************************************//**
1312 *
1313 * This is the interrupt function for the SCB configured in the UART mode.
1314 * This function must be called inside a user-defined interrupt service
1315 * routine to make \ref Cy_SCB_UART_Transmit and \ref Cy_SCB_UART_Receive
1316 * work. The ring buffer operation that enabled by calling \ref Cy_SCB_UART_StartRingBuffer
1317 * also requires interrupt processing.
1318 *
1319 * \param base
1320 * The pointer to the UART SCB instance.
1321 *
1322 * \param context
1323 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1324 * by the user. The structure is used during the UART operation for internal
1325 * configuration and data retention. The user must not modify anything
1326 * in this structure.
1327 *
1328 *******************************************************************************/
Cy_SCB_UART_Interrupt(CySCB_Type * base,cy_stc_scb_uart_context_t * context)1329 void Cy_SCB_UART_Interrupt(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
1330 {
1331     if (0UL != (CY_SCB_RX_INTR & Cy_SCB_GetInterruptCause(base)))
1332     {
1333         /* Get RX error events: a frame error, parity error, and overflow */
1334         uint32_t locRxErr = (CY_SCB_UART_RECEIVE_ERR & Cy_SCB_GetRxInterruptStatusMasked(base));
1335 
1336         /* Handle the error conditions */
1337         if (0UL != locRxErr)
1338         {
1339             context->rxStatus |= locRxErr;
1340 
1341             Cy_SCB_ClearRxInterrupt(base, locRxErr);
1342 
1343             if (NULL != context->cbEvents)
1344             {
1345                 context->cbEvents(CY_SCB_UART_RECEIVE_ERR_EVENT);
1346             }
1347         }
1348 
1349         /* Break the detect */
1350         if (0UL != (CY_SCB_RX_INTR_UART_BREAK_DETECT & Cy_SCB_GetRxInterruptStatusMasked(base)))
1351         {
1352             context->rxStatus |= CY_SCB_UART_RECEIVE_BREAK_DETECT;
1353 
1354             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_UART_BREAK_DETECT);
1355         }
1356 
1357         /* Copy the received data */
1358         if (0UL != (CY_SCB_RX_INTR_LEVEL & Cy_SCB_GetRxInterruptStatusMasked(base)))
1359         {
1360             if (context->rxBufSize > 0UL)
1361             {
1362                 HandleDataReceive(base, context);
1363             }
1364             else
1365             {
1366                 if (NULL != context->rxRingBuf)
1367                 {
1368                     HandleRingBuffer(base, context);
1369                 }
1370             }
1371 
1372             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_LEVEL);
1373         }
1374 
1375         if (0UL != (CY_SCB_RX_INTR_NOT_EMPTY & Cy_SCB_GetRxInterruptStatusMasked(base)))
1376         {
1377             if (NULL != context->cbEvents)
1378             {
1379                 context->cbEvents(CY_SCB_UART_RECEIVE_NOT_EMTPY);
1380             }
1381 
1382             Cy_SCB_ClearRxInterrupt(base, CY_SCB_RX_INTR_NOT_EMPTY);
1383         }
1384 
1385     }
1386 
1387     if (0UL != (CY_SCB_TX_INTR & Cy_SCB_GetInterruptCause(base)))
1388     {
1389         uint32_t locTxErr = (CY_SCB_UART_TRANSMIT_ERR & Cy_SCB_GetTxInterruptStatusMasked(base));
1390 
1391         /* Handle the TX error conditions */
1392         if (0UL != locTxErr)
1393         {
1394             context->txStatus |= locTxErr;
1395             Cy_SCB_ClearTxInterrupt(base, locTxErr);
1396 
1397             if (NULL != context->cbEvents)
1398             {
1399                 context->cbEvents(CY_SCB_UART_TRANSMIT_ERR_EVENT);
1400             }
1401         }
1402 
1403         /* Load data to transmit */
1404         if (0UL != (CY_SCB_TX_INTR_LEVEL & Cy_SCB_GetTxInterruptStatusMasked(base)))
1405         {
1406             HandleDataTransmit(base, context);
1407 
1408             Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_LEVEL);
1409         }
1410 
1411         /* Handle the TX complete */
1412         if (0UL != (CY_SCB_TX_INTR_UART_DONE & Cy_SCB_GetTxInterruptStatusMasked(base)))
1413         {
1414             if(context->txStatus != CY_SCB_UART_TRANSMIT_ACTIVE)
1415             {
1416                 /* Clear UART TX complete interrupt sources if UART transfer doesn't use high level APIs */
1417                 Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UART_DONE);
1418             }
1419             else
1420             {
1421                 /* Disable all TX interrupt sources */
1422                 Cy_SCB_SetTxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1423             }
1424 
1425             context->txStatus &= (uint32_t) ~CY_SCB_UART_TRANSMIT_ACTIVE;
1426             context->txLeftToTransmit = 0UL;
1427 
1428             if (NULL != context->cbEvents)
1429             {
1430                 context->cbEvents(CY_SCB_UART_TRANSMIT_DONE_EVENT);
1431             }
1432         }
1433 
1434         if (0UL != (CY_SCB_UART_TX_EMPTY & Cy_SCB_GetTxInterruptStatusMasked(base)))
1435         {
1436             if (NULL != context->cbEvents)
1437             {
1438                 context->cbEvents(CY_SCB_UART_TRANSMIT_EMTPY);
1439             }
1440 
1441             Cy_SCB_ClearTxInterrupt(base, CY_SCB_UART_TX_EMPTY);
1442         }
1443 
1444     }
1445 }
1446 
1447 
1448 
1449 /*******************************************************************************
1450 * Function Name: HandleDataReceive
1451 ****************************************************************************//**
1452 *
1453 * Reads data from the receive FIFO into the buffer provided by
1454 * \ref Cy_SCB_UART_Receive.
1455 *
1456 * \param base
1457 * The pointer to the UART SCB instance.
1458 *
1459 * \param context
1460 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1461 * by the user. The structure is used during the UART operation for internal
1462 * configuration and data retention. The user must not modify anything
1463 * in this structure.
1464 *
1465 *******************************************************************************/
HandleDataReceive(CySCB_Type * base,cy_stc_scb_uart_context_t * context)1466 static void HandleDataReceive(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
1467 {
1468     uint32_t numCopied;
1469     uint32_t irqRxLevel = SelectRxFifoLevel(base);
1470 
1471     /* Get data from RX FIFO */
1472     numCopied = Cy_SCB_UART_GetArray(base, context->rxBuf, context->rxBufSize);
1473 
1474     /* Move the buffer */
1475     context->rxBufIdx  += numCopied;
1476     context->rxBufSize -= numCopied;
1477 
1478     if (0UL == context->rxBufSize)
1479     {
1480         if (NULL != context->rxRingBuf)
1481         {
1482             /* Adjust the level to proceed with the ring buffer */
1483             Cy_SCB_SetRxFifoLevel(base, (context->rxRingBufSize >= irqRxLevel) ?
1484                                             (irqRxLevel - 1UL) : (context->rxRingBufSize - 1UL));
1485 
1486             Cy_SCB_SetRxInterruptMask(base, CY_SCB_RX_INTR_LEVEL);
1487         }
1488         else
1489         {
1490             Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1491         }
1492 
1493         /* Update the status */
1494         context->rxStatus &= (uint32_t) ~CY_SCB_UART_RECEIVE_ACTIVE;
1495 
1496         /* Notify that receive is done in a callback */
1497         if (NULL != context->cbEvents)
1498         {
1499             context->cbEvents(CY_SCB_UART_RECEIVE_DONE_EVENT);
1500         }
1501     }
1502     else
1503     {
1504         uint8_t *buf = (uint8_t *) context->rxBuf;
1505 
1506         buf = &buf[(Cy_SCB_IsRxDataWidthByte(base) ? (numCopied) : (2UL * numCopied))];
1507         context->rxBuf = (void *) buf;
1508 
1509         if (context->rxBufSize < irqRxLevel)
1510         {
1511             /* Set the RX FIFO level to trigger an interrupt */
1512             Cy_SCB_SetRxFifoLevel(base, (context->rxBufSize - 1UL));
1513         }
1514     }
1515 }
1516 
1517 
1518 /*******************************************************************************
1519 * Function Name: HandleRingBuffer
1520 ****************************************************************************//**
1521 *
1522 * Reads data from the receive FIFO into the receive ring buffer.
1523 *
1524 * \param base
1525 * The pointer to the UART SCB instance.
1526 *
1527 * \param context
1528 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1529 * by the user. The structure is used during the UART operation for internal
1530 * configuration and data retention. The user must not modify anything
1531 * in this structure.
1532 *
1533 *******************************************************************************/
HandleRingBuffer(CySCB_Type * base,cy_stc_scb_uart_context_t * context)1534 static void HandleRingBuffer(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
1535 {
1536     uint32_t irqRxLevel = SelectRxFifoLevel(base);
1537     uint32_t numToCopy = Cy_SCB_GetNumInRxFifo(base);
1538     uint32_t locHead = context->rxRingBufHead;
1539     uint32_t rxData;
1540 
1541     /* Get data into the ring buffer */
1542     while (numToCopy > 0UL)
1543     {
1544         ++locHead;
1545 
1546         if (locHead == context->rxRingBufSize)
1547         {
1548             locHead = 0UL;
1549         }
1550 
1551         if (locHead == context->rxRingBufTail)
1552         {
1553             /* The ring buffer is full, trigger a callback */
1554             if (NULL != context->cbEvents)
1555             {
1556                 context->cbEvents(CY_SCB_UART_RB_FULL_EVENT);
1557             }
1558 
1559             /* The ring buffer is still full. Disable the RX interrupt not to put data into the ring buffer.
1560             * The data is stored in the RX FIFO until it overflows. Revert the head index.
1561             */
1562             if (locHead == context->rxRingBufTail)
1563             {
1564                 Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);
1565 
1566                 locHead = (locHead > 0UL) ? (locHead - 1UL) : (context->rxRingBufSize - 1UL);
1567                 break;
1568             }
1569         }
1570 
1571         /* Get data from RX FIFO. */
1572         rxData = Cy_SCB_ReadRxFifo(base);
1573 
1574         /* Put a data item in the ring buffer */
1575         if (Cy_SCB_IsRxDataWidthByte(base))
1576         {
1577             ((uint8_t *) context->rxRingBuf)[locHead] = (uint8_t) rxData;
1578         }
1579         else
1580         {
1581             ((uint16_t *) context->rxRingBuf)[locHead] = (uint16_t) rxData;
1582         }
1583 
1584         --numToCopy;
1585     }
1586 
1587     /* Update the head index */
1588     context->rxRingBufHead = locHead;
1589 
1590     /* Get free entries in the ring buffer */
1591     numToCopy = context->rxRingBufSize - Cy_SCB_UART_GetNumInRingBuffer(base, context);
1592 
1593     if (numToCopy < irqRxLevel)
1594     {
1595         /* Adjust the level to copy to the ring buffer */
1596         uint32_t level = (numToCopy > 0UL) ? (numToCopy - 1UL) : 0UL;
1597         Cy_SCB_SetRxFifoLevel(base, level);
1598     }
1599 }
1600 
1601 
1602 /*******************************************************************************
1603 * Function Name: HandleDataTransmit
1604 ****************************************************************************//**
1605 *
1606 * Loads the transmit FIFO with data provided by \ref Cy_SCB_UART_Transmit.
1607 *
1608 * \param base
1609 * The pointer to the UART SCB instance.
1610 *
1611 * \param context
1612 * The pointer to the context structure \ref cy_stc_scb_uart_context_t allocated
1613 * by the user. The structure is used during the UART operation for internal
1614 * configuration and data retention. The user must not modify anything
1615 * in this structure.
1616 *
1617 *******************************************************************************/
HandleDataTransmit(CySCB_Type * base,cy_stc_scb_uart_context_t * context)1618 static void HandleDataTransmit(CySCB_Type *base, cy_stc_scb_uart_context_t *context)
1619 {
1620     uint32_t numToCopy;
1621     uint32_t fifoSize = Cy_SCB_GetFifoSize(base);
1622     bool     byteMode = Cy_SCB_IsTxDataWidthByte(base);
1623 
1624     if (context->txBufSize > 1UL)
1625     {
1626         uint8_t *buf = (uint8_t *) context->txBuf;
1627 
1628         /* Get the number of items left for transmission */
1629         context->txLeftToTransmit = context->txBufSize;
1630 
1631         /* Put data into TX FIFO */
1632         numToCopy = Cy_SCB_UART_PutArray(base, context->txBuf, (context->txBufSize - 1UL));
1633 
1634         /* Move the buffer */
1635         context->txBufSize -= numToCopy;
1636 
1637         buf = &buf[(byteMode) ? (numToCopy) : (2UL * numToCopy)];
1638         context->txBuf = (void *) buf;
1639     }
1640 
1641     /* Put the last data item into TX FIFO */
1642     if ((fifoSize != Cy_SCB_GetNumInTxFifo(base)) && (1UL == context->txBufSize))
1643     {
1644         uint32_t txData;
1645         uint32_t intrStatus;
1646 
1647         context->txBufSize = 0UL;
1648 
1649         /* Get the last item from the buffer */
1650         txData = (uint32_t) ((byteMode) ? ((uint8_t *)  context->txBuf)[0UL] :
1651                                           ((uint16_t *) context->txBuf)[0UL]);
1652 
1653         /* Put the last data element and make sure that "TX done" will happen for it */
1654         intrStatus = Cy_SysLib_EnterCriticalSection();
1655 
1656         Cy_SCB_ClearTxInterrupt(base, CY_SCB_TX_INTR_UART_DONE);
1657         Cy_SCB_WriteTxFifo(base, txData);
1658 
1659         Cy_SysLib_ExitCriticalSection(intrStatus);
1660 
1661         /* Disable the level interrupt source and enable "transfer done" */
1662         Cy_SCB_SetTxInterruptMask(base, (CY_SCB_TX_INTR_UART_DONE |
1663                     (Cy_SCB_GetTxInterruptMask(base) & (uint32_t) ~CY_SCB_TX_INTR_LEVEL)));
1664 
1665         /* Data is copied into TX FIFO */
1666         context->txStatus |= CY_SCB_UART_TRANSMIT_IN_FIFO;
1667 
1668         if (NULL != context->cbEvents)
1669         {
1670             context->cbEvents(CY_SCB_UART_TRANSMIT_IN_FIFO_EVENT);
1671         }
1672     }
1673 }
1674 
1675 
1676 #if defined(__cplusplus)
1677 }
1678 #endif
1679 
1680 #endif /* (defined (CY_IP_MXSCB) || defined (CY_IP_MXS22SCB)) */
1681 
1682 /* [] END OF FILE */
1683