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