1 /*
2  * Copyright (c) 2014-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 #include <stdint.h>
34 #include <stdbool.h>
35 #include <ti/drivers/Power.h>
36 #include <ti/drivers/power/PowerCC32XX.h>
37 
38 /*
39  * By default disable both asserts and log for this module.
40  * This must be done before DebugP.h is included.
41  */
42 #ifndef DebugP_ASSERT_ENABLED
43 #define DebugP_ASSERT_ENABLED 0
44 #endif
45 #ifndef DebugP_LOG_ENABLED
46 #define DebugP_LOG_ENABLED 0
47 #endif
48 
49 #include <ti/drivers/dpl/ClockP.h>
50 #include <ti/drivers/dpl/DebugP.h>
51 #include <ti/drivers/dpl/HwiP.h>
52 #include <ti/drivers/dpl/SemaphoreP.h>
53 
54 #include <ti/drivers/uart/UARTCC32XX.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/driverlib/uart.h>
64 #include <ti/devices/cc32xx/driverlib/pin.h>
65 
66 /* Pad configuration defines */
67 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
68 #define PAD_RESET_STATE 0xC61
69 
70 /* UARTCC32XX functions */
71 void         UARTCC32XX_close(UART_Handle handle);
72 int_fast16_t UARTCC32XX_control(UART_Handle handle, uint_fast16_t cmd,
73                 void *arg);
74 void         UARTCC32XX_init(UART_Handle handle);
75 UART_Handle  UARTCC32XX_open(UART_Handle handle, UART_Params *params);
76 int_fast32_t UARTCC32XX_read(UART_Handle handle, void *buffer, size_t size);
77 void         UARTCC32XX_readCancel(UART_Handle handle);
78 int_fast32_t UARTCC32XX_readPolling(UART_Handle handle, void *buffer,
79                 size_t size);
80 int_fast32_t UARTCC32XX_write(UART_Handle handle, const void *buffer,
81                 size_t size);
82 void         UARTCC32XX_writeCancel(UART_Handle handle);
83 int_fast32_t UARTCC32XX_writePolling(UART_Handle handle, const void *buffer,
84                 size_t size);
85 
86 /* Static functions */
87 static unsigned int getPowerMgrId(unsigned int baseAddr);
88 static void initHw(UART_Handle handle);
89 static int  postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
90     uintptr_t clientArg);
91 static void readBlockingTimeout(uintptr_t arg);
92 static bool readIsrBinaryBlocking(UART_Handle handle);
93 static bool readIsrBinaryCallback(UART_Handle handle);
94 static bool readIsrTextBlocking(UART_Handle handle);
95 static bool readIsrTextCallback(UART_Handle handle);
96 static void readSemCallback(UART_Handle handle, void *buffer, size_t count);
97 static int readTaskBlocking(UART_Handle handle);
98 static int readTaskCallback(UART_Handle handle);
99 static void releasePowerConstraint(UART_Handle handle);
100 static int ringBufGet(UART_Handle object, unsigned char *data);
101 static void writeData(UART_Handle handle, bool inISR);
102 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count);
103 
104 /*
105  * Function for checking whether flow control is enabled.
106  */
isFlowControlEnabled(UARTCC32XX_HWAttrsV1 const * hwAttrs)107 static inline bool isFlowControlEnabled(UARTCC32XX_HWAttrsV1 const  *hwAttrs) {
108     return ((hwAttrs->flowControl == UARTCC32XX_FLOWCTRL_HARDWARE) &&
109         (hwAttrs->ctsPin != UARTCC32XX_PIN_UNASSIGNED) &&
110             (hwAttrs->rtsPin != UARTCC32XX_PIN_UNASSIGNED));
111 }
112 
113 /* UART function table for UARTCC32XX implementation */
114 const UART_FxnTable UARTCC32XX_fxnTable = {
115     UARTCC32XX_close,
116     UARTCC32XX_control,
117     UARTCC32XX_init,
118     UARTCC32XX_open,
119     UARTCC32XX_read,
120     UARTCC32XX_readPolling,
121     UARTCC32XX_readCancel,
122     UARTCC32XX_write,
123     UARTCC32XX_writePolling,
124     UARTCC32XX_writeCancel
125 };
126 
127 static const uint32_t dataLength[] = {
128     UART_CONFIG_WLEN_5,     /* UART_LEN_5 */
129     UART_CONFIG_WLEN_6,     /* UART_LEN_6 */
130     UART_CONFIG_WLEN_7,     /* UART_LEN_7 */
131     UART_CONFIG_WLEN_8      /* UART_LEN_8 */
132 };
133 
134 static const uint32_t stopBits[] = {
135     UART_CONFIG_STOP_ONE,   /* UART_STOP_ONE */
136     UART_CONFIG_STOP_TWO    /* UART_STOP_TWO */
137 };
138 
139 static const uint32_t parityType[] = {
140     UART_CONFIG_PAR_NONE,   /* UART_PAR_NONE */
141     UART_CONFIG_PAR_EVEN,   /* UART_PAR_EVEN */
142     UART_CONFIG_PAR_ODD,    /* UART_PAR_ODD */
143     UART_CONFIG_PAR_ZERO,   /* UART_PAR_ZERO */
144     UART_CONFIG_PAR_ONE     /* UART_PAR_ONE */
145 };
146 
147 /*
148  *  ======== staticFxnTable ========
149  *  This is a function lookup table to simplify the UART driver modes.
150  */
151 static const UARTCC32XX_FxnSet staticFxnTable[2][2] = {
152     {/* UART_MODE_BLOCKING */
153         {/* UART_DATA_BINARY */
154             .readIsrFxn  = readIsrBinaryBlocking,
155             .readTaskFxn = readTaskBlocking
156         },
157         {/* UART_DATA_TEXT */
158             .readIsrFxn  = readIsrTextBlocking,
159             .readTaskFxn = readTaskBlocking
160         }
161     },
162     {/* UART_MODE_CALLBACK */
163         {/* UART_DATA_BINARY */
164             .readIsrFxn  = readIsrBinaryCallback,
165             .readTaskFxn = readTaskCallback
166 
167         },
168         {/* UART_DATA_TEXT */
169             .readIsrFxn  = readIsrTextCallback,
170             .readTaskFxn = readTaskCallback,
171         }
172     }
173 };
174 
175 /*
176  *  ======== UARTCC32XX_close ========
177  */
UARTCC32XX_close(UART_Handle handle)178 void UARTCC32XX_close(UART_Handle handle)
179 {
180     UARTCC32XX_Object           *object = handle->object;
181     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
182     uint_fast16_t               retVal;
183     uint32_t                    padRegister;
184 
185     /* Disable UART and interrupts. */
186     MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX | UART_INT_RX |
187         UART_INT_RT | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
188     MAP_UARTDisable(hwAttrs->baseAddr);
189 
190     if (object->hwiHandle) {
191         HwiP_delete(object->hwiHandle);
192     }
193     if (object->writeSem) {
194         SemaphoreP_delete(object->writeSem);
195     }
196     if (object->readSem) {
197         SemaphoreP_delete(object->readSem);
198     }
199     if (object->timeoutClk) {
200         ClockP_delete(object->timeoutClk);
201     }
202 
203     if (object->state.txEnabled) {
204         retVal = Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
205         DebugP_assert(retVal == Power_SOK);
206         object->state.txEnabled = false;
207     }
208 
209     Power_unregisterNotify(&object->postNotify);
210     if (object->state.rxEnabled) {
211         retVal = Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
212         DebugP_assert(retVal == Power_SOK);
213         object->state.rxEnabled = false;
214 
215         DebugP_log1("UART:(%p) UART_close released read power constraint",
216             hwAttrs->baseAddr);
217     }
218     Power_releaseDependency(object->powerMgrId);
219 
220     if (object->txPin != (uint16_t)-1) {
221         PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->txPin,
222             object->prevParkTX);
223         object->txPin = (uint16_t)-1;
224     }
225 
226     if (object->rtsPin != (uint16_t)-1) {
227         PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->rtsPin,
228             object->prevParkRTS);
229         object->rtsPin = (uint16_t)-1;
230     }
231 
232     /* Restore pin pads to their reset states */
233     padRegister = (PinToPadGet((hwAttrs->rxPin) & 0xff)<<2) + PAD_CONFIG_BASE;
234     HWREG(padRegister) = PAD_RESET_STATE;
235     padRegister = (PinToPadGet((hwAttrs->txPin) & 0xff)<<2) + PAD_CONFIG_BASE;
236     HWREG(padRegister) = PAD_RESET_STATE;
237     if (isFlowControlEnabled(hwAttrs)) {
238         padRegister = (PinToPadGet((hwAttrs->ctsPin) & 0xff)<<2)
239             + PAD_CONFIG_BASE;
240         HWREG(padRegister) = PAD_RESET_STATE;
241         padRegister = (PinToPadGet((hwAttrs->rtsPin) & 0xff)<<2)
242             + PAD_CONFIG_BASE;
243         HWREG(padRegister) = PAD_RESET_STATE;
244     }
245 
246     object->state.opened = false;
247 
248     DebugP_log1("UART:(%p) closed", hwAttrs->baseAddr);
249 
250     (void)retVal;
251 }
252 
253 /*
254  *  ======== UARTCC32XX_control ========
255  *  @pre    Function assumes that the handle is not NULL
256  */
UARTCC32XX_control(UART_Handle handle,uint_fast16_t cmd,void * arg)257 int_fast16_t UARTCC32XX_control(UART_Handle handle, uint_fast16_t cmd,
258         void *arg)
259 {
260     UARTCC32XX_Object          *object = handle->object;
261     UARTCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
262     unsigned char               data;
263     int                         bufferCount;
264     uint_fast16_t               retVal;
265 
266     bufferCount = RingBuf_peek(&object->ringBuffer, &data);
267 
268     switch (cmd) {
269         /* Common UART CMDs */
270         case (UART_CMD_PEEK):
271             *(int *)arg = (bufferCount) ? data : UART_ERROR;
272             DebugP_log2("UART:(%p) UART_CMD_PEEK: %d", hwAttrs->baseAddr,
273                 *(uintptr_t*)arg);
274             return (UART_STATUS_SUCCESS);
275 
276         case (UART_CMD_ISAVAILABLE):
277             *(bool *)arg = (bufferCount != 0);
278             DebugP_log2("UART:(%p) UART_CMD_ISAVAILABLE: %d", hwAttrs->baseAddr,
279                 *(uintptr_t*)arg);
280             return (UART_STATUS_SUCCESS);
281 
282         case (UART_CMD_GETRXCOUNT):
283             *(int *)arg = bufferCount;
284             DebugP_log2("UART:(%p) UART_CMD_GETRXCOUNT: %d", hwAttrs->baseAddr,
285                 *(uintptr_t*)arg);
286             return (UART_STATUS_SUCCESS);
287 
288         case (UART_CMD_RXENABLE):
289             if (!object->state.rxEnabled) {
290                 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
291                 MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT |
292                         UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
293                 object->state.rxEnabled = true;
294                 DebugP_log1("UART:(%p) UART_CMD_RXENABLE: Enabled",
295                     hwAttrs->baseAddr);
296                 DebugP_log1("UART:(%p) UART_control set read power constraint",
297                     hwAttrs->baseAddr);
298                 return (UART_STATUS_SUCCESS);
299             }
300             DebugP_log1("UART:(%p) UART_CMD_RXENABLE: Already enabled",
301                 hwAttrs->baseAddr);
302             return (UART_STATUS_ERROR);
303 
304         case (UART_CMD_RXDISABLE):
305             if (object->state.rxEnabled) {
306                 MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT |
307                         UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
308                 retVal = Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
309                 DebugP_assert(retVal == Power_SOK);
310                 object->state.rxEnabled = false;
311                 DebugP_log1("UART:(%p) UART_CMD_RXDISABLE: Disabled",
312                     hwAttrs->baseAddr);
313                 DebugP_log1("UART:(%p) UART_control released read power "
314                     "constraint", hwAttrs->baseAddr);
315 
316                 (void)retVal;
317                 return (UART_STATUS_SUCCESS);
318             }
319             DebugP_log1("UART:(%p) UART_CMD_RXDISABLE: Already disabled",
320                 hwAttrs->baseAddr);
321             return (UART_STATUS_ERROR);
322 
323         /* Specific UART CMDs */
324         case (UARTCC32XX_CMD_IS_BUSY):
325             *(bool *)arg = MAP_UARTBusy(hwAttrs->baseAddr);
326             return (UART_STATUS_SUCCESS);
327 
328         case (UARTCC32XX_CMD_IS_RX_DATA_AVAILABLE):
329             *(bool *)arg = MAP_UARTCharsAvail(hwAttrs->baseAddr);
330             return (UART_STATUS_SUCCESS);
331 
332         case (UARTCC32XX_CMD_IS_TX_SPACE_AVAILABLE):
333             *(bool *)arg = MAP_UARTSpaceAvail(hwAttrs->baseAddr);
334             return (UART_STATUS_SUCCESS);
335 
336         default:
337             DebugP_log2("UART:(%p) UART CMD undefined: %d",
338                 hwAttrs->baseAddr, cmd);
339             return (UART_STATUS_UNDEFINEDCMD);
340     }
341 }
342 
343 /*
344  *  ======== UARTCC32XX_hwiIntFxn ========
345  *  Hwi function that processes UART interrupts.
346  *
347  *  @param(arg)         The UART_Handle for this Hwi.
348  */
UARTCC32XX_hwiIntFxn(uintptr_t arg)349 static void UARTCC32XX_hwiIntFxn(uintptr_t arg)
350 {
351     uint32_t                     status;
352     UARTCC32XX_Object           *object = ((UART_Handle)arg)->object;
353     UARTCC32XX_HWAttrsV1 const  *hwAttrs = ((UART_Handle)arg)->hwAttrs;
354     uint32_t                     rxErrors;
355 
356     /* Clear interrupts */
357     status = MAP_UARTIntStatus(hwAttrs->baseAddr, true);
358     MAP_UARTIntClear(hwAttrs->baseAddr, status);
359 
360     if (status & (UART_INT_RX | UART_INT_RT | UART_INT_OE | UART_INT_BE |
361             UART_INT_PE | UART_INT_FE)) {
362         object->readFxns.readIsrFxn((UART_Handle)arg);
363     }
364 
365     /* Reading the data from the FIFO doesn't mean we caught an overrrun! */
366     rxErrors = MAP_UARTRxErrorGet(hwAttrs->baseAddr);
367     if (rxErrors) {
368         MAP_UARTRxErrorClear(hwAttrs->baseAddr);
369         if (hwAttrs->errorFxn) {
370             hwAttrs->errorFxn((UART_Handle)arg, rxErrors);
371         }
372     }
373 
374     if (status & UART_INT_TX) {
375         writeData((UART_Handle)arg, true);
376     }
377 }
378 
379 /*
380  *  ======== UARTCC32XX_init ========
381  */
UARTCC32XX_init(UART_Handle handle)382 void UARTCC32XX_init(UART_Handle handle)
383 {
384 }
385 
386 /*
387  *  ======== UARTCC32XX_open ========
388  */
UARTCC32XX_open(UART_Handle handle,UART_Params * params)389 UART_Handle UARTCC32XX_open(UART_Handle handle, UART_Params *params)
390 {
391     uintptr_t                    key;
392     UARTCC32XX_Object           *object = handle->object;
393     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
394     SemaphoreP_Params            semParams;
395     HwiP_Params                  hwiParams;
396     ClockP_Params                clockParams;
397     uint16_t                     pin;
398     uint16_t                     mode;
399 
400     /* Check for callback when in UART_MODE_CALLBACK */
401     DebugP_assert((params->readMode != UART_MODE_CALLBACK) ||
402                   (params->readCallback != NULL));
403     DebugP_assert((params->writeMode != UART_MODE_CALLBACK) ||
404                   (params->writeCallback != NULL));
405 
406     key = HwiP_disable();
407 
408     if (object->state.opened == true) {
409         HwiP_restore(key);
410 
411         DebugP_log1("UART:(%p) already in use.", hwAttrs->baseAddr);
412         return (NULL);
413     }
414     object->state.opened = true;
415 
416     HwiP_restore(key);
417 
418     object->state.readMode       = params->readMode;
419     object->state.writeMode      = params->writeMode;
420     object->state.readReturnMode = params->readReturnMode;
421     object->state.readDataMode   = params->readDataMode;
422     object->state.writeDataMode  = params->writeDataMode;
423     object->state.readEcho       = params->readEcho;
424     object->readTimeout          = params->readTimeout;
425     object->writeTimeout         = params->writeTimeout;
426     object->readCallback         = params->readCallback;
427     object->writeCallback        = params->writeCallback;
428     object->baudRate             = params->baudRate;
429     object->stopBits             = params->stopBits;
430     object->dataLength           = params->dataLength;
431     object->parityType           = params->parityType;
432     object->readFxns =
433         staticFxnTable[object->state.readMode][object->state.readDataMode];
434 
435     /* Set UART variables to defaults. */
436     object->writeBuf             = NULL;
437     object->readBuf              = NULL;
438     object->writeCount           = 0;
439     object->readCount            = 0;
440     object->writeSize            = 0;
441     object->readSize             = 0;
442     object->state.txEnabled      = false;
443     object->txPin                = (uint16_t)-1;
444     object->rtsPin               = (uint16_t)-1;
445 
446     RingBuf_construct(&object->ringBuffer, hwAttrs->ringBufPtr,
447         hwAttrs->ringBufSize);
448 
449     /* Get the Power resource Id from the base address */
450     object->powerMgrId = getPowerMgrId(hwAttrs->baseAddr);
451     if (object->powerMgrId == (unsigned int)-1) {
452         DebugP_log1("UART:(%p) Failed to determine Power resource id",
453                 hwAttrs->baseAddr);
454         return (NULL);
455     }
456 
457     /*
458      *  Register power dependency. Keeps the clock running in SLP
459      *  and DSLP modes.
460      */
461     Power_setDependency(object->powerMgrId);
462 
463     /* Do a software reset of the peripheral */
464     PowerCC32XX_reset(object->powerMgrId);
465 
466     pin = (hwAttrs->rxPin) & 0xff;
467     mode = (hwAttrs->rxPin >> 8) & 0xff;
468 
469     MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
470 
471     pin = (hwAttrs->txPin) & 0xff;
472     mode = (hwAttrs->txPin >> 8) & 0xff;
473 
474     MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
475 
476     /*
477      * Read and save TX pin park state; set to "don't park" while UART is
478      * open as device default is logic '1' during LPDS
479      */
480     object->prevParkTX =
481         (PowerCC32XX_ParkState) PowerCC32XX_getParkState((PowerCC32XX_Pin)pin);
482     PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
483     object->txPin = pin;
484 
485     if (isFlowControlEnabled(hwAttrs)) {
486         pin = (hwAttrs->ctsPin) & 0xff;
487         mode = (hwAttrs->ctsPin >> 8) & 0xff;
488         MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
489 
490         pin = (hwAttrs->rtsPin) & 0xff;
491         mode = (hwAttrs->rtsPin >> 8) & 0xff;
492         MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
493 
494         /*
495          * Read and save RTS pin park state; set to "don't park" while UART is
496          * open as device default is logic '1' during LPDS
497          */
498         object->prevParkRTS = (PowerCC32XX_ParkState)PowerCC32XX_getParkState(
499             (PowerCC32XX_Pin)pin);
500         PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
501         object->rtsPin = pin;
502 
503         /* Flow control will be enabled in initHw() */
504     }
505 
506     Power_registerNotify(&object->postNotify, PowerCC32XX_AWAKE_LPDS,
507         postNotifyFxn, (uintptr_t)handle);
508 
509     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
510     object->state.rxEnabled = true;
511 
512     DebugP_log1("UART:(%p) UART_open set read power constraint",
513         hwAttrs->baseAddr);
514 
515     HwiP_Params_init(&hwiParams);
516     hwiParams.arg = (uintptr_t)handle;
517     hwiParams.priority = hwAttrs->intPriority;
518     object->hwiHandle = HwiP_create(hwAttrs->intNum, UARTCC32XX_hwiIntFxn,
519         &hwiParams);
520     if (object->hwiHandle == NULL) {
521         DebugP_log1("UART:(%p) HwiP_create() failed", hwAttrs->baseAddr);
522         UARTCC32XX_close(handle);
523         return (NULL);
524     }
525 
526     SemaphoreP_Params_init(&semParams);
527     semParams.mode = SemaphoreP_Mode_BINARY;
528 
529     /* If write mode is blocking create a semaphore and set callback. */
530     if (object->state.writeMode == UART_MODE_BLOCKING) {
531         if ((object->writeSem = SemaphoreP_create(0, &semParams)) == NULL) {
532             DebugP_log1("UART:(%p) SemaphoreP_create() failed.",
533                 hwAttrs->baseAddr);
534             UARTCC32XX_close(handle);
535             return (NULL);
536         }
537         object->writeCallback = &writeSemCallback;
538     }
539 
540     ClockP_Params_init(&clockParams);
541     clockParams.arg = (uintptr_t)handle;
542 
543     /* If read mode is blocking create a semaphore and set callback. */
544     if (object->state.readMode == UART_MODE_BLOCKING) {
545         object->readSem = SemaphoreP_create(0, &semParams);
546         if (object->readSem == NULL) {
547             DebugP_log1("UART:(%p) SemaphoreP_create() failed.",
548                 hwAttrs->baseAddr);
549             UARTCC32XX_close(handle);
550             return (NULL);
551         }
552         object->readCallback = &readSemCallback;
553         object->timeoutClk =
554             ClockP_create((ClockP_Fxn)&readBlockingTimeout,
555                     0 /* timeout */, &(clockParams));
556         if (object->timeoutClk == NULL) {
557             DebugP_log1("UART:(%p) ClockP_create() failed.",
558                 hwAttrs->baseAddr);
559             UARTCC32XX_close(handle);
560             return (NULL);
561         }
562     }
563     else {
564         object->state.drainByISR = false;
565     }
566 
567     /* Initialize the hardware */
568     initHw(handle);
569 
570     DebugP_log1("UART:(%p) opened", hwAttrs->baseAddr);
571 
572     /* Return the handle */
573     return (handle);
574 }
575 
576 /*
577  *  ======== UARTCC32XX_read ========
578  */
UARTCC32XX_read(UART_Handle handle,void * buffer,size_t size)579 int_fast32_t UARTCC32XX_read(UART_Handle handle, void *buffer, size_t size)
580 {
581     uintptr_t           key;
582     UARTCC32XX_Object  *object = handle->object;
583 
584     key = HwiP_disable();
585 
586     if ((object->state.readMode == UART_MODE_CALLBACK) && object->readSize) {
587         HwiP_restore(key);
588 
589         DebugP_log1("UART:(%p) Could not read data, uart in use.",
590                 ((UARTCC32XX_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
591         return (UART_ERROR);
592     }
593 
594     /* Save the data to be read and restore interrupts. */
595     object->readBuf = buffer;
596     object->readSize = size;
597     object->readCount = size;
598 
599     HwiP_restore(key);
600 
601     return (object->readFxns.readTaskFxn(handle));
602 }
603 
604 /*
605  *  ======== UARTCC32XX_readCancel ========
606  */
UARTCC32XX_readCancel(UART_Handle handle)607 void UARTCC32XX_readCancel(UART_Handle handle)
608 {
609     uintptr_t             key;
610     UARTCC32XX_Object    *object = handle->object;
611 
612     if ((object->state.readMode != UART_MODE_CALLBACK) ||
613         (object->readSize == 0)) {
614         return;
615     }
616 
617     key = HwiP_disable();
618 
619     object->state.drainByISR = false;
620     /*
621      * Indicate that what we've currently received is what we asked for so that
622      * the existing logic handles the completion.
623      */
624     object->readSize -= object->readCount;
625     object->readCount = 0;
626 
627     HwiP_restore(key);
628 
629     object->readFxns.readTaskFxn(handle);
630 }
631 
632 /*
633  *  ======== UARTCC32XX_readPolling ========
634  */
UARTCC32XX_readPolling(UART_Handle handle,void * buf,size_t size)635 int_fast32_t UARTCC32XX_readPolling(UART_Handle handle, void *buf, size_t size)
636 {
637     int32_t                      count = 0;
638     UARTCC32XX_Object           *object = handle->object;
639     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
640     unsigned char               *buffer = (unsigned char *)buf;
641 
642     /* Read characters. */
643     while (size) {
644         /* Grab data from the RingBuf before getting it from the RX data reg */
645         MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT);
646         if (RingBuf_get(&object->ringBuffer, buffer) == -1) {
647             *buffer = MAP_UARTCharGet(hwAttrs->baseAddr);
648         }
649         if (object->state.rxEnabled) {
650             MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT);
651         }
652 
653         DebugP_log2("UART:(%p) Read character 0x%x", hwAttrs->baseAddr,
654             *buffer);
655         count++;
656         size--;
657 
658         if (object->state.readDataMode == UART_DATA_TEXT && *buffer == '\r') {
659             /* Echo character if enabled. */
660             if (object->state.readEcho) {
661                 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
662             }
663             *buffer = '\n';
664         }
665 
666         /* Echo character if enabled. */
667         if (object->state.readDataMode == UART_DATA_TEXT &&
668                 object->state.readEcho) {
669             MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
670         }
671 
672         /* If read return mode is newline, finish if a newline was received. */
673         if (object->state.readDataMode == UART_DATA_TEXT &&
674                 object->state.readReturnMode == UART_RETURN_NEWLINE &&
675                 *buffer == '\n') {
676             return (count);
677         }
678 
679         buffer++;
680     }
681 
682     DebugP_log2("UART:(%p) Read polling finished, %d bytes read",
683         hwAttrs->baseAddr, count);
684 
685     return (count);
686 }
687 
688 /*
689  *  ======== UARTCC32XX_write ========
690  */
UARTCC32XX_write(UART_Handle handle,const void * buffer,size_t size)691 int_fast32_t UARTCC32XX_write(UART_Handle handle, const void *buffer,
692         size_t size)
693 {
694     unsigned int                 key;
695     UARTCC32XX_Object           *object = handle->object;
696     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
697 
698     if (!size) {
699         return 0;
700     }
701 
702     key = HwiP_disable();
703 
704     if (object->writeCount || UARTBusy(hwAttrs->baseAddr)) {
705         HwiP_restore(key);
706         DebugP_log1("UART:(%p) Could not write data, uart in use.",
707             hwAttrs->baseAddr);
708 
709         return (UART_ERROR);
710     }
711 
712     /* Save the data to be written and restore interrupts. */
713     object->writeBuf = buffer;
714     object->writeSize = size;
715     object->writeCount = size;
716 
717     if (object->state.txEnabled == false){
718         object->state.txEnabled = true;
719         Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
720         DebugP_log1("UART:(%p) UART_write set write power constraint",
721             hwAttrs->baseAddr);
722     }
723 
724     HwiP_restore(key);
725 
726     if (!(MAP_UARTIntStatus(hwAttrs->baseAddr, false) & UART_INT_TX)) {
727         /*
728          *  Start the transfer going if the raw interrupt status TX bit
729          *  is 0.  This will cause the ISR to fire when we enable
730          *  UART_INT_TX.  If the RIS TX bit is not cleared, we don't
731          *  need to call writeData(), since the ISR will fire once we
732          *  enable the interrupt, causing the transfer to start.
733          */
734         writeData(handle, false);
735     }
736     if (object->writeCount) {
737         MAP_UARTTxIntModeSet(hwAttrs->baseAddr, UART_TXINT_MODE_FIFO);
738         MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_TX);
739     }
740 
741     /* If writeMode is blocking, block and get the state. */
742     if (object->state.writeMode == UART_MODE_BLOCKING) {
743         /* Pend on semaphore and wait for Hwi to finish. */
744         if (SemaphoreP_OK != SemaphoreP_pend(object->writeSem,
745                     object->writeTimeout)) {
746             /* Semaphore timed out, make the write empty and log the write. */
747             MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
748             MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_TX);
749             object->writeCount = 0;
750 
751             DebugP_log2("UART:(%p) Write timed out, %d bytes written",
752                 hwAttrs->baseAddr, object->writeCount);
753         }
754         return (object->writeSize - object->writeCount);
755     }
756 
757     return (0);
758 }
759 
760 /*
761  *  ======== UARTCC32XX_writeCancel ========
762  */
UARTCC32XX_writeCancel(UART_Handle handle)763 void UARTCC32XX_writeCancel(UART_Handle handle)
764 {
765     uintptr_t                    key;
766     UARTCC32XX_Object           *object = handle->object;
767     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
768     unsigned int                 written;
769     uint_fast16_t                retVal;
770 
771     key = HwiP_disable();
772 
773     /* Return if there is no write. */
774     if (!object->writeCount) {
775         HwiP_restore(key);
776         return;
777     }
778 
779     /* Set size = 0 to prevent writing and restore interrupts. */
780     written = object->writeCount;
781     object->writeCount = 0;
782     MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
783     MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_TX);
784 
785     retVal = Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
786     DebugP_assert(retVal == Power_SOK);
787     object->state.txEnabled = false;
788 
789     HwiP_restore(key);
790 
791     /* Reset the write buffer so we can pass it back */
792     object->writeCallback(handle, (void *)object->writeBuf,
793         object->writeSize - written);
794 
795     DebugP_log2("UART:(%p) Write canceled, %d bytes written",
796         hwAttrs->baseAddr, object->writeSize - written);
797 
798     (void)retVal;
799 }
800 
801 /*
802  *  ======== UARTCC32XX_writePolling ========
803  */
UARTCC32XX_writePolling(UART_Handle handle,const void * buf,size_t size)804 int_fast32_t UARTCC32XX_writePolling(UART_Handle handle, const void *buf,
805         size_t size)
806 {
807     int32_t                    count = 0;
808     UARTCC32XX_Object         *object = handle->object;
809     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
810     unsigned char             *buffer = (unsigned char *)buf;
811 
812     /* Write characters. */
813     while (size) {
814         if (object->state.writeDataMode == UART_DATA_TEXT && *buffer == '\n') {
815             MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
816             count++;
817         }
818         MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
819 
820         DebugP_log2("UART:(%p) Wrote character 0x%x", hwAttrs->baseAddr,
821             *buffer);
822         buffer++;
823         count++;
824         size--;
825     }
826 
827     while (MAP_UARTBusy(hwAttrs->baseAddr)) {
828         ;
829     }
830 
831     DebugP_log2("UART:(%p) Write polling finished, %d bytes written",
832         hwAttrs->baseAddr, count);
833 
834     return (count);
835 }
836 
837 /*
838  *  ======== getPowerMgrId ========
839  */
getPowerMgrId(unsigned int baseAddr)840 static unsigned int getPowerMgrId(unsigned int baseAddr)
841 {
842     switch (baseAddr) {
843         case UARTA0_BASE:
844             return (PowerCC32XX_PERIPH_UARTA0);
845         case UARTA1_BASE:
846             return (PowerCC32XX_PERIPH_UARTA1);
847         default:
848             return ((unsigned int)-1);
849     }
850 }
851 
852 /*
853  *  ======== initHw ========
854  */
initHw(UART_Handle handle)855 static void initHw(UART_Handle handle)
856 {
857     ClockP_FreqHz                 freq;
858     UARTCC32XX_Object            *object = handle->object;
859     UARTCC32XX_HWAttrsV1 const   *hwAttrs = handle->hwAttrs;
860 
861     /* Enable UART and its interrupt. */
862     MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_TX | UART_INT_RX |
863             UART_INT_RT);
864     MAP_UARTEnable(hwAttrs->baseAddr);
865 
866     /* Set the FIFO level to 7/8 empty and 4/8 full. */
867     MAP_UARTFIFOLevelSet(hwAttrs->baseAddr, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
868 
869     if (isFlowControlEnabled(hwAttrs)) {
870         /* Set flow control */
871         MAP_UARTFlowControlSet(hwAttrs->baseAddr,
872                 UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX);
873     }
874     else {
875         MAP_UARTFlowControlSet(hwAttrs->baseAddr, UART_FLOWCONTROL_NONE);
876     }
877 
878     ClockP_getCpuFreq(&freq);
879     MAP_UARTConfigSetExpClk(hwAttrs->baseAddr, freq.lo, object->baudRate,
880         dataLength[object->dataLength] | stopBits[object->stopBits] |
881         parityType[object->parityType]);
882 
883     MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_RX | UART_INT_RT |
884         UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE);
885 }
886 
887 /*
888  *  ======== postNotifyFxn ========
889  *  Called by Power module when waking up from LPDS.
890  */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)891 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
892         uintptr_t clientArg)
893 {
894     initHw((UART_Handle)clientArg);
895 
896     return (Power_NOTIFYDONE);
897 }
898 
899 /*
900  *  ======== readBlockingTimeout ========
901  */
readBlockingTimeout(uintptr_t arg)902 static void readBlockingTimeout(uintptr_t arg)
903 {
904     UARTCC32XX_Object *object = ((UART_Handle)arg)->object;
905     object->state.bufTimeout = true;
906     SemaphoreP_post(object->readSem);
907 }
908 
909 /*
910  *  ======== readIsrBinaryBlocking ========
911  *  Function that is called by the ISR
912  */
readIsrBinaryBlocking(UART_Handle handle)913 static bool readIsrBinaryBlocking(UART_Handle handle)
914 {
915     UARTCC32XX_Object           *object = handle->object;
916     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
917     int                          readIn;
918 
919     while (MAP_UARTCharsAvail(hwAttrs->baseAddr)) {
920         /*
921          *  If the Ring buffer is full, leave the data in the FIFO.
922          *  This will allow flow control to work, if it is enabled.
923          */
924         if (RingBuf_isFull(&object->ringBuffer)) {
925             return (false);
926         }
927 
928         readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
929         /*
930          *  Bits 0-7 contain the data, bits 8-11 are used for error codes.
931          *  (Bits 12-31 are reserved and read as 0)  If readIn > 0xFF, an
932          *  error has occurred.
933          */
934         if (readIn > 0xFF) {
935             if (hwAttrs->errorFxn) {
936                 hwAttrs->errorFxn(handle, (uint32_t)((readIn >> 8) & 0xF));
937             }
938             MAP_UARTRxErrorClear(hwAttrs->baseAddr);
939             return (false);
940         }
941 
942         RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
943 
944         if (object->state.callCallback) {
945             object->state.callCallback = false;
946             object->readCallback(handle, NULL, 0);
947         }
948     }
949     return (true);
950 }
951 
952 /*
953  *  ======== readIsrBinaryCallback ========
954  */
readIsrBinaryCallback(UART_Handle handle)955 static bool readIsrBinaryCallback(UART_Handle handle)
956 {
957     UARTCC32XX_Object           *object = handle->object;
958     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
959     int                          readIn;
960     bool                         ret = true;
961 
962     while (MAP_UARTCharsAvail(hwAttrs->baseAddr)) {
963         if (RingBuf_isFull(&object->ringBuffer)) {
964             ret = false;
965             break;
966         }
967 
968         readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
969         if (readIn > 0xFF) {
970             if (hwAttrs->errorFxn) {
971                 hwAttrs->errorFxn(handle, (uint32_t)((readIn >> 8) & 0xF));
972             }
973             MAP_UARTRxErrorClear(hwAttrs->baseAddr);
974             ret = false;
975             break;
976         }
977 
978         RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
979     }
980 
981     /*
982      * Check and see if a UART_read in callback mode told use to continue
983      * servicing the user buffer...
984      */
985     if (object->state.drainByISR) {
986         readTaskCallback(handle);
987     }
988 
989     return (ret);
990 }
991 
992 /*
993  *  ======== readIsrTextBlocking ========
994  */
readIsrTextBlocking(UART_Handle handle)995 static bool readIsrTextBlocking(UART_Handle handle)
996 {
997     UARTCC32XX_Object           *object = handle->object;
998     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
999     int                          readIn;
1000 
1001     while (MAP_UARTCharsAvail(hwAttrs->baseAddr)) {
1002         /*
1003          *  If the Ring buffer is full, leave the data in the FIFO.
1004          *  This will allow flow control to work, if it is enabled.
1005          */
1006         if (RingBuf_isFull(&object->ringBuffer)) {
1007             return (false);
1008         }
1009 
1010         readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
1011         if (readIn > 0xFF) {
1012             if (hwAttrs->errorFxn) {
1013                 hwAttrs->errorFxn(handle, (uint32_t)((readIn >> 8) & 0xF));
1014             }
1015             MAP_UARTRxErrorClear(hwAttrs->baseAddr);
1016             return (false);
1017         }
1018 
1019         if (readIn == '\r') {
1020             /* Echo character if enabled. */
1021             if (object->state.readEcho) {
1022                 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
1023             }
1024             readIn = '\n';
1025         }
1026         RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
1027 
1028         if (object->state.readEcho) {
1029             MAP_UARTCharPut(hwAttrs->baseAddr, (unsigned char)readIn);
1030         }
1031         if (object->state.callCallback) {
1032             object->state.callCallback = false;
1033             object->readCallback(handle, NULL, 0);
1034         }
1035     }
1036     return (true);
1037 }
1038 
1039 /*
1040  *  ======== readIsrTextCallback ========
1041  */
readIsrTextCallback(UART_Handle handle)1042 static bool readIsrTextCallback(UART_Handle handle)
1043 {
1044     UARTCC32XX_Object           *object = handle->object;
1045     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
1046     int                          readIn;
1047     bool                         ret = true;
1048 
1049     while (MAP_UARTCharsAvail(hwAttrs->baseAddr)) {
1050         /*
1051          *  If the Ring buffer is full, leave the data in the FIFO.
1052          *  This will allow flow control to work, if it is enabled.
1053          */
1054         if (RingBuf_isFull(&object->ringBuffer)) {
1055             ret = false;
1056             break;
1057         }
1058 
1059         readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
1060         if (readIn > 0xFF) {
1061             if (hwAttrs->errorFxn) {
1062                 hwAttrs->errorFxn(handle, (uint32_t)((readIn >> 8) & 0xF));
1063             }
1064             MAP_UARTRxErrorClear(hwAttrs->baseAddr);
1065             ret = false;
1066             break;
1067         }
1068 
1069         if (readIn == '\r') {
1070             /* Echo character if enabled. */
1071             if (object->state.readEcho) {
1072                 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
1073             }
1074             readIn = '\n';
1075         }
1076         RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
1077 
1078         if (object->state.readEcho) {
1079             MAP_UARTCharPut(hwAttrs->baseAddr, (unsigned char)readIn);
1080         }
1081     }
1082 
1083     /*
1084      * Check and see if a UART_read in callback mode told use to continue
1085      * servicing the user buffer...
1086      */
1087     if (object->state.drainByISR) {
1088         readTaskCallback(handle);
1089     }
1090 
1091     return (ret);
1092 }
1093 
1094 /*
1095  *  ======== readSemCallback ========
1096  *  Simple callback to post a semaphore for the blocking mode.
1097  */
readSemCallback(UART_Handle handle,void * buffer,size_t count)1098 static void readSemCallback(UART_Handle handle, void *buffer, size_t count)
1099 {
1100     UARTCC32XX_Object *object = handle->object;
1101 
1102     SemaphoreP_post(object->readSem);
1103 }
1104 
1105 /*
1106  *  ======== readTaskBlocking ========
1107  */
readTaskBlocking(UART_Handle handle)1108 static int readTaskBlocking(UART_Handle handle)
1109 {
1110     unsigned char              readIn;
1111     uintptr_t                  key;
1112     UARTCC32XX_Object         *object = handle->object;
1113     unsigned char             *buffer = object->readBuf;
1114 
1115     object->state.bufTimeout = false;
1116     object->state.callCallback = false;
1117 
1118     /*
1119      * It is possible for the object->timeoutClk and the callback function to
1120      * have posted the object->readSem Semaphore from the previous UART_read
1121      * call (if the code below didn't get to stop the clock object in time).
1122      * To clear this, we simply do a NO_WAIT pend on (binary) object->readSem
1123      * so that it resets the Semaphore count.
1124      */
1125     SemaphoreP_pend(object->readSem, SemaphoreP_NO_WAIT);
1126 
1127     if ((object->readTimeout != 0) &&
1128                 (object->readTimeout != UART_WAIT_FOREVER)) {
1129         ClockP_setTimeout(object->timeoutClk, object->readTimeout);
1130         ClockP_start(object->timeoutClk);
1131     }
1132 
1133     while (object->readCount) {
1134         key = HwiP_disable();
1135 
1136         if (ringBufGet(handle, &readIn) < 0) {
1137             object->state.callCallback = true;
1138             HwiP_restore(key);
1139 
1140             if (object->readTimeout == 0) {
1141                 break;
1142             }
1143 
1144             SemaphoreP_pend(object->readSem, SemaphoreP_WAIT_FOREVER);
1145             if (object->state.bufTimeout == true) {
1146                 break;
1147             }
1148             ringBufGet(handle, &readIn);
1149         }
1150         else {
1151             HwiP_restore(key);
1152         }
1153 
1154         *buffer = readIn;
1155         buffer++;
1156         /* In blocking mode, readCount doesn't not need a lock */
1157         object->readCount--;
1158 
1159         if (object->state.readDataMode == UART_DATA_TEXT &&
1160                 object->state.readReturnMode == UART_RETURN_NEWLINE &&
1161                 readIn == '\n') {
1162             break;
1163         }
1164     }
1165 
1166     ClockP_stop(object->timeoutClk);
1167     return (object->readSize - object->readCount);
1168 }
1169 
1170 /*
1171  *  ======== readTaskCallback ========
1172  *  This function is called the first time by the UART_read task and tries to
1173  *  get all the data it can get from the ringBuffer. If it finished, it will
1174  *  perform the user supplied callback. If it didn't finish, the ISR must handle
1175  *  the remaining data. By setting the drainByISR flag, the UART_read function
1176  *  handed over the responsibility to get the remaining data to the ISR.
1177  */
readTaskCallback(UART_Handle handle)1178 static int readTaskCallback(UART_Handle handle)
1179 {
1180     unsigned int               key;
1181     UARTCC32XX_Object         *object = handle->object;
1182     unsigned char              readIn;
1183     unsigned char             *bufferEnd;
1184     bool                       makeCallback = false;
1185     size_t                     tempCount;
1186 
1187     object->state.drainByISR = false;
1188     bufferEnd = (unsigned char*) object->readBuf + object->readSize;
1189 
1190     while (object->readCount) {
1191         key = HwiP_disable();
1192         if (ringBufGet(handle, &readIn) < 0) {
1193             /* Not all data has been read */
1194             object->state.drainByISR = true;
1195             HwiP_restore(key);
1196             break;
1197         }
1198         HwiP_restore(key);
1199 
1200         *(unsigned char *) (bufferEnd - object->readCount *
1201             sizeof(unsigned char)) = readIn;
1202 
1203         object->readCount--;
1204 
1205         if ((object->state.readDataMode == UART_DATA_TEXT) &&
1206                 (object->state.readReturnMode == UART_RETURN_NEWLINE) &&
1207                 (readIn == '\n')) {
1208             makeCallback = true;
1209             break;
1210         }
1211     }
1212 
1213     if (!object->readCount || makeCallback) {
1214         object->state.readCallbackPending = true;
1215         if (object->state.inReadCallback == false) {
1216             while (object->state.readCallbackPending) {
1217                 object->state.readCallbackPending = false;
1218                 tempCount = object->readSize;
1219                 object->readSize = 0;
1220 
1221                 object->state.inReadCallback = true;
1222                 object->readCallback(handle, object->readBuf,
1223                         tempCount - object->readCount);
1224                 object->state.inReadCallback = false;
1225             }
1226         }
1227     }
1228 
1229     return (0);
1230 }
1231 
1232 /*
1233  *  ======== releasePowerConstraint ========
1234  */
releasePowerConstraint(UART_Handle handle)1235 static void releasePowerConstraint(UART_Handle handle)
1236 {
1237     UARTCC32XX_Object *object = handle->object;
1238     uint_fast16_t      retVal;
1239 
1240     retVal = Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1241     DebugP_assert(retVal == Power_SOK);
1242     object->state.txEnabled = false;
1243 
1244     DebugP_log1("UART:(%p) UART released write power constraint",
1245         ((UARTCC32XX_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
1246 
1247     (void)retVal;
1248 }
1249 
1250 
1251 /*
1252  *  ======== ringBufGet ========
1253  */
ringBufGet(UART_Handle handle,unsigned char * data)1254 static int ringBufGet(UART_Handle handle, unsigned char *data)
1255 {
1256     UARTCC32XX_Object      *object = handle->object;
1257     UARTCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1258     uintptr_t               key;
1259     int32_t                 readIn;
1260     int                     count;
1261 
1262     key = HwiP_disable();
1263 
1264     if (RingBuf_isFull(&object->ringBuffer)) {
1265         count = RingBuf_get(&object->ringBuffer, data);
1266 
1267         readIn = MAP_UARTCharGetNonBlocking(hwAttrs->baseAddr);
1268         if (readIn != -1) {
1269             RingBuf_put(&object->ringBuffer, (unsigned char)readIn);
1270             count++;
1271         }
1272         HwiP_restore(key);
1273     }
1274     else {
1275         count = RingBuf_get(&object->ringBuffer, data);
1276         HwiP_restore(key);
1277     }
1278 
1279     return (count);
1280 }
1281 
1282 /*
1283  *  ======== writeData ========
1284  */
writeData(UART_Handle handle,bool inISR)1285 static void writeData(UART_Handle handle, bool inISR)
1286 {
1287     UARTCC32XX_Object           *object = handle->object;
1288     UARTCC32XX_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
1289     unsigned char               *writeOffset;
1290 
1291     writeOffset = (unsigned char *)object->writeBuf +
1292         object->writeSize * sizeof(unsigned char);
1293     while (object->writeCount) {
1294         if (!MAP_UARTCharPutNonBlocking(hwAttrs->baseAddr,
1295                 *(writeOffset - object->writeCount))) {
1296             /* TX FIFO is FULL */
1297             break;
1298         }
1299         if ((object->state.writeDataMode == UART_DATA_TEXT) &&
1300             (*(writeOffset - object->writeCount) == '\n')) {
1301             MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
1302         }
1303         object->writeCount--;
1304     }
1305 
1306     if (!object->writeCount) {
1307         MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_TX);
1308         MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_TX);
1309 
1310         /*
1311          *  Set TX interrupt for end of transmission mode.
1312          *  The TXRIS bit will be set only when all the data
1313          *  (including stop bits) have left the serializer.
1314          */
1315         MAP_UARTTxIntModeSet(hwAttrs->baseAddr, UART_TXINT_MODE_EOT);
1316 
1317         if (!UARTBusy(hwAttrs->baseAddr)) {
1318             object->writeCallback(handle, (void *)object->writeBuf,
1319                     object->writeSize);
1320             releasePowerConstraint(handle);
1321         }
1322         else {
1323             UARTIntEnable(hwAttrs->baseAddr, UART_INT_TX);
1324         }
1325 
1326         DebugP_log2("UART:(%p) Write finished, %d bytes written",
1327             hwAttrs->baseAddr, object->writeSize - object->writeCount);
1328     }
1329 }
1330 
1331 /*
1332  *  ======== writeSemCallback ========
1333  *  Simple callback to post a semaphore for the blocking mode.
1334  */
writeSemCallback(UART_Handle handle,void * buffer,size_t count)1335 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count)
1336 {
1337     UARTCC32XX_Object *object = handle->object;
1338 
1339     SemaphoreP_post(object->writeSem);
1340 }
1341