1 /*
2 * Copyright (c) 2015 - 2025, 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
541 #if defined(NRF_TWIS_CLOCKPIN_SCL_NEEDED)
542 nrf_gpio_pin_clock_set(p_config->scl_pin, true);
543 #endif
544 #if defined(NRF_TWIS_CLOCKPIN_SDA_NEEDED)
545 nrf_gpio_pin_clock_set(p_config->sda_pin, true);
546 #endif
547 #endif
548 }
549 twis_configure(p_instance, p_config);
550 }
551
552 /* Clear semaphore */
553 if (!NRFX_TWIS_NO_SYNC_MODE)
554 {
555 p_cb->semaphore = 0;
556 }
557 /* Set internal instance variables */
558 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
559 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
560 err_code = NRFX_SUCCESS;
561 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
562 return err_code;
563 }
564
nrfx_twis_reconfigure(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config)565 nrfx_err_t nrfx_twis_reconfigure(nrfx_twis_t const * p_instance,
566 nrfx_twis_config_t const * p_config)
567 {
568 NRFX_ASSERT(p_config);
569
570 if (m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_UNINITIALIZED)
571 {
572 return NRFX_ERROR_INVALID_STATE;
573 }
574 if (nrfx_twis_is_busy(p_instance))
575 {
576 return NRFX_ERROR_BUSY;
577 }
578
579 if (nrf_twis_enable_check(p_instance->p_reg))
580 {
581 nrf_twis_disable(p_instance->p_reg);
582 twis_configure(p_instance, p_config);
583 nrf_twis_enable(p_instance->p_reg);
584 }
585 else
586 {
587 twis_configure(p_instance, p_config);
588 }
589
590 return NRFX_SUCCESS;
591 }
592
nrfx_twis_uninit(nrfx_twis_t const * p_instance)593 void nrfx_twis_uninit(nrfx_twis_t const * p_instance)
594 {
595 NRF_TWIS_Type * p_reg = p_instance->p_reg;
596 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
597
598 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
599
600 nrfx_twis_swreset(p_reg);
601
602 if (!p_cb->skip_gpio_cfg)
603 {
604 nrf_gpio_cfg_default(nrf_twis_scl_pin_get(p_reg));
605 nrf_gpio_cfg_default(nrf_twis_sda_pin_get(p_reg));
606 }
607
608 #if NRFX_CHECK(NRFX_PRS_ENABLED)
609 nrfx_prs_release(p_reg);
610 #endif
611
612 /* Clear variables */
613 p_cb->ev_handler = NULL;
614 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
615 NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
616 }
617
nrfx_twis_init_check(nrfx_twis_t const * p_instance)618 bool nrfx_twis_init_check(nrfx_twis_t const * p_instance)
619 {
620 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
621
622 return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
623 }
624
nrfx_twis_enable(nrfx_twis_t const * p_instance)625 void nrfx_twis_enable(nrfx_twis_t const * p_instance)
626 {
627 NRF_TWIS_Type * p_reg = p_instance->p_reg;
628 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
629
630 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
631
632 nrfx_twis_clear_all_events(p_reg);
633
634 /* Enable interrupts */
635 if (NULL != p_cb->ev_handler)
636 {
637 nrf_twis_int_enable(p_reg, m_used_ints_mask);
638 }
639
640 nrf_twis_enable(p_reg);
641 p_cb->error = 0;
642 p_cb->state = NRFX_DRV_STATE_POWERED_ON;
643 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
644 }
645
nrfx_twis_disable(nrfx_twis_t const * p_instance)646 void nrfx_twis_disable(nrfx_twis_t const * p_instance)
647 {
648 NRF_TWIS_Type * p_reg = p_instance->p_reg;
649 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
650
651 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
652
653 nrf_twis_int_disable(p_reg, m_used_ints_mask);
654
655 nrf_twis_disable(p_reg);
656 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
657 }
658
659 /* ARM recommends not using the LDREX and STREX instructions in C code.
660 * This is because the compiler might generate loads and stores between
661 * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
662 * This recommendation also applies to the byte, halfword, and doubleword
663 * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
664 *
665 * This is the reason for the function below to be implemented in assembly.
666 */
667 #if defined (__CC_ARM )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)668 static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
669 {
670 mov r3, r0
671 mov r1, #0
672 nrfx_twis_error_get_and_clear_internal_try
673 ldrex r0, [r3]
674 strex r2, r1, [r3]
675 cmp r2, r1 /* did this succeed? */
676 bne nrfx_twis_error_get_and_clear_internal_try /* no - try again */
677 bx lr
678 }
679 #elif defined ( __GNUC__ ) && defined(ISA_ARM)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)680 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
681 {
682 uint32_t ret;
683 uint32_t temp;
684 __ASM volatile(
685 " .syntax unified \n"
686 "nrfx_twis_error_get_and_clear_internal_try: \n"
687 " ldrex %[ret], [%[perror]] \n"
688 " strex %[temp], %[zero], [%[perror]] \n"
689 " cmp %[temp], %[zero] \n"
690 " bne nrfx_twis_error_get_and_clear_internal_try \n"
691 : /* Output */
692 [ret]"=&l"(ret),
693 [temp]"=&l"(temp)
694 : /* Input */
695 [zero]"l"(0),
696 [perror]"l"(perror)
697 );
698 (void)temp;
699 return ret;
700 }
701 #elif defined ( __GNUC__ ) && defined(ISA_RISCV)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)702 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
703 {
704 uint32_t error = *perror;
705 *perror = 0;
706 return error;
707 }
708 #elif defined ( __ICCARM__ )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)709 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
710 {
711 uint32_t ret;
712 uint32_t temp;
713 __ASM volatile(
714 "1: \n"
715 " ldrex %[ret], [%[perror]] \n"
716 " strex %[temp], %[zero], [%[perror]] \n"
717 " cmp %[temp], %[zero] \n"
718 " bne.n 1b \n"
719 : /* Output */
720 [ret]"=&l"(ret),
721 [temp]"=&l"(temp)
722 : /* Input */
723 [zero]"l"(0),
724 [perror]"l"(perror)
725 );
726 (void)temp;
727 return ret;
728 }
729 #else
730 #error Unknown compiler
731 #endif
732
nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)733 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
734 {
735 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
736
737 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
738
739 nrfx_twis_preprocess_status(p_instance);
740 /* Make sure that access to error member is atomic
741 * so there is no bit that is cleared if it is not copied to local variable already. */
742 return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
743 }
744
nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,void const * p_buf,size_t size)745 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
746 void const * p_buf,
747 size_t size)
748 {
749 NRFX_ASSERT(p_buf);
750
751 nrfx_err_t err_code;
752 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
753
754 /* Check power state*/
755 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
756 {
757 err_code = NRFX_ERROR_INVALID_STATE;
758 NRFX_LOG_WARNING("Function: %s, error code: %s.",
759 __func__,
760 NRFX_LOG_ERROR_STRING_GET(err_code));
761 return err_code;
762 }
763 /* Check data address */
764 if (!nrfx_is_in_ram(p_buf))
765 {
766 err_code = NRFX_ERROR_INVALID_ADDR;
767 NRFX_LOG_WARNING("Function: %s, error code: %s.",
768 __func__,
769 NRFX_LOG_ERROR_STRING_GET(err_code));
770 return err_code;
771 }
772 /* Check data size */
773 if (size > NRF_TWIS_RX_MAX_COUNT_SIZE)
774 {
775 err_code = NRFX_ERROR_INVALID_LENGTH;
776 NRFX_LOG_WARNING("Function: %s, error code: %s.",
777 __func__,
778 NRFX_LOG_ERROR_STRING_GET(err_code));
779 return err_code;
780 }
781
782 nrf_twis_tx_prepare(p_instance->p_reg,
783 (uint8_t const *)p_buf,
784 size);
785 err_code = NRFX_SUCCESS;
786 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
787 return err_code;
788 }
789
nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,void * p_buf,size_t size)790 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
791 void * p_buf,
792 size_t size)
793 {
794 NRFX_ASSERT(p_buf);
795
796 nrfx_err_t err_code;
797 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
798
799 /* Check power state*/
800 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
801 {
802 err_code = NRFX_ERROR_INVALID_STATE;
803 NRFX_LOG_WARNING("Function: %s, error code: %s.",
804 __func__,
805 NRFX_LOG_ERROR_STRING_GET(err_code));
806 return err_code;
807 }
808 /* Check data address */
809 if (!nrfx_is_in_ram(p_buf))
810 {
811 err_code = NRFX_ERROR_INVALID_ADDR;
812 NRFX_LOG_WARNING("Function: %s, error code: %s.",
813 __func__,
814 NRFX_LOG_ERROR_STRING_GET(err_code));
815 return err_code;
816 }
817 /* Check data size */
818 if (size > NRF_TWIS_TX_MAX_COUNT_SIZE)
819 {
820 err_code = NRFX_ERROR_INVALID_LENGTH;
821 NRFX_LOG_WARNING("Function: %s, error code: %s.",
822 __func__,
823 NRFX_LOG_ERROR_STRING_GET(err_code));
824 return err_code;
825 }
826
827 nrf_twis_rx_prepare(p_instance->p_reg,
828 (uint8_t *)p_buf,
829 size);
830 err_code = NRFX_SUCCESS;
831 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
832 return err_code;
833 }
834
nrfx_twis_is_busy(nrfx_twis_t const * p_instance)835 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
836 {
837 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
838
839 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
840
841 nrfx_twis_preprocess_status(p_instance);
842 return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
843 }
844
nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)845 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
846 {
847 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
848
849 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
850
851 nrfx_twis_preprocess_status(p_instance);
852 return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
853 }
854
nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)855 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
856 {
857 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
858
859 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
860
861 nrfx_twis_preprocess_status(p_instance);
862 return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
863 }
864
nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)865 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
866 {
867 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
868
869 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
870
871 nrfx_twis_preprocess_status(p_instance);
872 return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
873 }
874
nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)875 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
876 {
877 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
878
879 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
880
881 nrfx_twis_preprocess_status(p_instance);
882 return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
883 }
884
885 NRFX_INSTANCE_IRQ_HANDLERS(TWIS, twis)
886
887 #endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
888