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