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