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