1 /** 2 * \file 3 * 4 * \brief Universal Asynchronous Receiver Transceiver (UART) driver for SAM. 5 * 6 * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved. 7 * 8 * \asf_license_start 9 * 10 * \page License 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright notice, 16 * this list of conditions and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright notice, 19 * this list of conditions and the following disclaimer in the documentation 20 * and/or other materials provided with the distribution. 21 * 22 * 3. The name of Atmel may not be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * 4. This software may only be redistributed and used in connection with an 26 * Atmel microcontroller product. 27 * 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 * 40 * \asf_license_stop 41 * 42 */ 43 /* 44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> 45 */ 46 47 #include "uart.h" 48 49 /// @cond 0 50 /**INDENT-OFF**/ 51 #ifdef __cplusplus 52 extern "C" { 53 #endif 54 /**INDENT-ON**/ 55 /// @endcond 56 57 /** 58 * \defgroup sam_drivers_uart_group Universal Asynchronous Receiver Transceiver (UART) 59 * 60 * The Universal Asynchronous Receiver Transmitter features a two-pin UART that 61 * can be used for communication and trace purposes and offers an ideal medium 62 * for in-situ programming solutions. Moreover, the association with two 63 * peripheral DMA controller (PDC) channels permits packet handling for these 64 * tasks with processor time reduced to a minimum. 65 * 66 * \par Usage 67 * 68 * -# Enable the UART peripheral clock in the PMC. 69 * -# Enable the required UART PIOs (see pio.h). 70 * -# Configure the UART by calling uart_init. 71 * -# Send data through the UART using the uart_write. 72 * -# Receive data from the UART using the uart_read; the availability of data 73 * can be polled with uart_is_rx_ready. 74 * -# Disable the transmitter and/or the receiver of the UART with 75 * uart_disable_tx and uart_disable_rx. 76 * 77 * @{ 78 */ 79 80 /** 81 * \brief Configure UART with the specified parameters. 82 * 83 * \note The PMC and PIOs must be configured first. 84 * 85 * \param p_uart Pointer to a UART instance. 86 * \param p_uart_opt Pointer to sam_uart_opt_t instance. 87 * 88 * \retval 0 Success. 89 * \retval 1 Bad baud rate generator value. 90 */ 91 uint32_t uart_init(Uart *p_uart, const sam_uart_opt_t *p_uart_opt) 92 { 93 uint32_t cd = 0; 94 95 /* Reset and disable receiver & transmitter */ 96 p_uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX 97 | UART_CR_RXDIS | UART_CR_TXDIS; 98 99 /* Check and configure baudrate */ 100 /* Asynchronous, no oversampling */ 101 cd = (p_uart_opt->ul_mck / p_uart_opt->ul_baudrate) / UART_MCK_DIV; 102 if (cd < UART_MCK_DIV_MIN_FACTOR || cd > UART_MCK_DIV_MAX_FACTOR) 103 return 1; 104 105 p_uart->UART_BRGR = cd; 106 /* Configure mode */ 107 p_uart->UART_MR = p_uart_opt->ul_mode; 108 109 #if (!SAMV71 && !SAMV70 && !SAME70 && !SAMS70) 110 /* Disable PDC channel */ 111 p_uart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; 112 #endif 113 114 /* Enable receiver and transmitter */ 115 p_uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; 116 117 return 0; 118 } 119 120 /** 121 * \brief Enable UART transmitter. 122 * 123 * \param p_uart Pointer to a UART instance. 124 */ 125 void uart_enable_tx(Uart *p_uart) 126 { 127 /* Enable transmitter */ 128 p_uart->UART_CR = UART_CR_TXEN; 129 } 130 131 /** 132 * \brief Disable UART transmitter. 133 * 134 * \param p_uart Pointer to a UART instance. 135 */ 136 void uart_disable_tx(Uart *p_uart) 137 { 138 /* Disable transmitter */ 139 p_uart->UART_CR = UART_CR_TXDIS; 140 } 141 142 /** 143 * \brief Reset UART transmitter. 144 * 145 * \param p_uart Pointer to a UART instance. 146 */ 147 void uart_reset_tx(Uart *p_uart) 148 { 149 /* Reset transmitter */ 150 p_uart->UART_CR = UART_CR_RSTTX | UART_CR_TXDIS; 151 } 152 153 /** 154 * \brief Enable UART receiver. 155 * 156 * \param p_uart Pointer to a UART instance. 157 */ 158 void uart_enable_rx(Uart *p_uart) 159 { 160 /* Enable receiver */ 161 p_uart->UART_CR = UART_CR_RXEN; 162 } 163 164 /** 165 * \brief Disable UART receiver. 166 * 167 * \param p_uart Pointer to a UART instance. 168 */ 169 void uart_disable_rx(Uart *p_uart) 170 { 171 /* Disable receiver */ 172 p_uart->UART_CR = UART_CR_RXDIS; 173 } 174 175 /** 176 * \brief Reset UART receiver. 177 * 178 * \param p_uart Pointer to a UART instance. 179 */ 180 void uart_reset_rx(Uart *p_uart) 181 { 182 /* Reset receiver */ 183 p_uart->UART_CR = UART_CR_RSTRX | UART_CR_RXDIS; 184 } 185 186 /** 187 * \brief Enable UART receiver and transmitter. 188 * 189 * \param p_uart Pointer to a UART instance. 190 */ 191 void uart_enable(Uart *p_uart) 192 { 193 /* Enable receiver and transmitter */ 194 p_uart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; 195 } 196 197 /** 198 * \brief Disable UART receiver and transmitter. 199 * 200 * \param p_uart Pointer to a UART instance. 201 */ 202 void uart_disable(Uart *p_uart) 203 { 204 /* Disable receiver and transmitter */ 205 p_uart->UART_CR = UART_CR_RXDIS | UART_CR_TXDIS; 206 } 207 208 /** 209 * \brief Reset UART receiver and transmitter. 210 * 211 * \param p_uart Pointer to a UART instance. 212 */ 213 void uart_reset(Uart *p_uart) 214 { 215 /* Reset and disable receiver & transmitter */ 216 p_uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX 217 | UART_CR_RXDIS | UART_CR_TXDIS; 218 } 219 220 /** \brief Enable UART interrupts. 221 * 222 * \param p_uart Pointer to a UART instance. 223 * \param ul_sources Interrupts to be enabled. 224 */ 225 void uart_enable_interrupt(Uart *p_uart, uint32_t ul_sources) 226 { 227 p_uart->UART_IER = ul_sources; 228 } 229 230 /** \brief Disable UART interrupts. 231 * 232 * \param p_uart Pointer to a UART instance. 233 * \param ul_sources Interrupts to be disabled. 234 */ 235 void uart_disable_interrupt(Uart *p_uart, uint32_t ul_sources) 236 { 237 p_uart->UART_IDR = ul_sources; 238 } 239 240 /** \brief Read UART interrupt mask. 241 * 242 * \param p_uart Pointer to a UART instance. 243 * 244 * \return The interrupt mask value. 245 */ 246 uint32_t uart_get_interrupt_mask(Uart *p_uart) 247 { 248 return p_uart->UART_IMR; 249 } 250 251 /** 252 * \brief Get current status. 253 * 254 * \param p_uart Pointer to a UART instance. 255 * 256 * \return The current UART status. 257 */ 258 uint32_t uart_get_status(Uart *p_uart) 259 { 260 return p_uart->UART_SR; 261 } 262 263 /** 264 * \brief Reset status bits. 265 * 266 * \param p_uart Pointer to a UART instance. 267 */ 268 void uart_reset_status(Uart *p_uart) 269 { 270 p_uart->UART_CR = UART_CR_RSTSTA; 271 } 272 273 /** 274 * \brief Check if Transmit is Ready. 275 * Check if data has been loaded in UART_THR and is waiting to be loaded in the 276 * Transmit Shift Register (TSR). 277 * 278 * \param p_uart Pointer to a UART instance. 279 * 280 * \retval 1 Data has been transmitted. 281 * \retval 0 Transmit is not ready, data pending. 282 */ 283 uint32_t uart_is_tx_ready(Uart *p_uart) 284 { 285 return (p_uart->UART_SR & UART_SR_TXRDY) > 0; 286 } 287 288 /** 289 * \brief Check if Transmit Hold Register is empty. 290 * Check if the last data written in UART_THR has been loaded in TSR and the 291 * last data loaded in TSR has been transmitted. 292 * 293 * \param p_uart Pointer to a UART instance. 294 * 295 * \retval 1 Transmitter is empty. 296 * \retval 0 Transmitter is not empty. 297 */ 298 uint32_t uart_is_tx_empty(Uart *p_uart) 299 { 300 return (p_uart->UART_SR & UART_SR_TXEMPTY) > 0; 301 } 302 303 /** 304 * \brief Check if Received data is ready. 305 * Check if data has been received and loaded in UART_RHR. 306 * 307 * \param p_uart Pointer to a UART instance. 308 * 309 * \retval 1 One data has been received. 310 * \retval 0 No data has been received. 311 */ 312 uint32_t uart_is_rx_ready(Uart *p_uart) 313 { 314 return (p_uart->UART_SR & UART_SR_RXRDY) > 0; 315 } 316 317 /** 318 * \brief Check if both transmit buffers are sent out. 319 * 320 * \param p_uart Pointer to a UART instance. 321 * 322 * \retval 1 Transmit buffer is empty. 323 * \retval 0 Transmit buffer is not empty. 324 */ 325 uint32_t uart_is_tx_buf_empty(Uart *p_uart) 326 { 327 return (p_uart->UART_SR & UART_SR_TXEMPTY) > 0; 328 } 329 330 /** 331 * \brief Set UART clock divisor value 332 * 333 * \param p_uart Pointer to a UART instance. 334 * \param us_divisor Value to be set. 335 * 336 */ 337 void uart_set_clock_divisor(Uart *p_uart, uint16_t us_divisor) 338 { 339 p_uart->UART_BRGR = us_divisor; 340 } 341 342 /** 343 * \brief Write to UART Transmit Holding Register 344 * Before writing user should check if tx is ready (or empty). 345 * 346 * \param p_uart Pointer to a UART instance. 347 * \param data Data to be sent. 348 * 349 * \retval 0 Success. 350 * \retval 1 I/O Failure, UART is not ready. 351 */ 352 uint32_t uart_write(Uart *p_uart, const uint8_t uc_data) 353 { 354 /* Check if the transmitter is ready */ 355 if (!(p_uart->UART_SR & UART_SR_TXRDY)) 356 return 1; 357 358 /* Send character */ 359 p_uart->UART_THR = uc_data; 360 return 0; 361 } 362 363 /** 364 * \brief Read from UART Receive Holding Register. 365 * Before reading user should check if rx is ready. 366 * 367 * \param p_uart Pointer to a UART instance. 368 * 369 * \retval 0 Success. 370 * \retval 1 I/O Failure, UART is not ready. 371 */ 372 uint32_t uart_read(Uart *p_uart, uint8_t *puc_data) 373 { 374 /* Check if the receiver is ready */ 375 if ((p_uart->UART_SR & UART_SR_RXRDY) == 0) 376 return 1; 377 378 /* Read character */ 379 *puc_data = (uint8_t) p_uart->UART_RHR; 380 return 0; 381 } 382 383 #if (!SAMV71 && !SAMV70 && !SAME70 && !SAMS70) 384 /** 385 * \brief Check if one receive buffer is filled. 386 * 387 * \param p_uart Pointer to a UART instance. 388 * 389 * \retval 1 Receive is completed. 390 * \retval 0 Receive is still pending. 391 */ 392 uint32_t uart_is_rx_buf_end(Uart *p_uart) 393 { 394 return (p_uart->UART_SR & UART_SR_ENDRX) > 0; 395 } 396 397 /** 398 * \brief Check if one transmit buffer is sent out. 399 * 400 * \param p_uart Pointer to a UART instance. 401 * 402 * \retval 1 Transmit is completed. 403 * \retval 0 Transmit is still pending. 404 */ 405 uint32_t uart_is_tx_buf_end(Uart *p_uart) 406 { 407 return (p_uart->UART_SR & UART_SR_ENDTX) > 0; 408 } 409 410 /** 411 * \brief Check if both receive buffers are full. 412 * 413 * \param p_uart Pointer to a UART instance. 414 * 415 * \retval 1 Receive buffers are full. 416 * \retval 0 Receive buffers are not full. 417 */ 418 uint32_t uart_is_rx_buf_full(Uart *p_uart) 419 { 420 return (p_uart->UART_SR & UART_SR_RXBUFF) > 0; 421 } 422 423 /** 424 * \brief Get UART PDC base address. 425 * 426 * \param p_uart Pointer to a UART instance. 427 * 428 * \return UART PDC registers base for PDC driver to access. 429 */ 430 Pdc *uart_get_pdc_base(Uart *p_uart) 431 { 432 Pdc *p_pdc_base; 433 434 #if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM) 435 if (p_uart == UART0) 436 p_pdc_base = PDC_UART0; 437 #elif (SAM3XA || SAM3U) 438 if (p_uart == UART) 439 p_pdc_base = PDC_UART; 440 #else 441 #error "Unsupported device" 442 #endif 443 444 #if (SAM3S || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM) 445 if (p_uart == UART1) 446 p_pdc_base = PDC_UART1; 447 #endif 448 449 #if (SAM4N) 450 if (p_uart == UART2) 451 p_pdc_base = PDC_UART2; 452 #endif 453 454 return p_pdc_base; 455 } 456 #endif 457 458 #if (SAM4C || SAM4CP || SAM4CM) 459 /** 460 * \brief Enable UART optical interface. 461 * 462 * \param p_uart Pointer to a UART instance. 463 */ 464 void uart_enable_optical_interface(Uart *p_uart) 465 { 466 Assert(p_uart == UART1); 467 p_uart->UART_MR |= UART_MR_OPT_EN; 468 } 469 470 /** 471 * \brief Disable UART optical interface. 472 * 473 * \param p_uart Pointer to a UART instance. 474 */ 475 void uart_disable_optical_interface(Uart *p_uart) 476 { 477 Assert(p_uart == UART1); 478 p_uart->UART_MR &= ~UART_MR_OPT_EN; 479 } 480 481 /** 482 * \brief Enable UART optical interface. 483 * 484 * \param p_uart Pointer to a UART instance. 485 * \param cfg Pointer to a UART optical interface configuration. 486 */ 487 void uart_config_optical_interface(Uart *p_uart, 488 struct uart_config_optical *cfg) 489 { 490 Assert(p_uart == UART1); 491 uint32_t reg = p_uart->UART_MR; 492 493 reg &= ~(UART_MR_OPT_RXINV | UART_MR_OPT_MDINV | UART_MR_FILTER 494 | UART_MR_OPT_CLKDIV_Msk | UART_MR_OPT_DUTY_Msk 495 | UART_MR_OPT_CMPTH_Msk); 496 reg |= (cfg->rx_inverted ? UART_MR_OPT_RXINV : 0) 497 | (cfg->tx_inverted ? UART_MR_OPT_MDINV : 0) 498 | (cfg->rx_filter ? UART_MR_FILTER : 0) 499 | UART_MR_OPT_CLKDIV(cfg->clk_div) 500 | cfg->duty | cfg->threshold; 501 502 p_uart->UART_MR = reg; 503 } 504 #endif 505 506 #if (SAMG53 || SAMG54 || SAMV71 || SAMV70 || SAME70 || SAMS70) 507 /** 508 * \brief Set sleepwalking match mode. 509 * 510 * \param p_uart Pointer to a UART instance. 511 * \param ul_low_value First comparison value for received character. 512 * \param ul_high_value Second comparison value for received character. 513 * \param cmpmode ture for start condition, false for flag only. 514 * \param cmppar ture for parity check, false for no. 515 */ 516 void uart_set_sleepwalking(Uart *p_uart, uint8_t ul_low_value, 517 bool cmpmode, bool cmppar, uint8_t ul_high_value) 518 { 519 Assert(ul_low_value <= ul_high_value); 520 521 uint32_t temp = 0; 522 523 if (cmpmode) { 524 temp |= UART_CMPR_CMPMODE_START_CONDITION; 525 } 526 527 if (cmppar) { 528 temp |= UART_CMPR_CMPPAR; 529 } 530 531 temp |= UART_CMPR_VAL1(ul_low_value); 532 533 temp |= UART_CMPR_VAL2(ul_high_value); 534 535 p_uart->UART_CMPR= temp; 536 } 537 538 /** 539 * \brief Enables/Disables write protection mode. 540 * 541 * \param p_uart Pointer to a UART instance. 542 * \param flag ture for enable, false for disable. 543 */ 544 void uart_set_write_protection(Uart *p_uart, bool flag) 545 { 546 if (flag) { 547 p_uart->UART_WPMR = UART_WPMR_WPKEY_PASSWD | UART_WPMR_WPEN; 548 } else { 549 p_uart->UART_WPMR = UART_WPMR_WPKEY_PASSWD; 550 } 551 } 552 #endif 553 554 //@} 555 556 /// @cond 0 557 /**INDENT-OFF**/ 558 #ifdef __cplusplus 559 } 560 #endif 561 /**INDENT-ON**/ 562 /// @endcond 563