blob: 4c3d0cac3a81280b6d8a9234fa699192ae58bd25 [file] [log] [blame]
/*
* Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NRFX_TWIS_H__
#define NRFX_TWIS_H__
#include <nrfx.h>
#include <hal/nrf_twis.h>
#include <hal/nrf_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrfx_twis TWIS driver
* @{
* @ingroup nrf_twis
* @brief Two Wire Interface Slave with EasyDMA (TWIS) peripheral driver.
*/
/** @brief TWIS driver instance data structure. */
typedef struct
{
NRF_TWIS_Type * p_reg; ///< Pointer to a structure with TWIS registers.
uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only.
} nrfx_twis_t;
#ifndef __NRFX_DOXYGEN__
enum {
#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
NRFX_TWIS0_INST_IDX,
#endif
#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
NRFX_TWIS1_INST_IDX,
#endif
#if NRFX_CHECK(NRFX_TWIS2_ENABLED)
NRFX_TWIS2_INST_IDX,
#endif
#if NRFX_CHECK(NRFX_TWIS3_ENABLED)
NRFX_TWIS3_INST_IDX,
#endif
NRFX_TWIS_ENABLED_COUNT
};
#endif
/** @brief Macro for creating a TWIS driver instance. */
#define NRFX_TWIS_INSTANCE(id) \
{ \
.p_reg = NRFX_CONCAT_2(NRF_TWIS, id), \
.drv_inst_idx = NRFX_CONCAT_3(NRFX_TWIS, id, _INST_IDX), \
}
/** @brief Event callback function event definitions. */
typedef enum
{
NRFX_TWIS_EVT_READ_REQ, ///< Read request detected.
/**< If there is no buffer prepared, buf_req flag in the even will be set.
Call then @ref nrfx_twis_tx_prepare to give parameters for buffer.
*/
NRFX_TWIS_EVT_READ_DONE, ///< Read request finished - free any data.
NRFX_TWIS_EVT_READ_ERROR, ///< Read request finished with error.
NRFX_TWIS_EVT_WRITE_REQ, ///< Write request detected.
/**< If there is no buffer prepared, buf_req flag in the even will be set.
Call then @ref nrfx_twis_rx_prepare to give parameters for buffer.
*/
NRFX_TWIS_EVT_WRITE_DONE, ///< Write request finished - process data.
NRFX_TWIS_EVT_WRITE_ERROR, ///< Write request finished with error.
NRFX_TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction.
} nrfx_twis_evt_type_t;
/**
* @brief Possible error sources.
*
* This is flag enum - values from this enum can be connected using logical or operator.
* @note
* You can use directly @ref nrf_twis_error_t. Error type enum is redefined here because
* of possible future extension (eg. supporting timeouts and synchronous mode).
*/
typedef enum
{
NRFX_TWIS_ERROR_OVERFLOW = NRF_TWIS_ERROR_OVERFLOW, /**< RX buffer overflow detected, and prevented. */
NRFX_TWIS_ERROR_DATA_NACK = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte. */
NRFX_TWIS_ERROR_OVERREAD = NRF_TWIS_ERROR_OVERREAD, /**< TX buffer over-read detected, and prevented. */
NRFX_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8 /**< Unexpected event detected by state machine. */
} nrfx_twis_error_t;
/** @brief TWIS driver event structure. */
typedef struct
{
nrfx_twis_evt_type_t type; ///< Event type.
union
{
bool buf_req; ///< Flag for @ref NRFX_TWIS_EVT_READ_REQ and @ref NRFX_TWIS_EVT_WRITE_REQ.
/**< Information if transmission buffer requires to be prepared. */
uint32_t tx_amount; ///< Data for @ref NRFX_TWIS_EVT_READ_DONE.
uint32_t rx_amount; ///< Data for @ref NRFX_TWIS_EVT_WRITE_DONE.
uint32_t error; ///< Data for @ref NRFX_TWIS_EVT_GENERAL_ERROR.
} data; ///< Union to store event data.
} nrfx_twis_evt_t;
/**
* @brief TWI slave event callback function type.
*
* @param[in] p_event Event information structure.
*/
typedef void (*nrfx_twis_event_handler_t)(nrfx_twis_evt_t const * p_event);
/** @brief Structure for TWIS configuration. */
typedef struct
{
uint32_t addr[2]; //!< Set addresses that this slave should respond. Set 0 to disable.
uint32_t scl; //!< SCL pin number.
uint32_t sda; //!< SDA pin number.
nrf_gpio_pin_pull_t scl_pull; //!< SCL pin pull.
nrf_gpio_pin_pull_t sda_pull; //!< SDA pin pull.
uint8_t interrupt_priority; //!< The priority of interrupt for the module to be set.
} nrfx_twis_config_t;
/** @brief Generate the default configuration for the TWIS driver instance. */
#define NRFX_TWIS_DEFAULT_CONFIG \
{ \
.addr = { NRFX_TWIS_DEFAULT_CONFIG_ADDR0, \
NRFX_TWIS_DEFAULT_CONFIG_ADDR1 }, \
.scl = 31, \
.sda = 31, \
.scl_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL, \
.sda_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL, \
.interrupt_priority = NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY \
}
/**
* @brief Function for initializing the TWIS driver instance.
*
* Function initializes and enables the TWIS driver.
* @attention After driver initialization enable it with @ref nrfx_twis_enable.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @attention @em p_instance has to be global object.
* It will be used by interrupts so make it sure that object
* is not destroyed when function is leaving.
* @param[in] p_config Pointer to the structure with the initial configuration.
* @param[in] event_handler Event handler provided by the user.
*
* @retval NRFX_SUCCESS Initialization is successful.
* @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
* @retval NRFX_ERROR_BUSY Some other peripheral with the same
* instance ID is already in use. This is
* possible only if NRFX_PRS_ENABLED
* is set to a value other than zero.
*/
nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance,
nrfx_twis_config_t const * p_config,
nrfx_twis_event_handler_t event_handler);
/**
* @brief Function for uninitializing the TWIS driver instance.
*
* Function uninitializes the peripheral and resets all registers to default values.
*
* @note
* It is safe to call nrfx_twis_uninit even before initialization.
* Actually, @ref nrfx_twis_init function calls this function to
* make sure that TWIS state is known.
* @note
* If TWIS driver was in uninitialized state before calling this function,
* the selected pins would not be reset to default configuration.
*
* @param[in] p_instance Pointer to the driver instance structure.
*/
void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
/**
* @brief Function for enabling the TWIS instance.
*
* This function enables the TWIS instance.
* Function defined if there is need for dynamically enabling and disabling the peripheral.
* Use @ref nrfx_twis_enable and @ref nrfx_twis_disable functions.
* They do not change any configuration registers.
*
* @param p_instance Pointer to the driver instance structure.
*/
void nrfx_twis_enable(nrfx_twis_t const * p_instance);
/**
* @brief Function for disabling the TWIS instance.
*
* This function disables the TWIS instance, which gives possibility to turn off the TWIS while
* holding configuration done by @ref nrfx_twis_init.
*
* @param p_instance Pointer to the driver instance structure.
*/
void nrfx_twis_disable(nrfx_twis_t const * p_instance);
/**
* @brief Function for getting and clearing the last error flags.
*
* This function gets the information about errors.
* This is also the only possibility to exit from the error substate of the internal state machine.
* @attention
* This function clears error state and flags.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @return Error flags defined in @ref nrfx_twis_error_t.
*/
uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
/**
* @brief Function for preparing the data for sending.
*
* This function is to be used in response to the @ref NRFX_TWIS_EVT_READ_REQ event.
*
* @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
* to be placed in the Data RAM region. If this condition is not met,
* this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
* @attention Transmission buffer must be placed in RAM.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @param[in] p_buf Transmission buffer.
* @param[in] size Maximum number of bytes that master may read from buffer given.
*
* @retval NRFX_SUCCESS The preparation finished properly.
* @retval NRFX_ERROR_INVALID_ADDR The given @em p_buf is not placed inside the RAM.
* @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
* @retval NRFX_ERROR_INVALID_STATE The module is not initialized or not enabled.
*/
nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
void const * p_buf,
size_t size);
/**
* @brief Function for getting the number of transmitted bytes.
*
* This function returns the number of bytes sent.
* This function can be called after @ref NRFX_TWIS_EVT_READ_DONE or @ref NRFX_TWIS_EVT_READ_ERROR events.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @return Number of bytes sent.
*/
__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance);
/**
* @brief Function for preparing the data for receiving.
*
* This function must be used in response to the @ref NRFX_TWIS_EVT_WRITE_REQ event.
*
* @note Peripherals using EasyDMA (including TWIS) require the transfer buffers
* to be placed in the Data RAM region. If this condition is not met,
* this function fails with the error code NRFX_ERROR_INVALID_ADDR.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @param[in] p_buf Buffer that is to be filled with received data.
* @param[in] size Size of the buffer (maximum amount of data to receive).
*
* @retval NRFX_SUCCESS The preparation finished properly.
* @retval NRFX_ERROR_INVALID_ADDR The given @em p_buf is not placed inside the RAM.
* @retval NRFX_ERROR_INVALID_LENGTH There is a wrong value in the @em size parameter.
* @retval NRFX_ERROR_INVALID_STATE The module is not initialized or not enabled.
*/
nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
void * p_buf,
size_t size);
/**
* @brief Function for getting the number of received bytes.
*
* This function returns number of bytes received.
* It can be called after @ref NRFX_TWIS_EVT_WRITE_DONE or @ref NRFX_TWIS_EVT_WRITE_ERROR events.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @return Number of bytes received.
*/
__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance);
/**
* @brief Function for checking if the driver is busy right now.
*
* This function tests the actual driver substate.
* If the driver is in any other state than IDLE or ERROR, this function returns true.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true The driver is in state other than ERROR or IDLE.
* @retval false There is no transmission pending.
*/
bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance);
/**
* @brief Function for checking if the driver is waiting for a TX buffer.
*
* If this function returns true, the driver is stalled expecting
* of the @ref nrfx_twis_tx_prepare function call.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true The driver is waiting for @ref nrfx_twis_tx_prepare.
* @retval false The driver is not in the state where it is waiting for preparing a TX buffer.
*/
bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
/**
* @brief Function for checking if the driver is waiting for an RX buffer.
*
* If this function returns true, the driver is stalled expecting
* of the @ref nrfx_twis_rx_prepare function call.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true The driver is waiting for @ref nrfx_twis_rx_prepare.
* @retval false The driver is not in the state where it is waiting for preparing an RX buffer.
*/
bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
/**
* @brief Function for checking if the driver is sending data.
*
* If this function returns true, there is an ongoing output transmission.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true There is an ongoing output transmission.
* @retval false The driver is in other state.
*/
bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
/**
* @brief Function for checking if the driver is receiving data.
*
* If this function returns true, there is an ongoing input transmission.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true There is an ongoing input transmission.
* @retval false The driver is in other state.
*/
bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE size_t nrfx_twis_tx_amount(nrfx_twis_t const * p_instance)
{
return nrf_twis_tx_amount_get(p_instance->p_reg);
}
__STATIC_INLINE size_t nrfx_twis_rx_amount(nrfx_twis_t const * p_instance)
{
return nrf_twis_rx_amount_get(p_instance->p_reg);
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
/** @} */
void nrfx_twis_0_irq_handler(void);
void nrfx_twis_1_irq_handler(void);
void nrfx_twis_2_irq_handler(void);
void nrfx_twis_3_irq_handler(void);
#ifdef __cplusplus
}
#endif
#endif // NRFX_TWIS_H__