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