1 /*
2  * Copyright (c) 2015 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifndef NRFX_TWIS_H__
35 #define NRFX_TWIS_H__
36 
37 #include <nrfx.h>
38 #include <hal/nrf_twis.h>
39 #include <hal/nrf_gpio.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /**
46  * @defgroup nrfx_twis TWIS driver
47  * @{
48  * @ingroup nrf_twis
49  * @brief   Two Wire Interface Slave with EasyDMA (TWIS) peripheral driver.
50  */
51 
52 /** @brief TWIS driver instance data structure. */
53 typedef struct
54 {
55     NRF_TWIS_Type * p_reg;        ///< Pointer to a structure with TWIS registers.
56     uint8_t         drv_inst_idx; ///< Index of the driver instance. For internal use only.
57 } nrfx_twis_t;
58 
59 #ifndef __NRFX_DOXYGEN__
60 enum {
61     /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */
62     NRFX_INSTANCE_ENUM_LIST(TWIS)
63     NRFX_TWIS_ENABLED_COUNT
64 };
65 #endif
66 
67 /** @brief Macro for creating a TWIS driver instance. */
68 #define NRFX_TWIS_INSTANCE(id)                               \
69 {                                                            \
70     .p_reg        = NRFX_CONCAT_2(NRF_TWIS, id),             \
71     .drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIS, id, _INST_IDX), \
72 }
73 
74 /** @brief Event callback function event definitions. */
75 typedef enum
76 {
77     NRFX_TWIS_EVT_READ_REQ,     ///< Read request detected.
78                                 /**< If there is no buffer prepared, buf_req flag in the even will be set.
79                                      Call then @ref nrfx_twis_tx_prepare to give parameters for buffer.
80                                      */
81     NRFX_TWIS_EVT_READ_DONE,    ///< Read request finished - free any data.
82     NRFX_TWIS_EVT_READ_ERROR,   ///< Read request finished with error.
83     NRFX_TWIS_EVT_WRITE_REQ,    ///< Write request detected.
84                                 /**< If there is no buffer prepared, buf_req flag in the even will be set.
85                                      Call then @ref nrfx_twis_rx_prepare to give parameters for buffer.
86                                      */
87     NRFX_TWIS_EVT_WRITE_DONE,   ///< Write request finished - process data.
88     NRFX_TWIS_EVT_WRITE_ERROR,  ///< Write request finished with error.
89     NRFX_TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction.
90 } nrfx_twis_evt_type_t;
91 
92 /**
93  * @brief Possible error sources.
94  *
95  * This is flag enum - values from this enum can be connected using logical or operator.
96  * @note
97  * You can use directly @ref nrf_twis_error_t. Error type enum is redefined here because
98  * of possible future extension (eg. supporting timeouts and synchronous mode).
99  */
100 typedef enum
101 {
102     NRFX_TWIS_ERROR_OVERFLOW         = NRF_TWIS_ERROR_OVERFLOW,  /**< RX buffer overflow detected, and prevented. */
103     NRFX_TWIS_ERROR_DATA_NACK        = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte. */
104     NRFX_TWIS_ERROR_OVERREAD         = NRF_TWIS_ERROR_OVERREAD,  /**< TX buffer over-read detected, and prevented. */
105     NRFX_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8                    /**< Unexpected event detected by state machine. */
106 } nrfx_twis_error_t;
107 
108 /** @brief TWIS driver event structure. */
109 typedef struct
110 {
111     nrfx_twis_evt_type_t type; ///< Event type.
112     union
113     {
114         bool buf_req;       ///< Flag for @ref NRFX_TWIS_EVT_READ_REQ and @ref NRFX_TWIS_EVT_WRITE_REQ.
115                             /**< Information if transmission buffer requires to be prepared. */
116         uint32_t tx_amount; ///< Data for @ref NRFX_TWIS_EVT_READ_DONE.
117         uint32_t rx_amount; ///< Data for @ref NRFX_TWIS_EVT_WRITE_DONE.
118         uint32_t error;     ///< Data for @ref NRFX_TWIS_EVT_GENERAL_ERROR.
119     } data;                 ///< Union to store event data.
120 } nrfx_twis_evt_t;
121 
122 /**
123  * @brief TWI slave event callback function type.
124  *
125  * @param[in] p_event Event information structure.
126  */
127 typedef void (*nrfx_twis_event_handler_t)(nrfx_twis_evt_t const * p_event);
128 
129 /** @brief Structure for TWIS configuration. */
130 typedef struct
131 {
132     uint32_t            addr[2];            ///< Set addresses that this slave should respond. Set 0 to disable.
133     uint32_t            scl_pin;            ///< SCL pin number.
134     uint32_t            sda_pin;            ///< SDA pin number.
135     nrf_gpio_pin_pull_t scl_pull;           ///< SCL pin pull.
136     nrf_gpio_pin_pull_t sda_pull;           ///< SDA pin pull.
137     uint8_t             interrupt_priority; ///< The priority of interrupt for the module to be set.
138     bool                skip_gpio_cfg;      ///< Skip GPIO configuration of pins.
139                                             /**< When set to true, the driver does not modify
140                                              *   any GPIO parameters of the used pins. Those
141                                              *   parameters are supposed to be configured
142                                              *   externally before the driver is initialized. */
143     bool                skip_psel_cfg;      ///< Skip pin selection configuration.
144                                             /**< When set to true, the driver does not modify
145                                              *   pin select registers in the peripheral.
146                                              *   Those registers are supposed to be set up
147                                              *   externally before the driver is initialized.
148                                              *   @note When both GPIO configuration and pin
149                                              *   selection are to be skipped, the structure
150                                              *   fields that specify pins can be omitted,
151                                              *   as they are ignored anyway. */
152 } nrfx_twis_config_t;
153 
154 /**
155  * @brief TWIS driver default configuration.
156  *
157  * This configuration sets up TWIS with the following options:
158  * - second slave address disabled
159  * - SCL pull-up disabled
160  * - SDA pull-up disabled
161  *
162  * @param[in] _pin_scl SCL pin.
163  * @param[in] _pin_sda SDA pin.
164  * @param[in] _addr    Slave address on TWI bus.
165  */
166 #define NRFX_TWIS_DEFAULT_CONFIG(_pin_scl, _pin_sda, _addr)      \
167 {                                                                \
168     .addr               = { _addr, 0x00 },                       \
169     .scl_pin            = _pin_scl,                              \
170     .sda_pin            = _pin_sda,                              \
171     .scl_pull           = NRF_GPIO_PIN_NOPULL,                   \
172     .sda_pull           = NRF_GPIO_PIN_NOPULL,                   \
173     .interrupt_priority = NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY  \
174 }
175 
176 /**
177  * @brief Function for initializing the TWIS driver instance.
178  *
179  * Function initializes and enables the TWIS driver.
180  * @attention After driver initialization enable it with @ref nrfx_twis_enable.
181  *
182  * @param[in] p_instance    Pointer to the driver instance structure.
183  * @attention               @em p_instance has to be global object.
184  *                          It will be used by interrupts so make it sure that object
185  *                          is not destroyed when function is leaving.
186  * @param[in] p_config      Pointer to the structure with the initial configuration.
187  * @param[in] event_handler Event handler provided by the user.
188  *
189  * @retval NRFX_SUCCESS             Initialization is successful.
190  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
191  * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
192  *                                  instance ID is already in use. This is
193  *                                  possible only if NRFX_PRS_ENABLED
194  *                                  is set to a value other than zero.
195  */
196 nrfx_err_t nrfx_twis_init(nrfx_twis_t const *        p_instance,
197                           nrfx_twis_config_t const * p_config,
198                           nrfx_twis_event_handler_t  event_handler);
199 
200 /**
201  * @brief Function for reconfiguring the TWIS driver instance.
202  *
203  * @param[in] p_instance Pointer to the driver instance structure.
204  * @param[in] p_config   Pointer to the structure with the configuration.
205  *
206  * @retval NRFX_SUCCESS             Reconfiguration was successful.
207  * @retval NRFX_ERROR_BUSY          The driver is during transaction.
208  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
209  */
210 nrfx_err_t nrfx_twis_reconfigure(nrfx_twis_t const *        p_instance,
211                                  nrfx_twis_config_t const * p_config);
212 
213 /**
214  * @brief Function for uninitializing the TWIS driver instance.
215  *
216  * Function uninitializes the peripheral and resets all registers to default values.
217  *
218  * @note
219  * It is safe to call nrfx_twis_uninit even before initialization.
220  * Actually, @ref nrfx_twis_init function calls this function to
221  * make sure that TWIS state is known.
222  * @note
223  * If TWIS driver was in uninitialized state before calling this function,
224  * the selected pins would not be reset to default configuration.
225  *
226  * @param[in] p_instance Pointer to the driver instance structure.
227  */
228 void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
229 
230 /**
231  * @brief Function for enabling the TWIS instance.
232  *
233  * This function enables the TWIS instance.
234  * Function defined if there is need for dynamically enabling and disabling the peripheral.
235  * Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
236  * They do not change any configuration registers.
237  *
238  * @param p_instance Pointer to the driver instance structure.
239  */
240 void nrfx_twis_enable(nrfx_twis_t const * p_instance);
241 
242 /**
243  * @brief Function for disabling the TWIS instance.
244  *
245  * This function disables the TWIS instance, which gives possibility to turn off the TWIS while
246  * holding configuration done by @ref nrfx_twis_init.
247  *
248  * @param p_instance Pointer to the driver instance structure.
249  */
250 void nrfx_twis_disable(nrfx_twis_t const * p_instance);
251 
252 /**
253  * @brief Function for getting and clearing the last error flags.
254  *
255  * This function gets the information about errors.
256  * This is also the only possibility to exit from the error substate of the internal state machine.
257  * @attention
258  * This function clears error state and flags.
259  *
260  * @param[in] p_instance Pointer to the driver instance structure.
261  *
262  * @return Error flags defined in @ref nrfx_twis_error_t.
263  */
264 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
265 
266 /**
267  * @brief Function for preparing the data for sending.
268  *
269  * This function is to be used in response to the @ref NRFX_TWIS_EVT_READ_REQ event.
270  *
271  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
272  *       to be placed in the Data RAM region. If this condition is not met,
273  *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
274  * @attention Transmission buffer must be placed in RAM.
275  *
276  * @param[in] p_instance Pointer to the driver instance structure.
277  * @param[in] p_buf      Transmission buffer.
278  * @param[in] size       Maximum number of bytes that master may read from buffer given.
279  *
280  * @retval NRFX_SUCCESS              The preparation finished properly.
281  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
282  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
283  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
284  */
285 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
286                                 void const *        p_buf,
287                                 size_t              size);
288 
289 /**
290  * @brief Function for getting the number of transmitted bytes.
291  *
292  * This function returns the number of bytes sent.
293  * This function can be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
294  *
295  * @param[in] p_instance Pointer to the driver instance structure.
296  *
297  * @return Number of bytes sent.
298  */
299 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
300 
301 /**
302  * @brief Function for preparing the data for receiving.
303  *
304  * This function must be used in response to the @ref NRFX_TWIS_EVT_WRITE_REQ event.
305  *
306  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
307  *       to be placed in the Data RAM region. If this condition is not met,
308  *       this function fails with the error code NRFX_ERROR_INVALID_ADDR.
309  *
310  * @param[in] p_instance Pointer to the driver instance structure.
311  * @param[in] p_buf      Buffer that is to be filled with received data.
312  * @param[in] size       Size of the buffer (maximum amount of data to receive).
313  *
314  * @retval NRFX_SUCCESS              The preparation finished properly.
315  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
316  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
317  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
318  */
319 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
320                                 void *              p_buf,
321                                 size_t              size);
322 
323 /**
324  * @brief Function for getting the number of received bytes.
325  *
326  * This function returns number of bytes received.
327  * It can be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
328  *
329  * @param[in] p_instance Pointer to the driver instance structure.
330  *
331  * @return Number of bytes received.
332  */
333 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
334 
335 /**
336  * @brief Function for checking if the driver is busy right now.
337  *
338  * This function tests the actual driver substate.
339  * If the driver is in any other state than IDLE or ERROR, this function returns true.
340  *
341  * @param[in] p_instance Pointer to the driver instance structure.
342  *
343  * @retval true  The driver is in state other than ERROR or IDLE.
344  * @retval false There is no transmission pending.
345  */
346 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
347 
348 /**
349  * @brief Function for checking if the driver is waiting for a TX buffer.
350  *
351  * If this function returns true, the driver is stalled expecting
352  * of the @ref nrfx_twis_tx_prepare function call.
353  *
354  * @param[in] p_instance Pointer to the driver instance structure.
355  *
356  * @retval true  The driver is waiting for @ref nrfx_twis_tx_prepare.
357  * @retval false The driver is not in the state where it is waiting for preparing a TX buffer.
358  */
359 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
360 
361 /**
362  * @brief Function for checking if the driver is waiting for an RX buffer.
363  *
364  * If this function returns true, the driver is stalled expecting
365  * of the @ref nrfx_twis_rx_prepare function call.
366  *
367  * @param[in] p_instance Pointer to the driver instance structure.
368  *
369  * @retval true  The driver is waiting for @ref nrfx_twis_rx_prepare.
370  * @retval false The driver is not in the state where it is waiting for preparing an RX buffer.
371  */
372 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
373 
374 /**
375  * @brief Function for checking if the driver is sending data.
376  *
377  * If this function returns true, there is an ongoing output transmission.
378  *
379  * @param[in] p_instance Pointer to the driver instance structure.
380  *
381  * @retval true  There is an ongoing output transmission.
382  * @retval false The driver is in other state.
383  */
384 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
385 
386 /**
387  * @brief Function for checking if the driver is receiving data.
388  *
389  * If this function returns true, there is an ongoing input transmission.
390  *
391  * @param[in] p_instance Pointer to the driver instance structure.
392  *
393  * @retval true  There is an ongoing input transmission.
394  * @retval false The driver is in other state.
395  */
396 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
397 
398 #ifndef NRFX_DECLARE_ONLY
nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)399 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
400 {
401     return nrf_twis_tx_amount_get(p_instance->p_reg);
402 }
403 
nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)404 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
405 {
406     return nrf_twis_rx_amount_get(p_instance->p_reg);
407 }
408 #endif // NRFX_DECLARE_ONLY
409 
410 /**
411  * @brief Macro returning TWIS interrupt handler.
412  *
413  * param[in] idx TWIS index.
414  *
415  * @return Interrupt handler.
416  */
417 #define NRFX_TWIS_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_twis_, idx, _irq_handler)
418 
419 /** @} */
420 
421 /*
422  * Declare interrupt handlers for all enabled driver instances in the following format:
423  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_twis_0_irq_handler).
424  *
425  * A specific interrupt handler for the driver instance can be retrieved by using
426  * the NRFX_TWIS_INST_HANDLER_GET macro.
427  *
428  * Here is a sample of using the NRFX_TWIS_INST_HANDLER_GET macro to directly map
429  * an interrupt handler in a Zephyr application:
430  *
431  * IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TWIS_INST_GET(\<instance_index\>)), \<priority\>,
432  *                    NRFX_TWIS_INST_HANDLER_GET(\<instance_index\>), 0);
433  */
434 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(TWIS, twis)
435 
436 
437 #ifdef __cplusplus
438 }
439 #endif
440 
441 #endif // NRFX_TWIS_H__
442