nrfx_spim.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA
  3. * All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright notice, this
  11. * list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * 3. Neither the name of the copyright holder nor the names of its
  18. * contributors may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  25. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. * POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #ifndef NRFX_SPIM_H__
  34. #define NRFX_SPIM_H__
  35. #include <stdint.h>
  36. #include <string.h>
  37. #include "board.h"
  38. #include "rtconfig.h"
  39. #include <nrfx.h>
  40. #include <hal/nrf_spim.h>
  41. #include <hal/nrf_gpio.h>
  42. #ifdef __cplusplus
  43. extern "C" {
  44. #endif
  45. /**
  46. * @defgroup nrfx_spim SPIM driver
  47. * @{
  48. * @ingroup nrf_spim
  49. * @brief Serial Peripheral Interface Master with EasyDMA (SPIM) driver.
  50. */
  51. /** @brief Data structure of the Serial Peripheral Interface Master with EasyDMA (SPIM) driver instance. */
  52. typedef struct
  53. {
  54. NRF_SPIM_Type * p_reg; /* /< Pointer to a structure with SPIM registers. */
  55. uint8_t drv_inst_idx; /* /< Index of the driver instance. For internal use only. */
  56. } nrfx_spim_t;
  57. #ifndef __NRFX_DOXYGEN__
  58. enum {
  59. #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
  60. NRFX_SPIM0_INST_IDX,
  61. #endif
  62. #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
  63. NRFX_SPIM1_INST_IDX,
  64. #endif
  65. #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
  66. NRFX_SPIM2_INST_IDX,
  67. #endif
  68. #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
  69. NRFX_SPIM3_INST_IDX,
  70. #endif
  71. #if NRFX_CHECK(NRFX_SPIM4_ENABLED)
  72. NRFX_SPIM4_INST_IDX,
  73. #endif
  74. NRFX_SPIM_ENABLED_COUNT
  75. };
  76. #endif
  77. /** @brief Macro for creating an instance of the SPIM driver. */
  78. #define NRFX_SPIM_INSTANCE(id) \
  79. { \
  80. .p_reg = NRFX_CONCAT_2(NRF_SPIM, id), \
  81. .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIM, id, _INST_IDX), \
  82. }
  83. /**
  84. * @brief This value can be provided instead of a pin number for signals MOSI,
  85. * MISO, and Slave Select to specify that the given signal is not used and
  86. * therefore does not need to be connected to a pin.
  87. */
  88. #define NRFX_SPIM_PIN_NOT_USED 0xFF
  89. /** @brief Configuration structure of the SPIM driver instance. */
  90. typedef struct
  91. {
  92. uint8_t sck_pin; /* /< SCK pin number. */
  93. uint8_t mosi_pin; /* /< MOSI pin number (optional). */
  94. /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
  95. * if this signal is not needed. */
  96. uint8_t miso_pin; /* /< MISO pin number (optional). */
  97. /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
  98. * if this signal is not needed. */
  99. uint8_t ss_pin; /* /< Slave Select pin number (optional). */
  100. /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
  101. * if this signal is not needed. */
  102. bool ss_active_high; /* /< Polarity of the Slave Select pin during transmission. */
  103. uint8_t irq_priority; /* /< Interrupt priority. */
  104. uint8_t orc; /* /< Overrun character. */
  105. /**< This character is used when all bytes from the TX buffer are sent,
  106. but the transfer continues due to RX. */
  107. nrf_spim_frequency_t frequency; /* /< SPIM frequency. */
  108. nrf_spim_mode_t mode; /* /< SPIM mode. */
  109. nrf_spim_bit_order_t bit_order; /* /< SPIM bit order. */
  110. nrf_gpio_pin_pull_t miso_pull; /* /< MISO pull up configuration. */
  111. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
  112. uint8_t dcx_pin; /* /< D/CX pin number (optional). */
  113. uint8_t rx_delay; /* /< Sample delay for input serial data on MISO. */
  114. /**< The value specifies the delay, in number of 64 MHz clock cycles
  115. * (15.625 ns), from the the sampling edge of SCK (leading edge for
  116. * CONFIG.CPHA = 0, trailing edge for CONFIG.CPHA = 1) until
  117. * the input serial data is sampled. */
  118. bool use_hw_ss; /* /< Indication to use software or hardware controlled Slave Select pin. */
  119. uint8_t ss_duration; /* /< Slave Select duration before and after transmission. */
  120. /**< Minimum duration between the edge of CSN and the edge of SCK.
  121. * Also, minimum duration of CSN inactivity between transactions.
  122. * The value is specified in number of 64 MHz clock cycles (15.625 ns).
  123. * Supported only for hardware-controlled Slave Select. */
  124. #endif
  125. } nrfx_spim_config_t;
  126. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
  127. /**
  128. * @brief SPIM driver extended default configuration.
  129. *
  130. * This configuration sets up SPIM additional options with the following values:
  131. * - DCX pin disabled
  132. * - RX sampling delay: 2 clock cycles
  133. * - hardware SS disabled
  134. * - hardware SS duration before and after transmission: 2 clock cycles
  135. */
  136. #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
  137. .dcx_pin = NRFX_SPIM_PIN_NOT_USED, \
  138. .rx_delay = 0x02, \
  139. .use_hw_ss = false, \
  140. .ss_duration = 0x02,
  141. #else
  142. #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
  143. #endif
  144. /**
  145. * @brief SPIM driver default configuration.
  146. *
  147. * This configuration sets up SPIM with the following options:
  148. * - SS pin active low
  149. * - over-run character set to 0xFF
  150. * - clock frequency: 4 MHz
  151. * - mode: 0 (SCK active high, sample on leading edge of the clock signal;)
  152. * - MSB shifted out first
  153. * - MISO pull-up disabled
  154. *
  155. * @param[in] _pin_sck SCK pin.
  156. * @param[in] _pin_mosi MOSI pin.
  157. * @param[in] _pin_miso MISO pin.
  158. * @param[in] _pin_ss SS pin.
  159. */
  160. #define NRFX_SPIM_DEFAULT_CONFIG(_pin_sck, _pin_mosi, _pin_miso, _pin_ss) \
  161. { \
  162. .sck_pin = _pin_sck, \
  163. .mosi_pin = _pin_mosi, \
  164. .miso_pin = _pin_miso, \
  165. .ss_pin = _pin_ss, \
  166. .ss_active_high = false, \
  167. .irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \
  168. .orc = 0xFF, \
  169. .frequency = NRF_SPIM_FREQ_4M, \
  170. .mode = NRF_SPIM_MODE_0, \
  171. .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, \
  172. .miso_pull = NRF_GPIO_PIN_NOPULL, \
  173. NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \
  174. }
  175. /** @brief Flag indicating that TX buffer address will be incremented after transfer. */
  176. #define NRFX_SPIM_FLAG_TX_POSTINC (1UL << 0)
  177. /** @brief Flag indicating that RX buffer address will be incremented after transfer. */
  178. #define NRFX_SPIM_FLAG_RX_POSTINC (1UL << 1)
  179. /** @brief Flag indicating that the interrupt after each transfer will be suppressed, and the event handler will not be called. */
  180. #define NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2)
  181. /** @brief Flag indicating that the transfer will be set up, but not started. */
  182. #define NRFX_SPIM_FLAG_HOLD_XFER (1UL << 3)
  183. /** @brief Flag indicating that the transfer will be executed multiple times. */
  184. #define NRFX_SPIM_FLAG_REPEATED_XFER (1UL << 4)
  185. /** @brief Single transfer descriptor structure. */
  186. typedef struct
  187. {
  188. uint8_t const * p_tx_buffer; /* /< Pointer to TX buffer. */
  189. size_t tx_length; /* /< TX buffer length. */
  190. uint8_t * p_rx_buffer; /* /< Pointer to RX buffer. */
  191. size_t rx_length; /* /< RX buffer length. */
  192. } nrfx_spim_xfer_desc_t;
  193. /**
  194. * @brief Macro for setting up single transfer descriptor.
  195. *
  196. * This macro is for internal use only.
  197. */
  198. #define NRFX_SPIM_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
  199. { \
  200. .p_tx_buffer = (uint8_t const *)(p_tx), \
  201. .tx_length = (tx_len), \
  202. .p_rx_buffer = (p_rx), \
  203. .rx_length = (rx_len), \
  204. }
  205. /** @brief Macro for setting the duplex TX RX transfer. */
  206. #define NRFX_SPIM_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
  207. NRFX_SPIM_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
  208. /** @brief Macro for setting the TX transfer. */
  209. #define NRFX_SPIM_XFER_TX(p_buf, length) \
  210. NRFX_SPIM_SINGLE_XFER(p_buf, length, NULL, 0)
  211. /** @brief Macro for setting the RX transfer. */
  212. #define NRFX_SPIM_XFER_RX(p_buf, length) \
  213. NRFX_SPIM_SINGLE_XFER(NULL, 0, p_buf, length)
  214. /**
  215. * @brief SPIM master driver event types, passed to the handler routine provided
  216. * during initialization.
  217. */
  218. typedef enum
  219. {
  220. NRFX_SPIM_EVENT_DONE, /* /< Transfer done. */
  221. } nrfx_spim_evt_type_t;
  222. /** @brief SPIM event description with transmission details. */
  223. typedef struct
  224. {
  225. nrfx_spim_evt_type_t type; /* /< Event type. */
  226. nrfx_spim_xfer_desc_t xfer_desc; /* /< Transfer details. */
  227. } nrfx_spim_evt_t;
  228. /** @brief SPIM driver event handler type. */
  229. typedef void (* nrfx_spim_evt_handler_t)(nrfx_spim_evt_t const * p_event,
  230. void * p_context);
  231. /**
  232. * @brief Function for initializing the SPIM driver instance.
  233. *
  234. * This function configures and enables the specified peripheral.
  235. *
  236. * @param[in] p_instance Pointer to the driver instance structure.
  237. * @param[in] p_config Pointer to the structure with the initial configuration.
  238. * @param[in] handler Event handler provided by the user. If NULL, transfers
  239. * will be performed in blocking mode.
  240. * @param[in] p_context Context passed to event handler.
  241. *
  242. * @warning On nRF5340, 32 MHz setting for SPIM4 peripheral instance is supported
  243. * only on the dedicated pins with @ref NRF_GPIO_PIN_MCUSEL_PERIPHERAL configuration.
  244. * See the chapter <a href=@nRF5340pinAssignmentsURL>Pin assignments</a> in the Product Specification.
  245. *
  246. * @retval NRFX_SUCCESS Initialization was successful.
  247. * @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
  248. * @retval NRFX_ERROR_BUSY Some other peripheral with the same
  249. * instance ID is already in use. This is
  250. * possible only if @ref nrfx_prs module
  251. * is enabled.
  252. * @retval NRFX_ERROR_NOT_SUPPORTED Requested configuration is not supported
  253. * by the SPIM instance.
  254. * @retval NRFX_ERROR_INVALID_PARAM Requested frequency is not available on the specified pins.
  255. */
  256. nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance,
  257. nrfx_spim_config_t const * p_config,
  258. nrfx_spim_evt_handler_t handler,
  259. void * p_context);
  260. /**
  261. * @brief Function for uninitializing the SPIM driver instance.
  262. *
  263. * @param[in] p_instance Pointer to the driver instance structure.
  264. */
  265. void nrfx_spim_uninit(nrfx_spim_t const * p_instance);
  266. /**
  267. * @brief Function for starting the SPIM data transfer.
  268. *
  269. * Additional options are provided using the @c flags parameter:
  270. *
  271. * - @ref NRFX_SPIM_FLAG_TX_POSTINC and @ref NRFX_SPIM_FLAG_RX_POSTINC -
  272. * Post-incrementation of buffer addresses.
  273. * - @ref NRFX_SPIM_FLAG_HOLD_XFER - Driver is not starting the transfer. Use this
  274. * flag if the transfer is triggered externally by PPI. Use
  275. * @ref nrfx_spim_start_task_get to get the address of the start task.
  276. * Chip select must be configured to @ref NRFX_SPIM_PIN_NOT_USED and managed outside the driver.
  277. * - @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER - No user event handler after transfer
  278. * completion. This also means no interrupt at the end of the transfer.
  279. * If @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into
  280. * busy state, so you must ensure that the next transfers are set up when SPIM is not active.
  281. * @ref nrfx_spim_end_event_get function can be used to detect end of transfer. Option can be used
  282. * together with @ref NRFX_SPIM_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers
  283. * without interruptions.
  284. * - @ref NRFX_SPIM_FLAG_REPEATED_XFER - Prepare for repeated transfers. You can set
  285. * up a number of transfers that will be triggered externally (for example by PPI). An example is
  286. * a TXRX transfer with the options @ref NRFX_SPIM_FLAG_RX_POSTINC,
  287. * @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_SPIM_FLAG_REPEATED_XFER. After the
  288. * transfer is set up, a set of transfers can be triggered by PPI that will read, for example,
  289. * the same register of an external component and put it into a RAM buffer without any interrupts.
  290. * @ref nrfx_spim_end_event_get can be used to get the address of the END event, which can be
  291. * used to count the number of transfers. If @ref NRFX_SPIM_FLAG_REPEATED_XFER is used,
  292. * the driver does not set the instance into busy state, so you must ensure that the next
  293. * transfers are set up when SPIM is not active.
  294. *
  295. * @note Peripherals using EasyDMA (including SPIM) require the transfer buffers
  296. * to be placed in the Data RAM region. If this condition is not met,
  297. * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
  298. *
  299. * @param p_instance Pointer to the driver instance structure.
  300. * @param p_xfer_desc Pointer to the transfer descriptor.
  301. * @param flags Transfer options (0 for default settings).
  302. *
  303. * @retval NRFX_SUCCESS The procedure is successful.
  304. * @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
  305. * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
  306. * @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data
  307. * RAM region.
  308. */
  309. nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * p_instance,
  310. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  311. uint32_t flags);
  312. nrfx_err_t rtt_nrfx_spim_xfer(nrfx_spim_t const * p_instance,
  313. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  314. uint32_t flags,
  315. struct rt_spi_message * message,
  316. struct rt_spi_device * dev);
  317. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
  318. /**
  319. * @brief Function for starting the SPIM data transfer with DCX control.
  320. *
  321. * See @ref nrfx_spim_xfer for description of additional options of transfer
  322. * provided by the @c flags parameter.
  323. *
  324. * @note Peripherals that use EasyDMA (including SPIM) require the transfer buffers
  325. * to be placed in the Data RAM region. If this condition is not met,
  326. * this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
  327. *
  328. * @param p_instance Pointer to the driver instance structure.
  329. * @param p_xfer_desc Pointer to the transfer descriptor.
  330. * @param flags Transfer options (0 for default settings).
  331. * @param cmd_length Length of the command bytes preceding the data
  332. * bytes. The DCX line will be low during transmission
  333. * of command bytes and high during transmission of data bytes.
  334. * Maximum value available for dividing the transmitted bytes
  335. * into command bytes and data bytes is @ref NRF_SPIM_DCX_CNT_ALL_CMD - 1.
  336. * The @ref NRF_SPIM_DCX_CNT_ALL_CMD value passed as the
  337. * @c cmd_length parameter causes all transmitted bytes
  338. * to be marked as command bytes.
  339. *
  340. * @retval NRFX_SUCCESS The procedure is successful.
  341. * @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer.
  342. * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
  343. * @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data
  344. * RAM region.
  345. */
  346. nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * p_instance,
  347. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  348. uint32_t flags,
  349. uint8_t cmd_length);
  350. #endif
  351. /**
  352. * @brief Function for returning the address of a SPIM start task.
  353. *
  354. * This function is to be used if @ref nrfx_spim_xfer was called with the flag @ref NRFX_SPIM_FLAG_HOLD_XFER.
  355. * In that case, the transfer is not started by the driver, but it must be started externally by PPI.
  356. *
  357. * @param[in] p_instance Pointer to the driver instance structure.
  358. *
  359. * @return Start task address.
  360. */
  361. uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance);
  362. /**
  363. * @brief Function for returning the address of a END SPIM event.
  364. *
  365. * The END event can be used to detect the end of a transfer
  366. * if the @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER option is used.
  367. *
  368. * @param[in] p_instance Pointer to the driver instance structure.
  369. *
  370. * @return END event address.
  371. */
  372. uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance);
  373. /**
  374. * @brief Function for aborting ongoing transfer.
  375. *
  376. * @param[in] p_instance Pointer to the driver instance structure.
  377. */
  378. void nrfx_spim_abort(nrfx_spim_t const * p_instance);
  379. /** @} */
  380. void nrfx_spim_0_irq_handler(void);
  381. void nrfx_spim_1_irq_handler(void);
  382. void nrfx_spim_2_irq_handler(void);
  383. void nrfx_spim_3_irq_handler(void);
  384. #ifdef __cplusplus
  385. }
  386. #endif
  387. #endif /* NRFX_SPIM_H__ */