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