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. If NULL, blocking mode is enabled.
188  *
189  * @retval NRFX_SUCCESS             Initialization is successful.
190  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
191  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
192  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
193  * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
194  *                                  instance ID is already in use. This is
195  *                                  possible only if NRFX_PRS_ENABLED
196  *                                  is set to a value other than zero.
197  */
198 nrfx_err_t nrfx_twis_init(nrfx_twis_t const *        p_instance,
199                           nrfx_twis_config_t const * p_config,
200                           nrfx_twis_event_handler_t  event_handler);
201 
202 /**
203  * @brief Function for reconfiguring the TWIS driver instance.
204  *
205  * @param[in] p_instance Pointer to the driver instance structure.
206  * @param[in] p_config   Pointer to the structure with the configuration.
207  *
208  * @retval NRFX_SUCCESS             Reconfiguration was successful.
209  * @retval NRFX_ERROR_BUSY          The driver is during transaction.
210  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
211  */
212 nrfx_err_t nrfx_twis_reconfigure(nrfx_twis_t const *        p_instance,
213                                  nrfx_twis_config_t const * p_config);
214 
215 /**
216  * @brief Function for uninitializing the TWIS driver instance.
217  *
218  * Function uninitializes the peripheral and resets all registers to default values.
219  *
220  * @note
221  * It is safe to call nrfx_twis_uninit even before initialization.
222  * Actually, @ref nrfx_twis_init function calls this function to
223  * make sure that TWIS state is known.
224  * @note
225  * If TWIS driver was in uninitialized state before calling this function,
226  * the selected pins would not be reset to default configuration.
227  *
228  * @param[in] p_instance Pointer to the driver instance structure.
229  */
230 void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
231 
232 /**
233  * @brief Function for checking if the TWIS driver instance is initialized.
234  *
235  * @param[in] p_instance Pointer to the driver instance structure.
236  *
237  * @retval true  Instance is already initialized.
238  * @retval false Instance is not initialized.
239  */
240 bool nrfx_twis_init_check(nrfx_twis_t const * p_instance);
241 
242 /**
243  * @brief Function for enabling the TWIS instance.
244  *
245  * This function enables the TWIS instance.
246  * Function defined if there is need for dynamically enabling and disabling the peripheral.
247  * Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
248  * They do not change any configuration registers.
249  *
250  * @param p_instance Pointer to the driver instance structure.
251  */
252 void nrfx_twis_enable(nrfx_twis_t const * p_instance);
253 
254 /**
255  * @brief Function for disabling the TWIS instance.
256  *
257  * This function disables the TWIS instance, which gives possibility to turn off the TWIS while
258  * holding configuration done by @ref nrfx_twis_init.
259  *
260  * @param p_instance Pointer to the driver instance structure.
261  */
262 void nrfx_twis_disable(nrfx_twis_t const * p_instance);
263 
264 /**
265  * @brief Function for getting and clearing the last error flags.
266  *
267  * This function gets the information about errors.
268  * This is also the only possibility to exit from the error substate of the internal state machine.
269  * @attention
270  * This function clears error state and flags.
271  *
272  * @param[in] p_instance Pointer to the driver instance structure.
273  *
274  * @return Error flags defined in @ref nrfx_twis_error_t.
275  */
276 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
277 
278 /**
279  * @brief Function for preparing the data for sending.
280  *
281  * This function is to be used in response to the @ref NRFX_TWIS_EVT_READ_REQ event.
282  *
283  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
284  *       to be placed in the Data RAM region. If this condition is not met,
285  *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
286  * @attention Transmission buffer must be placed in RAM.
287  *
288  * @param[in] p_instance Pointer to the driver instance structure.
289  * @param[in] p_buf      Transmission buffer.
290  * @param[in] size       Maximum number of bytes that master may read from buffer given.
291  *
292  * @retval NRFX_SUCCESS              The preparation finished properly.
293  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
294  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
295  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
296  */
297 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
298                                 void const *        p_buf,
299                                 size_t              size);
300 
301 /**
302  * @brief Function for getting the number of transmitted bytes.
303  *
304  * This function returns the number of bytes sent.
305  * This function can be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
306  *
307  * @param[in] p_instance Pointer to the driver instance structure.
308  *
309  * @return Number of bytes sent.
310  */
311 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
312 
313 /**
314  * @brief Function for preparing the data for receiving.
315  *
316  * This function must be used in response to the @ref NRFX_TWIS_EVT_WRITE_REQ event.
317  *
318  * @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
319  *       to be placed in the Data RAM region. If this condition is not met,
320  *       this function fails with the error code NRFX_ERROR_INVALID_ADDR.
321  *
322  * @param[in] p_instance Pointer to the driver instance structure.
323  * @param[in] p_buf      Buffer that is to be filled with received data.
324  * @param[in] size       Size of the buffer (maximum amount of data to receive).
325  *
326  * @retval NRFX_SUCCESS              The preparation finished properly.
327  * @retval NRFX_ERROR_INVALID_ADDR   The given @em p_buf is not placed inside the RAM.
328  * @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
329  * @retval NRFX_ERROR_INVALID_STATE  The module is not initialized or not enabled.
330  */
331 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
332                                 void *              p_buf,
333                                 size_t              size);
334 
335 /**
336  * @brief Function for getting the number of received bytes.
337  *
338  * This function returns number of bytes received.
339  * It can be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
340  *
341  * @param[in] p_instance Pointer to the driver instance structure.
342  *
343  * @return Number of bytes received.
344  */
345 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
346 
347 /**
348  * @brief Function for checking if the driver is busy right now.
349  *
350  * This function tests the actual driver substate.
351  * If the driver is in any other state than IDLE or ERROR, this function returns true.
352  *
353  * @param[in] p_instance Pointer to the driver instance structure.
354  *
355  * @retval true  The driver is in state other than ERROR or IDLE.
356  * @retval false There is no transmission pending.
357  */
358 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
359 
360 /**
361  * @brief Function for checking if the driver is waiting for a TX buffer.
362  *
363  * If this function returns true, the driver is stalled expecting
364  * of the @ref nrfx_twis_tx_prepare function call.
365  *
366  * @param[in] p_instance Pointer to the driver instance structure.
367  *
368  * @retval true  The driver is waiting for @ref nrfx_twis_tx_prepare.
369  * @retval false The driver is not in the state where it is waiting for preparing a TX buffer.
370  */
371 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
372 
373 /**
374  * @brief Function for checking if the driver is waiting for an RX buffer.
375  *
376  * If this function returns true, the driver is stalled expecting
377  * of the @ref nrfx_twis_rx_prepare function call.
378  *
379  * @param[in] p_instance Pointer to the driver instance structure.
380  *
381  * @retval true  The driver is waiting for @ref nrfx_twis_rx_prepare.
382  * @retval false The driver is not in the state where it is waiting for preparing an RX buffer.
383  */
384 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
385 
386 /**
387  * @brief Function for checking if the driver is sending data.
388  *
389  * If this function returns true, there is an ongoing output transmission.
390  *
391  * @param[in] p_instance Pointer to the driver instance structure.
392  *
393  * @retval true  There is an ongoing output transmission.
394  * @retval false The driver is in other state.
395  */
396 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
397 
398 /**
399  * @brief Function for checking if the driver is receiving data.
400  *
401  * If this function returns true, there is an ongoing input transmission.
402  *
403  * @param[in] p_instance Pointer to the driver instance structure.
404  *
405  * @retval true  There is an ongoing input transmission.
406  * @retval false The driver is in other state.
407  */
408 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
409 
410 #ifndef NRFX_DECLARE_ONLY
nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)411 NRFX_STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
412 {
413     return nrf_twis_tx_amount_get(p_instance->p_reg);
414 }
415 
nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)416 NRFX_STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
417 {
418     return nrf_twis_rx_amount_get(p_instance->p_reg);
419 }
420 #endif // NRFX_DECLARE_ONLY
421 
422 /**
423  * @brief Macro returning TWIS interrupt handler.
424  *
425  * param[in] idx TWIS index.
426  *
427  * @return Interrupt handler.
428  */
429 #define NRFX_TWIS_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_twis_, idx, _irq_handler)
430 
431 /** @} */
432 
433 /*
434  * Declare interrupt handlers for all enabled driver instances in the following format:
435  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_twis_0_irq_handler).
436  *
437  * A specific interrupt handler for the driver instance can be retrieved by using
438  * the NRFX_TWIS_INST_HANDLER_GET macro.
439  *
440  * Here is a sample of using the NRFX_TWIS_INST_HANDLER_GET macro to map an interrupt handler
441  * in a Zephyr application:
442  *
443  * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TWIS_INST_GET(\<instance_index\>)), \<priority\>,
444  *             NRFX_TWIS_INST_HANDLER_GET(\<instance_index\>), 0, 0);
445  */
446 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(TWIS, twis)
447 
448 
449 #ifdef __cplusplus
450 }
451 #endif
452 
453 #endif // NRFX_TWIS_H__
454