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.h"
47 
48 /**
49  * \brief Determines if the SPI module is currently synchronizing to the bus.
50  *
51  * This function will check if the underlying hardware peripheral module is
52  * currently synchronizing across multiple clock domains to the hardware bus.
53  * This function can be used to delay further operations on the module until it
54  * is ready.
55  *
56  * \param[in]  module  SPI hardware module
57  *
58  * \return Synchronization status of the underlying hardware module
59  * \retval true   Module synchronization is ongoing
60  * \retval false  Module synchronization is not ongoing
61  *
62  */
_spi_is_active(Spi * const spi_module)63 static bool _spi_is_active(Spi *const spi_module)
64 {
65 	Assert(spi_module);
66 
67 	return spi_module->SPI_BUS_STATUS.bit.SPI_ACTIVE;
68 }
69 
70 /**
71  * \internal Enable SPI clock.
72  *
73  * This function will enable SPI clock.
74  *
75  * \param[in]  module  Pointer to the software instance struct
76  */
_spi_clock_enable(struct spi_module * const module)77 static void _spi_clock_enable(struct spi_module *const module)
78 {
79 	Assert(module);
80 
81 	Spi *const spi_module = (module->hw);
82 
83 	if (spi_module == (void *)SPI0) {
84 		system_clock_peripheral_enable(PERIPHERAL_SPI0_SCK_CLK);
85 		system_clock_peripheral_enable(PERIPHERAL_SPI0_SCK_PHASE);
86 		system_clock_peripheral_enable(PERIPHERAL_SPI0_IF);
87 		system_clock_peripheral_enable(PERIPHERAL_SPI0_CORE);
88 	} else if (spi_module == (void *)SPI1) {
89 		system_clock_peripheral_enable(PERIPHERAL_SPI1_SCK_CLK);
90 		system_clock_peripheral_enable(PERIPHERAL_SPI1_SCK_PHASE);
91 		system_clock_peripheral_enable(PERIPHERAL_SPI1_IF);
92 		system_clock_peripheral_enable(PERIPHERAL_SPI1_CORE);
93 	}
94 }
95 
96 /**
97  * \internal Disable SPI clock.
98  *
99  * This function will disable SPI clock.
100  *
101  * \param[in]  module  Pointer to the software instance struct
102  */
_spi_clock_disable(struct spi_module * const module)103 static void _spi_clock_disable(struct spi_module *const module)
104 {
105 	Assert(module);
106 
107 	Spi *const spi_module = (module->hw);
108 
109 	if (spi_module == (void *)SPI0) {
110 		system_clock_peripheral_disable(PERIPHERAL_SPI0_SCK_CLK);
111 		system_clock_peripheral_disable(PERIPHERAL_SPI0_SCK_PHASE);
112 		system_clock_peripheral_disable(PERIPHERAL_SPI0_IF);
113 		system_clock_peripheral_disable(PERIPHERAL_SPI0_CORE);
114 	} else if (spi_module == (void *)SPI1) {
115 		system_clock_peripheral_disable(PERIPHERAL_SPI1_SCK_CLK);
116 		system_clock_peripheral_disable(PERIPHERAL_SPI1_SCK_PHASE);
117 		system_clock_peripheral_disable(PERIPHERAL_SPI1_IF);
118 		system_clock_peripheral_disable(PERIPHERAL_SPI1_CORE);
119 	}
120 }
121 
122 /**
123  * \internal Writes an SPI configuration to the hardware module.
124  *
125  * This function will write out a given configuration to the hardware module.
126  * Can only be done when the module is disabled.
127  *
128  * \param[in]  module  Pointer to the software instance struct
129  * \param[in]  config  Pointer to the configuration struct
130  *
131  * \return The status of the configuration
132  * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
133  * \retval STATUS_OK               If the configuration was written
134  */
_spi_set_config(struct spi_module * const module,const struct spi_config * const config)135 static enum status_code _spi_set_config(
136 		struct spi_module *const module,
137 		const struct spi_config *const config)
138 {
139 	Assert(module);
140 	Assert(config);
141 
142 	Spi *const spi_module = (module->hw);
143 
144 	module->mode  = config->mode;
145 
146 #if CONF_SPI_MASTER_ENABLE == true
147 	/* Find baud value and write it */
148 	if (config->mode == SPI_MODE_MASTER) {
149 		spi_module->SPI_CLK_DIVIDER.reg = config->clock_divider;
150 	}
151 #endif
152 
153 	/* Set data order */
154 	if (config->data_order == SPI_DATA_ORDER_LSB) {
155 		spi_module->SPI_CONFIGURATION.bit.LSB_FIRST_ENABLE = 0x1;
156 	} else {
157 		spi_module->SPI_CONFIGURATION.bit.LSB_FIRST_ENABLE = 0x0;
158 	}
159 
160 	/* Set clock polarity and clock phase */
161 	switch(config->transfer_mode)
162 	{
163 		case SPI_TRANSFER_MODE_0:
164 			spi_module->SPI_CONFIGURATION.bit.SCK_PHASE = 0x0;
165 			spi_module->SPI_CONFIGURATION.bit.SCK_POLARITY = 0x0;
166 			break;
167 		case SPI_TRANSFER_MODE_1:
168 			spi_module->SPI_CONFIGURATION.bit.SCK_PHASE = 0x1;
169 			spi_module->SPI_CONFIGURATION.bit.SCK_POLARITY = 0x0;
170 			break;
171 		case SPI_TRANSFER_MODE_2:
172 			spi_module->SPI_CONFIGURATION.bit.SCK_PHASE = 0x0;
173 			spi_module->SPI_CONFIGURATION.bit.SCK_POLARITY = 0x1;
174 			break;
175 		case SPI_TRANSFER_MODE_3:
176 			spi_module->SPI_CONFIGURATION.bit.SCK_PHASE = 0x1;
177 			spi_module->SPI_CONFIGURATION.bit.SCK_POLARITY = 0x1;
178 			break;
179 		default:
180 			break;
181 	}
182 
183 	return STATUS_OK;
184 }
185 
186 /**
187  * \brief Checks if the SPI in master mode has shifted out last data, or if the
188  * master has ended the transfer in slave mode.
189  *
190  * This function will check if the SPI master module has shifted out last data,
191  * or if the slave select pin has been drawn high by the master for the SPI
192  * slave module.
193  *
194  * \param[in]  module  Pointer to the software instance struct
195  *
196  * \return Indication of whether any writes are ongoing
197  * \retval true   If the SPI master module has shifted out data, or slave select
198  *                has been drawn high for SPI slave
199  * \retval false  If the SPI master module has not shifted out data
200  */
_spi_is_write_complete(Spi * const spi_module)201 static inline bool _spi_is_write_complete(
202 		Spi *const spi_module)
203 {
204 	Assert(spi_module);
205 
206 	/* Check interrupt flag */
207 	return (spi_module->TRANSMIT_STATUS.bit.TX_FIFO_EMPTY);
208 }
209 
210 
211  /**
212  * \brief Checks if the SPI module is ready to write data
213  *
214  * This function will check if the SPI module is ready to write data.
215  *
216  * \param[in]  module  Pointer to the software instance struct
217  *
218  * \return Indication of whether the module is ready to read data or not
219  * \retval true   If the SPI module is ready to write data
220  * \retval false  If the SPI module is not ready to write data
221  */
_spi_is_ready_to_write(Spi * const spi_module)222 static inline bool _spi_is_ready_to_write(
223 		Spi *const spi_module)
224 {
225 	Assert(spi_module);
226 
227 	/* Check interrupt flag */
228 	return (spi_module->TRANSMIT_STATUS.bit.TX_FIFO_NOT_FULL);
229 }
230 
231 /**
232  * \brief Checks if the SPI module is ready to read data
233  *
234  * This function will check if the SPI module is ready to read data.
235  *
236  * \param[in]  module Pointer to the software instance struct
237  *
238  * \return Indication of whether the module is ready to read data or not
239  * \retval true   If the SPI module is ready to read data
240  * \retval false  If the SPI module is not ready to read data
241  */
_spi_is_ready_to_read(Spi * const spi_module)242 static inline bool _spi_is_ready_to_read(
243 		Spi *const spi_module)
244 {
245 	Assert(spi_module);
246 
247 	/* Check interrupt flag */
248 	return (spi_module->RECEIVE_STATUS.bit.RX_FIFO_NOT_EMPTY);
249 }
250 
251 /**
252  * \brief Initializes an SPI peripheral slave device configuration structure to default values
253  *
254  * This function will initialize a given SPI slave device configuration
255  * structure to a set of known default values. This function should be called
256  * on any new instance of the configuration structures before being modified by
257  * the user application.
258  *
259  * The default configuration is as follows:
260  *  \li Slave Select on GPIO pin 12
261  *  \li Addressing not enabled
262  *
263  * \param[out] config  Configuration structure to initialize to default values
264  */
spi_slave_inst_get_config_defaults(struct spi_slave_inst_config * const config)265 void spi_slave_inst_get_config_defaults(
266 		struct spi_slave_inst_config *const config)
267 {
268 	Assert(config);
269 
270 	config->ss_pin          = PIN_LP_GPIO_12;
271 	config->address_enabled = false;
272 	config->address         = 0;
273 }
274 
275 /**
276  * \brief Initializes an SPI configuration structure to default values
277  *
278  * This function will initialize a given SPI configuration structure to a set
279  * of known default values. This function should be called on any new
280  * instance of the configuration structures before being modified by the
281  * user application.
282  *
283  * The default configuration is as follows:
284  *  \li Master mode enabled
285  *  \li MSB of the data is transmitted first
286  *  \li Transfer mode 0
287  *  \li MUX Setting 0
288  *  \li Character size 8 bit
289  *  \li Not enabled in sleep mode
290  *  \li Receiver enabled
291  *  \li Baudrate 50000
292  *  \li Default pinmux settings for all pads
293  *  \li Clock source 0 (26MHz)
294  *  \li	Clock divider  (Formula: baud_rate = ((clock input freq/clock_divider+1)/2))
295  *                                  (For Example: if clock source is CLOCK_INPUT_0 then
296  *                                  ((26000000/(129+1))/2) = 100000 bps)
297  *
298  * \param[in,out] config  Configuration structure to initialize to default values
299  */
spi_get_config_defaults(struct spi_config * const config)300 void spi_get_config_defaults(
301 		struct spi_config *const config)
302 {
303 	Assert(config);
304 
305 	config->mode             = SPI_MODE_MASTER;
306 	config->data_order       = SPI_DATA_ORDER_MSB;
307 	config->transfer_mode    = SPI_TRANSFER_MODE_0;
308 	config->clock_source     = SPI_CLK_INPUT_0;
309 	config->clock_divider    = 129;
310 
311 	config->pin_number_pad[0] = PIN_LP_GPIO_10;
312 	config->pin_number_pad[1] = PIN_LP_GPIO_11;
313 	config->pin_number_pad[2] = PIN_LP_GPIO_12;
314 	config->pin_number_pad[3] = PIN_LP_GPIO_13;
315 
316 	config->pinmux_sel_pad[0] = MUX_LP_GPIO_10_SPI0_SCK;
317 	config->pinmux_sel_pad[1] = MUX_LP_GPIO_11_SPI0_MOSI;
318 	config->pinmux_sel_pad[2] = MUX_LP_GPIO_12_SPI0_SSN;
319 	config->pinmux_sel_pad[3] = MUX_LP_GPIO_13_SPI0_MISO;
320 };
321 
322 /**
323  * \brief Attaches an SPI peripheral slave
324  *
325  * This function will initialize the software SPI peripheral slave, based on
326  * the values of the config struct. The slave can then be selected and
327  * optionally addressed by the \ref spi_select_slave function.
328  *
329  * \param[out] slave   Pointer to the software slave instance struct
330  * \param[in]  config  Pointer to the config struct
331  *
332  */
spi_attach_slave(struct spi_slave_inst * const slave,struct spi_slave_inst_config * const config)333 void spi_attach_slave(
334 		struct spi_slave_inst *const slave,
335 		struct spi_slave_inst_config *const config)
336 {
337 	Assert(slave);
338 	Assert(config);
339 
340 	slave->ss_pin          = config->ss_pin;
341 	slave->address_enabled = config->address_enabled;
342 	slave->address         = config->address;
343 
344 	struct gpio_config config_gpio;
345 	gpio_get_config_defaults(&config_gpio);
346 	config_gpio.direction = GPIO_PIN_DIR_OUTPUT;
347 	gpio_pin_set_config(slave->ss_pin, &config_gpio);
348 
349 	gpio_pin_set_output_level(slave->ss_pin, true);
350 }
351 
352 /**
353  * \brief Resets the SPI module
354  *
355  * This function will reset the SPI module to its power on default values and
356  * disable it.
357  *
358  * \param[in,out] module Pointer to the software instance struct
359  */
spi_reset(struct spi_module * const module)360 void spi_reset(struct spi_module *const module)
361 {
362 	/* Sanity check arguments */
363 	Spi *const spi_module = (module->hw);
364 
365 	/* Disable the module */
366 	spi_disable(module);
367 
368 	/* Software reset the module */
369 	if(spi_module == (void *)SPI0) {
370 		system_peripheral_reset(PERIPHERAL_SPI0_CORE);
371 		system_peripheral_reset(PERIPHERAL_SPI0_IF);
372 	} else if (spi_module == (void *)SPI1) {
373 		system_peripheral_reset(PERIPHERAL_SPI1_CORE);
374 		system_peripheral_reset(PERIPHERAL_SPI1_IF);
375 	}
376 }
377 
378 /**
379  * \brief Initializes the SPI module
380  *
381  * This function will initialize the SPI module, based on the values
382  * of the config struct.
383  *
384  * \param[out]  module  Pointer to the software instance struct
385  * \param[in]   hw      Pointer to hardware instance
386  * \param[in]   config  Pointer to the config struct
387  *
388  * \return Status of the initialization
389  * \retval STATUS_OK               Module initiated correctly
390  * \retval STATUS_ERR_DENIED       If module is enabled
391  * \retval STATUS_BUSY             If module is busy resetting
392  * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
393  */
spi_init(struct spi_module * const module,Spi * const hw,const struct spi_config * const config)394 enum status_code spi_init(
395 		struct spi_module *const module,
396 		Spi *const hw,
397 		const struct spi_config *const config)
398 {
399 	/* Sanity check arguments */
400 	Assert(module);
401 	Assert(hw);
402 	Assert(config);
403 
404 	uint8_t idx;
405 
406 	/* Initialize device instance */
407 	module->hw = hw;
408 
409 	Spi *const spi_module = (module->hw);
410 
411 	/* Check if module is enabled. */
412 	if (spi_module->SPI_MODULE_ENABLE.reg & SPI_MODULE_ENABLE_MASK) {
413 		spi_module->SPI_MODULE_ENABLE.reg = (0x0ul << SPI_MODULE_ENABLE_ENABLE_Pos);
414 	}
415 
416 	spi_reset(module);
417 	_spi_clock_enable(module);
418 
419 #if SPI_CALLBACK_MODE == true
420 	if (module->hw == SPI0) {
421 		_spi_instances[0] = module;
422 		system_register_isr(RAM_ISR_TABLE_SPIRX0_INDEX, (uint32_t)spi_rx0_isr_handler);
423 		system_register_isr(RAM_ISR_TABLE_SPITX0_INDEX, (uint32_t)spi_tx0_isr_handler);
424 	} else if (module->hw == SPI1) {
425 		_spi_instances[1] = module;
426 		system_register_isr(RAM_ISR_TABLE_SPIRX1_INDEX, (uint32_t)spi_rx1_isr_handler);
427 		system_register_isr(RAM_ISR_TABLE_SPITX1_INDEX, (uint32_t)spi_tx1_isr_handler);
428 	}
429 #endif
430 
431 	//Program the pinmux.
432 	struct gpio_config config_gpio;
433 	gpio_get_config_defaults(&config_gpio);
434 
435 	/* Set the pinmux for this spi module. */
436 	for(idx = 0; idx < 4; idx++) {
437 		if (config->pin_number_pad[idx] != PINMUX_UNUSED) {
438 			if (config->mode == SPI_MODE_MASTER) {
439 				config_gpio.direction = GPIO_PIN_DIR_OUTPUT;
440 			} else if (config->mode == SPI_MODE_SLAVE) {
441 				config_gpio.direction = GPIO_PIN_DIR_INPUT;
442 			}
443 			gpio_pin_set_config(config->pin_number_pad[idx], &config_gpio);
444 			gpio_pinmux_cofiguration(config->pin_number_pad[idx], \
445 						(uint16_t)(config->pinmux_sel_pad[idx]));
446 		}
447 	}
448 
449 	/* Set up the input clock for the module */
450 	spi_module->CLOCK_SOURCE_SELECT.reg = config->clock_source;
451 
452 #  if CONF_SPI_MASTER_ENABLE == true
453 	if (config->mode == SPI_MODE_MASTER) {
454 		/* Set the mode in SPI master mode */
455 		spi_module->SPI_MASTER_MODE.reg = SPI_MODE_MASTER;
456 	}
457 #  endif
458 
459 #  if CONF_SPI_SLAVE_ENABLE == true
460 	if (config->mode == SPI_MODE_SLAVE) {
461 		/* Set the mode in SPI slave mode */
462 		spi_module->SPI_MASTER_MODE.reg = SPI_MODE_SLAVE;
463 	}
464 #  endif
465 
466 #if SPI_CALLBACK_MODE == true
467 	/* Temporary variables */
468 	uint8_t i;
469 
470 	/* Initialize parameters */
471 	for (i = 0; i < SPI_CALLBACK_N; i++) {
472 		module->callback[i]        = NULL;
473 	}
474 	module->tx_buffer_ptr              = NULL;
475 	module->rx_buffer_ptr              = NULL;
476 	module->remaining_tx_buffer_length = 0x0000;
477 	module->remaining_rx_buffer_length = 0x0000;
478 	module->registered_callback        = 0x00;
479 	module->enabled_callback           = 0x00;
480 	module->status                     = STATUS_OK;
481 	module->dir                        = SPI_DIRECTION_IDLE;
482 	module->locked                     = 0;
483 #endif
484 
485 	/* Write configuration to module and return status code */
486 	return _spi_set_config(module, config);
487 }
488 
489 /**
490  * \name Enable/Disable
491  * @{
492  */
493 
494 /**
495  * \brief Enables the SPI module
496  *
497  * This function will enable the SPI module.
498  *
499  * \param[in,out] module  Pointer to the software instance struct
500  */
spi_enable(struct spi_module * const module)501 void spi_enable(struct spi_module *const module)
502 {
503 	Spi *const spi_module = (module->hw);
504 
505 #if SPI_CALLBACK_MODE == true
506 	if(spi_module == SPI0) {
507 		NVIC_EnableIRQ(SPI0_RX_IRQn);
508 		NVIC_EnableIRQ(SPI0_TX_IRQn);
509 	} else if(spi_module == SPI1) {
510 		NVIC_EnableIRQ(SPI1_RX_IRQn);
511 		NVIC_EnableIRQ(SPI1_TX_IRQn);
512 	}
513 #endif
514 
515 	/* Enable SPI */
516 	spi_module->SPI_MODULE_ENABLE.reg = SPI_MODULE_ENABLE_ENABLE;
517 }
518 
519 /**
520  * \brief Disables the SPI module
521  *
522  * This function will disable the SPI module.
523  *
524  * \param[in,out] module  Pointer to the software instance struct
525  */
spi_disable(struct spi_module * const module)526 void spi_disable(struct spi_module *const module)
527 {
528 	Spi *const spi_module = (module->hw);
529 
530 #  if SPI_CALLBACK_MODE == true
531 	if(spi_module == SPI0) {
532 		NVIC_DisableIRQ(SPI0_RX_IRQn);
533 		NVIC_DisableIRQ(SPI0_TX_IRQn);
534 	} else if(spi_module == SPI1) {
535 		NVIC_DisableIRQ(SPI1_RX_IRQn);
536 		NVIC_DisableIRQ(SPI1_TX_IRQn);
537 	}
538 #  endif
539 
540 	/* Disable SPI */
541 	spi_module->SPI_MODULE_ENABLE.reg = (0x0ul << SPI_MODULE_ENABLE_ENABLE_Pos);
542 	_spi_clock_disable(module);
543 }
544 
545 /**
546  * \brief Attempt to get lock on driver instance
547  *
548  * This function checks the instance's lock, which indicates whether or not it
549  * is currently in use, and sets the lock if it was not already set.
550  *
551  * The purpose of this is to enable exclusive access to driver instances, so
552  * that, e.g., transactions by different services will not interfere with each
553  * other.
554  *
555  * \param[in,out] module Pointer to the driver instance to lock
556  *
557  * \retval STATUS_OK   If the module was locked
558  * \retval STATUS_BUSY If the module was already locked
559  */
spi_lock(struct spi_module * const module)560 enum status_code spi_lock(struct spi_module *const module)
561 {
562 	enum status_code status;
563 
564 	if (module->locked) {
565 		status = STATUS_BUSY;
566 	} else {
567 		module->locked = true;
568 		status = STATUS_OK;
569 	}
570 
571 	return status;
572 }
573 
574 /**
575  * \brief Unlock driver instance
576  *
577  * This function clears the instance lock, indicating that it is available for
578  * use.
579  *
580  * \param[in,out] module Pointer to the driver instance to lock.
581  *
582  * \retval STATUS_OK   If the module was locked
583  * \retval STATUS_BUSY If the module was already locked
584  */
spi_unlock(struct spi_module * const module)585 void spi_unlock(struct spi_module *const module)
586 {
587 	module->locked = false;
588 }
589 
590 /**
591  * \brief Transfers a single SPI character
592  *
593  * This function will send a single SPI character via SPI and ignore any data
594  * shifted in by the connected device. To both send and receive data, use the
595  * \ref spi_transceive_wait function or use the \ref spi_read function after
596  * writing a character.
597  *
598  * Note that this function does not handle the SS (Slave Select)
599  * pin(s) in master mode; this must be handled from the user application.
600  *
601  * \note In slave mode, the data will not be transferred before a master
602  *       initiates a transaction.
603  *
604  * \param[in] module   Pointer to the software instance struct
605  * \param[in] tx_data  Data to transmit
606  *
607  * \return Status of the procedure
608  * \retval STATUS_OK    If the data was written
609  * \retval STATUS_BUSY  If the last write was not completed
610  */
spi_write(struct spi_module * module,uint8_t tx_data)611 enum status_code spi_write(struct spi_module *module, uint8_t tx_data)
612 {
613 	/* Sanity check arguments */
614 	Assert(module);
615 	Assert(module->hw);
616 
617 	Spi *const spi_module = (module->hw);
618 
619 	/* Check if the data register has been copied to the shift register */
620 	if (!_spi_is_ready_to_write(spi_module)) {
621 		/* Data register has not been copied to the shift register, return */
622 		return STATUS_BUSY;
623 	}
624 
625 	/* Write the character to the DATA register */
626 	spi_module->TRANSMIT_DATA.reg = tx_data & SPI_TRANSMIT_DATA_MASK;
627 
628 	return STATUS_OK;
629 }
630 
631 /**
632  * \brief Reads last received SPI character
633  *
634  * This function will return the last SPI character shifted into the receive
635  * register by the \ref spi_write function
636  *
637  * \note Receiver must be enabled in the configuration
638  *
639  * \param[in] module    Pointer to the software instance struct
640  * \param[out] rx_data  Pointer to store the received data
641  *
642  * \returns Status of the read operation.
643  * \retval STATUS_OK            If data was read
644  * \retval STATUS_ERR_IO        If no data is available
645  * \retval STATUS_ERR_OVERFLOW  If the data is overflown
646  */
spi_read(struct spi_module * const module,uint8_t * rx_data)647 enum status_code spi_read(
648 		struct spi_module *const module,
649 		uint8_t *rx_data)
650 {
651 	/* Sanity check arguments */
652 	Assert(module);
653 	Assert(module->hw);
654 
655 	Spi *const spi_module = (module->hw);
656 
657 	/* Check if data is ready to be read */
658 	if (!_spi_is_ready_to_read(spi_module)) {
659 		/* No data has been received, return */
660 		return STATUS_ERR_IO;
661 	}
662 
663 	/* Return value */
664 	enum status_code retval = STATUS_OK;
665 
666 	/* Check if data is overflown */
667 	if (spi_module->RECEIVE_STATUS.bit.FIFO_OVERRUN) {
668 		retval = STATUS_ERR_OVERFLOW;
669 	}
670 
671 	/* Read the character from the DATA register */
672 	*rx_data = ((uint8_t)spi_module->RECEIVE_DATA.reg & SPI_RECEIVE_DATA_MASK);
673 
674 	return retval;
675 }
676 
677 /**
678  * \brief Transceive requested amount of data to and from the SPI.
679  *
680  * This function will return after sending and receiving requested amount of data
681  *
682  * \note Receiver must be enabled in the configuration
683  * \note The \ref spi_select_slave function should be called before calling
684  *       this function.
685  *
686  * \param[in] module    Pointer to the software instance struct
687  * \param[in] tx_data   Pointer containing the data to be transmitted
688  * \param[in] length    Length of data to be read
689  * \param[out] rx_data  Pointer to store the received data
690  *
691  * \returns Status of the read operation.
692  * \retval STATUS_OK            If data was read
693  * \retval STATUS_ERR_IO        If no data is available
694  * \retval STATUS_ERR_OVERFLOW  If the data is overflown
695  */
spi_transceive_buffer_wait(struct spi_module * const module,uint8_t * tx_data,uint8_t * rx_data,uint16_t length)696 enum status_code spi_transceive_buffer_wait(
697 		struct spi_module *const module,
698 		uint8_t *tx_data,
699 		uint8_t *rx_data,
700 		uint16_t length)
701 {
702 	Spi *spi_module = module->hw;
703 	uint8_t dummy = 0;
704 	uint8_t skip_mosi = 0;
705 	uint8_t skip_miso = 0;
706 	uint8_t status;
707 	uint16_t transfer_len = 0;
708 
709 	if(spi_module == 0) {
710 		return STATUS_ERR_NOT_INITIALIZED;
711 	}
712 	if(!tx_data) {
713 		tx_data = &dummy;
714 		*tx_data = module->tx_dummy_byte;
715 		skip_mosi = 1;
716 	} else if(!rx_data) {
717 		rx_data = &dummy;
718 		skip_miso = 1;
719 	} else if(length == 0) {
720 		return STATUS_ERR_INVALID_ARG;
721 	}
722 
723 	/* Check for Idle */
724 	do {
725 		status = _spi_is_active(spi_module);
726 	}while(status);
727 
728 	/* Clear all status registers */
729 	spi_module->RECEIVE_STATUS.reg;
730 	spi_module->TRANSMIT_STATUS.reg;
731 
732 	/* Start transfer */
733 	while(transfer_len < length) {
734 		/* Write data to MOSI */
735 		while(!_spi_is_ready_to_write(spi_module));
736 		spi_module->TRANSMIT_DATA.reg = *tx_data;
737 		/* Read data shifted from MISO */
738 		while(!_spi_is_ready_to_read(spi_module));
739 		*rx_data = spi_module->RECEIVE_DATA.reg;
740 		transfer_len++;
741 		if (!skip_mosi) {
742 			tx_data++;
743 		}
744 		if (!skip_miso) {
745 			rx_data++;
746 		}
747 	}
748 	/* check TXFIFO is empty */
749 	do {
750 		status = _spi_is_write_complete(spi_module);
751 	}while(!status);
752 
753 	return STATUS_OK;
754 
755 }
756 
757 /**
758  * \brief Transceive single byte of data to and from the SPI.
759  *
760  * This function will return after single byte of data transceived.
761  *
762  * \note Receiver must be enabled in the configuration
763  * \note The \ref spi_select_slave function should be called before calling
764  *       this function.
765  *
766  * \param[in] module    Pointer to the software instance struct
767  * \param[in] tx_data   Pointer containing the data to be transmitted
768  * \param[out] rx_data  Pointer to store the received data
769  *
770  * \returns Status of the read operation.
771  * \retval STATUS_OK            If data was read
772  * \retval STATUS_ERR_IO        If no data is available
773  * \retval STATUS_ERR_OVERFLOW  If the data is overflown
774  */
spi_transceive_wait(struct spi_module * const module,uint8_t * tx_data,uint8_t * rx_data)775 enum status_code spi_transceive_wait(
776 		struct spi_module *const module,
777 		uint8_t *tx_data,
778 		uint8_t *rx_data)
779 {
780 	return spi_transceive_buffer_wait(module, tx_data, rx_data, 1);
781 }
782 
783 /**
784  * \brief Reads requested amount of data from the SPI.
785  *
786  * This function will return after reading requested amount of data
787  *
788  * \note Receiver must be enabled in the configuration
789  * \note The \ref spi_select_slave function should be called before calling
790  *       this function.
791  *
792  * \param[in] module    Pointer to the software instance struct
793  * \param[in] length    Length of data to be read
794  * \param[in] dummy     Dummy byte to be sent on bus when reading data
795  * \param[out] rx_data  Pointer to store the received data
796  *
797  * \returns Status of the read operation.
798  * \retval STATUS_OK            If data was read
799  * \retval STATUS_ERR_IO        If no data is available
800  * \retval STATUS_ERR_OVERFLOW  If the data is overflown
801  */
spi_read_buffer_wait(struct spi_module * const module,uint8_t * rx_data,uint16_t length,uint8_t dummy)802 enum status_code spi_read_buffer_wait(
803 		struct spi_module *const module,
804 		uint8_t *rx_data,
805 		uint16_t length,
806 		uint8_t dummy)
807 {
808 	module->tx_dummy_byte = dummy;
809 	return spi_transceive_buffer_wait(module, NULL, rx_data, length);
810 }
811 
812 /**
813  * \brief Writes requested amount of data to the SPI.
814  *
815  * This function will return after writing requested amount of data
816  *
817  * \note The \ref spi_select_slave function should be called before calling
818  *       this function.
819  *
820  * \param[in] module    Pointer to the software instance struct
821  * \param[in] length    length of data to be read
822  * \param[out] tx_data  Pointer to buffer to be transmitted
823  *
824  * \returns Status of the read operation.
825  * \retval STATUS_OK            If data was read
826  * \retval STATUS_ERR_IO        If no data is available
827  * \retval STATUS_ERR_OVERFLOW  If the data is overflown
828  */
spi_write_buffer_wait(struct spi_module * const module,uint8_t * tx_data,uint16_t length)829 enum status_code spi_write_buffer_wait(
830 		struct spi_module *const module,
831 		uint8_t *tx_data,
832 		uint16_t length)
833 {
834 	return spi_transceive_buffer_wait(module, tx_data, NULL, length);
835 }
836 
837 /**
838  * \brief Asserting/Deasserting the slave select for the corresponding slave.
839  *
840  * This function will assert or deassert the SS of the requested slave device.
841  *
842  * \param[in] module    Pointer to the software instance struct
843  * \param[in] slave     Pointer containing slave instance
844  * \param[in] select    Bool to select the salve or deselect
845  *
846  * \returns Status of the slave select operation.
847  *
848  * \retval STATUS_OK                If SS pin is a valid one and selected/deselected
849  * \retval STATUS_ERR_INVALID_ARG   Invalid SS pin
850  */
spi_select_slave(struct spi_module * const module,struct spi_slave_inst * const slave,bool select)851 enum status_code spi_select_slave(
852 		struct spi_module *const module,
853 		struct spi_slave_inst *const slave,
854 		bool select)
855 {
856 	uint8_t gpio_num = slave->ss_pin;
857 	if(select) {
858 		/* ASSERT Slave select pin */
859 		gpio_pin_set_output_level(gpio_num, false);
860 	} else {
861 		/* DEASSERT Slave select pin */
862 		gpio_pin_set_output_level(gpio_num, true);
863 	}
864 
865 	return STATUS_OK;
866 }
867