spi_transfer.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /****************************************************************************
  2. * drivers/spi/spi_transfer.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <unistd.h>
  25. #include <assert.h>
  26. #include <errno.h>
  27. #include <debug.h>
  28. #include <nuttx/signal.h>
  29. #include <nuttx/spi/spi.h>
  30. #include <nuttx/spi/spi_transfer.h>
  31. #ifdef CONFIG_SPI_EXCHANGE
  32. /****************************************************************************
  33. * Public Functions
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Name: spi_transfer
  37. *
  38. * Description:
  39. * This is a helper function that can be used to encapsulate and manage
  40. * a sequence of SPI transfers. The SPI bus will be locked and the
  41. * SPI device selected for the duration of the transfers.
  42. *
  43. * Input Parameters:
  44. * spi - An instance of the SPI device to use for the transfer
  45. * seq - Describes the sequence of transfers.
  46. *
  47. * Returned Value:
  48. * Zero (OK) on success; a negated errno value on failure.
  49. *
  50. ****************************************************************************/
  51. int spi_transfer(FAR struct spi_dev_s *spi, FAR struct spi_sequence_s *seq)
  52. {
  53. FAR struct spi_trans_s *trans;
  54. int ret = OK;
  55. int i;
  56. DEBUGASSERT(spi != NULL && seq != NULL && seq->trans != NULL);
  57. /* Get exclusive access to the SPI bus */
  58. SPI_LOCK(spi, true);
  59. /* Establish the fixed SPI attributes for all transfers in the sequence */
  60. SPI_SETFREQUENCY(spi, seq->frequency);
  61. #ifdef CONFIG_SPI_CS_DELAY_CONTROL
  62. ret = SPI_SETDELAY(spi, seq->a, seq->b, seq->c);
  63. if (ret < 0)
  64. {
  65. spierr("ERROR: SPI_SETDELAY failed: %d\n", ret);
  66. SPI_LOCK(spi, false);
  67. return ret;
  68. }
  69. #endif
  70. SPI_SETMODE(spi, seq->mode);
  71. SPI_SETBITS(spi, seq->nbits);
  72. /* Select the SPI device in preparation for the transfer.
  73. * REVISIT: This is redundant.
  74. */
  75. SPI_SELECT(spi, seq->dev, true);
  76. /* Then perform each transfer is the sequence */
  77. for (i = 0, trans = seq->trans; i < (int)seq->ntrans; i++, trans++)
  78. {
  79. /* Establish the fixed SPI attributes for unique to this transaction */
  80. #ifdef CONFIG_SPI_HWFEATURES
  81. ret = SPI_HWFEATURES(spi, trans->hwfeat);
  82. if (ret < 0)
  83. {
  84. spierr("ERROR: SPI_HWFEATURES failed: %d\n", ret);
  85. break;
  86. }
  87. #endif
  88. #ifdef CONFIG_SPI_CMDDATA
  89. ret = SPI_CMDDATA(spi, seq->dev, trans->cmd);
  90. if (ret < 0)
  91. {
  92. spierr("ERROR: SPI_CMDDATA failed: %d\n", ret);
  93. break;
  94. }
  95. #endif
  96. /* [Re-]select the SPI device in preparation for the transfer */
  97. SPI_SELECT(spi, seq->dev, true);
  98. /* Perform the transfer */
  99. SPI_EXCHANGE(spi, trans->txbuffer, trans->rxbuffer, trans->nwords);
  100. /* Possibly de-select the SPI device after the transfer */
  101. if (trans->deselect)
  102. {
  103. SPI_SELECT(spi, seq->dev, false);
  104. }
  105. /* Perform any requested inter-transfer delay */
  106. if (trans->delay > 0)
  107. {
  108. nxsig_usleep(trans->delay);
  109. }
  110. }
  111. SPI_SELECT(spi, seq->dev, false);
  112. SPI_LOCK(spi, false);
  113. return ret;
  114. }
  115. #endif /* CONFIG_SPI_EXCHANGE */