xref: /btstack/port/msp432p401lp-cc256x/ti/devices/msp432p4xx/driverlib/uart.c (revision 5fd0122a3e19d95e11e1f3eb8a08a2b2acb2557e)
1 /* --COPYRIGHT--,BSD
2  * Copyright (c) 2017, 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  * --/COPYRIGHT--*/
32 #include <ti/devices/msp432p4xx/driverlib/uart.h>
33 #include <ti/devices/msp432p4xx/driverlib/interrupt.h>
34 #include <ti/devices/msp432p4xx/driverlib/debug.h>
35 #include <ti/devices/msp432p4xx/driverlib/eusci.h>
36 
UART_initModule(uint32_t moduleInstance,const eUSCI_UART_ConfigV1 * config)37 bool UART_initModule(uint32_t moduleInstance, const eUSCI_UART_ConfigV1 *config)
38 {
39     bool retVal = true;
40 
41     ASSERT(
42             (EUSCI_A_UART_MODE == config->uartMode)
43             || (EUSCI_A_UART_IDLE_LINE_MULTI_PROCESSOR_MODE
44                     == config->uartMode)
45             || (EUSCI_A_UART_ADDRESS_BIT_MULTI_PROCESSOR_MODE
46                     == config->uartMode)
47             || (EUSCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE
48                     == config->uartMode));
49 
50     ASSERT(
51             (EUSCI_A_UART_CLOCKSOURCE_ACLK == config->selectClockSource)
52             || (EUSCI_A_UART_CLOCKSOURCE_SMCLK
53                     == config->selectClockSource));
54 
55     ASSERT(
56             (EUSCI_A_UART_MSB_FIRST == config->msborLsbFirst)
57             || (EUSCI_A_UART_LSB_FIRST == config->msborLsbFirst));
58 
59     ASSERT(
60             (EUSCI_A_UART_ONE_STOP_BIT == config->numberofStopBits)
61             || (EUSCI_A_UART_TWO_STOP_BITS == config->numberofStopBits));
62 
63     ASSERT(
64             (EUSCI_A_UART_NO_PARITY == config->parity)
65             || (EUSCI_A_UART_ODD_PARITY == config->parity)
66             || (EUSCI_A_UART_EVEN_PARITY == config->parity));
67     ASSERT(
68             (EUSCI_A_UART_8_BIT_LEN == config->dataLength)
69             || (EUSCI_A_UART_7_BIT_LEN == config->dataLength));
70 
71     /* Disable the USCI Module */
72     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_SWRST_OFS) = 1;
73 
74     /* Clock source select */
75     EUSCI_A_CMSIS(moduleInstance)->CTLW0 =
76             (EUSCI_A_CMSIS(moduleInstance)->CTLW0 & ~EUSCI_A_CTLW0_SSEL_MASK)
77                     | config->selectClockSource;
78 
79     /* MSB, LSB select */
80     if (config->msborLsbFirst)
81         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_MSB_OFS) = 1;
82     else
83         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_MSB_OFS) = 0;
84 
85     /* UCSPB = 0(1 stop bit) OR 1(2 stop bits) */
86     if (config->numberofStopBits)
87         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_SPB_OFS) = 1;
88     else
89         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_SPB_OFS) = 0;
90 
91     /* Parity */
92     switch (config->parity)
93     {
94     case EUSCI_A_UART_NO_PARITY:
95         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_PEN_OFS) = 0;
96         break;
97     case EUSCI_A_UART_ODD_PARITY:
98         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_PEN_OFS) = 1;
99         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_PAR_OFS) = 0;
100         break;
101     case EUSCI_A_UART_EVEN_PARITY:
102         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_PEN_OFS) = 1;
103         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_PAR_OFS) = 1;
104         break;
105     }
106 
107     /* UC7BIT = 0(8 bit) OR 1(7 bit) */
108     if (config->dataLength)
109         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_B_CTLW0_SEVENBIT_OFS) = 1;
110     else
111         BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_B_CTLW0_SEVENBIT_OFS) = 0;
112 
113     /* BaudRate Control Register */
114     EUSCI_A_CMSIS(moduleInstance)->BRW = config->clockPrescalar;
115     EUSCI_A_CMSIS(moduleInstance)->MCTLW = ((config->secondModReg << 8)
116             + (config->firstModReg << 4) + config->overSampling);
117 
118     /* Asynchronous mode & 8 bit character select & clear mode */
119     EUSCI_A_CMSIS(moduleInstance)->CTLW0 =
120             (EUSCI_A_CMSIS(moduleInstance)->CTLW0
121                     & ~(EUSCI_A_CTLW0_SYNC | EUSCI_A_CTLW0_MODE_3 | EUSCI_A_CTLW0_RXEIE | EUSCI_A_CTLW0_BRKIE | EUSCI_A_CTLW0_DORM
122                             | EUSCI_A_CTLW0_TXADDR | EUSCI_A_CTLW0_TXBRK)) | config->uartMode;
123 
124     return retVal;
125 }
126 
UART_transmitData(uint32_t moduleInstance,uint_fast8_t transmitData)127 void UART_transmitData(uint32_t moduleInstance, uint_fast8_t transmitData)
128 {
129     /* If interrupts are not used, poll for flags */
130     if (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IE, EUSCI_A_IE_TXIE_OFS))
131         while (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IFG, EUSCI_A_IFG_TXIFG_OFS))
132             ;
133 
134     EUSCI_A_CMSIS(moduleInstance)->TXBUF = transmitData;
135 }
136 
UART_receiveData(uint32_t moduleInstance)137 uint8_t UART_receiveData(uint32_t moduleInstance)
138 {
139     /* If interrupts are not used, poll for flags */
140     if (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IE, EUSCI_A_IE_RXIE_OFS))
141         while (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IFG, EUSCI_A_IFG_RXIFG_OFS))
142             ;
143 
144     return EUSCI_A_CMSIS(moduleInstance)->RXBUF;
145 }
146 
UART_enableModule(uint32_t moduleInstance)147 void UART_enableModule(uint32_t moduleInstance)
148 {
149     /* Reset the UCSWRST bit to enable the USCI Module */
150     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_SWRST_OFS) = 0;
151 }
152 
UART_disableModule(uint32_t moduleInstance)153 void UART_disableModule(uint32_t moduleInstance)
154 {
155     /* Set the UCSWRST bit to disable the USCI Module */
156     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_SWRST_OFS) = 1;
157 }
158 
UART_queryStatusFlags(uint32_t moduleInstance,uint_fast8_t mask)159 uint_fast8_t UART_queryStatusFlags(uint32_t moduleInstance, uint_fast8_t mask)
160 {
161     ASSERT(
162             0x00 != mask
163             && (EUSCI_A_UART_LISTEN_ENABLE + EUSCI_A_UART_FRAMING_ERROR
164                     + EUSCI_A_UART_OVERRUN_ERROR
165                     + EUSCI_A_UART_PARITY_ERROR
166                     + EUSCI_A_UART_BREAK_DETECT
167                     + EUSCI_A_UART_RECEIVE_ERROR
168                     + EUSCI_A_UART_ADDRESS_RECEIVED
169                     + EUSCI_A_UART_IDLELINE + EUSCI_A_UART_BUSY));
170 
171     return EUSCI_A_CMSIS(moduleInstance)->STATW & mask;
172 }
173 
UART_setDormant(uint32_t moduleInstance)174 void UART_setDormant(uint32_t moduleInstance)
175 {
176     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_DORM_OFS) = 1;
177 }
178 
UART_resetDormant(uint32_t moduleInstance)179 void UART_resetDormant(uint32_t moduleInstance)
180 {
181     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_DORM_OFS) = 0;
182 }
183 
UART_transmitAddress(uint32_t moduleInstance,uint_fast8_t transmitAddress)184 void UART_transmitAddress(uint32_t moduleInstance, uint_fast8_t transmitAddress)
185 {
186     /* Set UCTXADDR bit */
187     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_TXADDR_OFS) = 1;
188 
189     /* Place next byte to be sent into the transmit buffer */
190     EUSCI_A_CMSIS(moduleInstance)->TXBUF = transmitAddress;
191 }
192 
UART_transmitBreak(uint32_t moduleInstance)193 void UART_transmitBreak(uint32_t moduleInstance)
194 {
195     /* Set UCTXADDR bit */
196     BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_TXBRK_OFS) = 1;
197 
198     /* If current mode is automatic baud-rate detection */
199     if (EUSCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE
200             == (EUSCI_A_CMSIS(moduleInstance)->CTLW0
201                     & EUSCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE))
202         EUSCI_A_CMSIS(moduleInstance)->TXBUF =
203         EUSCI_A_UART_AUTOMATICBAUDRATE_SYNC;
204     else
205         EUSCI_A_CMSIS(moduleInstance)->TXBUF = DEFAULT_SYNC;
206 
207     /* If interrupts are not used, poll for flags */
208     if (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IE, EUSCI_A_IE_TXIE_OFS))
209         while (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->IFG, EUSCI_A_IFG_TXIFG_OFS))
210             ;
211 }
212 
UART_getReceiveBufferAddressForDMA(uint32_t moduleInstance)213 uint32_t UART_getReceiveBufferAddressForDMA(uint32_t moduleInstance)
214 {
215     return (uint32_t)&EUSCI_A_CMSIS(moduleInstance)->RXBUF;
216 }
217 
UART_getTransmitBufferAddressForDMA(uint32_t moduleInstance)218 uint32_t UART_getTransmitBufferAddressForDMA(uint32_t moduleInstance)
219 {
220     return (uint32_t)&EUSCI_B_CMSIS(moduleInstance)->TXBUF;
221 }
222 
UART_selectDeglitchTime(uint32_t moduleInstance,uint32_t deglitchTime)223 void UART_selectDeglitchTime(uint32_t moduleInstance, uint32_t deglitchTime)
224 {
225     ASSERT(
226             (EUSCI_A_UART_DEGLITCH_TIME_2ns == deglitchTime)
227             || (EUSCI_A_UART_DEGLITCH_TIME_50ns == deglitchTime)
228             || (EUSCI_A_UART_DEGLITCH_TIME_100ns == deglitchTime)
229             || (EUSCI_A_UART_DEGLITCH_TIME_200ns == deglitchTime));
230 
231     EUSCI_A_CMSIS(moduleInstance)->CTLW1 =
232             (EUSCI_A_CMSIS(moduleInstance)->CTLW1 & ~(EUSCI_A_CTLW1_GLIT_MASK))
233                     | deglitchTime;
234 
235 }
236 
UART_enableInterrupt(uint32_t moduleInstance,uint_fast8_t mask)237 void UART_enableInterrupt(uint32_t moduleInstance, uint_fast8_t mask)
238 {
239     uint_fast8_t locMask;
240 
241     ASSERT(
242             !(mask
243                     & ~(EUSCI_A_UART_RECEIVE_INTERRUPT
244                             | EUSCI_A_UART_TRANSMIT_INTERRUPT
245                             | EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
246                             | EUSCI_A_UART_BREAKCHAR_INTERRUPT
247                             | EUSCI_A_UART_STARTBIT_INTERRUPT
248                             | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT)));
249 
250     locMask = (mask
251             & (EUSCI_A_UART_RECEIVE_INTERRUPT | EUSCI_A_UART_TRANSMIT_INTERRUPT
252                     | EUSCI_A_UART_STARTBIT_INTERRUPT
253                     | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT));
254 
255     EUSCI_A_CMSIS(moduleInstance)->IE |= locMask;
256 
257     locMask = (mask
258             & (EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
259                     | EUSCI_A_UART_BREAKCHAR_INTERRUPT));
260     EUSCI_A_CMSIS(moduleInstance)->CTLW0 |= locMask;
261 }
262 
UART_disableInterrupt(uint32_t moduleInstance,uint_fast8_t mask)263 void UART_disableInterrupt(uint32_t moduleInstance, uint_fast8_t mask)
264 {
265     uint_fast8_t locMask;
266 
267     ASSERT(
268             !(mask
269                     & ~(EUSCI_A_UART_RECEIVE_INTERRUPT
270                             | EUSCI_A_UART_TRANSMIT_INTERRUPT
271                             | EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
272                             | EUSCI_A_UART_BREAKCHAR_INTERRUPT
273                             | EUSCI_A_UART_STARTBIT_INTERRUPT
274                             | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT)));
275 
276     locMask = (mask
277             & (EUSCI_A_UART_RECEIVE_INTERRUPT | EUSCI_A_UART_TRANSMIT_INTERRUPT
278                     | EUSCI_A_UART_STARTBIT_INTERRUPT
279                     | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT));
280     EUSCI_A_CMSIS(moduleInstance)->IE &= ~locMask;
281 
282     locMask = (mask
283             & (EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT
284                     | EUSCI_A_UART_BREAKCHAR_INTERRUPT));
285     EUSCI_A_CMSIS(moduleInstance)->CTLW0 &= ~locMask;
286 }
287 
UART_getInterruptStatus(uint32_t moduleInstance,uint8_t mask)288 uint_fast8_t UART_getInterruptStatus(uint32_t moduleInstance, uint8_t mask)
289 {
290     ASSERT(
291             !(mask
292                     & ~(EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
293                             | EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG
294                             | EUSCI_A_UART_STARTBIT_INTERRUPT_FLAG
295                             | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG)));
296 
297     return EUSCI_A_CMSIS(moduleInstance)->IFG & mask;
298 }
299 
UART_getEnabledInterruptStatus(uint32_t moduleInstance)300 uint_fast8_t UART_getEnabledInterruptStatus(uint32_t moduleInstance)
301 {
302     uint_fast8_t intStatus = UART_getInterruptStatus(moduleInstance,
303     EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG | EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG);
304     uint_fast8_t intEnabled = EUSCI_A_CMSIS(moduleInstance)->IE;
305 
306     if (!(intEnabled & EUSCI_A_UART_RECEIVE_INTERRUPT))
307     {
308         intStatus &= ((uint_fast8_t)~EUSCI_A_UART_RECEIVE_INTERRUPT);
309     }
310 
311     if (!(intEnabled & EUSCI_A_UART_TRANSMIT_INTERRUPT))
312     {
313         intStatus &= ((uint_fast8_t)~EUSCI_A_UART_TRANSMIT_INTERRUPT);
314     }
315     if(!(intEnabled & EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT))
316     {
317         intStatus &= ((uint_fast8_t)~EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT);
318     }
319 
320     intEnabled = EUSCI_A_CMSIS(moduleInstance)->CTLW0;
321 
322     if (!(intEnabled & EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT))
323     {
324         intStatus &= ((uint_fast8_t)~EUSCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT);
325     }
326 
327     if (!(intEnabled & EUSCI_A_UART_BREAKCHAR_INTERRUPT))
328     {
329         intStatus &= ((uint_fast8_t)~EUSCI_A_UART_BREAKCHAR_INTERRUPT);
330     }
331 
332     return intStatus;
333 }
334 
UART_clearInterruptFlag(uint32_t moduleInstance,uint_fast8_t mask)335 void UART_clearInterruptFlag(uint32_t moduleInstance, uint_fast8_t mask)
336 {
337     ASSERT(
338             !(mask
339                     & ~(EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
340                             | EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG
341                             | EUSCI_A_UART_STARTBIT_INTERRUPT_FLAG
342                             | EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG)));
343 
344     //Clear the UART interrupt source.
345     EUSCI_A_CMSIS(moduleInstance)->IFG &= ~(mask);
346 }
347 
UART_registerInterrupt(uint32_t moduleInstance,void (* intHandler)(void))348 void UART_registerInterrupt(uint32_t moduleInstance, void (*intHandler)(void))
349 {
350     switch (moduleInstance)
351     {
352     case EUSCI_A0_BASE:
353         Interrupt_registerInterrupt(INT_EUSCIA0, intHandler);
354         Interrupt_enableInterrupt(INT_EUSCIA0);
355         break;
356     case EUSCI_A1_BASE:
357         Interrupt_registerInterrupt(INT_EUSCIA1, intHandler);
358         Interrupt_enableInterrupt(INT_EUSCIA1);
359         break;
360 #ifdef EUSCI_A2_BASE
361     case EUSCI_A2_BASE:
362         Interrupt_registerInterrupt(INT_EUSCIA2, intHandler);
363         Interrupt_enableInterrupt(INT_EUSCIA2);
364         break;
365 #endif
366 #ifdef EUSCI_A3_BASE
367     case EUSCI_A3_BASE:
368         Interrupt_registerInterrupt(INT_EUSCIA3, intHandler);
369         Interrupt_enableInterrupt(INT_EUSCIA3);
370         break;
371 #endif
372     default:
373         ASSERT(false);
374     }
375 }
376 
UART_unregisterInterrupt(uint32_t moduleInstance)377 void UART_unregisterInterrupt(uint32_t moduleInstance)
378 {
379     switch (moduleInstance)
380     {
381     case EUSCI_A0_BASE:
382         Interrupt_disableInterrupt(INT_EUSCIA0);
383         Interrupt_unregisterInterrupt(INT_EUSCIA0);
384         break;
385     case EUSCI_A1_BASE:
386         Interrupt_disableInterrupt(INT_EUSCIA1);
387         Interrupt_unregisterInterrupt(INT_EUSCIA1);
388         break;
389 #ifdef EUSCI_A2_BASE
390     case EUSCI_A2_BASE:
391         Interrupt_disableInterrupt(INT_EUSCIA2);
392         Interrupt_unregisterInterrupt(INT_EUSCIA2);
393         break;
394 #endif
395 #ifdef EUSCI_A3_BASE
396     case EUSCI_A3_BASE:
397         Interrupt_disableInterrupt(INT_EUSCIA3);
398         Interrupt_unregisterInterrupt(INT_EUSCIA3);
399         break;
400 #endif
401     default:
402         ASSERT(false);
403     }
404 }
405