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