1 /**
2 * \file
3 *
4 * \brief SAM Serial Peripheral Interface Driver
5 *
6 * Copyright (c) 2013-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 #include "spi_interrupt.h"
47
48 /**
49 * \internal
50 *
51 * Dummy byte to send when reading in master mode.
52 */
53 uint16_t dummy_write;
54
55 /**
56 * \internal
57 * Starts transceive of buffers with a given length
58 *
59 * \param[in] module Pointer to SPI software instance struct
60 * \param[in] rx_data Pointer to data to be received
61 * \param[in] tx_data Pointer to data to be transmitted
62 * \param[in] length Length of data buffer
63 *
64 */
_spi_transceive_buffer(struct spi_module * const module,uint8_t * tx_data,uint8_t * rx_data,uint16_t length)65 static void _spi_transceive_buffer(
66 struct spi_module *const module,
67 uint8_t *tx_data,
68 uint8_t *rx_data,
69 uint16_t length)
70 {
71 Assert(module);
72 Assert(tx_data);
73
74 /* Write parameters to the device instance */
75 module->remaining_tx_buffer_length = length;
76 module->remaining_rx_buffer_length = length;
77 module->rx_buffer_ptr = rx_data;
78 module->tx_buffer_ptr = tx_data;
79 module->status = STATUS_BUSY;
80
81 module->dir = SPI_DIRECTION_BOTH;
82
83 /* Get a pointer to the hardware module instance */
84 SercomSpi *const hw = &(module->hw->SPI);
85
86 /* Enable the Data Register Empty and RX Complete Interrupt */
87 hw->INTENSET.reg = (SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY |
88 SPI_INTERRUPT_FLAG_RX_COMPLETE);
89
90 # if CONF_SPI_SLAVE_ENABLE == true
91 if (module->mode == SPI_MODE_SLAVE) {
92 /* Clear TXC flag if set */
93 hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
94 /* Enable transmit complete interrupt for slave */
95 hw->INTENSET.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
96 }
97 # endif
98 }
99
100 /**
101 * \internal
102 * Starts write of a buffer with a given length
103 *
104 * \param[in] module Pointer to SPI software instance struct
105 * \param[in] tx_data Pointer to data to be transmitted
106 * \param[in] length Length of data buffer
107 *
108 */
_spi_write_buffer(struct spi_module * const module,uint8_t * tx_data,uint16_t length)109 static void _spi_write_buffer(
110 struct spi_module *const module,
111 uint8_t *tx_data,
112 uint16_t length)
113 {
114 Assert(module);
115 Assert(tx_data);
116
117 /* Write parameters to the device instance */
118 module->remaining_tx_buffer_length = length;
119 module->remaining_dummy_buffer_length = length;
120 module->tx_buffer_ptr = tx_data;
121 module->status = STATUS_BUSY;
122
123 module->dir = SPI_DIRECTION_WRITE;
124
125 /* Get a pointer to the hardware module instance */
126 SercomSpi *const hw = &(module->hw->SPI);
127
128 # if CONF_SPI_SLAVE_ENABLE == true
129 if (module->mode == SPI_MODE_SLAVE) {
130 /* Clear TXC flag if set */
131 hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
132 /* Enable transmit complete interrupt for slave */
133 hw->INTENSET.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
134 }
135 # endif
136
137 if (module->receiver_enabled) {
138 /* Enable the Data Register Empty and RX Complete interrupt */
139 hw->INTENSET.reg = (SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY |
140 SPI_INTERRUPT_FLAG_RX_COMPLETE);
141 } else {
142 /* Enable the Data Register Empty interrupt */
143 hw->INTENSET.reg = SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
144 }
145 }
146
147 /**
148 * \internal
149 * Setup SPI to read a buffer with a given length
150 *
151 * \param[in] module Pointer to SPI software instance struct
152 * \param[in] rx_data Pointer to data to be received
153 * \param[in] length Length of data buffer
154 *
155 */
_spi_read_buffer(struct spi_module * const module,uint8_t * rx_data,uint16_t length)156 static void _spi_read_buffer(
157 struct spi_module *const module,
158 uint8_t *rx_data,
159 uint16_t length)
160 {
161 Assert(module);
162 Assert(rx_data);
163
164 uint8_t tmp_intenset = 0;
165
166 /* Set length for the buffer and the pointer, and let
167 * the interrupt handler do the rest */
168 module->remaining_rx_buffer_length = length;
169 module->remaining_dummy_buffer_length = length;
170 module->rx_buffer_ptr = rx_data;
171 module->status = STATUS_BUSY;
172
173 module->dir = SPI_DIRECTION_READ;
174
175 /* Get a pointer to the hardware module instance */
176 SercomSpi *const hw = &(module->hw->SPI);
177
178 /* Enable the RX Complete Interrupt */
179 tmp_intenset = SPI_INTERRUPT_FLAG_RX_COMPLETE;
180
181 # if CONF_SPI_MASTER_ENABLE == true
182 if (module->mode == SPI_MODE_MASTER && module->dir == SPI_DIRECTION_READ) {
183 /* Enable Data Register Empty interrupt for master */
184 tmp_intenset |= SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
185 }
186 # endif
187 # if CONF_SPI_SLAVE_ENABLE == true
188 if (module->mode == SPI_MODE_SLAVE) {
189 /* Clear TXC flag if set */
190 hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
191 /* Enable transmit complete interrupt for slave */
192 tmp_intenset |= SPI_INTERRUPT_FLAG_TX_COMPLETE;
193
194 /* Workaround for SSL flag enable */
195 #ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
196 /* Clear SSL flag if set */
197 hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW;
198 /* Enable Slave Select Low Interrupt for slave */
199 tmp_intenset |= SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW;
200 #endif
201 }
202 # endif
203
204 /* Enable all interrupts simultaneously */
205 hw->INTENSET.reg = tmp_intenset;
206 }
207
208 /**
209 * \brief Registers a SPI callback function
210 *
211 * Registers a callback function which is implemented by the user.
212 *
213 * \note The callback must be enabled by \ref spi_enable_callback, in order
214 * for the interrupt handler to call it when the conditions for the
215 * callback type are met.
216 *
217 * \param[in] module Pointer to USART software instance struct
218 * \param[in] callback_func Pointer to callback function
219 * \param[in] callback_type Callback type given by an enum
220 *
221 */
spi_register_callback(struct spi_module * const module,spi_callback_t callback_func,enum spi_callback callback_type)222 void spi_register_callback(
223 struct spi_module *const module,
224 spi_callback_t callback_func,
225 enum spi_callback callback_type)
226 {
227 /* Sanity check arguments */
228 Assert(module);
229 Assert(callback_func);
230
231 /* Register callback function */
232 module->callback[callback_type] = callback_func;
233
234 /* Set the bit corresponding to the callback_type */
235 module->registered_callback |= (1 << callback_type);
236 }
237
238 /**
239 * \brief Unregisters a SPI callback function
240 *
241 * Unregisters a callback function which is implemented by the user.
242 *
243 * \param[in] module Pointer to SPI software instance struct
244 * \param[in] callback_type Callback type given by an enum
245 *
246 */
spi_unregister_callback(struct spi_module * const module,enum spi_callback callback_type)247 void spi_unregister_callback(
248 struct spi_module *const module,
249 enum spi_callback callback_type)
250 {
251 /* Sanity check arguments */
252 Assert(module);
253
254 /* Unregister callback function */
255 module->callback[callback_type] = NULL;
256
257 /* Clear the bit corresponding to the callback_type */
258 module->registered_callback &= ~(1 << callback_type);
259 }
260
261 /**
262 * \brief Asynchronous buffer write
263 *
264 * Sets up the driver to write to the SPI from a given buffer. If registered
265 * and enabled, a callback function will be called when the write is finished.
266 *
267 * \param[in] module Pointer to SPI software instance struct
268 * \param[out] tx_data Pointer to data buffer to receive
269 * \param[in] length Data buffer length
270 *
271 * \returns Status of the write request operation.
272 * \retval STATUS_OK If the operation completed successfully
273 * \retval STATUS_ERR_BUSY If the SPI was already busy with a write
274 * operation
275 * \retval STATUS_ERR_INVALID_ARG If requested write length was zero
276 */
spi_write_buffer_job(struct spi_module * const module,uint8_t * tx_data,uint16_t length)277 enum status_code spi_write_buffer_job(
278 struct spi_module *const module,
279 uint8_t *tx_data,
280 uint16_t length)
281 {
282 Assert(module);
283 Assert(tx_data);
284
285 if (length == 0) {
286 return STATUS_ERR_INVALID_ARG;
287 }
288
289 /* Check if the SPI is busy transmitting or slave waiting for TXC*/
290 if (module->status == STATUS_BUSY) {
291 return STATUS_BUSY;
292 }
293
294 /* Issue internal write */
295 _spi_write_buffer(module, tx_data, length);
296
297 return STATUS_OK;
298 }
299
300 /**
301 * \brief Asynchronous buffer read
302 *
303 * Sets up the driver to read from the SPI to a given buffer. If registered
304 * and enabled, a callback function will be called when the read is finished.
305 *
306 * \note If address matching is enabled for the slave, the first character
307 * received and placed in the RX buffer will be the address.
308 *
309 * \param[in] module Pointer to SPI software instance struct
310 * \param[out] rx_data Pointer to data buffer to receive
311 * \param[in] length Data buffer length
312 * \param[in] dummy Dummy character to send when reading in master mode
313 *
314 * \returns Status of the operation.
315 * \retval STATUS_OK If the operation completed successfully
316 * \retval STATUS_ERR_BUSY If the SPI was already busy with a read
317 * operation
318 * \retval STATUS_ERR_DENIED If the receiver is not enabled
319 * \retval STATUS_ERR_INVALID_ARG If requested read length was zero
320 */
spi_read_buffer_job(struct spi_module * const module,uint8_t * rx_data,uint16_t length,uint16_t dummy)321 enum status_code spi_read_buffer_job(
322 struct spi_module *const module,
323 uint8_t *rx_data,
324 uint16_t length,
325 uint16_t dummy)
326 {
327 /* Sanity check arguments */
328 Assert(module);
329 Assert(rx_data);
330
331 if (length == 0) {
332 return STATUS_ERR_INVALID_ARG;
333 }
334
335 if (!(module->receiver_enabled)) {
336 return STATUS_ERR_DENIED;
337 }
338
339 /* Check if the SPI is busy transmitting or slave waiting for TXC*/
340 if (module->status == STATUS_BUSY) {
341 return STATUS_BUSY;
342 }
343
344 dummy_write = dummy;
345 /* Issue internal read */
346 _spi_read_buffer(module, rx_data, length);
347 return STATUS_OK;
348 }
349
350 /**
351 * \brief Asynchronous buffer write and read
352 *
353 * Sets up the driver to write and read to and from given buffers. If registered
354 * and enabled, a callback function will be called when the transfer is finished.
355 *
356 * \note If address matching is enabled for the slave, the first character
357 * received and placed in the RX buffer will be the address.
358 *
359 * \param[in] module Pointer to SPI software instance struct
360 * \param[in] tx_data Pointer to data buffer to send
361 * \param[out] rx_data Pointer to data buffer to receive
362 * \param[in] length Data buffer length
363 *
364 * \returns Status of the operation.
365 * \retval STATUS_OK If the operation completed successfully
366 * \retval STATUS_ERR_BUSY If the SPI was already busy with a read
367 * operation
368 * \retval STATUS_ERR_DENIED If the receiver is not enabled
369 * \retval STATUS_ERR_INVALID_ARG If requested read length was zero
370 */
spi_transceive_buffer_job(struct spi_module * const module,uint8_t * tx_data,uint8_t * rx_data,uint16_t length)371 enum status_code spi_transceive_buffer_job(
372 struct spi_module *const module,
373 uint8_t *tx_data,
374 uint8_t *rx_data,
375 uint16_t length)
376 {
377 /* Sanity check arguments */
378 Assert(module);
379 Assert(rx_data);
380
381 if (length == 0) {
382 return STATUS_ERR_INVALID_ARG;
383 }
384
385 if (!(module->receiver_enabled)) {
386 return STATUS_ERR_DENIED;
387 }
388
389 /* Check if the SPI is busy transmitting or slave waiting for TXC*/
390 if (module->status == STATUS_BUSY) {
391 return STATUS_BUSY;
392 }
393
394 /* Issue internal transceive */
395 _spi_transceive_buffer(module, tx_data, rx_data, length);
396
397 return STATUS_OK;
398 }
399 /**
400 * \brief Aborts an ongoing job
401 *
402 * This function will abort the specified job type.
403 *
404 * \param[in] module Pointer to SPI software instance struct
405 */
spi_abort_job(struct spi_module * const module)406 void spi_abort_job(
407 struct spi_module *const module)
408 {
409 /* Pointer to the hardware module instance */
410 SercomSpi *const spi_hw
411 = &(module->hw->SPI);
412
413 /* Abort ongoing job */
414
415 /* Disable interrupts */
416 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_RX_COMPLETE |
417 SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY |
418 SPI_INTERRUPT_FLAG_TX_COMPLETE;
419
420 module->status = STATUS_ABORTED;
421 module->remaining_rx_buffer_length = 0;
422 module->remaining_dummy_buffer_length = 0;
423 module->remaining_tx_buffer_length = 0;
424
425 module->dir = SPI_DIRECTION_IDLE;
426 }
427
428 # if CONF_SPI_SLAVE_ENABLE == true || CONF_SPI_MASTER_ENABLE == true
429 /**
430 * \internal
431 * Writes a character from the TX buffer to the Data register.
432 *
433 * \param[in,out] module Pointer to SPI software instance struct
434 */
_spi_write(struct spi_module * const module)435 static void _spi_write(
436 struct spi_module *const module)
437 {
438 /* Pointer to the hardware module instance */
439 SercomSpi *const spi_hw = &(module->hw->SPI);
440
441 /* Write value will be at least 8-bits long */
442 uint16_t data_to_send = *(module->tx_buffer_ptr);
443 /* Increment 8-bit pointer */
444 (module->tx_buffer_ptr)++;
445
446 if (module->character_size == SPI_CHARACTER_SIZE_9BIT) {
447 data_to_send |= ((*(module->tx_buffer_ptr)) << 8);
448 /* Increment 8-bit pointer */
449 (module->tx_buffer_ptr)++;
450 }
451
452 /* Write the data to send*/
453 spi_hw->DATA.reg = data_to_send & SERCOM_SPI_DATA_MASK;
454
455 /* Decrement remaining buffer length */
456 (module->remaining_tx_buffer_length)--;
457 }
458 # endif
459
460 # if CONF_SPI_MASTER_ENABLE == true
461 /**
462 * \internal
463 * Writes a dummy character to the Data register.
464 *
465 * \param[in,out] module Pointer to SPI software instance struct
466 */
_spi_write_dummy(struct spi_module * const module)467 static void _spi_write_dummy(
468 struct spi_module *const module)
469 {
470 /* Pointer to the hardware module instance */
471 SercomSpi *const spi_hw = &(module->hw->SPI);
472
473 /* Write dummy byte */
474 spi_hw->DATA.reg = dummy_write;
475
476 /* Decrement remaining dummy buffer length */
477 module->remaining_dummy_buffer_length--;
478 }
479 # endif
480
481 /**
482 * \internal
483 * Writes a dummy character from the to the Data register.
484 *
485 * \param[in,out] module Pointer to SPI software instance struct
486 */
_spi_read_dummy(struct spi_module * const module)487 static void _spi_read_dummy(
488 struct spi_module *const module)
489 {
490 /* Pointer to the hardware module instance */
491 SercomSpi *const spi_hw = &(module->hw->SPI);
492 uint16_t flush = 0;
493
494 /* Read dummy byte */
495 flush = spi_hw->DATA.reg;
496 UNUSED(flush);
497
498 /* Decrement remaining dummy buffer length */
499 module->remaining_dummy_buffer_length--;
500 }
501
502 /**
503 * \internal
504 * Reads a character from the Data register to the RX buffer.
505 *
506 * \param[in,out] module Pointer to SPI software instance struct
507 */
_spi_read(struct spi_module * const module)508 static void _spi_read(
509 struct spi_module *const module)
510 {
511 /* Pointer to the hardware module instance */
512 SercomSpi *const spi_hw = &(module->hw->SPI);
513
514 uint16_t received_data = (spi_hw->DATA.reg & SERCOM_SPI_DATA_MASK);
515
516 /* Read value will be at least 8-bits long */
517 *(module->rx_buffer_ptr) = received_data;
518 /* Increment 8-bit pointer */
519 module->rx_buffer_ptr += 1;
520
521 if(module->character_size == SPI_CHARACTER_SIZE_9BIT) {
522 /* 9-bit data, write next received byte to the buffer */
523 *(module->rx_buffer_ptr) = (received_data >> 8);
524 /* Increment 8-bit pointer */
525 module->rx_buffer_ptr += 1;
526 }
527
528 /* Decrement length of the remaining buffer */
529 module->remaining_rx_buffer_length--;
530 }
531
532 /**
533 * \internal
534 *
535 * Handles interrupts as they occur, and it will run callback functions
536 * which are registered and enabled.
537 *
538 * \note This function will be called by the Sercom_Handler, and should
539 * not be called directly from any application code.
540 *
541 * \param[in] instance ID of the SERCOM instance calling the interrupt
542 * handler.
543 */
_spi_interrupt_handler(uint8_t instance)544 void _spi_interrupt_handler(
545 uint8_t instance)
546 {
547 /* Get device instance from the look-up table */
548 struct spi_module *module
549 = (struct spi_module *)_sercom_instances[instance];
550
551 /* Pointer to the hardware module instance */
552 SercomSpi *const spi_hw = &(module->hw->SPI);
553
554 /* Combine callback registered and enabled masks. */
555 uint8_t callback_mask =
556 module->enabled_callback & module->registered_callback;
557
558 /* Read and mask interrupt flag register */
559 uint16_t interrupt_status = spi_hw->INTFLAG.reg;
560 interrupt_status &= spi_hw->INTENSET.reg;
561
562 /* Data register empty interrupt */
563 if (interrupt_status & SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY) {
564 # if CONF_SPI_MASTER_ENABLE == true
565 if ((module->mode == SPI_MODE_MASTER) &&
566 (module->dir == SPI_DIRECTION_READ)) {
567 /* Send dummy byte when reading in master mode */
568 _spi_write_dummy(module);
569 if (module->remaining_dummy_buffer_length == 0) {
570 /* Disable the Data Register Empty Interrupt */
571 spi_hw->INTENCLR.reg
572 = SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
573 }
574 }
575 # endif
576
577 if (0
578 # if CONF_SPI_MASTER_ENABLE == true
579 || ((module->mode == SPI_MODE_MASTER) &&
580 (module->dir != SPI_DIRECTION_READ))
581 # endif
582 # if CONF_SPI_SLAVE_ENABLE == true
583 || ((module->mode == SPI_MODE_SLAVE) &&
584 (module->dir != SPI_DIRECTION_READ))
585 # endif
586 ) {
587 /* Write next byte from buffer */
588 _spi_write(module);
589 if (module->remaining_tx_buffer_length == 0) {
590 /* Disable the Data Register Empty Interrupt */
591 spi_hw->INTENCLR.reg
592 = SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
593
594 if (module->dir == SPI_DIRECTION_WRITE &&
595 !(module->receiver_enabled)) {
596 /* Enable the Data Register transmit complete Interrupt */
597 spi_hw->INTENSET.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
598 }
599 }
600 }
601 }
602
603 /* Receive complete interrupt*/
604 if (interrupt_status & SPI_INTERRUPT_FLAG_RX_COMPLETE) {
605 /* Check for overflow */
606 if (spi_hw->STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
607 if (module->dir != SPI_DIRECTION_WRITE) {
608 /* Store the error code */
609 module->status = STATUS_ERR_OVERFLOW;
610
611 /* End transaction */
612 module->dir = SPI_DIRECTION_IDLE;
613
614 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_RX_COMPLETE |
615 SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
616 /* Run callback if registered and enabled */
617 if (callback_mask & (1 << SPI_CALLBACK_ERROR)) {
618 (module->callback[SPI_CALLBACK_ERROR])(module);
619 }
620 }
621 /* Flush */
622 uint16_t flush = spi_hw->DATA.reg;
623 UNUSED(flush);
624 /* Clear overflow flag */
625 spi_hw->STATUS.reg = SERCOM_SPI_STATUS_BUFOVF;
626 } else {
627 if (module->dir == SPI_DIRECTION_WRITE) {
628 /* Flush receive buffer when writing */
629 _spi_read_dummy(module);
630 if (module->remaining_dummy_buffer_length == 0) {
631 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_RX_COMPLETE;
632 module->status = STATUS_OK;
633 module->dir = SPI_DIRECTION_IDLE;
634 /* Run callback if registered and enabled */
635 if (callback_mask &
636 (1 << SPI_CALLBACK_BUFFER_TRANSMITTED)){
637 (module->callback[SPI_CALLBACK_BUFFER_TRANSMITTED])(module);
638 }
639 }
640 } else {
641 /* Read data register */
642 _spi_read(module);
643
644 /* Check if the last character have been received */
645 if (module->remaining_rx_buffer_length == 0) {
646 module->status = STATUS_OK;
647 /* Disable RX Complete Interrupt and set status */
648 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_RX_COMPLETE;
649 if(module->dir == SPI_DIRECTION_BOTH) {
650 if (callback_mask & (1 << SPI_CALLBACK_BUFFER_TRANSCEIVED)) {
651 (module->callback[SPI_CALLBACK_BUFFER_TRANSCEIVED])(module);
652 }
653 } else if (module->dir == SPI_DIRECTION_READ) {
654 if (callback_mask & (1 << SPI_CALLBACK_BUFFER_RECEIVED)) {
655 (module->callback[SPI_CALLBACK_BUFFER_RECEIVED])(module);
656 }
657 }
658 }
659 }
660 }
661 }
662
663 /* Transmit complete */
664 if (interrupt_status & SPI_INTERRUPT_FLAG_TX_COMPLETE) {
665 # if CONF_SPI_SLAVE_ENABLE == true
666 if (module->mode == SPI_MODE_SLAVE) {
667 /* Transaction ended by master */
668
669 /* Disable interrupts */
670 spi_hw->INTENCLR.reg =
671 SPI_INTERRUPT_FLAG_TX_COMPLETE |
672 SPI_INTERRUPT_FLAG_RX_COMPLETE |
673 SPI_INTERRUPT_FLAG_DATA_REGISTER_EMPTY;
674 /* Clear interrupt flag */
675 spi_hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_TX_COMPLETE;
676
677
678 /* Reset all status information */
679 module->dir = SPI_DIRECTION_IDLE;
680 module->remaining_tx_buffer_length = 0;
681 module->remaining_rx_buffer_length = 0;
682 module->status = STATUS_OK;
683
684 if (callback_mask &
685 (1 << SPI_CALLBACK_SLAVE_TRANSMISSION_COMPLETE)) {
686 (module->callback[SPI_CALLBACK_SLAVE_TRANSMISSION_COMPLETE])
687 (module);
688 }
689
690 }
691 # endif
692 # if CONF_SPI_MASTER_ENABLE == true
693 if ((module->mode == SPI_MODE_MASTER) &&
694 (module->dir == SPI_DIRECTION_WRITE) && !(module->receiver_enabled)) {
695 /* Clear interrupt flag */
696 spi_hw->INTENCLR.reg
697 = SPI_INTERRUPT_FLAG_TX_COMPLETE;
698 /* Buffer sent with receiver disabled */
699 module->dir = SPI_DIRECTION_IDLE;
700 module->status = STATUS_OK;
701 /* Run callback if registered and enabled */
702 if (callback_mask & (1 << SPI_CALLBACK_BUFFER_TRANSMITTED)){
703 (module->callback[SPI_CALLBACK_BUFFER_TRANSMITTED])
704 (module);
705 }
706 }
707 #endif
708 }
709
710 # ifdef FEATURE_SPI_SLAVE_SELECT_LOW_DETECT
711 # if CONF_SPI_SLAVE_ENABLE == true
712 /* When a high to low transition is detected on the _SS pin in slave mode */
713 if (interrupt_status & SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW) {
714 if (module->mode == SPI_MODE_SLAVE) {
715 /* Disable interrupts */
716 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW;
717 /* Clear interrupt flag */
718 spi_hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_SLAVE_SELECT_LOW;
719
720 if (callback_mask & (1 << SPI_CALLBACK_SLAVE_SELECT_LOW)) {
721 (module->callback[SPI_CALLBACK_SLAVE_SELECT_LOW])(module);
722 }
723 }
724 }
725 # endif
726 # endif
727
728 # ifdef FEATURE_SPI_ERROR_INTERRUPT
729 /* When combined error happen */
730 if (interrupt_status & SPI_INTERRUPT_FLAG_COMBINED_ERROR) {
731 /* Disable interrupts */
732 spi_hw->INTENCLR.reg = SPI_INTERRUPT_FLAG_COMBINED_ERROR;
733 /* Clear interrupt flag */
734 spi_hw->INTFLAG.reg = SPI_INTERRUPT_FLAG_COMBINED_ERROR;
735
736 if (callback_mask & (1 << SPI_CALLBACK_COMBINED_ERROR)) {
737 (module->callback[SPI_CALLBACK_COMBINED_ERROR])(module);
738 }
739 }
740 # endif
741 }
742