1 /*
2  * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <nrfx.h>
33 
34 #if NRFX_CHECK(NRFX_TWIM_ENABLED)
35 
36 #if !(NRFX_CHECK(NRFX_TWIM0_ENABLED) || \
37       NRFX_CHECK(NRFX_TWIM1_ENABLED) || \
38       NRFX_CHECK(NRFX_TWIM2_ENABLED) || \
39       NRFX_CHECK(NRFX_TWIM3_ENABLED))
40 #error "No enabled TWIM instances. Check <nrfx_config.h>."
41 #endif
42 
43 #include <nrfx_twim.h>
44 #include <hal/nrf_gpio.h>
45 #include "prs/nrfx_prs.h"
46 
47 #define NRFX_LOG_MODULE TWIM
48 #include <nrfx_log.h>
49 
50 #define EVT_TO_STR(event)                                       \
51     (event == NRFX_TWIM_EVT_DONE         ? "EVT_DONE"         : \
52     (event == NRFX_TWIM_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
53     (event == NRFX_TWIM_EVT_DATA_NACK    ? "EVT_DATA_NACK"    : \
54     (event == NRFX_TWIM_EVT_OVERRUN      ? "EVT_OVERRUN"      : \
55     (event == NRFX_TWIM_EVT_BUS_ERROR    ? "EVT_BUS_ERROR"    : \
56                                            "UNKNOWN ERROR")))))
57 
58 #define EVT_TO_STR_TWIM(event)                                        \
59     (event == NRF_TWIM_EVENT_STOPPED   ? "NRF_TWIM_EVENT_STOPPED"   : \
60     (event == NRF_TWIM_EVENT_ERROR     ? "NRF_TWIM_EVENT_ERROR"     : \
61     (event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \
62     (event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \
63     (event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \
64     (event == NRF_TWIM_EVENT_LASTRX    ? "NRF_TWIM_EVENT_LASTRX"    : \
65     (event == NRF_TWIM_EVENT_LASTTX    ? "NRF_TWIM_EVENT_LASTTX"    : \
66                                          "UNKNOWN ERROR")))))))
67 
68 #define TRANSFER_TO_STR(type)                    \
69     (type == NRFX_TWIM_XFER_TX   ? "XFER_TX"   : \
70     (type == NRFX_TWIM_XFER_RX   ? "XFER_RX"   : \
71     (type == NRFX_TWIM_XFER_TXRX ? "XFER_TXRX" : \
72     (type == NRFX_TWIM_XFER_TXTX ? "XFER_TXTX" : \
73                                    "UNKNOWN TRANSFER TYPE"))))
74 
75 #define TWIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin),                     \
76                                          NRF_GPIO_PIN_DIR_INPUT,     \
77                                          NRF_GPIO_PIN_INPUT_CONNECT, \
78                                          NRF_GPIO_PIN_PULLUP,        \
79                                          NRF_GPIO_PIN_S0D1,          \
80                                          NRF_GPIO_PIN_NOSENSE)
81 
82 #define TWIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2)     \
83     (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
84      NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
85 
86 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
87 #define TWIM0_LENGTH_VALIDATE(...)  TWIMX_LENGTH_VALIDATE(TWIM0, __VA_ARGS__)
88 #else
89 #define TWIM0_LENGTH_VALIDATE(...)  0
90 #endif
91 
92 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
93 #define TWIM1_LENGTH_VALIDATE(...)  TWIMX_LENGTH_VALIDATE(TWIM1, __VA_ARGS__)
94 #else
95 #define TWIM1_LENGTH_VALIDATE(...)  0
96 #endif
97 
98 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
99 #define TWIM2_LENGTH_VALIDATE(...)  TWIMX_LENGTH_VALIDATE(TWIM2, __VA_ARGS__)
100 #else
101 #define TWIM2_LENGTH_VALIDATE(...)  0
102 #endif
103 
104 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
105 #define TWIM3_LENGTH_VALIDATE(...)  TWIMX_LENGTH_VALIDATE(TWIM3, __VA_ARGS__)
106 #else
107 #define TWIM3_LENGTH_VALIDATE(...)  0
108 #endif
109 
110 #define TWIM_LENGTH_VALIDATE(drv_inst_idx, len1, len2)  \
111     (TWIM0_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
112      TWIM1_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
113      TWIM2_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
114      TWIM3_LENGTH_VALIDATE(drv_inst_idx, len1, len2))
115 
116 // Control block - driver instance local data.
117 typedef struct
118 {
119     nrfx_twim_evt_handler_t handler;
120     void *                  p_context;
121     volatile uint32_t       int_mask;
122     nrfx_twim_xfer_desc_t   xfer_desc;
123     uint32_t                flags;
124     uint8_t *               p_curr_buf;
125     size_t                  curr_length;
126     bool                    curr_no_stop;
127     nrfx_drv_state_t        state;
128     bool                    error;
129     volatile bool           busy;
130     bool                    repeated;
131     uint8_t                 bytes_transferred;
132     bool                    hold_bus_uninit;
133 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
134     nrf_twim_frequency_t    bus_frequency;
135 #endif
136 } twim_control_block_t;
137 
138 static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT];
139 
twi_process_error(uint32_t errorsrc)140 static nrfx_err_t twi_process_error(uint32_t errorsrc)
141 {
142     nrfx_err_t ret = NRFX_ERROR_INTERNAL;
143 
144     if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
145     {
146         ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
147     }
148 
149     if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
150     {
151         ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
152     }
153 
154     if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
155     {
156         ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
157     }
158 
159     return ret;
160 }
161 
xfer_completeness_check(NRF_TWIM_Type * p_twim,twim_control_block_t const * p_cb)162 static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t const * p_cb)
163 {
164     // If the actual number of transferred bytes is not equal to what was requested,
165     // but there was no error signaled by the peripheral, this means that something
166     // unexpected, like a premature STOP condition, was received on the bus.
167     // In such case the peripheral has to be disabled and re-enabled, so that its
168     // internal state machine is reinitialized.
169 
170     bool transfer_complete = true;
171     switch (p_cb->xfer_desc.type)
172     {
173     case NRFX_TWIM_XFER_TXTX:
174             // int_mask variable is used to determine which length should be checked
175             // against number of bytes latched in EasyDMA.
176             // NRF_TWIM_INT_SUSPENDED_MASK is configured only in first TX of TXTX transfer.
177             if (((p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
178                  (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)) ||
179                 (!(p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
180                  (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length)))
181             {
182                 transfer_complete = false;
183             }
184         break;
185     case NRFX_TWIM_XFER_TXRX:
186             if ((nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length) ||
187                 (nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length))
188             {
189                 transfer_complete = false;
190             }
191         break;
192     case NRFX_TWIM_XFER_TX:
193             if (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
194             {
195                 transfer_complete = false;
196             }
197         break;
198     case NRFX_TWIM_XFER_RX:
199             if (nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
200             {
201                 transfer_complete = false;
202             }
203         break;
204     default:
205         break;
206     }
207 
208     if (!transfer_complete)
209     {
210         nrf_twim_disable(p_twim);
211         nrf_twim_enable(p_twim);
212     }
213 
214     return transfer_complete;
215 }
216 
nrfx_twim_init(nrfx_twim_t const * p_instance,nrfx_twim_config_t const * p_config,nrfx_twim_evt_handler_t event_handler,void * p_context)217 nrfx_err_t nrfx_twim_init(nrfx_twim_t const *        p_instance,
218                           nrfx_twim_config_t const * p_config,
219                           nrfx_twim_evt_handler_t    event_handler,
220                           void *                     p_context)
221 {
222     NRFX_ASSERT(p_config);
223     NRFX_ASSERT(p_config->scl != p_config->sda);
224     twim_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
225     nrfx_err_t err_code;
226 
227     if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
228     {
229         err_code = NRFX_ERROR_INVALID_STATE;
230         NRFX_LOG_WARNING("Function: %s, error code: %s.",
231                          __func__,
232                          NRFX_LOG_ERROR_STRING_GET(err_code));
233         return err_code;
234     }
235 
236 #if NRFX_CHECK(NRFX_PRS_ENABLED)
237     static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = {
238         #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
239         nrfx_twim_0_irq_handler,
240         #endif
241         #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
242         nrfx_twim_1_irq_handler,
243         #endif
244         #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
245         nrfx_twim_2_irq_handler,
246         #endif
247         #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
248         nrfx_twim_3_irq_handler,
249         #endif
250     };
251     if (nrfx_prs_acquire(p_instance->p_twim,
252             irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
253     {
254         err_code = NRFX_ERROR_BUSY;
255         NRFX_LOG_WARNING("Function: %s, error code: %s.",
256                          __func__,
257                          NRFX_LOG_ERROR_STRING_GET(err_code));
258         return err_code;
259     }
260 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
261 
262     p_cb->handler         = event_handler;
263     p_cb->p_context       = p_context;
264     p_cb->int_mask        = 0;
265     p_cb->repeated        = false;
266     p_cb->busy            = false;
267     p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
268 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
269     p_cb->bus_frequency   = (nrf_twim_frequency_t)p_config->frequency;
270 #endif
271 
272     /* To secure correct signal levels on the pins used by the TWI
273        master when the system is in OFF mode, and when the TWI master is
274        disabled, these pins must be configured in the GPIO peripheral.
275     */
276     TWIM_PIN_INIT(p_config->scl);
277     TWIM_PIN_INIT(p_config->sda);
278 
279     NRF_TWIM_Type * p_twim = p_instance->p_twim;
280     nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
281     nrf_twim_frequency_set(p_twim,
282         (nrf_twim_frequency_t)p_config->frequency);
283 
284     if (p_cb->handler)
285     {
286         NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twim),
287             p_config->interrupt_priority);
288         NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twim));
289     }
290 
291     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
292 
293     err_code = NRFX_SUCCESS;
294     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
295     return err_code;
296 }
297 
nrfx_twim_uninit(nrfx_twim_t const * p_instance)298 void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
299 {
300     twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
301     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
302 
303     if (p_cb->handler)
304     {
305         NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twim));
306     }
307     nrfx_twim_disable(p_instance);
308 
309 #if NRFX_CHECK(NRFX_PRS_ENABLED)
310     nrfx_prs_release(p_instance->p_twim);
311 #endif
312 
313     if (!p_cb->hold_bus_uninit)
314     {
315         nrf_gpio_cfg_default(nrf_twim_scl_pin_get(p_instance->p_twim));
316         nrf_gpio_cfg_default(nrf_twim_sda_pin_get(p_instance->p_twim));
317     }
318 
319     p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
320     NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
321 }
322 
nrfx_twim_enable(nrfx_twim_t const * p_instance)323 void nrfx_twim_enable(nrfx_twim_t const * p_instance)
324 {
325     twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
326     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
327 
328     nrf_twim_enable(p_instance->p_twim);
329 
330     p_cb->state = NRFX_DRV_STATE_POWERED_ON;
331     NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
332 }
333 
nrfx_twim_disable(nrfx_twim_t const * p_instance)334 void nrfx_twim_disable(nrfx_twim_t const * p_instance)
335 {
336     twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
337     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
338 
339     NRF_TWIM_Type * p_twim = p_instance->p_twim;
340     p_cb->int_mask = 0;
341     nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
342     nrf_twim_shorts_disable(p_twim, NRF_TWIM_ALL_SHORTS_MASK);
343     nrf_twim_disable(p_twim);
344 
345     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
346     NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
347 }
348 
349 
nrfx_twim_is_busy(nrfx_twim_t const * p_instance)350 bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance)
351 {
352     twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
353     return p_cb->busy;
354 }
355 
356 
twim_list_enable_handle(NRF_TWIM_Type * p_twim,uint32_t flags)357 static void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
358 {
359     if (NRFX_TWIM_FLAG_TX_POSTINC & flags)
360     {
361         nrf_twim_tx_list_enable(p_twim);
362     }
363     else
364     {
365         nrf_twim_tx_list_disable(p_twim);
366     }
367 
368     if (NRFX_TWIM_FLAG_RX_POSTINC & flags)
369     {
370         nrf_twim_rx_list_enable(p_twim);
371     }
372     else
373     {
374         nrf_twim_rx_list_disable(p_twim);
375     }
376 }
twim_xfer(twim_control_block_t * p_cb,NRF_TWIM_Type * p_twim,nrfx_twim_xfer_desc_t const * p_xfer_desc,uint32_t flags)377 static nrfx_err_t twim_xfer(twim_control_block_t        * p_cb,
378                             NRF_TWIM_Type               * p_twim,
379                             nrfx_twim_xfer_desc_t const * p_xfer_desc,
380                             uint32_t                      flags)
381 {
382     nrfx_err_t err_code = NRFX_SUCCESS;
383     nrf_twim_task_t  start_task = NRF_TWIM_TASK_STARTTX;
384     p_cb->error = false;
385 
386     if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf))
387     {
388         err_code = NRFX_ERROR_INVALID_ADDR;
389         NRFX_LOG_WARNING("Function: %s, error code: %s.",
390                          __func__,
391                          NRFX_LOG_ERROR_STRING_GET(err_code));
392         return err_code;
393     }
394     /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
395     nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
396     if (p_cb->busy)
397     {
398         nrf_twim_int_enable(p_twim, p_cb->int_mask);
399         err_code = NRFX_ERROR_BUSY;
400         NRFX_LOG_WARNING("Function: %s, error code: %s.",
401                          __func__,
402                          NRFX_LOG_ERROR_STRING_GET(err_code));
403         return err_code;
404     }
405     else
406     {
407         p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) ||
408                       (NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true;
409     }
410 
411     p_cb->xfer_desc = *p_xfer_desc;
412     p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false;
413     p_cb->flags = flags;
414     nrf_twim_address_set(p_twim, p_xfer_desc->address);
415 
416     nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
417     nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
418     nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
419     nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
420 
421     twim_list_enable_handle(p_twim, flags);
422     switch (p_xfer_desc->type)
423     {
424     case NRFX_TWIM_XFER_TXTX:
425         NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER));
426         NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER));
427         NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER));
428         if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
429         {
430             err_code = NRFX_ERROR_INVALID_ADDR;
431             NRFX_LOG_WARNING("Function: %s, error code: %s.",
432                              __func__,
433                              NRFX_LOG_ERROR_STRING_GET(err_code));
434             return err_code;
435         }
436         nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
437         nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
438         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
439         nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
440         nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
441         while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
442         {}
443         NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED));
444         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
445         nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
446         p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
447         break;
448     case NRFX_TWIM_XFER_TXRX:
449         nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
450         if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
451         {
452             err_code = NRFX_ERROR_INVALID_ADDR;
453             NRFX_LOG_WARNING("Function: %s, error code: %s.",
454                              __func__,
455                              NRFX_LOG_ERROR_STRING_GET(err_code));
456             return err_code;
457         }
458         nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
459         nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
460                                     NRF_TWIM_SHORT_LASTRX_STOP_MASK);
461         p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
462         nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
463         break;
464     case NRFX_TWIM_XFER_TX:
465         nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
466         if (NRFX_TWIM_FLAG_TX_NO_STOP & flags)
467         {
468             nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
469             p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
470         }
471         else
472         {
473             nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
474             p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
475         }
476         nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
477         break;
478     case NRFX_TWIM_XFER_RX:
479         nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
480         nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
481         p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
482         start_task = NRF_TWIM_TASK_STARTRX;
483         nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
484         break;
485     default:
486         err_code = NRFX_ERROR_INVALID_PARAM;
487         break;
488     }
489 
490     if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX))
491     {
492         nrf_twim_task_trigger(p_twim, start_task);
493     }
494 
495     if (p_cb->handler)
496     {
497         if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)
498         {
499             p_cb->int_mask = 0;
500         }
501 
502         if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK))
503         {
504             p_cb->int_mask |= NRF_TWIM_INT_STOPPED_MASK;
505         }
506 
507         // Interrupts for ERROR are implicitly enabled, regardless of driver configuration.
508         p_cb->int_mask |= NRF_TWIM_INT_ERROR_MASK;
509         nrf_twim_int_enable(p_twim, p_cb->int_mask);
510 
511 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
512         if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_RX))
513         {
514             twim_list_enable_handle(p_twim, 0);
515             p_twim->FREQUENCY = 0;
516             nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
517             nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
518         }
519         else
520         {
521             nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
522         }
523 #endif
524     }
525     else
526     {
527         bool transmission_finished = false;
528         do {
529             if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_SUSPENDED))
530             {
531                 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
532                 transmission_finished = true;
533             }
534 
535             if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
536             {
537                 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
538                 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
539                 transmission_finished = true;
540             }
541 
542             if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
543             {
544                 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
545                 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
546 
547                 bool lasttx_triggered = nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX);
548                 uint32_t shorts_mask = nrf_twim_shorts_get(p_twim);
549 
550                 if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
551                 {
552                     // Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
553                     // triggering of STOP task in case of error has to be done manually.
554                     nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
555                     nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
556 
557                     // Mark transmission as not finished yet,
558                     // as STOPPED event is expected to arrive.
559                     // If LASTTX_SUSPENDED shortcut is active,
560                     // NACK has been received on last byte sent
561                     // and SUSPENDED event happened to be checked before ERROR,
562                     // transmission will be marked as finished.
563                     // In such case this flag has to be overwritten.
564                     transmission_finished = false;
565                 }
566 
567                 if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
568                 {
569                     // When STOP task was triggered just before SUSPEND task has taken effect,
570                     // SUSPENDED event may not arrive.
571                     // However if SUSPENDED arrives it always arrives after ERROR.
572                     // Therefore SUSPENDED has to be cleared
573                     // so it does not cause premature termination of busy loop
574                     // waiting for STOPPED event to arrive.
575                     nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
576 
577                     // Mark transmission as not finished yet,
578                     // for same reasons as above.
579                     transmission_finished = false;
580                 }
581             }
582         } while (!transmission_finished);
583 
584         uint32_t errorsrc =  nrf_twim_errorsrc_get_and_clear(p_twim);
585 
586         p_cb->busy = false;
587 
588         if (errorsrc)
589         {
590             err_code = twi_process_error(errorsrc);
591         }
592         else
593         {
594             if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) &&
595                 !xfer_completeness_check(p_twim, p_cb))
596             {
597                 err_code = NRFX_ERROR_INTERNAL;
598             }
599         }
600     }
601     return err_code;
602 }
603 
604 
nrfx_twim_xfer(nrfx_twim_t const * p_instance,nrfx_twim_xfer_desc_t const * p_xfer_desc,uint32_t flags)605 nrfx_err_t nrfx_twim_xfer(nrfx_twim_t           const * p_instance,
606                           nrfx_twim_xfer_desc_t const * p_xfer_desc,
607                           uint32_t                      flags)
608 {
609     NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
610                                      p_xfer_desc->primary_length,
611                                      p_xfer_desc->secondary_length));
612 
613     nrfx_err_t err_code = NRFX_SUCCESS;
614     twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
615 
616     // TXRX and TXTX transfers are supported only in non-blocking mode.
617     NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
618     NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));
619 
620     NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
621     NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
622                   p_xfer_desc->primary_length,
623                   p_xfer_desc->secondary_length);
624     NRFX_LOG_DEBUG("Primary buffer data:");
625     NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
626                            p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
627     NRFX_LOG_DEBUG("Secondary buffer data:");
628     NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
629                            p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
630 
631     err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
632     NRFX_LOG_WARNING("Function: %s, error code: %s.",
633                      __func__,
634                      NRFX_LOG_ERROR_STRING_GET(err_code));
635     return err_code;
636 }
637 
nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,nrfx_twim_xfer_type_t xfer_type)638 uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,
639                                   nrfx_twim_xfer_type_t xfer_type)
640 {
641     return nrf_twim_task_address_get(p_instance->p_twim,
642         (xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
643 }
644 
nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)645 uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)
646 {
647     return nrf_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED);
648 }
649 
twim_irq_handler(NRF_TWIM_Type * p_twim,twim_control_block_t * p_cb)650 static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
651 {
652 
653 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
654     /* Handle only workaround case. Can be used without TWIM handler in IRQs. */
655     if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
656     {
657         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
658         nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
659         if (p_twim->FREQUENCY == 0)
660         {
661             // Set enable to zero to reset TWIM internal state.
662             nrf_twim_disable(p_twim);
663             nrf_twim_enable(p_twim);
664 
665             // Set proper frequency.
666             nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
667             twim_list_enable_handle(p_twim, p_cb->flags);
668 
669             // Start proper transmission.
670             nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
671             return;
672         }
673     }
674 #endif
675 
676     NRFX_ASSERT(p_cb->handler);
677 
678     if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
679     {
680         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
681         NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
682         if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
683         {
684             nrf_twim_int_disable(p_twim, p_cb->int_mask);
685             p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
686             nrf_twim_int_enable(p_twim, p_cb->int_mask);
687 
688             if (!(nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX) &&
689                  (nrf_twim_shorts_get(p_twim) & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
690             {
691                 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
692                 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
693             }
694 
695             p_cb->error = true;
696             return;
697         }
698     }
699 
700     nrfx_twim_evt_t event;
701 
702     if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
703     {
704         NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
705         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
706 
707         if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) && !p_cb->error)
708         {
709             p_cb->error = !xfer_completeness_check(p_twim, p_cb);
710         }
711 
712         // Further processing of STOPPED event is valid only if NO_XFER_EVT_HANDLER
713         // setting is not used.
714         if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER))
715         {
716             event.xfer_desc = p_cb->xfer_desc;
717             nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
718             nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
719             if (!p_cb->repeated || p_cb->error)
720             {
721                 nrf_twim_shorts_set(p_twim, 0);
722                 p_cb->int_mask = 0;
723                 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
724 
725                 // At this point interrupt handler should not be invoked again for current transfer.
726                 // If STOPPED arrived during ERROR processing,
727                 // its pending interrupt should be ignored.
728                 // Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
729                 // would be passed to user's handler.
730                 NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
731             }
732         }
733 
734 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
735         else if (p_cb->xfer_desc.type != NRFX_TWIM_XFER_RX)
736         {
737             /* Add Anomaly 109 workaround for each potential repeated transfer starting from TX. */
738             twim_list_enable_handle(p_twim, 0);
739             p_twim->FREQUENCY = 0;
740             nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
741         }
742 #endif
743     }
744     else
745     {
746         nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
747         NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
748         if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
749         {
750             event.xfer_desc = p_cb->xfer_desc;
751             if (!p_cb->repeated)
752             {
753                 nrf_twim_shorts_set(p_twim, 0);
754                 p_cb->int_mask = 0;
755                 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
756 
757                 // At this point interrupt handler should not be invoked again for current transfer.
758                 // If STOPPED arrived during SUSPENDED processing,
759                 // its pending interrupt should be ignored.
760                 // Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
761                 // would be passed to user's handler.
762                 NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
763             }
764         }
765         else
766         {
767             nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
768             p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
769             nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
770             nrf_twim_int_enable(p_twim, p_cb->int_mask);
771             nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
772             nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
773             return;
774         }
775     }
776 
777     uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
778     if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
779     {
780         event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
781         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
782     }
783     else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
784     {
785         event.type = NRFX_TWIM_EVT_DATA_NACK;
786         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
787     }
788     else if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
789     {
790         event.type = NRFX_TWIM_EVT_OVERRUN;
791         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_OVERRUN));
792     }
793     else if (p_cb->error)
794     {
795         event.type = NRFX_TWIM_EVT_BUS_ERROR;
796         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_BUS_ERROR));
797     }
798     else
799     {
800         event.type = NRFX_TWIM_EVT_DONE;
801         NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
802     }
803 
804     if (!p_cb->repeated)
805     {
806         p_cb->busy = false;
807     }
808 
809     if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER) || p_cb->error)
810     {
811         p_cb->handler(&event, p_cb->p_context);
812     }
813 }
814 
815 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
nrfx_twim_0_irq_handler(void)816 void nrfx_twim_0_irq_handler(void)
817 {
818     twim_irq_handler(NRF_TWIM0, &m_cb[NRFX_TWIM0_INST_IDX]);
819 }
820 #endif
821 
822 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
nrfx_twim_1_irq_handler(void)823 void nrfx_twim_1_irq_handler(void)
824 {
825     twim_irq_handler(NRF_TWIM1, &m_cb[NRFX_TWIM1_INST_IDX]);
826 }
827 #endif
828 
829 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
nrfx_twim_2_irq_handler(void)830 void nrfx_twim_2_irq_handler(void)
831 {
832     twim_irq_handler(NRF_TWIM2, &m_cb[NRFX_TWIM2_INST_IDX]);
833 }
834 #endif
835 
836 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
nrfx_twim_3_irq_handler(void)837 void nrfx_twim_3_irq_handler(void)
838 {
839     twim_irq_handler(NRF_TWIM3, &m_cb[NRFX_TWIM3_INST_IDX]);
840 }
841 #endif
842 
843 #endif // NRFX_CHECK(NRFX_TWIM_ENABLED)
844