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 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 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 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 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 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 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 174 void UART_setDormant(uint32_t moduleInstance) 175 { 176 BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_DORM_OFS) = 1; 177 } 178 179 void UART_resetDormant(uint32_t moduleInstance) 180 { 181 BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->CTLW0, EUSCI_A_CTLW0_DORM_OFS) = 0; 182 } 183 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 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 213 uint32_t UART_getReceiveBufferAddressForDMA(uint32_t moduleInstance) 214 { 215 return (uint32_t)&EUSCI_A_CMSIS(moduleInstance)->RXBUF; 216 } 217 218 uint32_t UART_getTransmitBufferAddressForDMA(uint32_t moduleInstance) 219 { 220 return (uint32_t)&EUSCI_B_CMSIS(moduleInstance)->TXBUF; 221 } 222 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 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 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 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 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 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 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 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