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 */
uart_init(Uart * p_uart,const sam_uart_opt_t * p_uart_opt)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 */
uart_enable_tx(Uart * p_uart)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 */
uart_disable_tx(Uart * p_uart)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 */
uart_reset_tx(Uart * p_uart)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 */
uart_enable_rx(Uart * p_uart)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 */
uart_disable_rx(Uart * p_uart)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 */
uart_reset_rx(Uart * p_uart)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 */
uart_enable(Uart * p_uart)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 */
uart_disable(Uart * p_uart)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 */
uart_reset(Uart * p_uart)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 */
uart_enable_interrupt(Uart * p_uart,uint32_t ul_sources)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 */
uart_disable_interrupt(Uart * p_uart,uint32_t ul_sources)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 */
uart_get_interrupt_mask(Uart * p_uart)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 */
uart_get_status(Uart * p_uart)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 */
uart_reset_status(Uart * p_uart)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 */
uart_is_tx_ready(Uart * p_uart)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 */
uart_is_tx_empty(Uart * p_uart)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 */
uart_is_rx_ready(Uart * p_uart)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 */
uart_is_tx_buf_empty(Uart * p_uart)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 */
uart_set_clock_divisor(Uart * p_uart,uint16_t us_divisor)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 */
uart_write(Uart * p_uart,const uint8_t uc_data)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 */
uart_read(Uart * p_uart,uint8_t * puc_data)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 */
uart_is_rx_buf_end(Uart * p_uart)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 */
uart_is_tx_buf_end(Uart * p_uart)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 */
uart_is_rx_buf_full(Uart * p_uart)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 */
uart_get_pdc_base(Uart * p_uart)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 */
uart_enable_optical_interface(Uart * p_uart)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 */
uart_disable_optical_interface(Uart * p_uart)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 */
uart_config_optical_interface(Uart * p_uart,struct uart_config_optical * cfg)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 */
uart_set_sleepwalking(Uart * p_uart,uint8_t ul_low_value,bool cmpmode,bool cmppar,uint8_t ul_high_value)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 */
uart_set_write_protection(Uart * p_uart,bool flag)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