blob: a424a1e98f98ce787ffcde566e539b979eea775b [file] [log] [blame]
/**
* Copyright (c) 2015 - 2018, 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 Slave interface (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; ///< Driver instance index.
} nrfx_twis_t;
enum {
#if NRFX_CHECK(NRFX_TWIS0_ENABLED)
NRFX_TWIS0_INST_IDX,
#endif
#if NRFX_CHECK(NRFX_TWIS1_ENABLED)
NRFX_TWIS1_INST_IDX,
#endif
NRFX_TWIS_ENABLED_COUNT
};
/**
* @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 has 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 has 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
* We could 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;
} 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 set.
} nrfx_twis_config_t;
/**
* @brief Generate default configuration for TWIS driver instance.
*/
#define NRFX_TWIS_DEFAULT_CONFIG \
{ \
.addr = { NRFX_TWIS_DEFAULT_CONFIG_ADDR0, \
NRFX_TWIS_DEFAULT_CONFIG_ADDR1 }, \
.scl = 31, \
.scl_pull = (nrf_gpio_pin_pull_t)NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL, \
.sda = 31, \
.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 TWIS driver.
* @attention After driver initialization enable it by @ref nrfx_twis_enable.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @attention @em p_instance has to be global object.
* It would be used by interrupts so make it sure that object
* would not be destroyed when function is leaving.
* @param[in] p_config Pointer to the structure with initial configuration.
* @param[in] event_handler Event handler provided by the user.
*
* @retval NRFX_SUCCESS If initialization was successful.
* @retval NRFX_ERROR_INVALID_STATE If the driver is already initialized.
* @retval NRFX_ERROR_BUSY If 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 initializes the peripheral and resets all registers to default values.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @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,
* selected pins would not be reset to default configuration.
*/
void nrfx_twis_uninit(nrfx_twis_t const * p_instance);
/**
* @brief Enable TWIS instance.
*
* This function enables TWIS instance.
* Function defined if there is needs 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 Disable TWIS instance.
*
* Disabling TWIS instance 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 Get and clear last error flags.
*
* Function gets information about errors.
* This is also the only possibility to exit from error substate of the internal state machine.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @return Error flags defined in @ref nrfx_twis_error_t.
* @attention
* This function clears error state and flags.
*/
uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance);
/**
* @brief Prepare data for sending.
*
* This function should be used in response for @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.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @param[in] p_buf Transmission buffer.
* @attention Transmission buffer has to be placed in RAM.
* @param size Maximum number of bytes that master may read from buffer given.
*
* @retval NRFX_SUCCESS Preparation finished properly.
* @retval NRFX_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM.
* @retval NRFX_ERROR_INVALID_LENGTH Wrong value in @em size parameter.
* @retval NRFX_ERROR_INVALID_STATE Module 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 Get number of transmitted bytes.
*
* Function returns number of bytes sent.
* This function may 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 Prepare data for receiving
*
* This function should be used in response for @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 will fail with the error code NRFX_ERROR_INVALID_ADDR.
*
* @param[in] p_instance Pointer to the driver instance structure.
* @param[in] p_buf Buffer that would be filled with received data.
* @attention Receiving buffer has to be placed in RAM.
* @param size Size of the buffer (maximum amount of data to receive).
*
* @retval NRFX_SUCCESS Preparation finished properly.
* @retval NRFX_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM.
* @retval NRFX_ERROR_INVALID_LENGTH Wrong value in @em size parameter.
* @retval NRFX_ERROR_INVALID_STATE Module 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 Get number of received bytes.
*
* Function returns number of bytes received.
* This function may 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 checks if driver is busy right now.
*
* Actual driver substate is tested.
* If 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 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 checks if driver is waiting for tx buffer.
*
* If this function returns true, it means that 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 Driver waits for @ref nrfx_twis_tx_prepare.
* @retval false Driver is not in the state where it waits for preparing tx buffer.
*/
bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance);
/**
* @brief Function checks if driver is waiting for rx buffer.
*
* If this function returns true, it means that driver is staled expecting
* of the @ref nrfx_twis_rx_prepare function call.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true Driver waits for @ref nrfx_twis_rx_prepare.
* @retval false Driver is not in the state where it waits for preparing rx buffer.
*/
bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance);
/**
* @brief Check if driver is sending data.
*
* If this function returns true, it means that there is ongoing output transmission.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true There is ongoing output transmission.
* @retval false Driver is in other state.
*/
bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance);
/**
* @brief Check if driver is receiving data.
*
* If this function returns true, it means that there is ongoing input transmission.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true There is ongoing input transmission.
* @retval false 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);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRFX_TWIS_H__