1 /**
2  * \file
3  *
4  * \brief SAM SERCOM USART Asynchronous Driver
5  *
6  * Copyright (C) 2012-2016 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 "usart_interrupt.h"
48 
49 /**
50  * \internal
51  * Asynchronous write of a buffer with a given length
52  *
53  * \param[in]  module   Pointer to USART software instance struct
54  * \param[in]  tx_data  Pointer to data to be transmitted
55  * \param[in]  length   Length of data buffer
56  *
57  */
_usart_write_buffer(struct usart_module * const module,uint8_t * tx_data,uint16_t length)58 enum status_code _usart_write_buffer(
59 		struct usart_module *const module,
60 		uint8_t *tx_data,
61 		uint16_t length)
62 {
63 	/* Sanity check arguments */
64 	Assert(module);
65 	Assert(module->hw);
66 	Assert(tx_data);
67 
68 	/* Get a pointer to the hardware module instance */
69 	SercomUsart *const usart_hw = &(module->hw->USART);
70 
71 	system_interrupt_enter_critical_section();
72 
73 	/* Check if the USART transmitter is busy */
74 	if (module->remaining_tx_buffer_length > 0) {
75 		system_interrupt_leave_critical_section();
76 		return STATUS_BUSY;
77 	}
78 
79 	/* Write parameters to the device instance */
80 	module->remaining_tx_buffer_length = length;
81 
82 	system_interrupt_leave_critical_section();
83 
84 	module->tx_buffer_ptr              = tx_data;
85 	module->tx_status                  = STATUS_BUSY;
86 
87 	/* Enable the Data Register Empty Interrupt */
88 	usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_DRE;
89 
90 	return STATUS_OK;
91 }
92 
93 /**
94  * \internal
95  * Asynchronous read of a buffer with a given length
96  *
97  * \param[in]  module   Pointer to USART software instance struct
98  * \param[in]  rx_data  Pointer to data to be received
99  * \param[in]  length   Length of data buffer
100  *
101  */
_usart_read_buffer(struct usart_module * const module,uint8_t * rx_data,uint16_t length)102 enum status_code _usart_read_buffer(
103 		struct usart_module *const module,
104 		uint8_t *rx_data,
105 		uint16_t length)
106 {
107 	/* Sanity check arguments */
108 	Assert(module);
109 	Assert(module->hw);
110 	Assert(rx_data);
111 
112 	/* Get a pointer to the hardware module instance */
113 	SercomUsart *const usart_hw = &(module->hw->USART);
114 
115 	system_interrupt_enter_critical_section();
116 
117 	/* Check if the USART receiver is busy */
118 	if (module->remaining_rx_buffer_length > 0) {
119 		system_interrupt_leave_critical_section();
120 		return STATUS_BUSY;
121 	}
122 
123 	/* Set length for the buffer and the pointer, and let
124 	 * the interrupt handler do the rest */
125 	module->remaining_rx_buffer_length = length;
126 
127 	system_interrupt_leave_critical_section();
128 
129 	module->rx_buffer_ptr              = rx_data;
130 	module->rx_status                  = STATUS_BUSY;
131 
132 	/* Enable the RX Complete Interrupt */
133 	usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
134 
135 #ifdef FEATURE_USART_LIN_SLAVE
136 	/* Enable the break character is received Interrupt */
137 	if(module->lin_slave_enabled) {
138 		usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXBRK;
139 	}
140 #endif
141 
142 #ifdef FEATURE_USART_START_FRAME_DECTION
143 	/* Enable a start condition is detected Interrupt */
144 	if(module->start_frame_detection_enabled) {
145 		usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXS;
146 	}
147 #endif
148 
149 	return STATUS_OK;
150 }
151 
152 /**
153  * \brief Registers a callback
154  *
155  * Registers a callback function, which is implemented by the user.
156  *
157  * \note The callback must be enabled by \ref usart_enable_callback
158  *       in order for the interrupt handler to call it when the conditions for
159  *       the callback type are met.
160  *
161  * \param[in]  module         Pointer to USART software instance struct
162  * \param[in]  callback_func  Pointer to callback function
163  * \param[in]  callback_type  Callback type given by an enum
164  *
165  */
usart_register_callback(struct usart_module * const module,usart_callback_t callback_func,enum usart_callback callback_type)166 void usart_register_callback(
167 		struct usart_module *const module,
168 		usart_callback_t callback_func,
169 		enum usart_callback callback_type)
170 {
171 	/* Sanity check arguments */
172 	Assert(module);
173 	Assert(callback_func);
174 
175 	/* Register callback function */
176 	module->callback[callback_type] = callback_func;
177 
178 	/* Set the bit corresponding to the callback_type */
179 	module->callback_reg_mask |= (1 << callback_type);
180 }
181 
182 /**
183  * \brief Unregisters a callback
184  *
185  * Unregisters a callback function, which is implemented by the user.
186  *
187  * \param[in,out]  module         Pointer to USART software instance struct
188  * \param[in]      callback_type  Callback type given by an enum
189  *
190  */
usart_unregister_callback(struct usart_module * const module,enum usart_callback callback_type)191 void usart_unregister_callback(
192 		struct usart_module *const module,
193 		enum usart_callback callback_type)
194 {
195 	/* Sanity check arguments */
196 	Assert(module);
197 
198 	/* Unregister callback function */
199 	module->callback[callback_type] = NULL;
200 
201 	/* Clear the bit corresponding to the callback_type */
202 	module->callback_reg_mask &= ~(1 << callback_type);
203 }
204 
205 /**
206  * \brief Asynchronous write a single char
207  *
208  * Sets up the driver to write the data given. If registered and enabled,
209  * a callback function will be called when the transmit is completed.
210  *
211  * \param[in]  module   Pointer to USART software instance struct
212  * \param[in]  tx_data  Data to transfer
213  *
214  * \returns Status of the operation.
215  * \retval STATUS_OK         If operation was completed
216  * \retval STATUS_BUSY       If operation was not completed, due to the
217  *                           USART module being busy
218  * \retval STATUS_ERR_DENIED If the transmitter is not enabled
219  */
usart_write_job(struct usart_module * const module,const uint16_t * tx_data)220 enum status_code usart_write_job(
221 		struct usart_module *const module,
222 		const uint16_t *tx_data)
223 {
224 	/* Sanity check arguments */
225 	Assert(module);
226 	Assert(tx_data);
227 
228 
229 	/* Check that the transmitter is enabled */
230 	if (!(module->transmitter_enabled)) {
231 		return STATUS_ERR_DENIED;
232 	}
233 
234 	/* Call internal write buffer function with length 1 */
235 	return _usart_write_buffer(module, (uint8_t *)tx_data, 1);
236 }
237 
238 /**
239  * \brief Asynchronous read a single char
240  *
241  * Sets up the driver to read data from the USART module to the data
242  * pointer given. If registered and enabled, a callback will be called
243  * when the receiving is completed.
244  *
245  * \param[in]   module   Pointer to USART software instance struct
246  * \param[out]  rx_data  Pointer to where received data should be put
247  *
248  * \returns Status of the operation.
249  * \retval  STATUS_OK    If operation was completed
250  * \retval  STATUS_BUSY  If operation was not completed
251  */
usart_read_job(struct usart_module * const module,uint16_t * const rx_data)252 enum status_code usart_read_job(
253 		struct usart_module *const module,
254 		uint16_t *const rx_data)
255 {
256 	/* Sanity check arguments */
257 	Assert(module);
258 	Assert(rx_data);
259 
260 	/* Call internal read buffer function with length 1 */
261 	return _usart_read_buffer(module, (uint8_t *)rx_data, 1);
262 }
263 
264 /**
265  * \brief Asynchronous buffer write
266  *
267  * Sets up the driver to write a given buffer over the USART. If registered and
268  * enabled, a callback function will be called.
269  *
270  * \param[in]  module   Pointer to USART software instance struct
271  * \param[in]  tx_data  Pointer do data buffer to transmit
272  * \param[in]  length   Length of the data to transmit
273  *
274  * \note If using 9-bit data, the array that *tx_data point to should be defined
275  *       as uint16_t array and should be casted to uint8_t* pointer. Because it
276  *       is an address pointer, the highest byte is not discarded. For example:
277  *   \code
278           #define TX_LEN 3
279           uint16_t tx_buf[TX_LEN] = {0x0111, 0x0022, 0x0133};
280           usart_write_buffer_job(&module, (uint8_t*)tx_buf, TX_LEN);
281     \endcode
282  *
283  * \returns Status of the operation.
284  * \retval STATUS_OK              If operation was completed successfully.
285  * \retval STATUS_BUSY            If operation was not completed, due to the
286  *                                USART module being busy
287  * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
288  *                                arguments
289  * \retval STATUS_ERR_DENIED      If the transmitter is not enabled
290  */
usart_write_buffer_job(struct usart_module * const module,uint8_t * tx_data,uint16_t length)291 enum status_code usart_write_buffer_job(
292 		struct usart_module *const module,
293 		uint8_t *tx_data,
294 		uint16_t length)
295 {
296 	/* Sanity check arguments */
297 	Assert(module);
298 	Assert(tx_data);
299 
300 	if (length == 0) {
301 		return STATUS_ERR_INVALID_ARG;
302 	}
303 
304 	/* Check that the transmitter is enabled */
305 	if (!(module->transmitter_enabled)) {
306 		return STATUS_ERR_DENIED;
307 	}
308 
309 	/* Issue internal asynchronous write */
310 	return _usart_write_buffer(module, tx_data, length);
311 }
312 
313 /**
314  * \brief Asynchronous buffer read
315  *
316  * Sets up the driver to read from the USART to a given buffer. If registered
317  * and enabled, a callback function will be called.
318  *
319  * \param[in]  module   Pointer to USART software instance struct
320  * \param[out] rx_data  Pointer to data buffer to receive
321  * \param[in]  length   Data buffer length
322  *
323  * \note If using 9-bit data, the array that *rx_data point to should be defined
324  *       as uint16_t array and should be casted to uint8_t* pointer. Because it
325  *       is an address pointer, the highest byte is not discarded. For example:
326  *   \code
327            #define RX_LEN 3
328            uint16_t rx_buf[RX_LEN] = {0x0,};
329            usart_read_buffer_job(&module, (uint8_t*)rx_buf, RX_LEN);
330     \endcode
331  *
332  * \returns Status of the operation.
333  * \retval STATUS_OK              If operation was completed
334  * \retval STATUS_BUSY            If operation was not completed, due to the
335  *                                USART module being busy
336  * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
337  *                                arguments
338  * \retval STATUS_ERR_DENIED      If the transmitter is not enabled
339  */
usart_read_buffer_job(struct usart_module * const module,uint8_t * rx_data,uint16_t length)340 enum status_code usart_read_buffer_job(
341 		struct usart_module *const module,
342 		uint8_t *rx_data,
343 		uint16_t length)
344 {
345 	/* Sanity check arguments */
346 	Assert(module);
347 	Assert(rx_data);
348 
349 	if (length == 0) {
350 		return STATUS_ERR_INVALID_ARG;
351 	}
352 
353 	/* Check that the receiver is enabled */
354 	if (!(module->receiver_enabled)) {
355 		return STATUS_ERR_DENIED;
356 	}
357 
358 	/* Issue internal asynchronous read */
359 	return _usart_read_buffer(module, rx_data, length);
360 }
361 
362 /**
363  * \brief Cancels ongoing read/write operation
364  *
365  * Cancels the ongoing read/write operation modifying parameters in the
366  * USART software struct.
367  *
368  * \param[in]  module            Pointer to USART software instance struct
369  * \param[in]  transceiver_type  Transfer type to cancel
370  */
usart_abort_job(struct usart_module * const module,enum usart_transceiver_type transceiver_type)371 void usart_abort_job(
372 		struct usart_module *const module,
373 		enum usart_transceiver_type transceiver_type)
374 {
375 	/* Sanity check arguments */
376 	Assert(module);
377 	Assert(module->hw);
378 
379 	/* Get a pointer to the hardware module instance */
380 	SercomUsart *const usart_hw = &(module->hw->USART);
381 
382 	switch(transceiver_type) {
383 		case USART_TRANSCEIVER_RX:
384 			/* Clear the interrupt flag in order to prevent the receive
385 			 * complete callback to fire */
386 			usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
387 
388 			/* Clear the software reception buffer */
389 			module->remaining_rx_buffer_length = 0;
390 
391 			break;
392 
393 		case USART_TRANSCEIVER_TX:
394 			/* Clear the interrupt flag in order to prevent the receive
395 			 * complete callback to fire */
396 			usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
397 
398 			/* Clear the software reception buffer */
399 			module->remaining_tx_buffer_length = 0;
400 
401 			break;
402 	}
403 }
404 
405 /**
406  * \brief Get status from the ongoing or last asynchronous transfer operation
407  *
408  * Returns the error from a given ongoing or last asynchronous transfer operation.
409  * Either from a read or write transfer.
410  *
411  * \param[in]  module            Pointer to USART software instance struct
412  * \param[in]  transceiver_type  Transfer type to check
413   *
414  * \return Status of the given job.
415  * \retval STATUS_OK               No error occurred during the last transfer
416  * \retval STATUS_BUSY             A transfer is ongoing
417  * \retval STATUS_ERR_BAD_DATA     The last operation was aborted due to a
418  *                                 parity error. The transfer could be affected
419  *                                 by external noise
420  * \retval STATUS_ERR_BAD_FORMAT   The last operation was aborted due to a
421  *                                 frame error
422  * \retval STATUS_ERR_OVERFLOW     The last operation was aborted due to a
423  *                                 buffer overflow
424  * \retval STATUS_ERR_INVALID_ARG  An invalid transceiver enum given
425  */
usart_get_job_status(struct usart_module * const module,enum usart_transceiver_type transceiver_type)426 enum status_code usart_get_job_status(
427 		struct usart_module *const module,
428 		enum usart_transceiver_type transceiver_type)
429 {
430 	/* Sanity check arguments */
431 	Assert(module);
432 
433 	/* Variable for status code */
434 	enum status_code status_code;
435 
436 	switch(transceiver_type) {
437 	case USART_TRANSCEIVER_RX:
438 			status_code = module->rx_status;
439 			break;
440 
441 	case USART_TRANSCEIVER_TX:
442 			status_code = module->tx_status;
443 			break;
444 
445 	default:
446 			status_code = STATUS_ERR_INVALID_ARG;
447 			break;
448 	}
449 
450 	return status_code;
451 }
452 
453 /**
454  * \internal
455  * Handles interrupts as they occur, and it will run callback functions
456  * which are registered and enabled.
457  *
458  * \param[in]  instance  ID of the SERCOM instance calling the interrupt
459  *                       handler.
460  */
_usart_interrupt_handler(uint8_t instance)461 void _usart_interrupt_handler(
462 		uint8_t instance)
463 {
464 	/* Temporary variables */
465 	uint16_t interrupt_status;
466 	uint16_t callback_status;
467 	uint8_t error_code;
468 
469 
470 	/* Get device instance from the look-up table */
471 	struct usart_module *module
472 		= (struct usart_module *)_sercom_instances[instance];
473 
474 	/* Pointer to the hardware module instance */
475 	SercomUsart *const usart_hw
476 		= &(module->hw->USART);
477 
478 	/* Wait for the synchronization to complete */
479 	_usart_wait_for_sync(module);
480 
481 	/* Read and mask interrupt flag register */
482 	interrupt_status = usart_hw->INTFLAG.reg;
483 	interrupt_status &= usart_hw->INTENSET.reg;
484 	callback_status = module->callback_reg_mask &
485 			module->callback_enable_mask;
486 
487 	/* Check if a DATA READY interrupt has occurred,
488 	 * and if there is more to transfer */
489 	if (interrupt_status & SERCOM_USART_INTFLAG_DRE) {
490 		if (module->remaining_tx_buffer_length) {
491 			/* Write value will be at least 8-bits long */
492 			uint16_t data_to_send = *(module->tx_buffer_ptr);
493 			/* Increment 8-bit pointer */
494 			(module->tx_buffer_ptr)++;
495 
496 			if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
497 				data_to_send |= (*(module->tx_buffer_ptr) << 8);
498 				/* Increment 8-bit pointer */
499 				(module->tx_buffer_ptr)++;
500 			}
501 			/* Write the data to send */
502 			usart_hw->DATA.reg = (data_to_send & SERCOM_USART_DATA_MASK);
503 
504 			if (--(module->remaining_tx_buffer_length) == 0) {
505 				/* Disable the Data Register Empty Interrupt */
506 				usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
507 				/* Enable Transmission Complete interrupt */
508 				usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
509 
510 			}
511 		} else {
512 			usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
513 		}
514 	}
515 
516 	/* Check if the Transmission Complete interrupt has occurred and
517 	 * that the transmit buffer is empty */
518 	if (interrupt_status & SERCOM_USART_INTFLAG_TXC) {
519 
520 		/* Disable TX Complete Interrupt, and set STATUS_OK */
521 		usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
522 		module->tx_status = STATUS_OK;
523 
524 		/* Run callback if registered and enabled */
525 		if (callback_status & (1 << USART_CALLBACK_BUFFER_TRANSMITTED)) {
526 			(*(module->callback[USART_CALLBACK_BUFFER_TRANSMITTED]))(module);
527 		}
528 	}
529 
530 	/* Check if the Receive Complete interrupt has occurred, and that
531 	 * there's more data to receive */
532 	if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
533 
534 		if (module->remaining_rx_buffer_length) {
535 			/* Read out the status code and mask away all but the 4 LSBs*/
536 			error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
537 #if !SAMD20
538 			/* CTS status should not be considered as an error */
539 			if(error_code & SERCOM_USART_STATUS_CTS) {
540 				error_code &= ~SERCOM_USART_STATUS_CTS;
541 			}
542 #endif
543 #ifdef FEATURE_USART_LIN_MASTER
544 			/* TXE status should not be considered as an error */
545 			if(error_code & SERCOM_USART_STATUS_TXE) {
546 				error_code &= ~SERCOM_USART_STATUS_TXE;
547 			}
548 #endif
549 			/* Check if an error has occurred during the receiving */
550 			if (error_code) {
551 				/* Check which error occurred */
552 				if (error_code & SERCOM_USART_STATUS_FERR) {
553 					/* Store the error code and clear flag by writing 1 to it */
554 					module->rx_status = STATUS_ERR_BAD_FORMAT;
555 					usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
556 				} else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
557 					/* Store the error code and clear flag by writing 1 to it */
558 					module->rx_status = STATUS_ERR_OVERFLOW;
559 					usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
560 				} else if (error_code & SERCOM_USART_STATUS_PERR) {
561 					/* Store the error code and clear flag by writing 1 to it */
562 					module->rx_status = STATUS_ERR_BAD_DATA;
563 					usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
564 				}
565 #ifdef FEATURE_USART_LIN_SLAVE
566 				else if (error_code & SERCOM_USART_STATUS_ISF) {
567 					/* Store the error code and clear flag by writing 1 to it */
568 					module->rx_status = STATUS_ERR_PROTOCOL;
569 					usart_hw->STATUS.reg = SERCOM_USART_STATUS_ISF;
570 				}
571 #endif
572 #ifdef FEATURE_USART_COLLISION_DECTION
573 				else if (error_code & SERCOM_USART_STATUS_COLL) {
574 					/* Store the error code and clear flag by writing 1 to it */
575 					module->rx_status = STATUS_ERR_PACKET_COLLISION;
576 					usart_hw->STATUS.reg = SERCOM_USART_STATUS_COLL;
577 				}
578 #endif
579 
580 				/* Run callback if registered and enabled */
581 				if (callback_status
582 						& (1 << USART_CALLBACK_ERROR)) {
583 					(*(module->callback[USART_CALLBACK_ERROR]))(module);
584 				}
585 
586 			} else {
587 
588 				/* Read current packet from DATA register,
589 				 * increment buffer pointer and decrement buffer length */
590 				uint16_t received_data = (usart_hw->DATA.reg & SERCOM_USART_DATA_MASK);
591 
592 				/* Read value will be at least 8-bits long */
593 				*(module->rx_buffer_ptr) = received_data;
594 				/* Increment 8-bit pointer */
595 				module->rx_buffer_ptr += 1;
596 
597 				if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
598 					/* 9-bit data, write next received byte to the buffer */
599 					*(module->rx_buffer_ptr) = (received_data >> 8);
600 					/* Increment 8-bit pointer */
601 					module->rx_buffer_ptr += 1;
602 				}
603 
604 				/* Check if the last character have been received */
605 				if(--(module->remaining_rx_buffer_length) == 0) {
606 					/* Disable RX Complete Interrupt,
607 					 * and set STATUS_OK */
608 					usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
609 					module->rx_status = STATUS_OK;
610 
611 					/* Run callback if registered and enabled */
612 					if (callback_status
613 							& (1 << USART_CALLBACK_BUFFER_RECEIVED)) {
614 						(*(module->callback[USART_CALLBACK_BUFFER_RECEIVED]))(module);
615 					}
616 				}
617 			}
618 		} else {
619 			/* This should not happen. Disable Receive Complete interrupt. */
620 			usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
621 		}
622 	}
623 
624 #ifdef FEATURE_USART_HARDWARE_FLOW_CONTROL
625 	if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) {
626 		/* Disable interrupts */
627 		usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
628 		/* Clear interrupt flag */
629 		usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_CTSIC;
630 
631 		/* Run callback if registered and enabled */
632 		if (callback_status & (1 << USART_CALLBACK_CTS_INPUT_CHANGE)) {
633 			(*(module->callback[USART_CALLBACK_CTS_INPUT_CHANGE]))(module);
634 		}
635 	}
636 #endif
637 
638 #ifdef FEATURE_USART_LIN_SLAVE
639 	if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) {
640 		/* Disable interrupts */
641 		usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXBRK;
642 		/* Clear interrupt flag */
643 		usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK;
644 
645 		/* Run callback if registered and enabled */
646 		if (callback_status & (1 << USART_CALLBACK_BREAK_RECEIVED)) {
647 			(*(module->callback[USART_CALLBACK_BREAK_RECEIVED]))(module);
648 		}
649 	}
650 #endif
651 
652 #ifdef FEATURE_USART_START_FRAME_DECTION
653 	if (interrupt_status & SERCOM_USART_INTFLAG_RXS) {
654 		/* Disable interrupts */
655 		usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXS;
656 		/* Clear interrupt flag */
657 		usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXS;
658 
659 		/* Run callback if registered and enabled */
660 		if (callback_status & (1 << USART_CALLBACK_START_RECEIVED)) {
661 			(*(module->callback[USART_CALLBACK_START_RECEIVED]))(module);
662 		}
663 	}
664 #endif
665 }
666 
667