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 #ifndef NRFX_TWIS_H__
33 #define NRFX_TWIS_H__
34 
35 #include <nrfx.h>
36 #include <hal/nrf_twis.h>
37 #include <hal/nrf_gpio.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrfx_twis TWIS driver
45  * @{
46  * @ingroup nrf_twis
47  * @brief   Two Wire Interface Slave with EasyDMA (TWIS) peripheral driver.
48  */
49 
50 /** @brief TWIS driver instance data structure. */
51 typedef struct
52 {
53     NRF_TWIS_Type * p_reg;        ///< Pointer to a structure with TWIS registers.
54     uint8_t         drv_inst_idx; ///< Index of the driver instance. For internal use only.
55 } nrfx_twis_t;
56 
57 #ifndef __NRFX_DOXYGEN__
58 enum {
59 #if NRFX_CHECK(NRFX_TWIS0_ENABLED)
60     NRFX_TWIS0_INST_IDX,
61 #endif
62 #if NRFX_CHECK(NRFX_TWIS1_ENABLED)
63     NRFX_TWIS1_INST_IDX,
64 #endif
65 #if NRFX_CHECK(NRFX_TWIS2_ENABLED)
66     NRFX_TWIS2_INST_IDX,
67 #endif
68 #if NRFX_CHECK(NRFX_TWIS3_ENABLED)
69     NRFX_TWIS3_INST_IDX,
70 #endif
71     NRFX_TWIS_ENABLED_COUNT
72 };
73 #endif
74 
75 /** @brief Macro for creating a TWIS driver instance. */
76 #define NRFX_TWIS_INSTANCE(id)                               \
77 {                                                            \
78     .p_reg        = NRFX_CONCAT_2(NRF_TWIS, id),             \
79     .drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIS, id, _INST_IDX), \
80 }
81 
82 /** @brief Event callback function event definitions. */
83 typedef enum
84 {
85     NRFX_TWIS_EVT_READ_REQ,     ///< Read request detected.
86                                 /**< If there is no buffer prepared, buf_req flag in the even will be set.
87                                      Call then @ref nrfx_twis_tx_prepare to give parameters for buffer.
88                                      */
89     NRFX_TWIS_EVT_READ_DONE,    ///< Read request finished - free any data.
90     NRFX_TWIS_EVT_READ_ERROR,   ///< Read request finished with error.
91     NRFX_TWIS_EVT_WRITE_REQ,    ///< Write request detected.
92                                 /**< If there is no buffer prepared, buf_req flag in the even will be set.
93                                      Call then @ref nrfx_twis_rx_prepare to give parameters for buffer.
94                                      */
95     NRFX_TWIS_EVT_WRITE_DONE,   ///< Write request finished - process data.
96     NRFX_TWIS_EVT_WRITE_ERROR,  ///< Write request finished with error.
97     NRFX_TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction.
98 } nrfx_twis_evt_type_t;
99 
100 /**
101  * @brief Possible error sources.
102  *
103  * This is flag enum - values from this enum can be connected using logical or operator.
104  * @note
105  * You can use directly @ref nrf_twis_error_t. Error type enum is redefined here because
106  * of possible future extension (eg. supporting timeouts and synchronous mode).
107  */
108 typedef enum
109 {
110     NRFX_TWIS_ERROR_OVERFLOW         = NRF_TWIS_ERROR_OVERFLOW,  /**< RX buffer overflow detected, and prevented. */
111     NRFX_TWIS_ERROR_DATA_NACK        = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte. */
112     NRFX_TWIS_ERROR_OVERREAD         = NRF_TWIS_ERROR_OVERREAD,  /**< TX buffer over-read detected, and prevented. */
113     NRFX_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8                    /**< Unexpected event detected by state machine. */
114 } nrfx_twis_error_t;
115 
116 /** @brief TWIS driver event structure. */
117 typedef struct
118 {
119     nrfx_twis_evt_type_t type; ///< Event type.
120     union
121     {
122         bool buf_req;       ///< Flag for @ref NRFX_TWIS_EVT_READ_REQ and @ref NRFX_TWIS_EVT_WRITE_REQ.
123                             /**< Information if transmission buffer requires to be prepared. */
124         uint32_t tx_amount; ///< Data for @ref NRFX_TWIS_EVT_READ_DONE.
125         uint32_t rx_amount; ///< Data for @ref NRFX_TWIS_EVT_WRITE_DONE.
126         uint32_t error;     ///< Data for @ref NRFX_TWIS_EVT_GENERAL_ERROR.
127     } data;                 ///< Union to store event data.
128 } nrfx_twis_evt_t;
129 
130 /**
131  * @brief TWI slave event callback function type.
132  *
133  * @param[in] p_event Event information structure.
134  */
135 typedef void (*nrfx_twis_event_handler_t)(nrfx_twis_evt_t const * p_event);
136 
137 /** @brief Structure for TWIS configuration. */
138 typedef struct
139 {
140     uint32_t            addr[2];            //!< Set addresses that this slave should respond. Set 0 to disable.
141     uint32_t            scl;                //!< SCL pin number.
142     uint32_t            sda;                //!< SDA pin number.
143     nrf_gpio_pin_pull_t scl_pull;           //!< SCL pin pull.
144     nrf_gpio_pin_pull_t sda_pull;           //!< SDA pin pull.
145     uint8_t             interrupt_priority; //!< The priority of interrupt for the module to be set.
146 } nrfx_twis_config_t;
147 
148 /**
149  * @brief TWIS driver default configuration.
150  *
151  * This configuration sets up TWIS with the following options:
152  * - second slave address disabled
153  * - SCL pull-up disabled
154  * - SDA pull-up disabled
155  *
156  * @param[in] _pin_scl SCL pin.
157  * @param[in] _pin_sda SDA pin.
158  * @param[in] _addr    Slave address on TWI bus.
159  */
160 #define NRFX_TWIS_DEFAULT_CONFIG(_pin_scl, _pin_sda, _addr)      \
161 {                                                                \
162     .addr               = { _addr, 0x00 },                       \
163     .scl                = _pin_scl,                              \
164     .scl_pull           = NRF_GPIO_PIN_NOPULL,                   \
165     .sda                = _pin_sda,                              \
166     .sda_pull           = NRF_GPIO_PIN_NOPULL,                   \
167     .interrupt_priority = NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY  \
168 }
169 
170 /**
171  * @brief Function for initializing the TWIS driver instance.
172  *
173  * Function initializes and enables the TWIS driver.
174  * @attention After driver initialization enable it with @ref nrfx_twis_enable.
175  *
176  * @param[in] p_instance    Pointer to the driver instance structure.
177  * @attention               @em p_instance has to be global object.
178  *                          It will be used by interrupts so make it sure that object
179  *                          is not destroyed when function is leaving.
180  * @param[in] p_config      Pointer to the structure with the initial configuration.
181  * @param[in] event_handler Event handler provided by the user.
182  *
183  * @retval NRFX_SUCCESS             Initialization is successful.
184  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
185  * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
186  *                                  instance ID is already in use. This is
187  *                                  possible only if NRFX_PRS_ENABLED
188  *                                  is set to a value other than zero.
189  */
190 nrfx_err_t nrfx_twis_init(nrfx_twis_t const *        p_instance,
191                           nrfx_twis_config_t const * p_config,
192                           nrfx_twis_event_handler_t  event_handler);
193 
194 /**
195  * @brief Function for uninitializing the TWIS driver instance.
196  *
197  * Function uninitializes the peripheral and resets all registers to default values.
198  *
199  * @note
200  * It is safe to call nrfx_twis_uninit even before initialization.
201  * Actually, @ref nrfx_twis_init function calls this function to
202  * make sure that TWIS state is known.
203  * @note
204  * If TWIS driver was in uninitialized state before calling this function,
205  * the selected pins would not be reset to default configuration.
206  *
207  * @param[in] p_instance Pointer to the driver instance structure.
208  */
209 void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
210 
211 /**
212  * @brief Function for enabling the TWIS instance.
213  *
214  * This function enables the TWIS instance.
215  * Function defined if there is need for dynamically enabling and disabling the peripheral.
216  * Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
217  * They do not change any configuration registers.
218  *
219  * @param p_instance Pointer to the driver instance structure.
220  */
221 void nrfx_twis_enable(nrfx_twis_t const * p_instance);
222 
223 /**
224  * @brief Function for disabling the TWIS instance.
225  *
226  * This function disables the TWIS instance, which gives possibility to turn off the TWIS while
227  * holding configuration done by @ref nrfx_twis_init.
228  *
229  * @param p_instance Pointer to the driver instance structure.
230  */
231 void nrfx_twis_disable(nrfx_twis_t const * p_instance);
232 
233 /**
234  * @brief Function for getting and clearing the last error flags.
235  *
236  * This function gets the information about errors.
237  * This is also the only possibility to exit from the error substate of the internal state machine.
238  * @attention
239  * This function clears error state and flags.
240  *
241  * @param[in] p_instance Pointer to the driver instance structure.
242  *
243  * @return Error flags defined in @ref nrfx_twis_error_t.
244  */
245 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
246 
247 /**
248  * @brief Function for preparing the data for sending.
249  *
250  * This function is to be used in response to the @ref NRFX_TWIS_EVT_READ_REQ event.
251  *
252  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
253  *       to be placed in the Data RAM region. If this condition is not met,
254  *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
255  * @attention Transmission buffer must be placed in RAM.
256  *
257  * @param[in] p_instance Pointer to the driver instance structure.
258  * @param[in] p_buf      Transmission buffer.
259  * @param[in] size       Maximum number of bytes that master may read from buffer given.
260  *
261  * @retval NRFX_SUCCESS              The preparation finished properly.
262  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
263  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
264  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
265  */
266 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
267                                 void const *        p_buf,
268                                 size_t              size);
269 
270 /**
271  * @brief Function for getting the number of transmitted bytes.
272  *
273  * This function returns the number of bytes sent.
274  * This function can be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
275  *
276  * @param[in] p_instance Pointer to the driver instance structure.
277  *
278  * @return Number of bytes sent.
279  */
280 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
281 
282 /**
283  * @brief Function for preparing the data for receiving.
284  *
285  * This function must be used in response to the @ref NRFX_TWIS_EVT_WRITE_REQ event.
286  *
287  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
288  *       to be placed in the Data RAM region. If this condition is not met,
289  *       this function fails with the error code NRFX_ERROR_INVALID_ADDR.
290  *
291  * @param[in] p_instance Pointer to the driver instance structure.
292  * @param[in] p_buf      Buffer that is to be filled with received data.
293  * @param[in] size       Size of the buffer (maximum amount of data to receive).
294  *
295  * @retval NRFX_SUCCESS              The preparation finished properly.
296  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
297  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
298  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
299  */
300 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
301                                 void *              p_buf,
302                                 size_t              size);
303 
304 /**
305  * @brief Function for getting the number of received bytes.
306  *
307  * This function returns number of bytes received.
308  * It can be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
309  *
310  * @param[in] p_instance Pointer to the driver instance structure.
311  *
312  * @return Number of bytes received.
313  */
314 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
315 
316 /**
317  * @brief Function for checking if the driver is busy right now.
318  *
319  * This function tests the actual driver substate.
320  * If the driver is in any other state than IDLE or ERROR, this function returns true.
321  *
322  * @param[in] p_instance Pointer to the driver instance structure.
323  *
324  * @retval true  The driver is in state other than ERROR or IDLE.
325  * @retval false There is no transmission pending.
326  */
327 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
328 
329 /**
330  * @brief Function for checking if the driver is waiting for a TX buffer.
331  *
332  * If this function returns true, the driver is stalled expecting
333  * of the @ref nrfx_twis_tx_prepare function call.
334  *
335  * @param[in] p_instance Pointer to the driver instance structure.
336  *
337  * @retval true  The driver is waiting for @ref nrfx_twis_tx_prepare.
338  * @retval false The driver is not in the state where it is waiting for preparing a TX buffer.
339  */
340 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
341 
342 /**
343  * @brief Function for checking if the driver is waiting for an RX buffer.
344  *
345  * If this function returns true, the driver is stalled expecting
346  * of the @ref nrfx_twis_rx_prepare function call.
347  *
348  * @param[in] p_instance Pointer to the driver instance structure.
349  *
350  * @retval true  The driver is waiting for @ref nrfx_twis_rx_prepare.
351  * @retval false The driver is not in the state where it is waiting for preparing an RX buffer.
352  */
353 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
354 
355 /**
356  * @brief Function for checking if the driver is sending data.
357  *
358  * If this function returns true, there is an ongoing output transmission.
359  *
360  * @param[in] p_instance Pointer to the driver instance structure.
361  *
362  * @retval true  There is an ongoing output transmission.
363  * @retval false The driver is in other state.
364  */
365 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
366 
367 /**
368  * @brief Function for checking if the driver is receiving data.
369  *
370  * If this function returns true, there is an ongoing input transmission.
371  *
372  * @param[in] p_instance Pointer to the driver instance structure.
373  *
374  * @retval true  There is an ongoing input transmission.
375  * @retval false The driver is in other state.
376  */
377 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
378 
379 #ifndef NRFX_DECLARE_ONLY
nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)380 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
381 {
382     return nrf_twis_tx_amount_get(p_instance->p_reg);
383 }
384 
nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)385 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
386 {
387     return nrf_twis_rx_amount_get(p_instance->p_reg);
388 }
389 #endif // NRFX_DECLARE_ONLY
390 
391 /** @} */
392 
393 
394 void nrfx_twis_0_irq_handler(void);
395 void nrfx_twis_1_irq_handler(void);
396 void nrfx_twis_2_irq_handler(void);
397 void nrfx_twis_3_irq_handler(void);
398 
399 
400 #ifdef __cplusplus
401 }
402 #endif
403 
404 #endif // NRFX_TWIS_H__
405