1 /*
2 * Copyright (c) 2014-2019, 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 #include <stdint.h>
34
35 /*
36 * By default disable both asserts and log for this module.
37 * This must be done before DebugP.h is included.
38 */
39 #ifndef DebugP_ASSERT_ENABLED
40 #define DebugP_ASSERT_ENABLED 0
41 #endif
42 #ifndef DebugP_LOG_ENABLED
43 #define DebugP_LOG_ENABLED 0
44 #endif
45
46 #include <ti/drivers/dpl/ClockP.h>
47 #include <ti/drivers/dpl/DebugP.h>
48 #include <ti/drivers/dpl/HwiP.h>
49 #include <ti/drivers/dpl/SemaphoreP.h>
50
51 #include <ti/drivers/Power.h>
52 #include <ti/drivers/power/PowerCC32XX.h>
53 #include <ti/drivers/uart/UARTCC32XXDMA.h>
54 #include <ti/drivers/dma/UDMACC32XX.h>
55
56 /* driverlib header files */
57 #include <ti/devices/cc32xx/inc/hw_memmap.h>
58 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
59 #include <ti/devices/cc32xx/inc/hw_ints.h>
60 #include <ti/devices/cc32xx/inc/hw_types.h>
61 #include <ti/devices/cc32xx/driverlib/rom.h>
62 #include <ti/devices/cc32xx/driverlib/rom_map.h>
63 #include <ti/devices/cc32xx/inc/hw_uart.h>
64 #include <ti/devices/cc32xx/driverlib/uart.h>
65 #include <ti/devices/cc32xx/driverlib/udma.h>
66
67 /* DMA can handle transfers of at most 1024 elements */
68 #define MAXXFERSIZE 1024
69
70 /* Pad configuration defines */
71 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
72 #define PAD_RESET_STATE 0xC61
73
74 /* UARTCC32XXDMA functions */
75 void UARTCC32XXDMA_close(UART_Handle handle);
76 int_fast16_t UARTCC32XXDMA_control(UART_Handle handle, uint_fast16_t cmd,
77 void *arg);
78 void UARTCC32XXDMA_init(UART_Handle handle);
79 UART_Handle UARTCC32XXDMA_open(UART_Handle handle, UART_Params *params);
80 int_fast32_t UARTCC32XXDMA_read(UART_Handle handle, void *buffer, size_t size);
81 void UARTCC32XXDMA_readCancel(UART_Handle handle);
82 int_fast32_t UARTCC32XXDMA_readPolling(UART_Handle handle, void *buffer,
83 size_t size);
84 int_fast32_t UARTCC32XXDMA_write(UART_Handle handle, const void *buffer,
85 size_t size);
86 void UARTCC32XXDMA_writeCancel(UART_Handle handle);
87 int_fast32_t UARTCC32XXDMA_writePolling(UART_Handle handle, const void *buffer,
88 size_t size);
89
90 /* UART function table for UARTCC32XXDMA implementation */
91 const UART_FxnTable UARTCC32XXDMA_fxnTable = {
92 UARTCC32XXDMA_close,
93 UARTCC32XXDMA_control,
94 UARTCC32XXDMA_init,
95 UARTCC32XXDMA_open,
96 UARTCC32XXDMA_read,
97 UARTCC32XXDMA_readPolling,
98 UARTCC32XXDMA_readCancel,
99 UARTCC32XXDMA_write,
100 UARTCC32XXDMA_writePolling,
101 UARTCC32XXDMA_writeCancel
102 };
103
104 /* Static functions */
105 static void UARTCC32XXDMA_configDMA(UART_Handle handle, bool isWrite);
106 static void UARTCC32XXDMA_hwiIntFxn(uintptr_t arg);
107
108 static unsigned int getPowerMgrId(unsigned int baseAddr);
109 static void initHw(UART_Handle handle);
110 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
111 uintptr_t clientArg);
112
113 static size_t readCancel(UART_Handle handle);
114 static void readSemCallback(UART_Handle handle, void *buffer, size_t count);
115 static void startTxFifoEmptyClk(UART_Handle handle, unsigned int size);
116 static size_t writeCancel(UART_Handle handle);
117 static void writeFinishedDoCallback(UART_Handle handle);
118 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count);
119
120 /*
121 * Function for checking whether flow control is enabled.
122 */
isFlowControlEnabled(UARTCC32XXDMA_HWAttrsV1 const * hwAttrs)123 static inline bool isFlowControlEnabled(UARTCC32XXDMA_HWAttrsV1 const *hwAttrs) {
124 return ((hwAttrs->flowControl == UARTCC32XXDMA_FLOWCTRL_HARDWARE) &&
125 (hwAttrs->ctsPin != UARTCC32XXDMA_PIN_UNASSIGNED) &&
126 (hwAttrs->rtsPin != UARTCC32XXDMA_PIN_UNASSIGNED));
127 }
128
129
130 static const uint32_t dataLength[] = {
131 UART_CONFIG_WLEN_5, /* UART_LEN_5 */
132 UART_CONFIG_WLEN_6, /* UART_LEN_6 */
133 UART_CONFIG_WLEN_7, /* UART_LEN_7 */
134 UART_CONFIG_WLEN_8 /* UART_LEN_8 */
135 };
136
137 static const uint32_t stopBits[] = {
138 UART_CONFIG_STOP_ONE, /* UART_STOP_ONE */
139 UART_CONFIG_STOP_TWO /* UART_STOP_TWO */
140 };
141
142 static const uint32_t parityType[] = {
143 UART_CONFIG_PAR_NONE, /* UART_PAR_NONE */
144 UART_CONFIG_PAR_EVEN, /* UART_PAR_EVEN */
145 UART_CONFIG_PAR_ODD, /* UART_PAR_ODD */
146 UART_CONFIG_PAR_ZERO, /* UART_PAR_ZERO */
147 UART_CONFIG_PAR_ONE /* UART_PAR_ONE */
148 };
149
150 /*
151 * ======== UARTCC32XXDMA_close ========
152 */
UARTCC32XXDMA_close(UART_Handle handle)153 void UARTCC32XXDMA_close(UART_Handle handle)
154 {
155 UARTCC32XXDMA_Object *object = handle->object;
156 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
157 uint32_t padRegister;
158
159 /* Disable UART and interrupts. */
160 MAP_UARTDMADisable(hwAttrs->baseAddr, UART_DMA_TX | UART_DMA_RX);
161 MAP_UARTDisable(hwAttrs->baseAddr);
162
163 if (object->hwiHandle) {
164 HwiP_delete(object->hwiHandle);
165 }
166 if (object->writeSem) {
167 SemaphoreP_delete(object->writeSem);
168 }
169 if (object->readSem) {
170 SemaphoreP_delete(object->readSem);
171 }
172 if (object->txFifoEmptyClk) {
173 ClockP_delete(object->txFifoEmptyClk);
174 }
175
176 if (object->dmaHandle) {
177 UDMACC32XX_close(object->dmaHandle);
178 }
179
180 Power_unregisterNotify(&object->postNotify);
181 Power_releaseDependency(object->powerMgrId);
182
183 if (object->txPin != (uint16_t)-1) {
184 PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->txPin,
185 object->prevParkTX);
186 object->txPin = (uint16_t)-1;
187 }
188
189 if (object->rtsPin != (uint16_t)-1) {
190 PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->rtsPin,
191 object->prevParkRTS);
192 object->rtsPin = (uint16_t)-1;
193 }
194
195 /* Restore pin pads to their reset states */
196 padRegister = (PinToPadGet((hwAttrs->rxPin) & 0xff)<<2) + PAD_CONFIG_BASE;
197 HWREG(padRegister) = PAD_RESET_STATE;
198 padRegister = (PinToPadGet((hwAttrs->txPin) & 0xff)<<2) + PAD_CONFIG_BASE;
199 HWREG(padRegister) = PAD_RESET_STATE;
200 if (isFlowControlEnabled(hwAttrs)) {
201 padRegister = (PinToPadGet((hwAttrs->ctsPin) & 0xff)<<2)
202 + PAD_CONFIG_BASE;
203 HWREG(padRegister) = PAD_RESET_STATE;
204 padRegister = (PinToPadGet((hwAttrs->rtsPin) & 0xff)<<2)
205 + PAD_CONFIG_BASE;
206 HWREG(padRegister) = PAD_RESET_STATE;
207 }
208
209 object->opened = false;
210
211 DebugP_log1("UART:(%p) closed", hwAttrs->baseAddr);
212 }
213
214 /*
215 * ======== UARTCC32XXDMA_control ========
216 * @pre Function assumes that the handle is not NULL
217 */
UARTCC32XXDMA_control(UART_Handle handle,uint_fast16_t cmd,void * arg)218 int_fast16_t UARTCC32XXDMA_control(UART_Handle handle, uint_fast16_t cmd,
219 void *arg)
220 {
221 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
222
223 switch (cmd) {
224 /* Specific UART CMDs */
225 case (UARTCC32XXDMA_CMD_IS_BUSY):
226 *(bool *)arg = MAP_UARTBusy(hwAttrs->baseAddr);
227 return (UART_STATUS_SUCCESS);
228
229 case (UARTCC32XXDMA_CMD_IS_RX_DATA_AVAILABLE):
230 *(bool *)arg = MAP_UARTCharsAvail(hwAttrs->baseAddr);
231 return (UART_STATUS_SUCCESS);
232
233 case (UARTCC32XXDMA_CMD_IS_TX_SPACE_AVAILABLE):
234 *(bool *)arg = MAP_UARTSpaceAvail(hwAttrs->baseAddr);
235 return (UART_STATUS_SUCCESS);
236
237 default:
238 DebugP_log2("UART:(%p) UART CMD undefined: %d",
239 hwAttrs->baseAddr, cmd);
240 return (UART_STATUS_UNDEFINEDCMD);
241 }
242 }
243
244 /*
245 * ======== UARTCC32XXDMA_init ========
246 */
UARTCC32XXDMA_init(UART_Handle handle)247 void UARTCC32XXDMA_init(UART_Handle handle)
248 {
249 }
250
251 /*
252 * ======== UARTCC32XXDMA_open ========
253 */
UARTCC32XXDMA_open(UART_Handle handle,UART_Params * params)254 UART_Handle UARTCC32XXDMA_open(UART_Handle handle, UART_Params *params)
255 {
256 uintptr_t key;
257 UARTCC32XXDMA_Object *object = handle->object;
258 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
259 SemaphoreP_Params semParams;
260 HwiP_Params hwiParams;
261 ClockP_Params clockParams;
262 uint16_t pin;
263 uint16_t mode;
264
265 /* Timeouts cannot be 0 */
266 DebugP_assert((params->writeTimeout != 0) && (params->readTimeout != 0));
267
268 /* Check that a callback is set */
269 DebugP_assert((params->readMode != UART_MODE_CALLBACK) ||
270 (params->readCallback != NULL));
271 DebugP_assert((params->writeMode != UART_MODE_CALLBACK) ||
272 (params->writeCallback != NULL));
273
274 /* Initialize the DMA */
275 UDMACC32XX_init();
276
277 object->powerMgrId = getPowerMgrId(hwAttrs->baseAddr);
278 if (object->powerMgrId == (unsigned int)-1) {
279 DebugP_log1("UART:(%p) Failed to determine power resource id",
280 hwAttrs->baseAddr);
281 return (NULL);
282 }
283
284 /* Disable preemption while checking if the UART is open. */
285 key = HwiP_disable();
286
287 /* Check if the UART is open already with the base addr. */
288 if (object->opened == true) {
289 HwiP_restore(key);
290
291 DebugP_log1("UART:(%p) already in use.", hwAttrs->baseAddr);
292 return (NULL);
293 }
294
295 object->opened = true;
296 HwiP_restore(key);
297
298 /*
299 * Register power dependency. Keeps the clock running in SLP
300 * and DSLP modes.
301 */
302
303 Power_setDependency(object->powerMgrId);
304
305 /* Do a software reset of the peripheral */
306 PowerCC32XX_reset(object->powerMgrId);
307
308 Power_registerNotify(&object->postNotify, PowerCC32XX_AWAKE_LPDS,
309 postNotifyFxn, (uintptr_t)handle);
310
311 object->readMode = params->readMode;
312 object->writeMode = params->writeMode;
313 object->readTimeout = params->readTimeout;
314 object->writeTimeout = params->writeTimeout;
315 object->readCallback = params->readCallback;
316 object->writeCallback = params->writeCallback;
317 object->readReturnMode = params->readReturnMode;
318 object->readDataMode = params->readDataMode;
319 object->writeDataMode = params->writeDataMode;
320 object->readEcho = params->readEcho;
321 object->baudRate = params->baudRate;
322 object->stopBits = params->stopBits;
323 object->dataLength = params->dataLength;
324 object->parityType = params->parityType;
325
326 /* Set UART variables to defaults. */
327 object->writeBuf = NULL;
328 object->readBuf = NULL;
329 object->writeCount = 0;
330 object->readCount = 0;
331 object->writeSize = 0;
332 object->readSize = 0;
333 object->readSem = NULL;
334 object->writeSem = NULL;
335 object->txFifoEmptyClk = NULL;
336 object->txPin = (uint16_t)-1;
337
338 /* DMA first */
339 object->dmaHandle = UDMACC32XX_open();
340 if (object->dmaHandle == NULL) {
341 UARTCC32XXDMA_close(handle);
342 DebugP_log1("UART:(%p) UDMACC32XX_open() failed.", hwAttrs->baseAddr);
343 return (NULL);
344 }
345
346 pin = (hwAttrs->rxPin) & 0xff;
347 mode = (hwAttrs->rxPin >> 8) & 0xff;
348
349 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
350
351 pin = (hwAttrs->txPin) & 0xff;
352 mode = (hwAttrs->txPin >> 8) & 0xff;
353
354 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
355
356 /*
357 * Read and save TX pin park state; set to "don't park" while UART is
358 * open as device default is logic '1' during LPDS
359 */
360 object->prevParkTX =
361 (PowerCC32XX_ParkState) PowerCC32XX_getParkState((PowerCC32XX_Pin)pin);
362 PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
363 object->txPin = pin;
364
365 if (isFlowControlEnabled(hwAttrs)) {
366 pin = (hwAttrs->ctsPin) & 0xff;
367 mode = (hwAttrs->ctsPin >> 8) & 0xff;
368 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
369
370 pin = (hwAttrs->rtsPin) & 0xff;
371 mode = (hwAttrs->rtsPin >> 8) & 0xff;
372 MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
373
374 /*
375 * Read and save RTS pin park state; set to "don't park" while UART is
376 * open as device default is logic '1' during LPDS
377 */
378 object->prevParkRTS = (PowerCC32XX_ParkState)PowerCC32XX_getParkState(
379 (PowerCC32XX_Pin)pin);
380 PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
381 object->rtsPin = pin;
382
383 /* Flow control will be enabled in initHw() */
384 }
385 HwiP_clearInterrupt(hwAttrs->intNum);
386
387 HwiP_Params_init(&hwiParams);
388 hwiParams.arg = (uintptr_t)handle;
389 hwiParams.priority = hwAttrs->intPriority;
390 object->hwiHandle = HwiP_create(hwAttrs->intNum,
391 UARTCC32XXDMA_hwiIntFxn,
392 &hwiParams);
393 if (object->hwiHandle == NULL) {
394 DebugP_log1("UART:(%p) HwiP_create() failed", hwAttrs->baseAddr);
395 UARTCC32XXDMA_close(handle);
396 return (NULL);
397 }
398
399 /* Disable the UART interrupt. */
400 MAP_UARTIntDisable(hwAttrs->baseAddr,
401 (UART_INT_TX | UART_INT_RX | UART_INT_RT));
402
403 SemaphoreP_Params_init(&semParams);
404 semParams.mode = SemaphoreP_Mode_BINARY;
405
406 /* Create semaphores and set callbacks for BLOCKING modes. */
407 if (object->writeMode == UART_MODE_BLOCKING) {
408 object->writeCallback = &writeSemCallback;
409
410 object->writeSem = SemaphoreP_create(0, &semParams);
411 if (object->writeSem == NULL) {
412 UARTCC32XXDMA_close(handle);
413 DebugP_log1("UART:(%p) Failed to create semaphore.",
414 hwAttrs->baseAddr);
415 return (NULL);
416 }
417 }
418
419 if (object->readMode == UART_MODE_BLOCKING) {
420 object->readCallback = &readSemCallback;
421
422 object->readSem = SemaphoreP_create(0, &semParams);
423 if (object->readSem == NULL) {
424 UARTCC32XXDMA_close(handle);
425 DebugP_log1("UART:(%p) Failed to create semaphore.",
426 hwAttrs->baseAddr);
427 return (NULL);
428 }
429 }
430
431 /*
432 * Clock object to ensure FIFO is drained before releasing Power
433 * constraints.
434 */
435 ClockP_Params_init(&clockParams);
436 clockParams.arg = (uintptr_t)handle;
437
438 object->txFifoEmptyClk = ClockP_create((ClockP_Fxn)&writeFinishedDoCallback,
439 0 /* timeout */, &(clockParams));
440
441 if (object->txFifoEmptyClk == NULL) {
442 UARTCC32XXDMA_close(handle);
443 DebugP_log1("UART:(%p) ClockP_create() failed.",
444 hwAttrs->baseAddr);
445 return (NULL);
446 }
447
448 /* Initialize the hardware */
449 initHw(handle);
450
451
452 DebugP_log1("UART:(%p) opened", hwAttrs->baseAddr);
453
454 /* Return the handle */
455 return (handle);
456 }
457
458 /*
459 * ======== UARTCC32XXDMA_read ========
460 */
UARTCC32XXDMA_read(UART_Handle handle,void * buffer,size_t size)461 int_fast32_t UARTCC32XXDMA_read(UART_Handle handle, void *buffer, size_t size)
462 {
463 uintptr_t key;
464 UARTCC32XXDMA_Object *object = handle->object;
465
466 /* DMA cannot handle transfer sizes > 1024 elements */
467 if (size > MAXXFERSIZE) {
468 DebugP_log1("UART:(%p) Data size too large.",
469 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
470
471 return (UART_ERROR);
472 }
473
474 /* Disable preemption while checking if the uart is in use. */
475 key = HwiP_disable();
476 if (object->readSize) {
477 HwiP_restore(key);
478
479 DebugP_log1("UART:(%p) Could not read data, uart in use.",
480 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
481 return (UART_ERROR);
482 }
483
484 /* Save the data to be read and restore interrupts. */
485 object->readBuf = buffer;
486 object->readSize = size;
487 object->readCount = 0;
488
489 /* Set constraints to guarantee transaction */
490 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
491
492 /*
493 * Start the DMA transfer. Do this inside the critical
494 * section to prevent UARTCC32XXDMA_readCancel() being called
495 * after object->readSize is set, but before the DMA is
496 * configured. If that happened, the size in the DMA control
497 * register would be 0, causing UARTCC32XXDMA_readCancel()
498 * to assume all bytes were transferred.
499 */
500 UARTCC32XXDMA_configDMA(handle, false /* isWrite */);
501
502 HwiP_restore(key);
503
504 /* If readMode is blocking, block and get the status. */
505 if (object->readMode == UART_MODE_BLOCKING) {
506
507 /* Pend on semaphore and wait for Hwi to finish. */
508 if (SemaphoreP_OK != SemaphoreP_pend(object->readSem,
509 object->readTimeout)) {
510 key = HwiP_disable();
511
512 /* Cancel the DMA without posting the semaphore */
513 (void)readCancel(handle);
514
515 /*
516 * If ISR ran after timeout, but before the call to
517 * readCancel(), readSem would be posted. Pend on
518 * the semaphore with 0 timeout so the next read
519 * will block.
520 */
521 if (object->readCount == size) {
522 SemaphoreP_pend(object->readSem, 0);
523 }
524
525 HwiP_restore(key);
526
527 DebugP_log2("UART:(%p) Read timed out, %d bytes read",
528 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
529 object->readCount);
530
531 }
532 return (object->readCount);
533 }
534
535 return (0);
536 }
537
538 /*
539 * ======== UARTCC32XXDMA_readPolling ========
540 */
UARTCC32XXDMA_readPolling(UART_Handle handle,void * buf,size_t size)541 int_fast32_t UARTCC32XXDMA_readPolling(UART_Handle handle, void *buf,
542 size_t size)
543 {
544 int32_t count = 0;
545 UARTCC32XXDMA_Object *object = handle->object;
546 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
547 unsigned char *buffer = (unsigned char *)buf;
548
549 /* Read characters. */
550 while (size) {
551 *buffer = MAP_UARTCharGet(hwAttrs->baseAddr);
552 DebugP_log2("UART:(%p) Read character 0x%x",
553 hwAttrs->baseAddr, *buffer);
554 count++;
555 size--;
556
557 if (object->readDataMode == UART_DATA_TEXT && *buffer == '\r') {
558 /* Echo character if enabled. */
559 if (object->readEcho) {
560 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
561 }
562 *buffer = '\n';
563 }
564
565 /* Echo character if enabled. */
566 if (object->readEcho) {
567 MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
568 }
569
570 /* If read return mode is newline, finish if a newline was received. */
571 if (object->readReturnMode == UART_RETURN_NEWLINE &&
572 *buffer == '\n') {
573 return (count);
574 }
575
576 buffer++;
577 }
578
579 DebugP_log2("UART:(%p) Read polling finished, %d bytes read",
580 hwAttrs->baseAddr, count);
581
582 return (count);
583 }
584
585 /*
586 * ======== UARTCC32XXDMA_readCancel ========
587 */
UARTCC32XXDMA_readCancel(UART_Handle handle)588 void UARTCC32XXDMA_readCancel(UART_Handle handle)
589 {
590 UARTCC32XXDMA_Object *object = handle->object;
591 size_t size;
592
593 /* Stop any ongoing DMA read */
594 size = readCancel(handle);
595
596 if (size == 0) {
597 return;
598 }
599
600 if (object->readMode == UART_MODE_CALLBACK) {
601 object->readCallback(handle, object->readBuf, object->readCount);
602 }
603 else if (object->readMode == UART_MODE_BLOCKING) {
604 /* We don't know if we're in an ISR, but we'll assume not. */
605 SemaphoreP_post(object->readSem);
606 }
607
608 DebugP_log1("UART:(%p) Read canceled, 0 bytes read",
609 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
610 }
611
612 /*
613 * ======== UARTCC32XXDMA_write ========
614 */
UARTCC32XXDMA_write(UART_Handle handle,const void * buffer,size_t size)615 int_fast32_t UARTCC32XXDMA_write(UART_Handle handle, const void *buffer,
616 size_t size)
617 {
618 uintptr_t key;
619 UARTCC32XXDMA_Object *object = handle->object;
620 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
621
622 /* DMA cannot handle transfer sizes > 1024 elements */
623 if (size > MAXXFERSIZE) {
624 DebugP_log1("UART:(%p) Data size too large.", hwAttrs->baseAddr);
625
626 return (UART_ERROR);
627 }
628
629 /* Disable preemption while checking if the uart is in use. */
630 key = HwiP_disable();
631 if (object->writeSize || UARTBusy(hwAttrs->baseAddr)) {
632 HwiP_restore(key);
633 DebugP_log1("UART:(%p) Could not write data, uart in use.",
634 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
635
636 return (UART_ERROR);
637 }
638
639 /* Save the data to be written and restore interrupts. */
640 object->writeBuf = buffer;
641 object->writeCount = 0;
642 object->writeSize = size;
643
644 /* Set constraints to guarantee transaction */
645 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
646
647 UARTCC32XXDMA_configDMA(handle, true /* isWrite */);
648
649 HwiP_restore(key);
650
651 /* If writeMode is blocking, block and get the status. */
652 if (object->writeMode == UART_MODE_BLOCKING) {
653 /* Pend on semaphore and wait for Hwi to finish. */
654 if (SemaphoreP_OK != SemaphoreP_pend(object->writeSem,
655 object->writeTimeout)) {
656
657 key = HwiP_disable();
658
659 /* Stop any ongoing DMA writes and release Power constraints. */
660 (void)writeCancel(handle);
661
662 /*
663 * If ISR ran after timeout, but before the call to
664 * writeCancel(), writeSem would be posted. Pend on
665 * the semaphore so the next write call will block.
666 */
667 if (object->writeCount == size) {
668 SemaphoreP_pend(object->writeSem, 0);
669 }
670
671 HwiP_restore(key);
672
673 DebugP_log2("UART:(%p) Write timed out, %d bytes written",
674 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
675 object->writeCount);
676
677 }
678 return (object->writeCount);
679 }
680
681 return (0);
682 }
683
684 /*
685 * ======== UARTCC32XXDMA_writePolling ========
686 */
UARTCC32XXDMA_writePolling(UART_Handle handle,const void * buf,size_t size)687 int_fast32_t UARTCC32XXDMA_writePolling(UART_Handle handle, const void *buf,
688 size_t size)
689 {
690 int32_t count = 0;
691 UARTCC32XXDMA_Object *object = handle->object;
692 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
693 unsigned char *buffer = (unsigned char *)buf;
694
695 /* Write characters. */
696 while (size) {
697 if (object->writeDataMode == UART_DATA_TEXT && *buffer == '\n') {
698 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
699 count++;
700 }
701 MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
702
703 DebugP_log2("UART:(%p) Wrote character 0x%x",
704 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
705 *buffer);
706 buffer++;
707 count++;
708 size--;
709 }
710
711 DebugP_log2("UART:(%p) Write polling finished, %d bytes written",
712 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
713 count);
714
715 return (count);
716 }
717
718 /*
719 * ======== UARTCC32XXDMA_writeCancel ========
720 */
UARTCC32XXDMA_writeCancel(UART_Handle handle)721 void UARTCC32XXDMA_writeCancel(UART_Handle handle)
722 {
723 UARTCC32XXDMA_Object *object = handle->object;
724 size_t size;
725
726 /* Stop any ongoing DMA transmits */
727 size = writeCancel(handle);
728
729 if (size == 0) {
730 return;
731 }
732
733 if (object->writeMode == UART_MODE_CALLBACK) {
734 object->writeCallback(handle, (uint8_t*)object->writeBuf,
735 object->writeCount);
736 }
737 else if (object->writeMode == UART_MODE_BLOCKING) {
738 /* We don't know if we're in an ISR, but we'll assume not. */
739 SemaphoreP_post(object->writeSem);
740 }
741
742 DebugP_log2("UART:(%p) Write canceled, %d bytes written",
743 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
744 object->writeCount);
745 }
746
747 /*
748 * ======== UARTCC32XXDMA_configDMA ========
749 * Call with interrupts disabled.
750 */
UARTCC32XXDMA_configDMA(UART_Handle handle,bool isWrite)751 static void UARTCC32XXDMA_configDMA(UART_Handle handle, bool isWrite)
752 {
753 UARTCC32XXDMA_Object *object = handle->object;
754 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
755 unsigned long channelControlOptions;
756
757 if (isWrite) {
758 channelControlOptions = UDMA_SIZE_8 | UDMA_SRC_INC_8 |
759 UDMA_DST_INC_NONE | UDMA_ARB_4;
760
761 MAP_uDMAChannelControlSet(hwAttrs->txChannelIndex | UDMA_PRI_SELECT,
762 channelControlOptions);
763
764 MAP_uDMAChannelTransferSet(hwAttrs->txChannelIndex | UDMA_PRI_SELECT,
765 UDMA_MODE_BASIC,
766 (void *)object->writeBuf,
767 (void *)(hwAttrs->baseAddr + UART_O_DR),
768 object->writeSize);
769
770 /*
771 * Enable the DMA channel
772 * This sets the channel's corresponding bit in the uDMA ENASET register.
773 * The bit will be cleared when the transfer completes.
774 */
775 MAP_uDMAChannelEnable(hwAttrs->txChannelIndex);
776
777 MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
778 MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMATX);
779 }
780 else {
781 channelControlOptions = UDMA_SIZE_8 | UDMA_SRC_INC_NONE |
782 UDMA_DST_INC_8 | UDMA_ARB_4;
783
784 MAP_uDMAChannelControlSet(hwAttrs->rxChannelIndex | UDMA_PRI_SELECT,
785 channelControlOptions);
786
787 MAP_uDMAChannelTransferSet(hwAttrs->rxChannelIndex | UDMA_PRI_SELECT,
788 UDMA_MODE_BASIC,
789 (void *)(hwAttrs->baseAddr + UART_O_DR),
790 object->readBuf,
791 object->readSize);
792
793 /* Enable DMA Channel */
794 MAP_uDMAChannelEnable(hwAttrs->rxChannelIndex);
795
796 MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
797 MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMARX);
798 }
799
800 DebugP_log1("UART:(%p) DMA transfer enabled", hwAttrs->baseAddr);
801
802 if (isWrite) {
803 DebugP_log3("UART:(%p) DMA transmit, txBuf: %p; Count: %d",
804 hwAttrs->baseAddr, (uintptr_t)(object->writeBuf),
805 object->writeSize);
806 }
807 else {
808 DebugP_log3("UART:(%p) DMA receive, rxBuf: %p; Count: %d",
809 hwAttrs->baseAddr, (uintptr_t)(object->readBuf),
810 object->readSize);
811 }
812 }
813
814 /*
815 * ======== UARTCC32XXDMA_hwiIntFxn ========
816 * Hwi function that processes UART interrupts.
817 *
818 * Three UART interrupts are enabled: Transmit FIFO is 4/8 empty,
819 * receive FIFO is 4/8 full and a receive timeout between the time
820 * the last character was received.
821 *
822 * @param(arg) The UART_Handle for this Hwi.
823 */
UARTCC32XXDMA_hwiIntFxn(uintptr_t arg)824 static void UARTCC32XXDMA_hwiIntFxn(uintptr_t arg)
825 {
826 uint32_t status;
827 UARTCC32XXDMA_Object *object = ((UART_Handle)arg)->object;
828 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = ((UART_Handle)arg)->hwAttrs;
829
830 /*
831 * Clear interrupts
832 * UARTIntStatus(base, false) - read the raw interrupt status
833 * UARTIntStatus(base, true) - read masked interrupt status
834 */
835 status = MAP_UARTIntStatus(hwAttrs->baseAddr, false);
836 if (status & UART_INT_DMATX) {
837 MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMATX);
838 MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
839 }
840
841 if (status & UART_INT_DMARX) {
842 MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMARX);
843 MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
844 }
845
846 DebugP_log2("UART:(%p) Interrupt with mask 0x%x",
847 hwAttrs->baseAddr, status);
848
849 /* Read data if characters are available. */
850 if (object->readSize &&
851 !MAP_uDMAChannelIsEnabled(hwAttrs->rxChannelIndex)) {
852 object->readCount = object->readSize;
853 object->readSize = 0;
854 object->readCallback((UART_Handle)arg, object->readBuf,
855 object->readCount);
856
857 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
858
859 DebugP_log2("UART:(%p) Read finished, %d bytes read",
860 hwAttrs->baseAddr, object->readCount);
861 }
862
863 /* Write completed. */
864 if (object->writeSize &&
865 !MAP_uDMAChannelIsEnabled(hwAttrs->txChannelIndex)) {
866 object->writeCount = object->writeSize;
867 object->writeSize = 0;
868 /*
869 * No more to write, but data is not shifted out yet.
870 * Start TX FIFO Empty clock.
871 * + 4 because it is 4 bytes left in TX FIFO when the TX FIFO
872 * threshold interrupt occurs.
873 */
874 startTxFifoEmptyClk((UART_Handle)arg, 4);
875
876 DebugP_log2("UART:(%p) Write finished, %d bytes written",
877 hwAttrs->baseAddr, object->writeCount);
878 }
879 }
880
881 /*
882 * ======== getPowerMgrId ========
883 */
getPowerMgrId(unsigned int baseAddr)884 static unsigned int getPowerMgrId(unsigned int baseAddr)
885 {
886 switch (baseAddr) {
887 case UARTA0_BASE:
888 return (PowerCC32XX_PERIPH_UARTA0);
889 case UARTA1_BASE:
890 return (PowerCC32XX_PERIPH_UARTA1);
891 default:
892 return ((unsigned int)-1);
893 }
894 }
895
896 /*
897 * ======== initHw ========
898 * Initialize the hardware.
899 */
initHw(UART_Handle handle)900 static void initHw(UART_Handle handle)
901 {
902 ClockP_FreqHz freq;
903 UARTCC32XXDMA_Object *object = handle->object;
904 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
905
906 /*
907 * Set the FIFO level to 4/8 empty and 4/8 full.
908 * The UART generates a burst request based on the FIFO trigger
909 * level. The arbitration size should be set to the amount
910 * of data that the FIFO can transfer when the trigger level is reached.
911 * Since arbitration size is a power of 2, we'll set the FIFO levels
912 * to 4_8 so they can match the arbitration size of 4.
913 */
914 MAP_UARTFIFOLevelSet(hwAttrs->baseAddr, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
915
916 if (isFlowControlEnabled(hwAttrs)) {
917 /* Set flow control */
918 MAP_UARTFlowControlSet(hwAttrs->baseAddr,
919 UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX);
920 }
921 else {
922 MAP_UARTFlowControlSet(hwAttrs->baseAddr, UART_FLOWCONTROL_NONE);
923 }
924
925 ClockP_getCpuFreq(&freq);
926 MAP_UARTConfigSetExpClk(hwAttrs->baseAddr,
927 freq.lo,
928 object->baudRate,
929 dataLength[object->dataLength] |
930 stopBits[object->stopBits] |
931 parityType[object->parityType]);
932
933 MAP_UARTDMAEnable(hwAttrs->baseAddr, UART_DMA_TX | UART_DMA_RX);
934
935 /* Configure DMA for TX and RX */
936 MAP_uDMAChannelAssign(hwAttrs->txChannelIndex);
937 MAP_uDMAChannelAttributeDisable(hwAttrs->txChannelIndex, UDMA_ATTR_ALTSELECT);
938
939 MAP_uDMAChannelAssign(hwAttrs->rxChannelIndex);
940 MAP_uDMAChannelAttributeDisable(hwAttrs->rxChannelIndex, UDMA_ATTR_ALTSELECT);
941 MAP_UARTEnable(hwAttrs->baseAddr);
942 }
943
944 /*
945 * ======== postNotifyFxn ========
946 * Called by Power module when waking up from LPDS.
947 */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)948 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
949 uintptr_t clientArg)
950 {
951 initHw((UART_Handle)clientArg);
952
953 return (Power_NOTIFYDONE);
954 }
955
956 /*
957 * ======== readCancel ========
958 * Stop the current DMA receive transfer.
959 */
readCancel(UART_Handle handle)960 static size_t readCancel(UART_Handle handle)
961 {
962 uintptr_t key;
963 UARTCC32XXDMA_Object *object = handle->object;
964 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
965 uint32_t remainder;
966 int bytesTransferred;
967 size_t size;
968
969 /* Disable interrupts to avoid reading data while changing state. */
970 key = HwiP_disable();
971
972 size = object->readSize;
973
974 /* Return if there is no read. */
975 if (!object->readSize) {
976 HwiP_restore(key);
977 return (size);
978 }
979
980 /* Set channel bit in the ENACLR register */
981 MAP_uDMAChannelDisable(hwAttrs->rxChannelIndex);
982
983 remainder = MAP_uDMAChannelSizeGet(hwAttrs->rxChannelIndex);
984 bytesTransferred = object->readSize - remainder;
985
986 /*
987 * Since object->readSize != 0, the ISR has not run and released
988 * the Power constraint. Release the constraint here. Setting
989 * object->readSize to 0 will prevent the ISR from releasing the
990 * constraint in case it is pending.
991 */
992 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
993
994 /* Set size = 0 to prevent reading and restore interrupts. */
995 object->readSize = 0;
996 object->readCount = bytesTransferred;
997
998 HwiP_restore(key);
999
1000 return (size);
1001 }
1002
1003 /*
1004 * ======== readSemCallback ========
1005 * Simple callback to post a semaphore for the blocking mode.
1006 */
readSemCallback(UART_Handle handle,void * buffer,size_t count)1007 static void readSemCallback(UART_Handle handle, void *buffer, size_t count)
1008 {
1009 UARTCC32XXDMA_Object *object = handle->object;
1010
1011 SemaphoreP_post(object->readSem);
1012 }
1013
1014 /*
1015 * ======== writeSemCallback ========
1016 * Simple callback to post a semaphore for the blocking mode.
1017 */
writeSemCallback(UART_Handle handle,void * buffer,size_t count)1018 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count)
1019 {
1020 UARTCC32XXDMA_Object *object = handle->object;
1021
1022 SemaphoreP_post(object->writeSem);
1023 }
1024
1025 /*
1026 * ======== writeCancel ========
1027 */
writeCancel(UART_Handle handle)1028 static size_t writeCancel(UART_Handle handle)
1029 {
1030 uintptr_t key;
1031 UARTCC32XXDMA_Object *object = handle->object;
1032 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1033 uint32_t remainder;
1034 int bytesTransferred;
1035 size_t size;
1036
1037 /* Disable interrupts to avoid writing data while changing state. */
1038 key = HwiP_disable();
1039
1040 size = object->writeSize;
1041
1042 /* Set channel bit in the ENACLR register */
1043 MAP_uDMAChannelDisable(hwAttrs->txChannelIndex);
1044
1045 remainder = MAP_uDMAChannelSizeGet(hwAttrs->txChannelIndex);
1046 bytesTransferred = object->writeSize - remainder;
1047
1048 /* Return if there is no write. */
1049 if (!object->writeSize) {
1050 HwiP_restore(key);
1051
1052 return (size);
1053 }
1054
1055 /*
1056 * If the transfer didn't complete, the ISR will not run to
1057 * release the Power constraint, so do it here.
1058 */
1059 if (bytesTransferred < object->writeSize) {
1060 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1061 }
1062
1063 /* Set size = 0 to prevent writing and restore interrupts. */
1064 object->writeSize = 0;
1065 object->writeCount = bytesTransferred;
1066
1067 HwiP_restore(key);
1068
1069 return (size);
1070 }
1071
1072 /*
1073 * ======== startTxFifoEmptyClk ========
1074 * Last write to TX FIFO is done, but not shifted out yet. Start a clock
1075 * which will trigger when the TX FIFO should be empty.
1076 *
1077 * @param(handle) The UART_Handle for ongoing write.
1078 * @param(numData) The number of data present in FIFO after last write
1079 */
startTxFifoEmptyClk(UART_Handle handle,unsigned int numData)1080 static void startTxFifoEmptyClk(UART_Handle handle, unsigned int numData)
1081 {
1082 UARTCC32XXDMA_Object *object = handle->object;
1083 unsigned int writeTimeout;
1084 unsigned int ticksPerSec;
1085
1086 /* No more to write, but data is not shiftet out properly yet.
1087 * 1. Compute appropriate wait time for FIFO to empty out
1088 * - 8 - for maximum data length
1089 * - 3 - for one start bit and maximum of two stop bits
1090 */
1091 ticksPerSec = ClockP_getSystemTickFreq();
1092 writeTimeout = ((numData * (8 + 3) * ticksPerSec) + object->baudRate - 1)
1093 / object->baudRate;
1094
1095 /* 2. Configure clock object to trigger when FIFO is empty */
1096 ClockP_setTimeout(object->txFifoEmptyClk, writeTimeout);
1097 ClockP_start(object->txFifoEmptyClk);
1098 }
1099
1100 /*
1101 * ======== writeFinishedDoCallback ========
1102 * Write finished - make callback
1103 *
1104 * This function is called when the txFifoEmptyClk times out. The TX FIFO
1105 * should now be empty. Standby is allowed again.
1106 *
1107 * @param(handle) The UART_Handle for ongoing write.
1108 */
writeFinishedDoCallback(UART_Handle handle)1109 static void writeFinishedDoCallback(UART_Handle handle)
1110 {
1111 UARTCC32XXDMA_Object *object;
1112 UARTCC32XXDMA_HWAttrsV1 const *hwAttrs;
1113
1114 /* Get the pointer to the object and hwAttrs */
1115 object = handle->object;
1116 hwAttrs = handle->hwAttrs;
1117
1118 /* Stop the txFifoEmpty clock */
1119 ClockP_stop((ClockP_Handle)object->txFifoEmptyClk);
1120
1121 /* 1. Function verifies that the FIFO is empty via BUSY flag */
1122 /* 2. Polls this flag if not yet ready (should not be necessary) */
1123 while (MAP_UARTBusy(hwAttrs->baseAddr));
1124
1125 /* Release constraint since transaction is done */
1126 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1127
1128 /* Make callback */
1129 object->writeCallback(handle, (uint8_t *)object->writeBuf,
1130 object->writeCount);
1131 DebugP_log2("UART:(%p) Write finished, %d bytes written",
1132 hwAttrs->baseAddr, object->writeCount);
1133 }
1134