1 /*
2 * Copyright (c) 2015 - 2023, 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
36 #if NRFX_CHECK(NRFX_TWIS_ENABLED)
37
38 #if !NRFX_FEATURE_PRESENT(NRFX_TWIS, _ENABLED)
39 #error "No enabled TWIS instances. Check <nrfx_config.h>."
40 #endif
41
42 #include <nrfx_twis.h>
43 #include "prs/nrfx_prs.h"
44
45 #define NRFX_LOG_MODULE TWIS
46 #include <nrfx_log.h>
47
48 #define EVT_TO_STR(event) \
49 (event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \
50 (event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \
51 (event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \
52 (event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \
53 (event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \
54 (event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : \
55 "UNKNOWN EVENT"))))))
56
57 /**
58 * @brief Actual state of internal state machine
59 *
60 * Current substate of powered on state.
61 */
62 typedef enum
63 {
64 NRFX_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission
65 NRFX_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data
66 NRFX_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending)
67 NRFX_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer
68 NRFX_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving)
69 } nrfx_twis_substate_t;
70
71 // Control block - driver instance local data.
72 typedef struct
73 {
74 nrfx_twis_event_handler_t ev_handler;
75 // Internal copy of hardware errors flags merged with specific internal
76 // driver errors flags.
77 // This value can be changed in the interrupt and cleared in the main program.
78 // Always use Atomic load-store when updating this value in main loop.
79 volatile uint32_t error;
80 nrfx_drv_state_t state;
81 volatile nrfx_twis_substate_t substate;
82
83 volatile bool semaphore;
84 bool skip_gpio_cfg;
85 } twis_control_block_t;
86 static twis_control_block_t m_cb[NRFX_TWIS_ENABLED_COUNT];
87
88 /**
89 * @brief Used interrupts mask
90 *
91 * Mask for all interrupts used by this library
92 */
93 static const uint32_t m_used_ints_mask = NRF_TWIS_INT_STOPPED_MASK |
94 NRF_TWIS_INT_ERROR_MASK |
95 NRF_TWIS_INT_RXSTARTED_MASK |
96 NRF_TWIS_INT_TXSTARTED_MASK |
97 NRF_TWIS_INT_WRITE_MASK |
98 NRF_TWIS_INT_READ_MASK;
99
100 /**
101 * @brief Clear all events
102 *
103 * Function clears all actually pending events
104 */
nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)105 static void nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)
106 {
107 /* Clear all events */
108 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED);
109 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR);
110 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED);
111 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED);
112 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE);
113 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ);
114 }
115
116 /**
117 * @brief Reset all the registers to known state
118 *
119 * This function clears all registers that requires it to known state.
120 * TWIS is left disabled after this function.
121 * All events are cleared.
122 * @param[out] p_reg TWIS to reset register address
123 */
nrfx_twis_swreset(NRF_TWIS_Type * p_reg)124 static inline void nrfx_twis_swreset(NRF_TWIS_Type * p_reg)
125 {
126 /* Disable TWIS */
127 nrf_twis_disable(p_reg);
128
129 /* Disable interrupt global for the instance */
130 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
131
132 /* Disable interrupts */
133 nrf_twis_int_disable(p_reg, ~0U);
134 }
135
136 /**
137 * @brief Configure pin
138 *
139 * Function configures selected for work as SDA or SCL.
140 * @param pin Pin number to configure
141 */
nrfx_twis_config_pin(uint32_t pin,nrf_gpio_pin_pull_t pull)142 static inline void nrfx_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull)
143 {
144 nrf_gpio_cfg(pin,
145 NRF_GPIO_PIN_DIR_INPUT,
146 NRF_GPIO_PIN_INPUT_DISCONNECT,
147 pull,
148 NRF_GPIO_PIN_S0D1,
149 NRF_GPIO_PIN_NOSENSE);
150 }
151
152 /**
153 * @brief Auxiliary function for getting event state on right bit possition
154 *
155 * This function calls @ref nrf_twis_event_get function but the the result
156 * is shifted to match INTEN register scheme.
157 *
158 * @param[in,out] p_reg TWIS to read event from
159 * @param ev Event code
160 *
161 * @return Selected event state shifted by @ref nrfx_event_to_bitpos
162 *
163 * @sa nrf_twis_event_get
164 * @sa nrfx_event_to_bitpos
165 */
nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg,nrf_twis_event_t ev)166 static inline uint32_t nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg,
167 nrf_twis_event_t ev)
168 {
169 return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrfx_event_to_bitpos(ev);
170 }
171
172 /**
173 * @brief Auxiliary function for checking event bit inside given flags value
174 *
175 * Function used here to check presence of the event inside given flags value.
176 * It transforms given event to bit possition and then checks if in given variable it is cleared.
177 *
178 * @param flags Flags to test
179 * @param ev Event code
180 *
181 * @retval true Flag for selected event is set
182 * @retval false Flag for selected event is cleared
183 */
nrfx_twis_check_bit(uint32_t flags,nrf_twis_event_t ev)184 static inline bool nrfx_twis_check_bit(uint32_t flags,
185 nrf_twis_event_t ev)
186 {
187 return 0 != (flags & (1U << nrfx_event_to_bitpos(ev)));
188 }
189
190 /**
191 * @brief Auxiliary function for clearing event bit in given flags value
192 *
193 * Function used to clear selected event bit.
194 *
195 * @param flags Flags to process
196 * @param ev Event code to clear
197 *
198 * @return Value @em flags with cleared event bit that matches given @em ev
199 */
nrfx_twis_clear_bit(uint32_t flags,nrf_twis_event_t ev)200 static inline uint32_t nrfx_twis_clear_bit(uint32_t flags,
201 nrf_twis_event_t ev)
202 {
203 return flags & ~(1U << nrfx_event_to_bitpos(ev));
204 }
205
call_event_handler(twis_control_block_t const * p_cb,nrfx_twis_evt_t const * p_evt)206 static void call_event_handler(twis_control_block_t const * p_cb,
207 nrfx_twis_evt_t const * p_evt)
208 {
209 nrfx_twis_event_handler_t handler = p_cb->ev_handler;
210 if (handler != NULL)
211 {
212 handler(p_evt);
213 }
214 }
215
216 /**
217 * @brief Auxiliary function for error processing
218 *
219 * Function called when in current substate the event apears and it cannot be processed.
220 * It should be called also on ERROR event.
221 * If given @em error parameter has zero value the @ref NRFX_TWIS_ERROR_UNEXPECTED_EVENT
222 * would be set.
223 *
224 * @param p_cb Pointer to the driver instance control block.
225 * @param evt What error event raport to event handler
226 * @param error Error flags
227 */
nrfx_twis_process_error(twis_control_block_t * p_cb,nrfx_twis_evt_type_t evt,uint32_t error)228 static inline void nrfx_twis_process_error(twis_control_block_t * p_cb,
229 nrfx_twis_evt_type_t evt,
230 uint32_t error)
231 {
232 if (0 == error)
233 {
234 error = NRFX_TWIS_ERROR_UNEXPECTED_EVENT;
235 }
236 nrfx_twis_evt_t evdata;
237 evdata.type = evt;
238 evdata.data.error = error;
239
240 p_cb->error |= error;
241
242 call_event_handler(p_cb, &evdata);
243 }
244
irq_handler(NRF_TWIS_Type * p_reg,twis_control_block_t * p_cb)245 static void irq_handler(NRF_TWIS_Type * p_reg, twis_control_block_t * p_cb)
246 {
247 if (!NRFX_TWIS_NO_SYNC_MODE)
248 {
249 /* Exclude parallel processing of this function */
250 if (p_cb->semaphore)
251 {
252 return;
253 }
254 p_cb->semaphore = 1;
255 }
256
257 /* Event data structure to be passed into event handler */
258 nrfx_twis_evt_t evdata;
259 /* Current substate copy */
260 nrfx_twis_substate_t substate = p_cb->substate;
261 /* Event flags */
262 uint32_t ev = 0;
263
264 /* Get all events */
265 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED);
266 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR);
267 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED);
268 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED);
269 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE);
270 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ);
271
272 /* State machine */
273 while (0 != ev)
274 {
275 switch (substate)
276 {
277 case NRFX_TWIS_SUBSTATE_IDLE:
278 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
279 {
280 /* Stopped event is always allowed in IDLE state - just ignore */
281 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
282 }
283 else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ))
284 {
285 evdata.type = NRFX_TWIS_EVT_READ_REQ;
286 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED))
287 {
288 substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
289 evdata.data.buf_req = false;
290 }
291 else
292 {
293 substate = NRFX_TWIS_SUBSTATE_READ_WAITING;
294 evdata.data.buf_req = true;
295 }
296 call_event_handler(p_cb, &evdata);
297 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
298 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
299 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
300 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
301 }
302 else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE))
303 {
304 evdata.type = NRFX_TWIS_EVT_WRITE_REQ;
305 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED))
306 {
307 substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
308 evdata.data.buf_req = false;
309 }
310 else
311 {
312 substate = NRFX_TWIS_SUBSTATE_WRITE_WAITING;
313 evdata.data.buf_req = true;
314 }
315 call_event_handler(p_cb, &evdata);
316 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
317 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
318 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
319 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
320 }
321 else
322 {
323 nrfx_twis_process_error(p_cb,
324 NRFX_TWIS_EVT_GENERAL_ERROR,
325 nrf_twis_error_source_get_and_clear(p_reg));
326 ev = 0;
327 }
328 break;
329 case NRFX_TWIS_SUBSTATE_READ_WAITING:
330 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) ||
331 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
332 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
333 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
334 {
335 substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
336 /* Any other bits requires further processing in PENDING substate */
337 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
338 }
339 else
340 {
341 nrfx_twis_process_error(p_cb,
342 NRFX_TWIS_EVT_READ_ERROR,
343 nrf_twis_error_source_get_and_clear(p_reg));
344 substate = NRFX_TWIS_SUBSTATE_IDLE;
345 ev = 0;
346 }
347 break;
348 case NRFX_TWIS_SUBSTATE_READ_PENDING:
349 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
350 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
351 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
352 {
353 evdata.type = NRFX_TWIS_EVT_READ_DONE;
354 evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg);
355 NRFX_LOG_INFO("Transfer tx_len:%d", evdata.data.tx_amount);
356 NRFX_LOG_DEBUG("Tx data:");
357 NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)nrf_twis_tx_buffer_get(p_reg),
358 evdata.data.tx_amount * sizeof(uint8_t));
359 call_event_handler(p_cb, &evdata);
360 /* Go to idle and repeat the state machine if READ or WRITE events detected.
361 * This time READ or WRITE would be started */
362 substate = NRFX_TWIS_SUBSTATE_IDLE;
363 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
364 }
365 else
366 {
367 nrfx_twis_process_error(p_cb,
368 NRFX_TWIS_EVT_READ_ERROR,
369 nrf_twis_error_source_get_and_clear(p_reg));
370 substate = NRFX_TWIS_SUBSTATE_IDLE;
371 ev = 0;
372 }
373 break;
374 case NRFX_TWIS_SUBSTATE_WRITE_WAITING:
375 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) ||
376 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
377 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
378 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
379 {
380 substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
381 /* Any other bits requires further processing in PENDING substate */
382 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
383 }
384 else
385 {
386 nrfx_twis_process_error(p_cb,
387 NRFX_TWIS_EVT_WRITE_ERROR,
388 nrf_twis_error_source_get_and_clear(p_reg));
389 substate = NRFX_TWIS_SUBSTATE_IDLE;
390 ev = 0;
391 }
392 break;
393 case NRFX_TWIS_SUBSTATE_WRITE_PENDING:
394 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
395 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
396 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
397 {
398 evdata.type = NRFX_TWIS_EVT_WRITE_DONE;
399 evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg);
400 call_event_handler(p_cb, &evdata);
401 /* Go to idle and repeat the state machine if READ or WRITE events detected.
402 * This time READ or WRITE would be started */
403 substate = NRFX_TWIS_SUBSTATE_IDLE;
404 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
405 }
406 else
407 {
408 nrfx_twis_process_error(p_cb,
409 NRFX_TWIS_EVT_WRITE_ERROR,
410 nrf_twis_error_source_get_and_clear(p_reg));
411 substate = NRFX_TWIS_SUBSTATE_IDLE;
412 ev = 0;
413 }
414 break;
415 default:
416 substate = NRFX_TWIS_SUBSTATE_IDLE;
417 /* Do not clear any events and repeat the machine */
418 break;
419 }
420 }
421
422 p_cb->substate = substate;
423 if (!NRFX_TWIS_NO_SYNC_MODE)
424 {
425 p_cb->semaphore = 0;
426 }
427 }
428
nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)429 static inline void nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)
430 {
431 if (!NRFX_TWIS_NO_SYNC_MODE)
432 {
433 NRF_TWIS_Type * p_reg = p_instance->p_reg;
434 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
435 if (NULL == p_cb->ev_handler)
436 {
437 irq_handler(p_reg, p_cb);
438 }
439 }
440 }
441
twis_configure(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config)442 static void twis_configure(nrfx_twis_t const * p_instance,
443 nrfx_twis_config_t const * p_config)
444 {
445 uint32_t addr_mask = 0;
446 if (0 == (p_config->addr[0] | p_config->addr[1]))
447 {
448 addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK;
449 }
450 else
451 {
452 if (0 != p_config->addr[0])
453 {
454 addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK;
455 }
456 if (0 != p_config->addr[1])
457 {
458 addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK;
459 }
460 }
461
462 if (!p_config->skip_psel_cfg)
463 {
464 nrf_twis_pins_set(p_instance->p_reg, p_config->scl_pin, p_config->sda_pin);
465 }
466
467 nrf_twis_address_set(p_instance->p_reg, 0, (nrf_twis_address_t)p_config->addr[0]);
468 nrf_twis_address_set(p_instance->p_reg, 1, (nrf_twis_address_t)p_config->addr[1]);
469
470 nrf_twis_config_address_set(p_instance->p_reg, (nrf_twis_config_addr_mask_t)addr_mask);
471
472 if (m_cb[p_instance->drv_inst_idx].ev_handler)
473 {
474 /* Peripheral interrupt configure
475 * (note - interrupts still needs to be configured in INTEN register.
476 * This is done in enable function) */
477 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
478 p_config->interrupt_priority);
479 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
480 }
481 }
482
483 /* -------------------------------------------------------------------------
484 * Implementation of interface functions
485 *
486 */
487
nrfx_twis_init(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config,nrfx_twis_event_handler_t event_handler)488 nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
489 nrfx_twis_config_t const * p_config,
490 nrfx_twis_event_handler_t event_handler)
491 {
492 NRFX_ASSERT(p_config);
493 nrfx_err_t err_code;
494
495 NRF_TWIS_Type * p_reg = p_instance->p_reg;
496 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
497
498 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
499 {
500 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
501 err_code = NRFX_ERROR_ALREADY;
502 #else
503 err_code = NRFX_ERROR_INVALID_STATE;
504 #endif
505 NRFX_LOG_WARNING("Function: %s, error code: %s.",
506 __func__,
507 NRFX_LOG_ERROR_STRING_GET(err_code));
508 return err_code;
509 }
510
511 #if NRFX_CHECK(NRFX_PRS_ENABLED)
512 static nrfx_irq_handler_t const irq_handlers[NRFX_TWIS_ENABLED_COUNT] = {
513 NRFX_INSTANCE_IRQ_HANDLERS_LIST(TWIS, twis)
514 };
515 if (nrfx_prs_acquire(p_reg,
516 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
517 {
518 err_code = NRFX_ERROR_BUSY;
519 NRFX_LOG_WARNING("Function: %s, error code: %s.",
520 __func__,
521 NRFX_LOG_ERROR_STRING_GET(err_code));
522 return err_code;
523 }
524 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
525
526 if (!NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
527 {
528 nrfx_twis_swreset(p_reg);
529 }
530
531 p_cb->ev_handler = event_handler;
532 if (p_config)
533 {
534 p_cb->skip_gpio_cfg = p_config->skip_gpio_cfg;
535 if (!p_config->skip_gpio_cfg)
536 {
537 NRFX_ASSERT(p_config->scl_pin != p_config->sda_pin);
538 nrfx_twis_config_pin(p_config->scl_pin, p_config->scl_pull);
539 nrfx_twis_config_pin(p_config->sda_pin, p_config->sda_pull);
540 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_TWIS_CLOCKPIN_SCL_NEEDED)
541 nrf_gpio_pin_clock_set(p_config->scl_pin, true);
542 #endif
543 }
544 twis_configure(p_instance, p_config);
545 }
546
547 /* Clear semaphore */
548 if (!NRFX_TWIS_NO_SYNC_MODE)
549 {
550 p_cb->semaphore = 0;
551 }
552 /* Set internal instance variables */
553 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
554 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
555 err_code = NRFX_SUCCESS;
556 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
557 return err_code;
558 }
559
nrfx_twis_reconfigure(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config)560 nrfx_err_t nrfx_twis_reconfigure(nrfx_twis_t const * p_instance,
561 nrfx_twis_config_t const * p_config)
562 {
563 NRFX_ASSERT(p_config);
564
565 if (m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_UNINITIALIZED)
566 {
567 return NRFX_ERROR_INVALID_STATE;
568 }
569 if (nrfx_twis_is_busy(p_instance))
570 {
571 return NRFX_ERROR_BUSY;
572 }
573
574 if (nrf_twis_enable_check(p_instance->p_reg))
575 {
576 nrf_twis_disable(p_instance->p_reg);
577 twis_configure(p_instance, p_config);
578 nrf_twis_enable(p_instance->p_reg);
579 }
580 else
581 {
582 twis_configure(p_instance, p_config);
583 }
584
585 return NRFX_SUCCESS;
586 }
587
nrfx_twis_uninit(nrfx_twis_t const * p_instance)588 void nrfx_twis_uninit(nrfx_twis_t const * p_instance)
589 {
590 NRF_TWIS_Type * p_reg = p_instance->p_reg;
591 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
592
593 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
594
595 nrfx_twis_swreset(p_reg);
596
597 if (!p_cb->skip_gpio_cfg)
598 {
599 nrf_gpio_cfg_default(nrf_twis_scl_pin_get(p_reg));
600 nrf_gpio_cfg_default(nrf_twis_sda_pin_get(p_reg));
601 }
602
603 #if NRFX_CHECK(NRFX_PRS_ENABLED)
604 nrfx_prs_release(p_reg);
605 #endif
606
607 /* Clear variables */
608 p_cb->ev_handler = NULL;
609 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
610 NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
611 }
612
nrfx_twis_init_check(nrfx_twis_t const * p_instance)613 bool nrfx_twis_init_check(nrfx_twis_t const * p_instance)
614 {
615 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
616
617 return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
618 }
619
nrfx_twis_enable(nrfx_twis_t const * p_instance)620 void nrfx_twis_enable(nrfx_twis_t const * p_instance)
621 {
622 NRF_TWIS_Type * p_reg = p_instance->p_reg;
623 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
624
625 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
626
627 nrfx_twis_clear_all_events(p_reg);
628
629 /* Enable interrupts */
630 if (NULL != p_cb->ev_handler)
631 {
632 nrf_twis_int_enable(p_reg, m_used_ints_mask);
633 }
634
635 nrf_twis_enable(p_reg);
636 p_cb->error = 0;
637 p_cb->state = NRFX_DRV_STATE_POWERED_ON;
638 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
639 }
640
nrfx_twis_disable(nrfx_twis_t const * p_instance)641 void nrfx_twis_disable(nrfx_twis_t const * p_instance)
642 {
643 NRF_TWIS_Type * p_reg = p_instance->p_reg;
644 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
645
646 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
647
648 nrf_twis_int_disable(p_reg, m_used_ints_mask);
649
650 nrf_twis_disable(p_reg);
651 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
652 }
653
654 /* ARM recommends not using the LDREX and STREX instructions in C code.
655 * This is because the compiler might generate loads and stores between
656 * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
657 * This recommendation also applies to the byte, halfword, and doubleword
658 * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
659 *
660 * This is the reason for the function below to be implemented in assembly.
661 */
662 #if defined (__CC_ARM )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)663 static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
664 {
665 mov r3, r0
666 mov r1, #0
667 nrfx_twis_error_get_and_clear_internal_try
668 ldrex r0, [r3]
669 strex r2, r1, [r3]
670 cmp r2, r1 /* did this succeed? */
671 bne nrfx_twis_error_get_and_clear_internal_try /* no - try again */
672 bx lr
673 }
674 #elif defined ( __GNUC__ ) && defined(ISA_ARM)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)675 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
676 {
677 uint32_t ret;
678 uint32_t temp;
679 __ASM volatile(
680 " .syntax unified \n"
681 "nrfx_twis_error_get_and_clear_internal_try: \n"
682 " ldrex %[ret], [%[perror]] \n"
683 " strex %[temp], %[zero], [%[perror]] \n"
684 " cmp %[temp], %[zero] \n"
685 " bne nrfx_twis_error_get_and_clear_internal_try \n"
686 : /* Output */
687 [ret]"=&l"(ret),
688 [temp]"=&l"(temp)
689 : /* Input */
690 [zero]"l"(0),
691 [perror]"l"(perror)
692 );
693 (void)temp;
694 return ret;
695 }
696 #elif defined ( __GNUC__ ) && defined(ISA_RISCV)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)697 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
698 {
699 uint32_t error = *perror;
700 *perror = 0;
701 return error;
702 }
703 #elif defined ( __ICCARM__ )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)704 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
705 {
706 uint32_t ret;
707 uint32_t temp;
708 __ASM volatile(
709 "1: \n"
710 " ldrex %[ret], [%[perror]] \n"
711 " strex %[temp], %[zero], [%[perror]] \n"
712 " cmp %[temp], %[zero] \n"
713 " bne.n 1b \n"
714 : /* Output */
715 [ret]"=&l"(ret),
716 [temp]"=&l"(temp)
717 : /* Input */
718 [zero]"l"(0),
719 [perror]"l"(perror)
720 );
721 (void)temp;
722 return ret;
723 }
724 #else
725 #error Unknown compiler
726 #endif
727
nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)728 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
729 {
730 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
731
732 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
733
734 nrfx_twis_preprocess_status(p_instance);
735 /* Make sure that access to error member is atomic
736 * so there is no bit that is cleared if it is not copied to local variable already. */
737 return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
738 }
739
nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,void const * p_buf,size_t size)740 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
741 void const * p_buf,
742 size_t size)
743 {
744 NRFX_ASSERT(p_buf);
745
746 nrfx_err_t err_code;
747 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
748
749 /* Check power state*/
750 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
751 {
752 err_code = NRFX_ERROR_INVALID_STATE;
753 NRFX_LOG_WARNING("Function: %s, error code: %s.",
754 __func__,
755 NRFX_LOG_ERROR_STRING_GET(err_code));
756 return err_code;
757 }
758 /* Check data address */
759 if (!nrfx_is_in_ram(p_buf))
760 {
761 err_code = NRFX_ERROR_INVALID_ADDR;
762 NRFX_LOG_WARNING("Function: %s, error code: %s.",
763 __func__,
764 NRFX_LOG_ERROR_STRING_GET(err_code));
765 return err_code;
766 }
767 /* Check data size */
768 if (size > NRF_TWIS_RX_MAX_COUNT_SIZE)
769 {
770 err_code = NRFX_ERROR_INVALID_LENGTH;
771 NRFX_LOG_WARNING("Function: %s, error code: %s.",
772 __func__,
773 NRFX_LOG_ERROR_STRING_GET(err_code));
774 return err_code;
775 }
776
777 nrf_twis_tx_prepare(p_instance->p_reg,
778 (uint8_t const *)p_buf,
779 size);
780 err_code = NRFX_SUCCESS;
781 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
782 return err_code;
783 }
784
nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,void * p_buf,size_t size)785 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
786 void * p_buf,
787 size_t size)
788 {
789 NRFX_ASSERT(p_buf);
790
791 nrfx_err_t err_code;
792 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
793
794 /* Check power state*/
795 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
796 {
797 err_code = NRFX_ERROR_INVALID_STATE;
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 /* Check data address */
804 if (!nrfx_is_in_ram(p_buf))
805 {
806 err_code = NRFX_ERROR_INVALID_ADDR;
807 NRFX_LOG_WARNING("Function: %s, error code: %s.",
808 __func__,
809 NRFX_LOG_ERROR_STRING_GET(err_code));
810 return err_code;
811 }
812 /* Check data size */
813 if (size > NRF_TWIS_TX_MAX_COUNT_SIZE)
814 {
815 err_code = NRFX_ERROR_INVALID_LENGTH;
816 NRFX_LOG_WARNING("Function: %s, error code: %s.",
817 __func__,
818 NRFX_LOG_ERROR_STRING_GET(err_code));
819 return err_code;
820 }
821
822 nrf_twis_rx_prepare(p_instance->p_reg,
823 (uint8_t *)p_buf,
824 size);
825 err_code = NRFX_SUCCESS;
826 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
827 return err_code;
828 }
829
nrfx_twis_is_busy(nrfx_twis_t const * p_instance)830 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
831 {
832 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
833
834 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
835
836 nrfx_twis_preprocess_status(p_instance);
837 return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
838 }
839
nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)840 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
841 {
842 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
843
844 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
845
846 nrfx_twis_preprocess_status(p_instance);
847 return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
848 }
849
nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)850 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
851 {
852 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
853
854 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
855
856 nrfx_twis_preprocess_status(p_instance);
857 return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
858 }
859
nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)860 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
861 {
862 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
863
864 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
865
866 nrfx_twis_preprocess_status(p_instance);
867 return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
868 }
869
nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)870 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
871 {
872 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
873
874 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
875
876 nrfx_twis_preprocess_status(p_instance);
877 return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
878 }
879
880 NRFX_INSTANCE_IRQ_HANDLERS(TWIS, twis)
881
882 #endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
883