1 /*
2 * Copyright (c) 2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * ======== UART2CC32XX.c ========
35 */
36
37 #include <stdint.h>
38 #include <stdbool.h>
39
40 #include <ti/drivers/dpl/ClockP.h>
41 #include <ti/drivers/dpl/HwiP.h>
42 #include <ti/drivers/dpl/SemaphoreP.h>
43 #include <ti/drivers/Power.h>
44 #include <ti/drivers/power/PowerCC32XX.h>
45 #include <ti/drivers/dma/UDMACC32XX.h>
46
47 #include <ti/drivers/uart2/UART2CC32XX.h>
48
49 /* driverlib header files */
50 #include <ti/devices/cc32xx/inc/hw_memmap.h>
51 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
52 #include <ti/devices/cc32xx/inc/hw_ints.h>
53 #include <ti/devices/cc32xx/inc/hw_types.h>
54 #include <ti/devices/cc32xx/inc/hw_uart.h>
55 #include <ti/devices/cc32xx/driverlib/rom.h>
56 #include <ti/devices/cc32xx/driverlib/rom_map.h>
57 #include <ti/devices/cc32xx/driverlib/uart.h>
58 #include <ti/devices/cc32xx/driverlib/pin.h>
59 #include <ti/devices/cc32xx/driverlib/udma.h>
60
61 /* Pad configuration defines */
62 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
63 #define PAD_RESET_STATE 0xC61
64
65 #if defined(__IAR_SYSTEMS_ICC__)
66 #include <intrinsics.h>
67 #endif
68
69 #define MIN(a,b) (((a)<(b))?(a):(b))
70
71 /* Mazimum number of bytes that DMA can transfer */
72 #define MAX_SIZE 1024
73
74 /* Options for DMA write and read */
75 #define TX_CONTROL_OPTS (UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | \
76 UDMA_ARB_4)
77 #define RX_CONTROL_OPTS (UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | \
78 UDMA_ARB_4)
79
80 /* Static functions */
81 static void configDmaRx(UART2_Handle handle);
82 static void configDmaTx(UART2_Handle handle);
83 static void UART2CC32XX_hwiIntFxn(uintptr_t arg);
84 static uint_fast16_t getPowerMgrId(uint32_t baseAddr);
85 static void initHw(UART2_Handle handle);
86 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
87 uintptr_t clientArg);
88 static void cancelDmaRx(UART2_Handle handle);
89 static int32_t readData(UART2_Handle handle, int32_t size);
90 static void readSemCallback(UART2_Handle handle, void *buffer, size_t count,
91 void *userArg, int_fast16_t status);
92 static void readDone(UART2_Handle handle);
93 static void writeSemCallback(UART2_Handle handle, void *buffer, size_t count,
94 void *userArg, int_fast16_t status);
95
96 /* UART function table for UART2CC32XX implementation */
97 const UART2_FxnTable UART2CC32XX_fxnTable = {
98 UART2CC32XX_close,
99 UART2CC32XX_open,
100 UART2CC32XX_read,
101 UART2CC32XX_readCancel,
102 UART2CC32XX_write,
103 UART2CC32XX_writeCancel,
104 UART2CC32XX_flushRx,
105 };
106
107 /* Map UART2 data length to driverlib data length */
108 static const uint32_t dataLength[] = {
109 UART_CONFIG_WLEN_5, /* UART2_DataLen_5 */
110 UART_CONFIG_WLEN_6, /* UART2_DataLen_6 */
111 UART_CONFIG_WLEN_7, /* UART2_DataLen_7 */
112 UART_CONFIG_WLEN_8 /* UART2_DataLen_8 */
113 };
114
115 /* Map UART2 stop bits to driverlib stop bits */
116 static const uint32_t stopBits[] = {
117 UART_CONFIG_STOP_ONE, /* UART2_StopBits_1 */
118 UART_CONFIG_STOP_TWO /* UART2_StopBits_2 */
119 };
120
121 /* Map UART2 parity type to driverlib parity type */
122 static const uint32_t parityType[] = {
123 UART_CONFIG_PAR_NONE, /* UART2_Parity_NONE */
124 UART_CONFIG_PAR_EVEN, /* UART2_Parity_EVEN */
125 UART_CONFIG_PAR_ODD, /* UART2_Parity_ODD */
126 UART_CONFIG_PAR_ZERO, /* UART2_Parity_ZERO */
127 UART_CONFIG_PAR_ONE /* UART2_Parity_ONE */
128 };
129
130 /*
131 * Map UART2CC32XX FIFO threshold types to driverlib TX FIFO threshold
132 * defines.
133 */
134 static const uint8_t txFifoThreshold[5] = {
135 UART_FIFO_TX1_8, /* UART2CC32XX_FIFO_THRESHOLD_1_8 */
136 UART_FIFO_TX2_8, /* UART2CC32XX_FIFO_THRESHOLD_2_8 */
137 UART_FIFO_TX4_8, /* UART2CC32XX_FIFO_THRESHOLD_4_8 */
138 UART_FIFO_TX6_8, /* UART2CC32XX_FIFO_THRESHOLD_6_8 */
139 UART_FIFO_TX7_8 /* UART2CC32XX_FIFO_THRESHOLD_7_8 */
140 };
141
142 /*
143 * Map UART2CC32XXFIFO threshold types to driverlib RX FIFO threshold
144 * defines.
145 */
146 static const uint8_t rxFifoThreshold[5] = {
147 UART_FIFO_RX1_8, /* UART2CC32XX_FIFO_THRESHOLD_1_8 */
148 UART_FIFO_RX2_8, /* UART2CC32XX_FIFO_THRESHOLD_2_8 */
149 UART_FIFO_RX4_8, /* UART2CC32XX_FIFO_THRESHOLD_4_8 */
150 UART_FIFO_RX6_8, /* UART2CC32XX_FIFO_THRESHOLD_6_8 */
151 UART_FIFO_RX7_8 /* UART2CC32XX_FIFO_THRESHOLD_7_8 */
152 };
153
154 /* Number of bytes in the RX FIFO at the corresponding FIFO threshold level */
155 static const uint8_t rxFifoBytes[6] = {
156 2, /* UART2CC26X2_FIFO_THRESHOLD_1_8 */
157 4, /* UART2CC26X2_FIFO_THRESHOLD_2_8 */
158 8, /* UART2CC26X2_FIFO_THRESHOLD_4_8 */
159 12, /* UART2CC26X2_FIFO_THRESHOLD_6_8 */
160 14 /* UART2CC26X2_FIFO_THRESHOLD_7_8 */
161 };
162
163 /*
164 * ======== uartDmaEnable ========
165 * Atomic version of DriverLib UARTDMAEnable()
166 */
uartDmaEnable(uint32_t ui32Base,uint32_t ui32DMAFlags)167 static inline void uartDmaEnable(uint32_t ui32Base, uint32_t ui32DMAFlags)
168 {
169 uintptr_t key;
170
171 key = HwiP_disable();
172 /* Set the requested bits in the UART DMA control register. */
173 HWREG(ui32Base + UART_O_DMACTL) |= ui32DMAFlags;
174
175 HwiP_restore(key);
176 }
177
178 /*
179 * ======== uartDmaDisable ========
180 * Atomic version of DriverLib UARTDMADisable()
181 */
uartDmaDisable(uint32_t ui32Base,uint32_t ui32DMAFlags)182 static inline void uartDmaDisable(uint32_t ui32Base, uint32_t ui32DMAFlags)
183 {
184 uintptr_t key;
185
186 key = HwiP_disable();
187 /* Clear the requested bits in the UART DMA control register. */
188 HWREG(ui32Base + UART_O_DMACTL) &= ~ui32DMAFlags;
189
190 HwiP_restore(key);
191 }
192
193 /*
194 * ======== getRxStatus ========
195 * Get the left-most bit set in the RX error status (OE, BE, PE, FE)
196 * read from the RSR register:
197 * bit# 3 2 1 0
198 * OE BE PE FE
199 * e.g., if OE and FE are both set, OE wins. This will make it easier
200 * to convert an RX error status to a UART2 error code.
201 */
getRxStatus(uint32_t x)202 static inline uint32_t getRxStatus(uint32_t x)
203 {
204 #if defined(__TI_COMPILER_VERSION__)
205 return ((uint32_t) (x & (0x80000000 >> __clz(x))));
206 #elif defined(__GNUC__)
207 return ((uint32_t) (x & (0x80000000 >> __builtin_clz(x))));
208 #elif defined(__IAR_SYSTEMS_ICC__)
209 return ((uint32_t) (x & (0x80000000 >> __CLZ(x))));
210 #else
211 #error "Unsupported compiler"
212 #endif
213 }
214
215 /*
216 * ======== rxStatus2ErrorCode ========
217 * Convert RX status (OE, BE, PE, FE) to a UART2 error code.
218 */
rxStatus2ErrorCode(uint32_t x)219 static inline int_fast16_t rxStatus2ErrorCode(uint32_t x)
220 {
221 uint32_t status;
222
223 status = getRxStatus(x);
224 return (-((int_fast16_t)status));
225 }
226
227 /*
228 * Function for checking whether flow control is enabled.
229 */
isFlowControlEnabled(UART2CC32XX_HWAttrs const * hwAttrs)230 static inline bool isFlowControlEnabled(UART2CC32XX_HWAttrs const *hwAttrs) {
231 return (hwAttrs->flowControl == UART2CC32XX_FLOWCTRL_HARDWARE);
232 }
233
234 /*
235 * ======== UART2CC32XX_close ========
236 */
UART2CC32XX_close(UART2_Handle handle)237 void UART2CC32XX_close(UART2_Handle handle)
238 {
239 UART2CC32XX_Object *object = handle->object;
240 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
241 uint32_t padRegister;
242
243 /* Disable UART and interrupts. */
244 UARTIntDisable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT | UART_INT_OE |
245 UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_EOT);
246
247 /* Disable UART and interrupts. */
248 uartDmaDisable(hwAttrs->baseAddr, UART_DMA_TX | UART_DMA_RX);
249 MAP_UARTDisable(hwAttrs->baseAddr);
250
251 if (object->hwi) {
252 HwiP_delete(object->hwi);
253 }
254 if (object->writeSem) {
255 SemaphoreP_delete(object->writeSem);
256 }
257 if (object->readSem) {
258 SemaphoreP_delete(object->readSem);
259 }
260 if (object->udmaHandle) {
261 UDMACC32XX_close(object->udmaHandle);
262 }
263
264 Power_unregisterNotify(&object->postNotify);
265 Power_releaseDependency(object->powerMgrId);
266
267 if (object->txPin != (uint16_t)-1) {
268 PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->txPin,
269 object->prevParkTX);
270 object->txPin = (uint16_t)-1;
271 }
272
273 if (object->rtsPin != (uint16_t)-1) {
274 PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->rtsPin,
275 object->prevParkRTS);
276 object->rtsPin = (uint16_t)-1;
277 }
278
279 /* Restore pin pads to their reset states */
280 padRegister = (PinToPadGet((hwAttrs->rxPin) & 0xff)<<2) + PAD_CONFIG_BASE;
281 HWREG(padRegister) = PAD_RESET_STATE;
282 padRegister = (PinToPadGet((hwAttrs->txPin) & 0xff)<<2) + PAD_CONFIG_BASE;
283 HWREG(padRegister) = PAD_RESET_STATE;
284 if (isFlowControlEnabled(hwAttrs)) {
285 if (hwAttrs->ctsPin != UART2CC32XX_PIN_UNASSIGNED) {
286 padRegister = (PinToPadGet((hwAttrs->ctsPin) & 0xff)<<2)
287 + PAD_CONFIG_BASE;
288 HWREG(padRegister) = PAD_RESET_STATE;
289 }
290
291 if (hwAttrs->rtsPin != UART2CC32XX_PIN_UNASSIGNED) {
292 padRegister = (PinToPadGet((hwAttrs->rtsPin) & 0xff)<<2)
293 + PAD_CONFIG_BASE;
294 HWREG(padRegister) = PAD_RESET_STATE;
295 }
296 }
297
298 object->state.opened = false;
299 }
300
301 /*
302 * ======== UART2CC32XX_flushRx ========
303 */
UART2CC32XX_flushRx(UART2_Handle handle)304 void UART2CC32XX_flushRx(UART2_Handle handle)
305 {
306 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
307
308 /* Clear any read errors */
309 MAP_UARTRxErrorClear(hwAttrs->baseAddr);
310
311 /* Read RX FIFO until empty */
312 while (((int32_t)MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr)) != -1);
313 }
314
315 /*
316 * ======== UART2CC32XX_hwiIntFxn ========
317 * Hwi function that processes UART interrupts.
318 */
UART2CC32XX_hwiIntFxn(uintptr_t arg)319 static void UART2CC32XX_hwiIntFxn(uintptr_t arg)
320 {
321 uint32_t status;
322 uint32_t errStatus = 0;
323 uint32_t bytesToRead;
324 uint32_t fifoThresholdBytes;
325 UART2_Handle handle = (UART2_Handle)arg;
326 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
327 UART2CC32XX_Object *object = handle->object;
328
329 /* Clear interrupts */
330 status = MAP_UARTIntStatus(hwAttrs->baseAddr, true);
331 MAP_UARTIntClear(hwAttrs->baseAddr, status);
332
333 if (status & (UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE)) {
334 /* Handle the error */
335 if (object->state.readReturnMode != UART2_ReadReturnMode_PARTIAL) {
336 UARTDMADisable(hwAttrs->baseAddr, UART_DMA_RX);
337
338 /* Number of bytes not yet transferred by the DMA */
339 bytesToRead = uDMAChannelSizeGet(hwAttrs->rxDmaChannel);
340 object->bytesRead += (object->readCount - bytesToRead);
341 }
342
343 errStatus = UARTRxErrorGet(hwAttrs->baseAddr);
344 object->rxStatus = rxStatus2ErrorCode(errStatus);
345
346 readDone(handle);
347 }
348 else if (status & UART_INT_RT) {
349 if ((object->state.readReturnMode == UART2_ReadReturnMode_PARTIAL) &&
350 object->readCount > 0) {
351 readData(handle, object->readCount);
352
353 readDone(handle);
354 }
355 }
356 else if ((status & UART_INT_RX) &&
357 (object->state.readReturnMode == UART2_ReadReturnMode_PARTIAL)) {
358 /* Must leave at least one byte in the fifo to get read timeout */
359 fifoThresholdBytes = rxFifoBytes[hwAttrs->rxIntFifoThr];
360 bytesToRead = MIN(fifoThresholdBytes - 1, object->readCount);
361 readData(handle, bytesToRead);
362
363 if (object->readCount == 0) {
364 readDone(handle);
365 }
366 }
367
368 /* Read data if characters are available. */
369 if ((object->state.readReturnMode != UART2_ReadReturnMode_PARTIAL) &&
370 object->readSize && !uDMAChannelIsEnabled(hwAttrs->rxDmaChannel)) {
371 UARTDMADisable(hwAttrs->baseAddr, UART_DMA_RX);
372
373 errStatus = MAP_UARTRxErrorGet(hwAttrs->baseAddr);
374 object->rxStatus = rxStatus2ErrorCode(errStatus);
375 MAP_UARTRxErrorClear(hwAttrs->baseAddr);
376
377 UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMARX);
378 UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
379
380 if (object->readCount != 0) {
381 object->bytesRead += object->rxSize;
382 object->readCount -= object->rxSize;
383
384 if (--object->nReadTransfers == 0) {
385 readDone(handle);
386 }
387 else {
388 /* Start a new DMA transfer */
389 configDmaRx(handle);
390 }
391 }
392 }
393
394 /* Write completed. */
395 if (object->writeCount && !MAP_uDMAChannelIsEnabled(hwAttrs->txDmaChannel)) {
396 /*
397 * Cannot clear DMATXRIS in the UART_RIS register without disabling
398 * DMA
399 */
400 UARTDMADisable(hwAttrs->baseAddr, UART_DMA_TX);
401
402 UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMATX);
403 UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
404
405 object->bytesWritten += object->txSize;
406 object->writeCount -= object->txSize;
407
408 if ((object->writeCount) && (--object->nWriteTransfers > 0)) {
409 configDmaTx(handle);
410 }
411 }
412
413 /* EOT interrupt received */
414 if (status & (UART_INT_EOT)) {
415 /* Check txEnabled in case writeCancel was called */
416 if ((object->writeCount == 0) && object->state.txEnabled) {
417 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
418
419 object->state.txEnabled = false;
420 object->writeSize = 0;
421 object->writeCallback(handle, (void *)object->writeBuf,
422 object->bytesWritten, object->userArg, object->txStatus);
423 }
424 }
425 }
426
427 /*
428 * ======== UART2CC32XX_open ========
429 */
UART2CC32XX_open(uint_least8_t index,UART2_Params * params)430 UART2_Handle UART2CC32XX_open(uint_least8_t index, UART2_Params *params)
431 {
432 UART2_Handle handle = NULL;
433 UART2CC32XX_Object *object;
434 UART2CC32XX_HWAttrs const *hwAttrs;
435 HwiP_Params hwiParams;
436 uintptr_t key;
437 uint16_t pin;
438 uint16_t mode;
439
440 if (index < UART2_count) {
441 handle = (UART2_Handle)&(UART2_config[index]);
442 hwAttrs = handle->hwAttrs;
443 object = handle->object;
444 }
445 else {
446 return (NULL);
447 }
448
449 /* Check for callback when in UART2_Mode_CALLBACK */
450 if (((params->readMode == UART2_Mode_CALLBACK) &&
451 (params->readCallback == NULL)) ||
452 ((params->writeMode == UART2_Mode_CALLBACK) &&
453 (params->writeCallback == NULL))) {
454 return (NULL);
455 }
456
457 key = HwiP_disable();
458
459 if (object->state.opened) {
460 HwiP_restore(key);
461 return (NULL);
462 }
463 object->state.opened = true;
464
465 HwiP_restore(key);
466
467 object->state.txEnabled = false;
468 object->state.readMode = params->readMode;
469 object->state.writeMode = params->writeMode;
470 object->state.readReturnMode = params->readReturnMode;
471 object->readCallback = params->readCallback;
472 object->writeCallback = params->writeCallback;
473 object->baudRate = params->baudRate;
474 object->stopBits = params->stopBits;
475 object->dataLength = params->dataLength;
476 object->parityType = params->parityType;
477 object->userArg = params->userArg;
478
479 /* Set UART transaction variables to defaults. */
480 object->writeBuf = NULL;
481 object->readBuf = NULL;
482 object->writeCount = 0;
483 object->readCount = 0;
484 object->writeSize = 0;
485 object->readSize = 0;
486 object->nWriteTransfers = 0;
487 object->nReadTransfers = 0;
488 object->rxStatus = 0;
489 object->txStatus = 0;
490 object->state.txEnabled = false;
491 object->txPin = (uint16_t)-1;
492 object->rtsPin = (uint16_t)-1;
493
494 object->readSem = NULL;
495 object->writeSem = NULL;
496 object->hwi = NULL;
497
498 /* Determine the Power resource Id from the UART base address */
499 object->powerMgrId = getPowerMgrId(hwAttrs->baseAddr);
500 if (object->powerMgrId >= PowerCC32XX_NUMRESOURCES) {
501 object->state.opened = false;
502 return (NULL);
503 }
504
505 /*
506 * Register power dependency. Keeps the clock running in SLP
507 * and DSLP modes.
508 */
509 Power_setDependency(object->powerMgrId);
510
511 /* Do a software reset of the peripheral */
512 PowerCC32XX_reset(object->powerMgrId);
513
514 pin = (hwAttrs->rxPin) & 0xff;
515 mode = (hwAttrs->rxPin >> 8) & 0xff;
516
517 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
518
519 pin = (hwAttrs->txPin) & 0xff;
520 mode = (hwAttrs->txPin >> 8) & 0xff;
521
522 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
523
524 /*
525 * Read and save TX pin park state; set to "don't park" while UART is
526 * open as device default is logic '1' during LPDS
527 */
528 object->prevParkTX =
529 (PowerCC32XX_ParkState) PowerCC32XX_getParkState((PowerCC32XX_Pin)pin);
530 PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
531 object->txPin = pin;
532
533 if (isFlowControlEnabled(hwAttrs)) {
534 if (hwAttrs->ctsPin != UART2CC32XX_PIN_UNASSIGNED) {
535 pin = (hwAttrs->ctsPin) & 0xff;
536 mode = (hwAttrs->ctsPin >> 8) & 0xff;
537 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
538 }
539
540 if (hwAttrs->rtsPin != UART2CC32XX_PIN_UNASSIGNED) {
541 pin = (hwAttrs->rtsPin) & 0xff;
542 mode = (hwAttrs->rtsPin >> 8) & 0xff;
543 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
544
545 /*
546 * Read and save RTS pin park state; set to "don't park" while UART is
547 * open as device default is logic '1' during LPDS
548 */
549 object->prevParkRTS = (PowerCC32XX_ParkState)PowerCC32XX_getParkState(
550 (PowerCC32XX_Pin)pin);
551 PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
552 object->rtsPin = pin;
553 }
554
555 /* Flow control will be enabled in initHw() */
556 }
557
558 Power_registerNotify(&object->postNotify, PowerCC32XX_AWAKE_LPDS,
559 postNotifyFxn, (uintptr_t)handle);
560
561 /* DMA first */
562 UDMACC32XX_init();
563 object->udmaHandle = UDMACC32XX_open();
564 if (object->udmaHandle == NULL) {
565 UART2CC32XX_close(handle);
566 return (NULL);
567 }
568
569 /* Initialize the hardware */
570 initHw(handle);
571
572 HwiP_clearInterrupt(hwAttrs->intNum);
573
574 HwiP_Params_init(&hwiParams);
575 hwiParams.arg = (uintptr_t)handle;
576 hwiParams.priority = hwAttrs->intPriority;
577
578 object->hwi = HwiP_create(hwAttrs->intNum, UART2CC32XX_hwiIntFxn,
579 &hwiParams);
580
581 if (object->hwi == NULL) {
582 UART2CC32XX_close(handle);
583 return (NULL);
584 }
585
586 /* If write mode is blocking create a semaphore and set callback. */
587 if (object->state.writeMode == UART2_Mode_BLOCKING) {
588 object->writeSem = SemaphoreP_createBinary(0);
589 if (object->writeSem == NULL) {
590 UART2CC32XX_close(handle);
591 return (NULL);
592 }
593 object->writeCallback = &writeSemCallback;
594 }
595
596 /* If read mode is blocking create a semaphore and set callback. */
597 if (object->state.readMode == UART2_Mode_BLOCKING) {
598 object->readSem = SemaphoreP_createBinary(0);
599 if (object->readSem == NULL) {
600 UART2CC32XX_close(handle);
601 return (NULL);
602 }
603 object->readCallback = &readSemCallback;
604 }
605
606 return (handle);
607 }
608
609 /*
610 * ======== UART2CC32XX_read ========
611 */
UART2CC32XX_read(UART2_Handle handle,void * buffer,size_t size,size_t * bytesRead,uint32_t timeout)612 int_fast16_t UART2CC32XX_read(UART2_Handle handle, void *buffer,
613 size_t size, size_t *bytesRead, uint32_t timeout)
614 {
615 UART2CC32XX_Object *object = handle->object;
616 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
617 int status = UART2_STATUS_SUCCESS;
618 unsigned char *buf = (unsigned char *)buffer;
619 int32_t data;
620 uintptr_t key;
621 size_t nBytesRead;
622 size_t *pNBytesRead;
623 uint32_t errStatus;
624
625 pNBytesRead = (bytesRead == NULL) ? &nBytesRead : bytesRead;
626 *pNBytesRead = 0;
627
628 /* Check for Rx error since the last read */
629 errStatus = UARTRxErrorGet(hwAttrs->baseAddr);
630 status = rxStatus2ErrorCode(errStatus);
631 UARTRxErrorClear(hwAttrs->baseAddr);
632
633 if (status != UART2_STATUS_SUCCESS) {
634 object->readSize = 0;
635 return (status);
636 }
637
638 key = HwiP_disable();
639
640 if (object->readSize) {
641 HwiP_restore(key);
642 return (UART2_STATUS_EINUSE);
643 }
644
645 /* Save the data to be read and restore interrupts. */
646 object->readBuf = (unsigned char *)buffer;
647 object->readSize = size;
648 object->readCount = size; /* Number remaining to be read */
649 object->bytesRead = 0; /* Number of bytes read */
650 object->rxStatus = 0; /* Clear receive errors */
651
652 HwiP_restore(key);
653
654 if (object->state.readMode == UART2_Mode_POLLING) {
655 while (size) {
656 data = UARTCharGetNonBlocking(hwAttrs->baseAddr);
657 if (data == -1) {
658 break;
659 }
660 /* Convert error code in upper bytes of data to a UART2 status */
661 status = rxStatus2ErrorCode((data >> 8) & 0xF);
662 if (status < 0) {
663 break;
664 }
665 *buf++ = data & 0xFF;
666 size--;
667 }
668 *pNBytesRead = object->readSize - size;
669
670 /* Set readSize to 0 to allow another read */
671 object->readCount = 0;
672 object->readSize = 0;
673
674 return (status);
675 }
676
677 /* Set constraints to guarantee transaction */
678 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
679
680 /*
681 * Don't use DMA for return partial mode, since we have to leave
682 * one byte in the FIFO to get the read timeout.
683 */
684 if (object->state.readReturnMode != UART2_ReadReturnMode_PARTIAL) {
685 /* Can transfer maximum of 1024 bytes in one DMA transfer */
686 object->nReadTransfers = (object->readSize + MAX_SIZE - 1) / MAX_SIZE;
687 configDmaRx(handle);
688 }
689
690 if (object->state.readMode == UART2_Mode_BLOCKING) {
691 if (SemaphoreP_OK != SemaphoreP_pend(object->readSem, timeout)) {
692 key = HwiP_disable();
693 if (object->readSize == 0) {
694 /* Interrupt occurred just after SemaphoreP_pend() timeout */
695 status = object->rxStatus;
696 SemaphoreP_pend(object->readSem, SemaphoreP_NO_WAIT);
697 HwiP_restore(key);
698 }
699 else {
700 status = UART2_STATUS_ETIMEOUT;
701
702 /* Set readCount to 0 to prevent ISR from doing more work */
703 object->readCount = 0;
704 HwiP_restore(key);
705
706 cancelDmaRx(handle);
707
708 /* Release the power constraint */
709 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
710 }
711 }
712 else {
713 status = object->rxStatus;
714 }
715
716 *pNBytesRead = object->bytesRead;
717 object->readSize = 0; /* Allow the next read */
718 }
719 else {
720 /* ISR will do the work */
721 }
722
723 return (status);
724 }
725
726 /*
727 * ======== UART2CC32XX_readCancel ========
728 */
UART2CC32XX_readCancel(UART2_Handle handle)729 void UART2CC32XX_readCancel(UART2_Handle handle)
730 {
731 UART2CC32XX_Object *object = handle->object;
732 uintptr_t key;
733
734 if (object->state.readMode == UART2_Mode_POLLING) {
735 return;
736 }
737
738 key = HwiP_disable();
739
740 if (object->readSize == 0) {
741 HwiP_restore(key);
742 return;
743 }
744
745 cancelDmaRx(handle);
746
747 object->readSize = 0;
748 object->rxStatus = UART2_STATUS_ECANCELLED;
749
750 HwiP_restore(key);
751
752 object->readCallback(handle, object->readBuf, object->bytesRead,
753 object->userArg, UART2_STATUS_ECANCELLED);
754 }
755
756 /*
757 * ======== UART2CC32XX_write ========
758 */
UART2CC32XX_write(UART2_Handle handle,const void * buffer,size_t size,size_t * bytesWritten,uint32_t timeout)759 int_fast16_t UART2CC32XX_write(UART2_Handle handle, const void *buffer,
760 size_t size, size_t *bytesWritten, uint32_t timeout)
761 {
762 UART2CC32XX_Object *object = handle->object;
763 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
764 uintptr_t key;
765 int status = UART2_STATUS_SUCCESS;
766 uint32_t writeCount;
767 unsigned char *buf = (unsigned char *)buffer;
768 size_t nBytesWritten;
769 size_t *pNBytesWritten;
770
771 if (size == 0) {
772 return (UART2_STATUS_EINVALID);
773 }
774
775 pNBytesWritten = (bytesWritten == NULL) ? &nBytesWritten : bytesWritten;
776
777 key = HwiP_disable();
778
779 if (!object->state.opened) {
780 HwiP_restore(key);
781 return (UART2_STATUS_EINVALID);
782 }
783
784 /*
785 * Make sure any previous write has finished.
786 * In blocking mode, UART2_cancel() may have posted the semaphore,
787 * so we use writeSize to ensure that there are no on-going writes.
788 * This ensures that we can return the txStatus to the caller without
789 * it having been reset to 0 by a pre-empting thread.
790 */
791 if (object->state.txEnabled ||
792 (object->writeSize &&
793 (object->state.writeMode == UART2_Mode_BLOCKING))) {
794 HwiP_restore(key);
795 return (UART2_STATUS_EINUSE);
796 }
797
798 /* Save the data to be written and restore interrupts. */
799 object->writeBuf = buffer;
800 object->writeSize = size;
801 object->writeCount = size;
802 object->bytesWritten = 0;
803 object->state.txEnabled = true;
804
805 object->txStatus = UART2_STATUS_SUCCESS;
806
807 HwiP_restore(key);
808
809 if (object->state.writeMode == UART2_Mode_POLLING) {
810 writeCount = 0;
811 while (size) {
812 if (!UARTCharPutNonBlocking(hwAttrs->baseAddr, *buf)) {
813 break;
814 }
815 buf++;
816 writeCount++;
817 size--;
818 }
819 *pNBytesWritten = writeCount;
820 object->state.txEnabled = false;
821 return (status);
822 }
823
824 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
825
826 object->nWriteTransfers = (object->writeSize + MAX_SIZE - 1) / MAX_SIZE;
827 configDmaTx(handle);
828
829 /* If writeMode is blocking, block and get the state. */
830 if (object->state.writeMode == UART2_Mode_BLOCKING) {
831 /* Pend on semaphore and wait for Hwi to finish. */
832 if (SemaphoreP_OK != SemaphoreP_pend(object->writeSem, timeout)) {
833 /* Disable the TX interrupt and clear in case it's pending */
834 key = HwiP_disable();
835
836 UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
837 UARTIntClear(hwAttrs->baseAddr, UART_INT_TX);
838
839 object->state.txEnabled = false;
840 object->txStatus = UART2_STATUS_ETIMEOUT;
841
842 HwiP_restore(key);
843 }
844 status = object->txStatus; /* UART2_cancel() may have posted semaphore */
845 *pNBytesWritten = object->bytesWritten;
846 object->writeSize = 0; /* Allow the next UART2_write */
847 object->state.txEnabled = false;
848 }
849
850 return (status);
851 }
852
853 /*
854 * ======== UART2CC32XX_writeCancel ========
855 */
UART2CC32XX_writeCancel(UART2_Handle handle)856 void UART2CC32XX_writeCancel(UART2_Handle handle)
857 {
858 UART2CC32XX_Object *object = handle->object;
859 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
860 uint32_t bytesRemaining;
861 uintptr_t key;
862
863 key = HwiP_disable();
864
865 MAP_uDMAChannelDisable(hwAttrs->txDmaChannel);
866 uartDmaDisable(hwAttrs->baseAddr, UART_DMA_TX);
867
868 UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMATX);
869 UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
870
871 /* Return if there is no write */
872 if ((object->writeSize == 0) && !object->state.txEnabled) {
873 HwiP_restore(key);
874 return;
875 }
876
877 object->state.txEnabled = false;
878
879 bytesRemaining = MAP_uDMAChannelSizeGet(hwAttrs->txDmaChannel);
880 object->bytesWritten += object->writeCount - bytesRemaining;
881
882 /*
883 * If the transfer didn't complete, the ISR will not run to
884 * release the Power constraint, so do it here.
885 */
886 if (object->bytesWritten < object->writeCount) {
887 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
888 }
889
890 object->writeSize = 0;
891 object->txStatus = UART2_STATUS_ECANCELLED;
892
893 HwiP_restore(key);
894
895 object->writeCallback(handle, (void *)object->writeBuf,
896 object->bytesWritten, object->userArg,
897 UART2_STATUS_ECANCELLED);
898 }
899
900 /*
901 * ======== configDmaRx ========
902 * Call with interrupts disabled.
903 */
configDmaRx(UART2_Handle handle)904 static void configDmaRx(UART2_Handle handle)
905 {
906 UART2CC32XX_Object *object = handle->object;
907 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
908 unsigned int key;
909 uint32_t rxSize;
910
911 rxSize = MIN(object->readCount, MAX_SIZE);
912 object->rxSize = rxSize;
913
914 /* A lock is needed because we are accessing shared uDMA registers.*/
915 key = HwiP_disable();
916
917 MAP_uDMAChannelControlSet(hwAttrs->rxDmaChannel, RX_CONTROL_OPTS);
918 MAP_uDMAChannelTransferSet(hwAttrs->rxDmaChannel, UDMA_MODE_BASIC,
919 (void *)(hwAttrs->baseAddr + UART_O_DR),
920 (void *)(object->readBuf + object->bytesRead),
921 rxSize);
922
923 uartDmaEnable(hwAttrs->baseAddr, UART_DMA_RX);
924
925 MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMARX);
926
927 MAP_uDMAChannelEnable(hwAttrs->rxDmaChannel);
928
929 HwiP_restore(key);
930 }
931
932 /*
933 * ======== configDmaTx ========
934 * Call with interrupts disabled.
935 */
configDmaTx(UART2_Handle handle)936 static void configDmaTx(UART2_Handle handle)
937 {
938 UART2CC32XX_Object *object = handle->object;
939 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
940 unsigned int key;
941 uint32_t txSize;
942
943 /* TransferSize must be <= 1024 */
944 txSize = MIN(object->writeCount, MAX_SIZE);
945 object->txSize = txSize;
946
947 /* A lock is needed because we are accessing shared uDMA registers.*/
948 key = HwiP_disable();
949
950 MAP_uDMAChannelControlSet(hwAttrs->txDmaChannel, TX_CONTROL_OPTS);
951 MAP_uDMAChannelTransferSet(hwAttrs->txDmaChannel, UDMA_MODE_BASIC,
952 (void *)(object->writeBuf + object->bytesWritten),
953 (void *)(hwAttrs->baseAddr + UART_O_DR), txSize);
954
955 uartDmaEnable(hwAttrs->baseAddr, UART_DMA_TX);
956
957 MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMATX);
958
959 MAP_uDMAChannelEnable(hwAttrs->txDmaChannel);
960
961 HwiP_restore(key);
962 }
963
964 /*
965 * ======== getPowerMgrId ========
966 */
getPowerMgrId(uint32_t baseAddr)967 static uint_fast16_t getPowerMgrId(uint32_t baseAddr)
968 {
969 switch (baseAddr) {
970 case UARTA0_BASE:
971 return (PowerCC32XX_PERIPH_UARTA0);
972 case UARTA1_BASE:
973 return (PowerCC32XX_PERIPH_UARTA1);
974 default:
975 return ((uint_fast16_t)(~0U));
976 }
977 }
978
979 /*
980 * ======== initHw ========
981 */
initHw(UART2_Handle handle)982 static void initHw(UART2_Handle handle)
983 {
984 UART2CC32XX_Object *object = handle->object;
985 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
986 ClockP_FreqHz freq;
987 unsigned long mode = UART_FLOWCONTROL_NONE;
988
989 ClockP_getCpuFreq(&freq);
990 MAP_UARTConfigSetExpClk(hwAttrs->baseAddr, freq.lo, object->baudRate,
991 dataLength[object->dataLength] |
992 stopBits[object->stopBits] |
993 parityType[object->parityType]);
994
995 /* Clear all UART interrupts */
996 UARTIntClear(hwAttrs->baseAddr, UART_INT_OE | UART_INT_BE | UART_INT_PE |
997 UART_INT_FE | UART_INT_RT | UART_INT_TX |
998 UART_INT_RX | UART_INT_CTS | UART_INT_EOT);
999
1000 UARTEnable(hwAttrs->baseAddr);
1001
1002 UARTIntEnable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT | UART_INT_OE |
1003 UART_INT_BE | UART_INT_PE | UART_INT_FE | UART_INT_EOT);
1004
1005 MAP_UARTFIFOLevelSet(hwAttrs->baseAddr, txFifoThreshold[hwAttrs->txIntFifoThr],
1006 rxFifoThreshold[hwAttrs->rxIntFifoThr]);
1007
1008 if (isFlowControlEnabled(hwAttrs)) {
1009 /* Set flow control */
1010 if (hwAttrs->ctsPin != UART2CC32XX_PIN_UNASSIGNED) {
1011 mode = UART_FLOWCONTROL_TX;
1012 }
1013
1014 if (hwAttrs->rtsPin != UART2CC32XX_PIN_UNASSIGNED) {
1015 mode |= UART_FLOWCONTROL_RX;
1016 }
1017 }
1018 MAP_UARTFlowControlSet(hwAttrs->baseAddr, mode);
1019
1020 if (hwAttrs->rxPin != UART2CC32XX_PIN_UNASSIGNED) {
1021 MAP_uDMAChannelAssign(hwAttrs->rxDmaChannel);
1022
1023 uDMAChannelAttributeDisable(hwAttrs->rxDmaChannel, (UDMA_ATTR_ALTSELECT |
1024 UDMA_ATTR_USEBURST |
1025 UDMA_ATTR_REQMASK));
1026 }
1027
1028 if (hwAttrs->txPin != UART2CC32XX_PIN_UNASSIGNED) {
1029 MAP_uDMAChannelAssign(hwAttrs->txDmaChannel);
1030
1031 uDMAChannelAttributeDisable(hwAttrs->txDmaChannel, (UDMA_ATTR_ALTSELECT |
1032 UDMA_ATTR_USEBURST |
1033 UDMA_ATTR_REQMASK));
1034 }
1035 }
1036
1037 /*
1038 * ======== postNotifyFxn ========
1039 * Called by Power module when waking up from LPDS.
1040 */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)1041 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
1042 uintptr_t clientArg)
1043 {
1044 /* Reconfigure the hardware if returning from sleep */
1045 initHw((UART2_Handle) clientArg);
1046
1047 return (Power_NOTIFYDONE);
1048 }
1049
1050 /*
1051 * ======== cancelDmaRx ========
1052 * Stop the current DMA receive transfer.
1053 */
cancelDmaRx(UART2_Handle handle)1054 static void cancelDmaRx(UART2_Handle handle)
1055 {
1056 UART2CC32XX_Object *object = handle->object;
1057 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
1058 uint32_t bytesRemaining;
1059 uintptr_t key;
1060
1061 if ((object->state.readReturnMode == UART2_ReadReturnMode_PARTIAL) ||
1062 (object->state.readMode == UART2_Mode_POLLING)) {
1063 return;
1064 }
1065
1066 /* Disable interrupts to avoid reading data while changing state. */
1067 key = HwiP_disable();
1068
1069 MAP_uDMAChannelDisable(hwAttrs->rxDmaChannel);
1070 uartDmaDisable(hwAttrs->baseAddr, UART_DMA_RX);
1071
1072 UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMARX);
1073 UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
1074
1075 /* Return if there is no read. */
1076 if (object->readSize == 0) {
1077 HwiP_restore(key);
1078 return;
1079 }
1080
1081 bytesRemaining = MAP_uDMAChannelSizeGet(hwAttrs->rxDmaChannel);
1082 object->bytesRead += object->readCount - bytesRemaining;
1083
1084 /*
1085 * Since object->readSize != 0, the ISR has not run and released
1086 * the Power constraint. Release the constraint here. Setting
1087 * object->readSize to 0 will prevent the ISR from releasing the
1088 * constraint in case it is pending.
1089 */
1090 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1091
1092 HwiP_restore(key);
1093 }
1094
1095 /*
1096 * ======== readData ========
1097 */
readData(UART2_Handle handle,int32_t size)1098 static int32_t readData(UART2_Handle handle, int32_t size)
1099 {
1100 UART2CC32XX_Object *object = handle->object;
1101 UART2CC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
1102 int32_t data;
1103
1104 if (size > object->readCount) {
1105 size = object->readCount;
1106 }
1107
1108 while (size) {
1109 data = UARTCharGetNonBlocking(hwAttrs->baseAddr);
1110 if (data == -1) {
1111 break;
1112 }
1113 *(object->readBuf + object->bytesRead) = (uint8_t)(data & 0xFF);
1114 object->bytesRead++;
1115 object->readCount--;
1116 size--;
1117 }
1118
1119 return (size);
1120 }
1121
1122 /*
1123 * ======== readDone ========
1124 * Called from the ISR only.
1125 */
readDone(UART2_Handle handle)1126 static void readDone(UART2_Handle handle)
1127 {
1128 UART2CC32XX_Object *object = handle->object;
1129 size_t count;
1130
1131 /* Return if no ongoing read */
1132 if (object->readSize == 0) {
1133 return;
1134 }
1135
1136 count = object->bytesRead;
1137
1138 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1139
1140 /* Set readSize to 0 to allow UART2_read() to be called */
1141 object->readSize = 0;
1142
1143 object->readCallback(handle, object->readBuf, count, object->userArg,
1144 object->rxStatus);
1145 }
1146
1147 /*
1148 * ======== readSemCallback ========
1149 * Simple callback to post a semaphore for the blocking mode.
1150 */
readSemCallback(UART2_Handle handle,void * buffer,size_t count,void * userArg,int_fast16_t status)1151 static void readSemCallback(UART2_Handle handle, void *buffer, size_t count,
1152 void *userArg, int_fast16_t status)
1153 {
1154 UART2CC32XX_Object *object = handle->object;
1155
1156 SemaphoreP_post(object->readSem);
1157 }
1158
1159 /*
1160 * ======== writeSemCallback ========
1161 * Simple callback to post a semaphore for the blocking mode.
1162 */
writeSemCallback(UART2_Handle handle,void * buffer,size_t count,void * userArg,int_fast16_t status)1163 static void writeSemCallback(UART2_Handle handle, void *buffer, size_t count,
1164 void *userArg, int_fast16_t status)
1165 {
1166 UART2CC32XX_Object *object = handle->object;
1167
1168 SemaphoreP_post(object->writeSem);
1169 }
1170