nrfx_spim.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  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. #include <nrfx.h>
  34. #include <drivers/pin.h>
  35. #if NRFX_CHECK(NRFX_SPIM_ENABLED)
  36. #if !(NRFX_CHECK(NRFX_SPIM0_ENABLED) || NRFX_CHECK(NRFX_SPIM1_ENABLED) || \
  37. NRFX_CHECK(NRFX_SPIM2_ENABLED) || NRFX_CHECK(NRFX_SPIM3_ENABLED) || \
  38. NRFX_CHECK(NRFX_SPIM4_ENABLED))
  39. #error "No enabled SPIM instances. Check <nrfx_config.h>."
  40. #endif
  41. #include "drv_spim.h"
  42. #include <nrfx_spim.h>
  43. #include "prs/nrfx_prs.h"
  44. #include <hal/nrf_gpio.h>
  45. #define NRFX_LOG_MODULE SPIM
  46. #include <nrfx_log.h>
  47. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) && \
  48. ((!NRF_SPIM_HW_CSN_PRESENT) || !(NRF_SPIM_DCX_PRESENT) || !(NRF_SPIM_RXDELAY_PRESENT))
  49. #error "Extended options are not available in the SoC currently in use."
  50. #endif
  51. #define SPIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
  52. (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
  53. NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
  54. #define SPIMX_HW_CSN_PRESENT_VALIDATE(peripheral, drv_inst_idx) \
  55. (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
  56. NRFX_CONCAT_2(peripheral, _FEATURE_HARDWARE_CSN_PRESENT))
  57. #define SPIMX_DCX_PRESENT_VALIDATE(peripheral, drv_inst_idx) \
  58. (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
  59. NRFX_CONCAT_2(peripheral, _FEATURE_DCX_PRESENT))
  60. #define SPIMX_SUPPORTED_FREQ_VALIDATE(peripheral, drv_inst_idx, freq) \
  61. ( \
  62. ((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
  63. ( \
  64. (((freq) != NRF_SPIM_FREQ_16M) && ((freq) != NRF_SPIM_FREQ_32M)) || \
  65. (((freq) == NRF_SPIM_FREQ_16M) && ((NRFX_CONCAT_2(peripheral, _MAX_DATARATE) >= 16))) || \
  66. (((freq) == NRF_SPIM_FREQ_32M) && ((NRFX_CONCAT_2(peripheral, _MAX_DATARATE) >= 32))) \
  67. ) \
  68. )
  69. #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
  70. #define SPIM0_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM0, __VA_ARGS__)
  71. #define SPIM0_HW_CSN_PRESENT_VALIDATE(...) SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM0, __VA_ARGS__)
  72. #define SPIM0_DCX_PRESENT_VALIDATE(...) SPIMX_DCX_PRESENT_VALIDATE(SPIM0, __VA_ARGS__)
  73. #define SPIM0_SUPPORTED_FREQ_VALIDATE(...) SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM0, __VA_ARGS__)
  74. #else
  75. #define SPIM0_LENGTH_VALIDATE(...) 0
  76. #define SPIM0_HW_CSN_PRESENT_VALIDATE(...) 0
  77. #define SPIM0_DCX_PRESENT_VALIDATE(...) 0
  78. #define SPIM0_SUPPORTED_FREQ_VALIDATE(...) 0
  79. #endif
  80. #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
  81. #define SPIM1_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM1, __VA_ARGS__)
  82. #define SPIM1_HW_CSN_PRESENT_VALIDATE(...) SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM1, __VA_ARGS__)
  83. #define SPIM1_DCX_PRESENT_VALIDATE(...) SPIMX_DCX_PRESENT_VALIDATE(SPIM1, __VA_ARGS__)
  84. #define SPIM1_SUPPORTED_FREQ_VALIDATE(...) SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM1, __VA_ARGS__)
  85. #else
  86. #define SPIM1_LENGTH_VALIDATE(...) 0
  87. #define SPIM1_HW_CSN_PRESENT_VALIDATE(...) 0
  88. #define SPIM1_DCX_PRESENT_VALIDATE(...) 0
  89. #define SPIM1_SUPPORTED_FREQ_VALIDATE(...) 0
  90. #endif
  91. #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
  92. #define SPIM2_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM2, __VA_ARGS__)
  93. #define SPIM2_HW_CSN_PRESENT_VALIDATE(...) SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM2, __VA_ARGS__)
  94. #define SPIM2_DCX_PRESENT_VALIDATE(...) SPIMX_DCX_PRESENT_VALIDATE(SPIM2, __VA_ARGS__)
  95. #define SPIM2_SUPPORTED_FREQ_VALIDATE(...) SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM2, __VA_ARGS__)
  96. #else
  97. #define SPIM2_LENGTH_VALIDATE(...) 0
  98. #define SPIM2_HW_CSN_PRESENT_VALIDATE(...) 0
  99. #define SPIM2_DCX_PRESENT_VALIDATE(...) 0
  100. #define SPIM2_SUPPORTED_FREQ_VALIDATE(...) 0
  101. #endif
  102. #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
  103. #define SPIM3_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM3, __VA_ARGS__)
  104. #define SPIM3_HW_CSN_PRESENT_VALIDATE(...) SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM3, __VA_ARGS__)
  105. #define SPIM3_DCX_PRESENT_VALIDATE(...) SPIMX_DCX_PRESENT_VALIDATE(SPIM3, __VA_ARGS__)
  106. #define SPIM3_SUPPORTED_FREQ_VALIDATE(...) SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM3, __VA_ARGS__)
  107. #else
  108. #define SPIM3_LENGTH_VALIDATE(...) 0
  109. #define SPIM3_HW_CSN_PRESENT_VALIDATE(...) 0
  110. #define SPIM3_DCX_PRESENT_VALIDATE(...) 0
  111. #define SPIM3_SUPPORTED_FREQ_VALIDATE(...) 0
  112. #endif
  113. #if NRFX_CHECK(NRFX_SPIM4_ENABLED)
  114. #define SPIM4_LENGTH_VALIDATE(...) SPIMX_LENGTH_VALIDATE(SPIM4, __VA_ARGS__)
  115. #define SPIM4_HW_CSN_PRESENT_VALIDATE(...) SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM4, __VA_ARGS__)
  116. #define SPIM4_DCX_PRESENT_VALIDATE(...) SPIMX_DCX_PRESENT_VALIDATE(SPIM4, __VA_ARGS__)
  117. #define SPIM4_SUPPORTED_FREQ_VALIDATE(...) SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM4, __VA_ARGS__)
  118. #else
  119. #define SPIM4_LENGTH_VALIDATE(...) 0
  120. #define SPIM4_HW_CSN_PRESENT_VALIDATE(...) 0
  121. #define SPIM4_DCX_PRESENT_VALIDATE(...) 0
  122. #define SPIM4_SUPPORTED_FREQ_VALIDATE(...) 0
  123. #endif
  124. #define SPIM_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) \
  125. (SPIM0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
  126. SPIM1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
  127. SPIM2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
  128. SPIM3_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
  129. SPIM4_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
  130. #define SPIM_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) \
  131. (SPIM0_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
  132. SPIM1_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
  133. SPIM2_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
  134. SPIM3_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
  135. SPIM4_HW_CSN_PRESENT_VALIDATE(drv_inst_idx))
  136. #define SPIM_DCX_PRESENT_VALIDATE(drv_inst_idx) \
  137. (SPIM0_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
  138. SPIM1_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
  139. SPIM2_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
  140. SPIM3_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
  141. SPIM4_DCX_PRESENT_VALIDATE(drv_inst_idx))
  142. #define SPIM_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) \
  143. (SPIM0_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
  144. SPIM1_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
  145. SPIM2_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
  146. SPIM3_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
  147. SPIM4_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq))
  148. /* Requested pin can either match dedicated pin or be not connected at all. */
  149. #define SPIM_DEDICATED_PIN_VALIDATE(requested_pin, supported_pin) \
  150. (((requested_pin) == NRFX_SPIM_PIN_NOT_USED) || ((requested_pin) == (supported_pin)))
  151. #if !defined(USE_WORKAROUND_FOR_ANOMALY_195) && \
  152. defined(NRF52840_XXAA) && NRFX_CHECK(NRFX_SPIM3_ENABLED)
  153. /* Enable workaround for nRF52840 anomaly 195 (SPIM3 continues to draw current after disable). */
  154. #define USE_WORKAROUND_FOR_ANOMALY_195 1
  155. #endif
  156. /* Control block - driver instance local data. */
  157. typedef struct
  158. {
  159. nrfx_spim_evt_handler_t handler;
  160. void * p_context;
  161. nrfx_spim_evt_t evt; /* Keep the struct that is ready for event handler. Less memcpy. */
  162. nrfx_drv_state_t state;
  163. volatile bool transfer_in_progress;
  164. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  165. bool use_hw_ss;
  166. #endif
  167. /* [no need for 'volatile' attribute for the following members, as they */
  168. /* are not concurrently used in IRQ handlers and main line code] */
  169. bool ss_active_high;
  170. uint8_t ss_pin;
  171. uint8_t orc;
  172. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  173. size_t tx_length;
  174. size_t rx_length;
  175. #endif
  176. } spim_control_block_t;
  177. static spim_control_block_t m_cb[NRFX_SPIM_ENABLED_COUNT];
  178. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  179. /* Workaround for nRF52840 anomaly 198: SPIM3 transmit data might be corrupted. */
  180. static uint32_t m_anomaly_198_preserved_value;
  181. static void anomaly_198_enable(uint8_t const * p_buffer, size_t buf_len)
  182. {
  183. m_anomaly_198_preserved_value = *((volatile uint32_t *)0x40000E00);
  184. if (buf_len == 0)
  185. {
  186. return;
  187. }
  188. uint32_t buffer_end_addr = ((uint32_t)p_buffer) + buf_len;
  189. uint32_t block_addr = ((uint32_t)p_buffer) & ~0x1FFF;
  190. uint32_t block_flag = (1UL << ((block_addr >> 13) & 0xFFFF));
  191. uint32_t occupied_blocks = 0;
  192. if (block_addr >= 0x20010000)
  193. {
  194. occupied_blocks = (1UL << 8);
  195. }
  196. else
  197. {
  198. do {
  199. occupied_blocks |= block_flag;
  200. block_flag <<= 1;
  201. block_addr += 0x2000;
  202. } while ((block_addr < buffer_end_addr) && (block_addr < 0x20012000));
  203. }
  204. *((volatile uint32_t *)0x40000E00) = occupied_blocks;
  205. }
  206. static void anomaly_198_disable(void)
  207. {
  208. *((volatile uint32_t *)0x40000E00) = m_anomaly_198_preserved_value;
  209. }
  210. #endif /* NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED) */
  211. static void spim_abort(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
  212. {
  213. nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP);
  214. bool stopped;
  215. NRFX_WAIT_FOR(nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED), 100, 1, stopped);
  216. if (!stopped)
  217. {
  218. NRFX_LOG_ERROR("Failed to stop instance with base address: %p.", (void *)p_spim);
  219. }
  220. p_cb->transfer_in_progress = false;
  221. }
  222. nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance,
  223. nrfx_spim_config_t const * p_config,
  224. nrfx_spim_evt_handler_t handler,
  225. void * p_context)
  226. {
  227. NRFX_ASSERT(p_config);
  228. spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
  229. nrfx_err_t err_code;
  230. if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
  231. {
  232. err_code = NRFX_ERROR_INVALID_STATE;
  233. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  234. __func__,
  235. NRFX_LOG_ERROR_STRING_GET(err_code));
  236. return err_code;
  237. }
  238. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  239. /* Check if SPIM instance supports the extended features. */
  240. if (
  241. (!SPIM_SUPPORTED_FREQ_VALIDATE(p_instance->drv_inst_idx, p_config->frequency)) ||
  242. ((p_config->use_hw_ss) &&
  243. !SPIM_HW_CSN_PRESENT_VALIDATE(p_instance->drv_inst_idx)) ||
  244. ((p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED) &&
  245. !SPIM_DCX_PRESENT_VALIDATE(p_instance->drv_inst_idx))
  246. )
  247. {
  248. err_code = NRFX_ERROR_NOT_SUPPORTED;
  249. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  250. __func__,
  251. NRFX_LOG_ERROR_STRING_GET(err_code));
  252. return err_code;
  253. }
  254. #endif
  255. NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
  256. #if NRF_SPIM_HAS_32_MHZ_FREQ && defined(NRF5340_XXAA_APPLICATION)
  257. /* Check if dedicated SPIM pins are used. */
  258. if ((p_spim == NRF_SPIM4) && (p_config->frequency == NRF_SPIM_FREQ_32M))
  259. {
  260. enum {
  261. SPIM_SCK_DEDICATED = NRF_GPIO_PIN_MAP(0, 8),
  262. SPIM_MOSI_DEDICATED = NRF_GPIO_PIN_MAP(0, 9),
  263. SPIM_MISO_DEDICATED = NRF_GPIO_PIN_MAP(0, 10),
  264. SPIM_CSN_DEDICATED = NRF_GPIO_PIN_MAP(0, 11),
  265. SPIM_DCX_DEDICATED = NRF_GPIO_PIN_MAP(0, 12),
  266. };
  267. if (!SPIM_DEDICATED_PIN_VALIDATE(p_config->sck_pin, SPIM_SCK_DEDICATED) ||
  268. !SPIM_DEDICATED_PIN_VALIDATE(p_config->ss_pin, SPIM_CSN_DEDICATED) ||
  269. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  270. !SPIM_DEDICATED_PIN_VALIDATE(p_config->dcx_pin, SPIM_DCX_DEDICATED) ||
  271. #endif
  272. !SPIM_DEDICATED_PIN_VALIDATE(p_config->mosi_pin, SPIM_MOSI_DEDICATED) ||
  273. !SPIM_DEDICATED_PIN_VALIDATE(p_config->miso_pin, SPIM_MISO_DEDICATED))
  274. {
  275. err_code = NRFX_ERROR_INVALID_PARAM;
  276. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  277. __func__,
  278. NRFX_LOG_ERROR_STRING_GET(err_code));
  279. return err_code;
  280. }
  281. }
  282. #endif
  283. #if NRFX_CHECK(NRFX_PRS_ENABLED)
  284. static nrfx_irq_handler_t const irq_handlers[NRFX_SPIM_ENABLED_COUNT] = {
  285. #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
  286. nrfx_spim_0_irq_handler,
  287. #endif
  288. #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
  289. nrfx_spim_1_irq_handler,
  290. #endif
  291. #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
  292. nrfx_spim_2_irq_handler,
  293. #endif
  294. #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
  295. nrfx_spim_3_irq_handler,
  296. #endif
  297. #if NRFX_CHECK(NRFX_SPIM4_ENABLED)
  298. nrfx_spim_4_irq_handler,
  299. #endif
  300. };
  301. if (nrfx_prs_acquire(p_instance->p_reg,
  302. irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
  303. {
  304. err_code = NRFX_ERROR_BUSY;
  305. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  306. __func__,
  307. NRFX_LOG_ERROR_STRING_GET(err_code));
  308. return err_code;
  309. }
  310. #endif /* NRFX_CHECK(NRFX_PRS_ENABLED) */
  311. p_cb->handler = handler;
  312. p_cb->p_context = p_context;
  313. uint32_t mosi_pin;
  314. uint32_t miso_pin;
  315. /* Configure pins used by the peripheral: */
  316. /* - SCK - output with initial value corresponding with the SPI mode used: */
  317. /* 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1); */
  318. /* according to the reference manual guidelines this pin and its input */
  319. /* buffer must always be connected for the SPI to work. */
  320. if (p_config->mode <= NRF_SPIM_MODE_1)
  321. {
  322. nrf_gpio_pin_clear(p_config->sck_pin);
  323. }
  324. else
  325. {
  326. nrf_gpio_pin_set(p_config->sck_pin);
  327. }
  328. nrf_gpio_pin_drive_t pin_drive;
  329. /* Configure pin drive - high drive for 32 MHz clock frequency. */
  330. #if NRF_SPIM_HAS_32_MHZ_FREQ
  331. pin_drive = (p_config->frequency == NRF_SPIM_FREQ_32M) ? NRF_GPIO_PIN_H0H1 : NRF_GPIO_PIN_S0S1;
  332. #else
  333. pin_drive = NRF_GPIO_PIN_S0S1;
  334. #endif
  335. nrf_gpio_cfg(p_config->sck_pin,
  336. NRF_GPIO_PIN_DIR_OUTPUT,
  337. NRF_GPIO_PIN_INPUT_CONNECT,
  338. NRF_GPIO_PIN_NOPULL,
  339. pin_drive,
  340. NRF_GPIO_PIN_NOSENSE);
  341. /* - MOSI (optional) - output with initial value 0, */
  342. if (p_config->mosi_pin != NRFX_SPIM_PIN_NOT_USED)
  343. {
  344. mosi_pin = p_config->mosi_pin;
  345. nrf_gpio_pin_clear(mosi_pin);
  346. nrf_gpio_cfg(mosi_pin,
  347. NRF_GPIO_PIN_DIR_OUTPUT,
  348. NRF_GPIO_PIN_INPUT_DISCONNECT,
  349. NRF_GPIO_PIN_NOPULL,
  350. pin_drive,
  351. NRF_GPIO_PIN_NOSENSE);
  352. }
  353. else
  354. {
  355. mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED;
  356. }
  357. /* - MISO (optional) - input, */
  358. if (p_config->miso_pin != NRFX_SPIM_PIN_NOT_USED)
  359. {
  360. miso_pin = p_config->miso_pin;
  361. nrf_gpio_cfg(miso_pin,
  362. NRF_GPIO_PIN_DIR_INPUT,
  363. NRF_GPIO_PIN_INPUT_CONNECT,
  364. p_config->miso_pull,
  365. pin_drive,
  366. NRF_GPIO_PIN_NOSENSE);
  367. }
  368. else
  369. {
  370. miso_pin = NRF_SPIM_PIN_NOT_CONNECTED;
  371. }
  372. /* - Slave Select (optional) - output with initial value 1 (inactive). */
  373. /* 'p_cb->ss_pin' variable is used during transfers to check if SS pin should be toggled, */
  374. /* so this field needs to be initialized even if the pin is not used. */
  375. p_cb->ss_pin = p_config->ss_pin;
  376. if (p_config->ss_pin != NRFX_SPIM_PIN_NOT_USED)
  377. {
  378. if (p_config->ss_active_high)
  379. {
  380. nrf_gpio_pin_clear(p_config->ss_pin);
  381. }
  382. else
  383. {
  384. nrf_gpio_pin_set(p_config->ss_pin);
  385. }
  386. nrf_gpio_cfg(p_config->ss_pin,
  387. NRF_GPIO_PIN_DIR_OUTPUT,
  388. NRF_GPIO_PIN_INPUT_DISCONNECT,
  389. NRF_GPIO_PIN_NOPULL,
  390. pin_drive,
  391. NRF_GPIO_PIN_NOSENSE);
  392. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  393. if (p_config->use_hw_ss)
  394. {
  395. p_cb->use_hw_ss = p_config->use_hw_ss;
  396. nrf_spim_csn_configure(p_spim,
  397. p_config->ss_pin,
  398. (p_config->ss_active_high == true ?
  399. NRF_SPIM_CSN_POL_HIGH : NRF_SPIM_CSN_POL_LOW),
  400. p_config->ss_duration);
  401. }
  402. #endif
  403. p_cb->ss_active_high = p_config->ss_active_high;
  404. }
  405. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  406. /* - DCX (optional) - output. */
  407. if (p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED)
  408. {
  409. nrf_gpio_pin_set(p_config->dcx_pin);
  410. nrf_gpio_cfg(p_config->dcx_pin,
  411. NRF_GPIO_PIN_DIR_OUTPUT,
  412. NRF_GPIO_PIN_INPUT_DISCONNECT,
  413. NRF_GPIO_PIN_NOPULL,
  414. pin_drive,
  415. NRF_GPIO_PIN_NOSENSE);
  416. nrf_spim_dcx_pin_set(p_spim, p_config->dcx_pin);
  417. }
  418. /* Change rx delay */
  419. nrf_spim_iftiming_set(p_spim, p_config->rx_delay);
  420. #endif
  421. nrf_spim_pins_set(p_spim, p_config->sck_pin, mosi_pin, miso_pin);
  422. nrf_spim_frequency_set(p_spim, p_config->frequency);
  423. nrf_spim_configure(p_spim, p_config->mode, p_config->bit_order);
  424. nrf_spim_orc_set(p_spim, p_config->orc);
  425. nrf_spim_enable(p_spim);
  426. if (p_cb->handler)
  427. {
  428. NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
  429. p_config->irq_priority);
  430. NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
  431. }
  432. p_cb->transfer_in_progress = false;
  433. p_cb->state = NRFX_DRV_STATE_INITIALIZED;
  434. err_code = NRFX_SUCCESS;
  435. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  436. return err_code;
  437. }
  438. static void spim_pin_uninit(uint32_t pin)
  439. {
  440. if (pin == NRF_SPIM_PIN_NOT_CONNECTED)
  441. {
  442. return;
  443. }
  444. nrf_gpio_cfg_default(pin);
  445. }
  446. void nrfx_spim_uninit(nrfx_spim_t const * p_instance)
  447. {
  448. spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
  449. NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
  450. NRF_SPIM_Type * p_spim = p_instance->p_reg;
  451. if (p_cb->handler)
  452. {
  453. NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
  454. nrf_spim_int_disable(p_spim, NRF_SPIM_ALL_INTS_MASK);
  455. if (p_cb->transfer_in_progress)
  456. {
  457. /* Ensure that SPI is not performing any transfer. */
  458. spim_abort(p_spim, p_cb);
  459. }
  460. }
  461. nrf_spim_disable(p_spim);
  462. spim_pin_uninit(nrf_spim_sck_pin_get(p_spim));
  463. spim_pin_uninit(nrf_spim_miso_pin_get(p_spim));
  464. spim_pin_uninit(nrf_spim_mosi_pin_get(p_spim));
  465. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  466. if (SPIM_DCX_PRESENT_VALIDATE(p_instance->drv_inst_idx))
  467. {
  468. spim_pin_uninit(nrf_spim_dcx_pin_get(p_spim));
  469. }
  470. #endif
  471. if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
  472. {
  473. nrf_gpio_cfg_default(p_cb->ss_pin);
  474. }
  475. #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_195)
  476. if (p_spim == NRF_SPIM3)
  477. {
  478. *(volatile uint32_t *)0x4002F004 = 1;
  479. }
  480. #endif
  481. #if NRFX_CHECK(NRFX_PRS_ENABLED)
  482. nrfx_prs_release(p_instance->p_reg);
  483. #endif
  484. p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
  485. }
  486. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  487. nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * p_instance,
  488. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  489. uint32_t flags,
  490. uint8_t cmd_length)
  491. {
  492. (void)flags;
  493. NRFX_ASSERT(cmd_length <= NRF_SPIM_DCX_CNT_ALL_CMD);
  494. nrf_spim_dcx_cnt_set((NRF_SPIM_Type *)p_instance->p_reg, cmd_length);
  495. return nrfx_spim_xfer(p_instance, p_xfer_desc, 0);
  496. }
  497. #endif
  498. static void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable);
  499. static void finish_transfer(spim_control_block_t * p_cb)
  500. {
  501. struct spi_dma_message *mess = (struct spi_dma_message*)(p_cb->p_context);
  502. if (mess->cs_pin != PIN_NONE && mess->cs_release)
  503. {
  504. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  505. if (!mess->use_hw_ss)
  506. #endif
  507. {
  508. if (mess->ss_active_high)
  509. {
  510. nrf_gpio_pin_clear(mess->cs_pin);
  511. }
  512. else
  513. {
  514. nrf_gpio_pin_set(mess->cs_pin);
  515. }
  516. }
  517. }
  518. /* By clearing this flag before calling the handler we allow subsequent */
  519. /* transfers to be started directly from the handler function. */
  520. p_cb->transfer_in_progress = false;
  521. p_cb->evt.type = NRFX_SPIM_EVENT_DONE;
  522. p_cb->handler(&p_cb->evt, p_cb->p_context);
  523. spim_int_enable(mess->spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
  524. rt_completion_done(mess->cpt);
  525. }
  526. static void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable)
  527. {
  528. if (!enable)
  529. {
  530. nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
  531. }
  532. else
  533. {
  534. nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
  535. }
  536. }
  537. static void spim_list_enable_handle(NRF_SPIM_Type * p_spim, uint32_t flags)
  538. {
  539. if (NRFX_SPIM_FLAG_TX_POSTINC & flags)
  540. {
  541. nrf_spim_tx_list_enable(p_spim);
  542. }
  543. else
  544. {
  545. nrf_spim_tx_list_disable(p_spim);
  546. }
  547. if (NRFX_SPIM_FLAG_RX_POSTINC & flags)
  548. {
  549. nrf_spim_rx_list_enable(p_spim);
  550. }
  551. else
  552. {
  553. nrf_spim_rx_list_disable(p_spim);
  554. }
  555. }
  556. static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim,
  557. spim_control_block_t * p_cb,
  558. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  559. uint32_t flags)
  560. {
  561. nrfx_err_t err_code;
  562. /* EasyDMA requires that transfer buffers are placed in Data RAM region; */
  563. /* signal error if they are not. */
  564. if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
  565. (p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
  566. {
  567. p_cb->transfer_in_progress = false;
  568. err_code = NRFX_ERROR_INVALID_ADDR;
  569. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  570. __func__,
  571. NRFX_LOG_ERROR_STRING_GET(err_code));
  572. return err_code;
  573. }
  574. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  575. p_cb->tx_length = 0;
  576. p_cb->rx_length = 0;
  577. #endif
  578. nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
  579. nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
  580. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  581. if (p_spim == NRF_SPIM3)
  582. {
  583. anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
  584. }
  585. #endif
  586. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
  587. spim_list_enable_handle(p_spim, flags);
  588. if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
  589. {
  590. nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
  591. }
  592. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  593. if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
  594. {
  595. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
  596. p_cb->tx_length = p_xfer_desc->tx_length;
  597. p_cb->rx_length = p_xfer_desc->rx_length;
  598. nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
  599. nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
  600. nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
  601. }
  602. #endif
  603. if (!p_cb->handler)
  604. {
  605. if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
  606. {
  607. while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
  608. {}
  609. }
  610. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  611. if (p_spim == NRF_SPIM3)
  612. {
  613. anomaly_198_disable();
  614. }
  615. #endif
  616. if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
  617. {
  618. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  619. if (!p_cb->use_hw_ss)
  620. #endif
  621. {
  622. if (p_cb->ss_active_high)
  623. {
  624. nrf_gpio_pin_clear(p_cb->ss_pin);
  625. }
  626. else
  627. {
  628. nrf_gpio_pin_set(p_cb->ss_pin);
  629. }
  630. }
  631. }
  632. }
  633. else
  634. {
  635. spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
  636. }
  637. err_code = NRFX_SUCCESS;
  638. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  639. return err_code;
  640. }
  641. nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * p_instance,
  642. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  643. uint32_t flags)
  644. {
  645. spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
  646. NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
  647. NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
  648. NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
  649. NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
  650. p_xfer_desc->rx_length,
  651. p_xfer_desc->tx_length));
  652. NRFX_ASSERT(!(flags & NRFX_SPIM_FLAG_HOLD_XFER) ||
  653. (p_cb->ss_pin == NRFX_SPIM_PIN_NOT_USED));
  654. nrfx_err_t err_code = NRFX_SUCCESS;
  655. if (p_cb->transfer_in_progress)
  656. {
  657. err_code = NRFX_ERROR_BUSY;
  658. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  659. __func__,
  660. NRFX_LOG_ERROR_STRING_GET(err_code));
  661. return err_code;
  662. }
  663. else
  664. {
  665. if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
  666. NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
  667. {
  668. p_cb->transfer_in_progress = true;
  669. }
  670. }
  671. p_cb->evt.xfer_desc = *p_xfer_desc;
  672. if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
  673. {
  674. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  675. if (!p_cb->use_hw_ss)
  676. #endif
  677. {
  678. if (p_cb->ss_active_high)
  679. {
  680. nrf_gpio_pin_set(p_cb->ss_pin);
  681. }
  682. else
  683. {
  684. nrf_gpio_pin_clear(p_cb->ss_pin);
  685. }
  686. }
  687. }
  688. return spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags);
  689. }
  690. static nrfx_err_t rtt_spim_xfer(NRF_SPIM_Type * p_spim,
  691. spim_control_block_t * p_cb,
  692. nrfx_spim_xfer_desc_t const * p_xfer_desc,
  693. uint32_t flags,
  694. struct rt_spi_message * message,
  695. struct rt_spi_device * dev)
  696. {
  697. nrfx_err_t err_code;
  698. /* EasyDMA requires that transfer buffers are placed in Data RAM region; */
  699. /* signal error if they are not. */
  700. if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
  701. (p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
  702. {
  703. p_cb->transfer_in_progress = false;
  704. err_code = NRFX_ERROR_INVALID_ADDR;
  705. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  706. __func__,
  707. NRFX_LOG_ERROR_STRING_GET(err_code));
  708. return err_code;
  709. }
  710. struct spi_dma_message *mess = (struct spi_dma_message *)(p_cb->p_context);
  711. mess->cs_take = message->cs_take;
  712. mess->cs_release = message->cs_release;
  713. mess->flags = flags;
  714. mess->spim = p_spim;
  715. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
  716. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  717. p_cb->tx_length = 0;
  718. p_cb->rx_length = 0;
  719. #endif
  720. nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
  721. nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
  722. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  723. if (p_spim == NRF_SPIM3)
  724. {
  725. anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
  726. }
  727. #endif
  728. spim_list_enable_handle(p_spim, flags);
  729. if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
  730. {
  731. nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
  732. /* rt_kprintf("SPIM task started.\n"); */
  733. }
  734. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  735. if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
  736. {
  737. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
  738. p_cb->tx_length = p_xfer_desc->tx_length;
  739. p_cb->rx_length = p_xfer_desc->rx_length;
  740. nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
  741. nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
  742. nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
  743. }
  744. #endif
  745. if (p_cb->handler == RT_NULL || (p_xfer_desc->rx_length<= 20 && p_xfer_desc->tx_length<= 20))
  746. {
  747. /* no cb func or lenth < 20, wait for transfer end */
  748. /* spim_int_enable(p_spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)); */
  749. if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
  750. {
  751. while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
  752. {
  753. }
  754. /* rt_kprintf("SPIM transfer end.\n"); */
  755. p_cb->transfer_in_progress = false;
  756. }
  757. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  758. if (p_spim == NRF_SPIM3)
  759. {
  760. anomaly_198_disable();
  761. }
  762. #endif
  763. if (dev->cs_pin != PIN_NONE && message->cs_release)
  764. {
  765. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  766. if (!p_cb->use_hw_ss)
  767. #endif
  768. {
  769. if (p_cb->ss_active_high)
  770. nrf_gpio_pin_clear(dev->cs_pin);
  771. else
  772. nrf_gpio_pin_set(dev->cs_pin);
  773. }
  774. }
  775. }
  776. else
  777. {
  778. spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
  779. p_cb->transfer_in_progress = false;
  780. if (rt_completion_wait(mess->cpt, 5000) != RT_EOK)
  781. {
  782. rt_kprintf("wait for DMA interrupt overtime!");
  783. return NRFX_ERROR_TIMEOUT;
  784. }
  785. }
  786. err_code = NRFX_SUCCESS;
  787. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  788. return err_code;
  789. }
  790. nrfx_err_t rtt_nrfx_spim_xfer(nrfx_spim_t const *p_instance,
  791. nrfx_spim_xfer_desc_t const *p_xfer_desc,
  792. uint32_t flags,
  793. struct rt_spi_message *message,
  794. struct rt_spi_device *dev)
  795. {
  796. spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
  797. NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
  798. NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
  799. NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
  800. NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
  801. p_xfer_desc->rx_length,
  802. p_xfer_desc->tx_length));
  803. NRFX_ASSERT(!(flags & NRFX_SPIM_FLAG_HOLD_XFER) ||
  804. (p_cb->ss_pin == NRFX_SPIM_PIN_NOT_USED));
  805. nrfx_err_t err_code = NRFX_SUCCESS;
  806. if (p_cb->transfer_in_progress)
  807. {
  808. err_code = NRFX_ERROR_BUSY;
  809. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  810. __func__,
  811. NRFX_LOG_ERROR_STRING_GET(err_code));
  812. return err_code;
  813. }
  814. else
  815. {
  816. if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
  817. NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
  818. {
  819. p_cb->transfer_in_progress = true;
  820. }
  821. }
  822. p_cb->evt.xfer_desc = *p_xfer_desc;
  823. if (dev->cs_pin != PIN_NONE && message->cs_take)
  824. {
  825. #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
  826. if (!p_cb->use_hw_ss && message->cs_take)
  827. #endif
  828. {
  829. if (p_cb->ss_active_high)
  830. {
  831. nrf_gpio_pin_set(dev->cs_pin);
  832. }
  833. else
  834. {
  835. nrf_gpio_pin_clear(dev->cs_pin);
  836. }
  837. }
  838. }
  839. return rtt_spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags, message, dev);
  840. }
  841. void nrfx_spim_abort(nrfx_spim_t const * p_instance)
  842. {
  843. spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
  844. NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
  845. spim_abort(p_instance->p_reg, p_cb);
  846. }
  847. uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance)
  848. {
  849. NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
  850. return nrf_spim_task_address_get(p_spim, NRF_SPIM_TASK_START);
  851. }
  852. uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance)
  853. {
  854. NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
  855. return nrf_spim_event_address_get(p_spim, NRF_SPIM_EVENT_END);
  856. }
  857. static void irq_handler(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
  858. {
  859. #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
  860. if ((nrf_spim_int_enable_check(p_spim, NRF_SPIM_INT_STARTED_MASK)) &&
  861. (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STARTED)) )
  862. {
  863. /* Handle first, zero-length, auxiliary transmission. */
  864. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
  865. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
  866. NRFX_ASSERT(p_spim->TXD.MAXCNT == 0);
  867. p_spim->TXD.MAXCNT = p_cb->tx_length;
  868. NRFX_ASSERT(p_spim->RXD.MAXCNT == 0);
  869. p_spim->RXD.MAXCNT = p_cb->rx_length;
  870. /* Disable STARTED interrupt, used only in auxiliary transmission. */
  871. nrf_spim_int_disable(p_spim, NRF_SPIM_INT_STARTED_MASK);
  872. /* Start the actual, glitch-free transmission. */
  873. nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
  874. return;
  875. }
  876. #endif
  877. if (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
  878. {
  879. #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
  880. if (p_spim == NRF_SPIM3)
  881. {
  882. anomaly_198_disable();
  883. }
  884. #endif
  885. nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
  886. NRFX_ASSERT(p_cb->handler);
  887. NRFX_LOG_DEBUG("Event: NRF_SPIM_EVENT_END.");
  888. finish_transfer(p_cb);
  889. }
  890. }
  891. #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
  892. void nrfx_spim_0_irq_handler(void)
  893. {
  894. irq_handler(NRF_SPIM0, &m_cb[NRFX_SPIM0_INST_IDX]);
  895. }
  896. #endif
  897. #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
  898. void nrfx_spim_1_irq_handler(void)
  899. {
  900. rt_interrupt_enter();
  901. irq_handler(NRF_SPIM1, &m_cb[NRFX_SPIM1_INST_IDX]);
  902. rt_interrupt_leave();
  903. }
  904. #endif
  905. #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
  906. void nrfx_spim_2_irq_handler(void)
  907. {
  908. rt_interrupt_enter();
  909. irq_handler(NRF_SPIM2, &m_cb[NRFX_SPIM2_INST_IDX]);
  910. rt_interrupt_leave();
  911. }
  912. #endif
  913. #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
  914. void nrfx_spim_3_irq_handler(void)
  915. {
  916. rt_interrupt_enter();
  917. irq_handler(NRF_SPIM3, &m_cb[NRFX_SPIM3_INST_IDX]);
  918. rt_interrupt_leave();
  919. }
  920. #endif
  921. #if NRFX_CHECK(NRFX_SPIM4_ENABLED)
  922. void nrfx_spim_4_irq_handler(void)
  923. {
  924. rt_interrupt_enter();
  925. irq_handler(NRF_SPIM4, &m_cb[NRFX_SPIM4_INST_IDX]);
  926. rt_interrupt_leave();
  927. }
  928. #endif
  929. #endif /* NRFX_CHECK(NRFX_SPIM_ENABLED) */