xref: /btstack/port/samv71-xplained-atwilc3000/ASF/sam/drivers/uart/uart.c (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
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