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