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