move components to SDK dir

This commit is contained in:
Shuanglei Tao
2025-03-03 09:06:26 +08:00
parent 20d1297e57
commit f4f4c9e60d
1021 changed files with 58 additions and 35059 deletions

View File

@@ -0,0 +1,942 @@
/**
* Copyright (c) 2015 - 2017, 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, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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 Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(TWIS)
#define ENABLED_TWIS_COUNT (TWIS0_ENABLED+TWIS1_ENABLED)
#if ENABLED_TWIS_COUNT
#include "nrf_drv_twis.h"
#include "nrf_assert.h"
#include "app_util_platform.h"
#include "compiler_abstraction.h"
#define NRF_LOG_MODULE_NAME "TWIS"
#if TWIS_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL TWIS_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR TWIS_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR TWIS_CONFIG_DEBUG_COLOR
#define EVT_TO_STR(event) (event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \
(event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \
(event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \
(event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \
(event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \
(event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : "UNKNOWN EVENT"))))))
#else //TWIS_CONFIG_LOG_ENABLED
#define EVT_TO_STR(event) ""
#define NRF_LOG_LEVEL 0
#endif //TWIS_CONFIG_LOG_ENABLED
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
/**
* @internal
* @ingroup lib_twis_drv
* @defgroup lib_twis_drv_ivars Software controlled TWI Slave internal variables
*
* Internal variables for TWIS.
* @{
*/
/**
* @brief Actual state of internal state machine
*
* Current substate of powered on state.
*/
typedef enum
{
NRF_DRV_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission
NRF_DRV_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data
NRF_DRV_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending)
NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer
NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving)
}nrf_drv_twis_substate_t;
/**
* @brief Constant instance part
*
* Instance data that have not to change.
* It may be placed in FLASH memory.
*/
typedef struct
{
NRF_TWIS_Type * const p_reg; ///< Peripheral registry address
} nrf_drv_twis_const_inst_t;
/**
* @brief Variable instance part
*
* There are all informations for the instance that may change.
*/
typedef struct
{
nrf_drv_state_t state; ///< Actual driver state
volatile nrf_drv_twis_substate_t substate; ///< Actual driver substate
nrf_drv_twis_event_handler_t ev_handler; ///< Event handler functiomn
volatile uint32_t error; ///< Internal error flags
/**< Internal copy of hardware errors flags merged
* with specific internal driver errors flags.
*
* @note This value can be changed in the interrupt
* and cleared in the main program.
* Always use Atomic load-store when updating
* this value in main loop.
*/
}nrf_drv_twis_var_inst_t;
/** The constant instance part implementation */
static const nrf_drv_twis_const_inst_t m_const_inst[ENABLED_TWIS_COUNT] =
{
#define X(n) { .p_reg = NRF_TWIS##n },
#include "nrf_drv_twis_inst.def"
};
/** The variable instance part implementation */
static nrf_drv_twis_var_inst_t m_var_inst[ENABLED_TWIS_COUNT] =
{
#define X(n) { .state = NRF_DRV_STATE_UNINITIALIZED, \
.substate = NRF_DRV_TWIS_SUBSTATE_IDLE, \
.ev_handler = NULL, \
.error = 0 },
#include "nrf_drv_twis_inst.def"
};
#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING)
#define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n
#define IRQ_HANDLER(n) static void IRQ_HANDLER_NAME(n)(void)
#if NRF_MODULE_ENABLED(TWIS0)
IRQ_HANDLER(0);
#endif
#if NRF_MODULE_ENABLED(TWIS1)
IRQ_HANDLER(1);
#endif
static nrf_drv_irq_handler_t const m_irq_handlers[ENABLED_TWIS_COUNT] = {
#if NRF_MODULE_ENABLED(TWIS0)
IRQ_HANDLER_NAME(0),
#endif
#if NRF_MODULE_ENABLED(TWIS1)
IRQ_HANDLER_NAME(1),
#endif
};
#else
#define IRQ_HANDLER(n) \
void SPIM##n##_SPIS##n##_TWIM##n##_TWIS##n##_SPI##n##_TWI##n##_IRQHandler(void)
#endif // NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING)
/**
* @brief State processing semaphore
*
* There are semaphores used when when working in synchronous mode (without interrupts activated).
* @note
* In synchronous mode before every state checking the state machine is executed.
* But the situation where state checking function is called from main task and in the same from
* interrupt task has to be considered.
* In such a situation the @ref nrf_drv_twis_state_machine function may be interrupted by second
* call to the same function.
* If in this second call any event will be detected it may be lost because new substate would be
* overwritten when interrupted function finishes.
* In the same time information about event would be lost because it is cleared in interrupting
* function.
* @note
* To make situation described above safe, simple semaphore is implemented.
* It is just a binary flag that informs that state machine is actually executing and should not
* be processed in any interrupting function.
* Because of how it is used no atomic instructions are required to support this kind of semaphore.
* It is not waitable semaphore - function executed or not depending of its state.
*/
static uint8_t m_sm_semaphore[ENABLED_TWIS_COUNT];
/**
* @brief Used interrupts mask
*
* Mask for all interrupts used by this library
*/
static const uint32_t m_used_ints_mask =
NRF_TWIS_INT_STOPPED_MASK |
NRF_TWIS_INT_ERROR_MASK |
NRF_TWIS_INT_RXSTARTED_MASK |
NRF_TWIS_INT_TXSTARTED_MASK |
NRF_TWIS_INT_WRITE_MASK |
NRF_TWIS_INT_READ_MASK;
/** @} */ /* End of lib_driver_twis_slave_ivars */
/**
* @internal
* @ingroup lib_twis_drv
* @defgroup lib_twis_drv_ifunc Software controlled TWI Slave auxiliary internal functions
*
* Internal variables for TWIS.
* @{
*/
/**
* @brief Clear all events
*
* Function clears all actually pending events
*/
static void nrf_drv_twis_clear_all_events(NRF_TWIS_Type * const p_reg)
{
/* Clear all events */
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED);
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR);
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED);
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED);
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE);
nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ);
}
/**
* @brief Reset all the registers to known state
*
* This function clears all registers that requires it to known state.
* TWIS is left disabled after this function.
* All events are cleared.
* @param[out] p_reg TWIS to reset register address
*/
static inline void nrf_drv_twis_swreset(NRF_TWIS_Type * const p_reg)
{
/* Disable TWIS */
nrf_twis_disable(p_reg);
/* Disconnect pins */
nrf_twis_pins_set(p_reg, ~0U, ~0U);
/* Disable interrupt global for the instance */
nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_reg));
/* Disable interrupts */
nrf_twis_int_disable(p_reg, ~0U);
}
/**
* @brief Configure pin
*
* Function configures selected for work as SDA or SCL.
* @param pin Pin number to configure
*/
static inline void nrf_drv_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull)
{
nrf_gpio_cfg(pin,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
pull,
NRF_GPIO_PIN_S0D1,
NRF_GPIO_PIN_NOSENSE);
}
/**
* @brief Call event handler
*
* Function that calls event handler.
* The event handler would be only called if its value is != NULL.
* @param instNr Driver instance number that has called this runtime.
* @param[in] pev Event structure to pass to event handler
* @note
* Remember about possible multithreading.
* It is acceptable to call old event function if it was already disabled.
* What is unacceptable is jump into NULL pointer.
*/
static void nrf_drv_call_event_handler(uint8_t instNr, nrf_drv_twis_evt_t const * const pev)
{
nrf_drv_twis_event_handler_t evh = m_var_inst[instNr].ev_handler;
if (NULL != evh)
{
evh(pev);
}
}
/**
* @brief Auxiliary function for getting event state on right bit possition
*
* This function calls @ref nrf_twis_event_get function but the the result
* is shifted to match INTEN register scheme.
*
* @param[in,out] p_reg TWIS to read event from
* @param ev Event code
*
* @return Selected event state shifted by @ref nrf_drv_event_to_bitpos
*
* @sa nrf_twis_event_get
* @sa nrf_drv_event_to_bitpos
*/
static inline uint32_t nrf_drv_twis_event_bit_get(NRF_TWIS_Type * const p_reg, nrf_twis_event_t ev)
{
return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrf_drv_event_to_bitpos(ev);
}
/**
* @brief Auxiliary function for checking event bit inside given flags value
*
* Function used here to check presence of the event inside given flags value.
* It transforms given event to bit possition and then checks if in given variable it is cleared.
*
* @param flags Flags to test
* @param ev Event code
*
* @retval true Flag for selected event is set
* @retval false Flag for selected event is cleared
*/
static inline bool nrf_drv_twis_check_bit(uint32_t flags, nrf_twis_event_t ev)
{
return 0 != (flags & (1U<<nrf_drv_event_to_bitpos(ev)));
}
/**
* @brief Auxiliary function for clearing event bit in given flags value
*
* Function used to clear selected event bit.
*
* @param flags Flags to process
* @param ev Event code to clear
*
* @return Value @em flags with cleared event bit that matches given @em ev
*/
static inline uint32_t nrf_drv_twis_clear_bit(uint32_t flags, nrf_twis_event_t ev)
{
return flags & ~(1U<<nrf_drv_event_to_bitpos(ev));
}
/**
* @brief Auxiliary function for error processing
*
* Function called when in current substate the event apears and it cannot be processed.
* It should be called also on ERROR event.
* If given @em error parameter has zero value the @ref NRF_DRV_TWIS_ERROR_UNEXPECTED_EVENT
* would be set.
*
* @param instNr Instance number
* @param ev What error event raport to event handler
* @param error Error flags
*/
static inline void nrf_drv_twis_process_error(
uint8_t instNr,
nrf_drv_twis_evt_type_t ev,
uint32_t error)
{
if (0 == error)
error = NRF_DRV_TWIS_ERROR_UNEXPECTED_EVENT;
nrf_drv_twis_evt_t evdata;
evdata.type = ev;
evdata.data.error = error;
m_var_inst[instNr].error |= error;
nrf_drv_call_event_handler(instNr, &evdata);
}
/**
* @brief State machine main function
*
* State machine function that reacts on events.
* This function gets all events and reacts on them only if there is any event detected.
* It makes it possible to use it either in interrupt or in polling mode.
* @param instNr Driver instance number that has called this runtime.
*/
static void nrf_drv_twis_state_machine(uint8_t instNr)
{
if (!TWIS_NO_SYNC_MODE)
{
/* Exclude parallel processing of this function */
if (m_sm_semaphore[instNr])
{
return;
}
m_sm_semaphore[instNr] = 1;
}
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
/* Event data structure to be passed into event handler */
nrf_drv_twis_evt_t evdata;
/* Current substate copy */
nrf_drv_twis_substate_t substate = m_var_inst[instNr].substate;
/* Event flags */
uint32_t ev = 0;
/* Get all events */
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED);
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR);
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED);
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED);
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE);
ev |= nrf_drv_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ);
/* State machine */
while (0 != ev)
{
switch (substate)
{
case NRF_DRV_TWIS_SUBSTATE_IDLE:
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
{
/* Stopped event is always allowed in IDLE state - just ignore */
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
}
else if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ))
{
evdata.type = TWIS_EVT_READ_REQ;
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED))
{
substate = NRF_DRV_TWIS_SUBSTATE_READ_PENDING;
evdata.data.buf_req = false;
}
else
{
substate = NRF_DRV_TWIS_SUBSTATE_READ_WAITING;
evdata.data.buf_req = true;
}
nrf_drv_call_event_handler(instNr, &evdata);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
}
else if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE))
{
evdata.type = TWIS_EVT_WRITE_REQ;
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED))
{
substate = NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING;
evdata.data.buf_req = false;
}
else
{
substate = NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING;
evdata.data.buf_req = true;
}
nrf_drv_call_event_handler(instNr, &evdata);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
}
else
{
nrf_drv_twis_process_error(instNr, TWIS_EVT_GENERAL_ERROR, nrf_twis_error_source_get_and_clear(p_reg));
ev = 0;
}
break;
case NRF_DRV_TWIS_SUBSTATE_READ_WAITING:
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
{
substate = NRF_DRV_TWIS_SUBSTATE_READ_PENDING;
/* Any other bits requires further processing in PENDING substate */
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
}
else
{
nrf_drv_twis_process_error(instNr, TWIS_EVT_READ_ERROR, nrf_twis_error_source_get_and_clear(p_reg));
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = 0;
}
break;
case NRF_DRV_TWIS_SUBSTATE_READ_PENDING:
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE)||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
{
evdata.type = TWIS_EVT_READ_DONE;
evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg);
NRF_LOG_INFO("Transfer rx_len:%d\r\n", evdata.data.tx_amount);
NRF_LOG_DEBUG("Tx data:\r\n");
NRF_LOG_HEXDUMP_DEBUG((uint8_t *)p_reg->TXD.PTR, evdata.data.tx_amount * sizeof(p_reg->TXD.PTR));
nrf_drv_call_event_handler(instNr, &evdata);
/* Go to idle and repeat the state machine if READ or WRITE events detected.
* This time READ or WRITE would be started */
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
}
else
{
nrf_drv_twis_process_error(instNr, TWIS_EVT_READ_ERROR, nrf_twis_error_source_get_and_clear(p_reg));
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = 0;
}
break;
case NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING:
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
{
substate = NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING;
/* Any other bits requires further processing in PENDING substate */
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
}
else
{
nrf_drv_twis_process_error(instNr, TWIS_EVT_WRITE_ERROR, nrf_twis_error_source_get_and_clear(p_reg));
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = 0;
}
break;
case NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING:
if (nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE)||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_READ) ||
nrf_drv_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
{
evdata.type = TWIS_EVT_WRITE_DONE;
evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg);
nrf_drv_call_event_handler(instNr, &evdata);
/* Go to idle and repeat the state machine if READ or WRITE events detected.
* This time READ or WRITE would be started */
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = nrf_drv_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
}
else
{
nrf_drv_twis_process_error(instNr, TWIS_EVT_WRITE_ERROR, nrf_twis_error_source_get_and_clear(p_reg));
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
ev = 0;
}
break;
default:
substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
/* Do not clear any events and repeat the machine */
break;
}
}
m_var_inst[instNr].substate = substate;
if (!TWIS_NO_SYNC_MODE)
{
m_sm_semaphore[instNr] = 0;
}
}
/**
* @brief This function
*/
static inline void nrf_drv_twis_preprocess_status(uint8_t instNr)
{
if (!TWIS_NO_SYNC_MODE)
{
if (NULL == m_var_inst[instNr].ev_handler)
{
nrf_drv_twis_state_machine(instNr);
}
}
}
/**
* @brief Interrupt service
*
* This function is called by all interrupts runtime for instances enabled in this library.
* @param instNr Driver instance number that has called this runtime.
*/
static inline void nrf_drv_twis_on_ISR(uint8_t instNr)
{
nrf_drv_twis_state_machine(instNr);
}
/** @} */ /* End of lib_driver_twis_slave_ifunc */
/* -------------------------------------------------------------------------
* Implementation of IRQ Handlers
*/
#define X(n) \
IRQ_HANDLER(n) \
{ \
nrf_drv_twis_on_ISR(TWIS##n##_INSTANCE_INDEX); \
}
#include "nrf_drv_twis_inst.def"
/* -------------------------------------------------------------------------
* Implementation of interface functions
*
*/
ret_code_t nrf_drv_twis_init(
nrf_drv_twis_t const * const p_instance,
nrf_drv_twis_config_t const * p_config,
nrf_drv_twis_event_handler_t const event_handler)
{
ASSERT(p_config);
ASSERT(p_config->scl != p_config->sda);
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
nrf_twis_config_addr_mask_t addr_mask = (nrf_twis_config_addr_mask_t)0;
ret_code_t err_code;
if ( m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED)
{
err_code = NRF_ERROR_INVALID_STATE;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING)
if (nrf_drv_common_per_res_acquire(p_reg, m_irq_handlers[instNr]) !=
NRF_SUCCESS)
{
err_code = NRF_ERROR_BUSY;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
#endif
if (!TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
{
nrf_drv_twis_swreset(p_reg);
}
nrf_drv_twis_config_pin(p_config->scl, p_config->scl_pull);
nrf_drv_twis_config_pin(p_config->sda, p_config->sda_pull);
if (0 == (p_config->addr[0] | p_config->addr[1]))
addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK;
else
{
if (0 != p_config->addr[0])
{
addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK;
}
if (0 != p_config->addr[1])
{
addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK;
}
}
/* Peripheral interrupt configure
* (note - interrupts still needs to be configured in INTEN register.
* This is done in enable function) */
nrf_drv_common_irq_enable(nrf_drv_get_IRQn(p_reg), p_config->interrupt_priority);
/* Configure */
nrf_twis_pins_set (p_reg, p_config->scl, p_config->sda);
nrf_twis_address_set (p_reg, 0, p_config->addr[0]);
nrf_twis_address_set (p_reg, 1, p_config->addr[1]);
nrf_twis_config_address_set(p_reg, addr_mask);
/* Clear semaphore */
if (!TWIS_NO_SYNC_MODE)
{
m_sm_semaphore[instNr] = 0;
}
/* Set internal instance variables */
m_var_inst[instNr].substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
m_var_inst[instNr].ev_handler = event_handler;
m_var_inst[instNr].state = NRF_DRV_STATE_INITIALIZED;
err_code = NRF_SUCCESS;
NRF_LOG_INFO("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
void nrf_drv_twis_uninit(nrf_drv_twis_t const * const p_instance)
{
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
TWIS_PSEL_Type psel = p_reg->PSEL;
ASSERT(m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED);
nrf_drv_twis_swreset(p_reg);
/* Clear pins state if */
if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL))
{
nrf_gpio_cfg_default(psel.SCL);
}
if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA))
{
nrf_gpio_cfg_default(psel.SDA);
}
#if NRF_MODULE_ENABLED(PERIPHERAL_RESOURCE_SHARING)
nrf_drv_common_per_res_release(p_reg);
#endif
/* Clear variables */
m_var_inst[instNr].ev_handler = NULL;
m_var_inst[instNr].state = NRF_DRV_STATE_UNINITIALIZED;
}
void nrf_drv_twis_enable(nrf_drv_twis_t const * const p_instance)
{
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr];
ASSERT(m_var_inst[instNr].state == NRF_DRV_STATE_INITIALIZED);
nrf_drv_twis_clear_all_events(p_reg);
/* Enable interrupts */
if (NULL != p_var_inst->ev_handler)
{
nrf_twis_int_enable(p_reg, m_used_ints_mask);
}
nrf_twis_enable(p_reg);
p_var_inst->error = 0;
p_var_inst->state = NRF_DRV_STATE_POWERED_ON;
p_var_inst->substate = NRF_DRV_TWIS_SUBSTATE_IDLE;
}
void nrf_drv_twis_disable(nrf_drv_twis_t const * const p_instance)
{
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
ASSERT(m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED);
nrf_twis_int_disable(p_reg, m_used_ints_mask);
nrf_twis_disable(p_reg);
m_var_inst[instNr].state = NRF_DRV_STATE_INITIALIZED;
}
/* ARM recommends not using the LDREX and STREX instructions in C code.
* This is because the compiler might generate loads and stores between
* LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
* This recommendation also applies to the byte, halfword, and doubleword
* variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
*
* This is the reason for the function below to be implemented in assembly.
*/
//lint -save -e578
#if defined (__CC_ARM )
static __ASM uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror)
{
mov r3, r0
mov r1, #0
nrf_drv_twis_error_get_and_clear_internal_try
ldrex r0, [r3]
strex r2, r1, [r3]
cmp r2, r1 /* did this succeed? */
bne nrf_drv_twis_error_get_and_clear_internal_try /* no try again */
bx lr
}
#elif defined ( __GNUC__ )
static uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror)
{
uint32_t ret;
uint32_t temp;
__ASM volatile(
" .syntax unified \n"
"nrf_drv_twis_error_get_and_clear_internal_try: \n"
" ldrex %[ret], [%[perror]] \n"
" strex %[temp], %[zero], [%[perror]] \n"
" cmp %[temp], %[zero] \n"
" bne nrf_drv_twis_error_get_and_clear_internal_try \n"
: /* Output */
[ret]"=&l"(ret),
[temp]"=&l"(temp)
: /* Input */
[zero]"l"(0),
[perror]"l"(perror)
);
UNUSED_VARIABLE(temp);
return ret;
}
#elif defined ( __ICCARM__ )
static uint32_t nrf_drv_twis_error_get_and_clear_internal(uint32_t volatile * const perror)
{
uint32_t ret;
uint32_t temp;
__ASM volatile(
"1: \n"
" ldrex %[ret], [%[perror]] \n"
" strex %[temp], %[zero], [%[perror]] \n"
" cmp %[temp], %[zero] \n"
" bne.n 1b \n"
: /* Output */
[ret]"=&l"(ret),
[temp]"=&l"(temp)
: /* Input */
[zero]"l"(0),
[perror]"l"(perror)
);
UNUSED_VARIABLE(temp);
return ret;
}
#else
#error Unknown compiler
#endif
//lint -restore
uint32_t nrf_drv_twis_error_get_and_clear(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[p_instance->instNr];
nrf_drv_twis_preprocess_status(p_instance->instNr);
/* Make sure that access to error member is atomic
* so there is no bit that is cleared if it is not copied to local variable already. */
return nrf_drv_twis_error_get_and_clear_internal(&p_var_inst->error);
}
ret_code_t nrf_drv_twis_tx_prepare(
nrf_drv_twis_t const * const p_instance,
void const * const p_buf,
size_t size)
{
ret_code_t err_code = NRF_SUCCESS;;
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr];
/* Check power state*/
if (p_var_inst->state != NRF_DRV_STATE_POWERED_ON)
{
err_code = NRF_ERROR_INVALID_STATE;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
/* Check data address */
if (!nrf_drv_is_in_RAM(p_buf))
{
err_code = NRF_ERROR_INVALID_ADDR;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
/* Check data size */
if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size)
{
err_code = NRF_ERROR_INVALID_LENGTH;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
nrf_twis_tx_prepare(p_reg, (uint8_t const *)p_buf, (nrf_twis_amount_t)size);
NRF_LOG_INFO("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
size_t nrf_drv_twis_tx_amount(nrf_drv_twis_t const * const p_instance)
{
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type const * const p_reg = m_const_inst[instNr].p_reg;
return nrf_twis_tx_amount_get(p_reg);
}
ret_code_t nrf_drv_twis_rx_prepare(
nrf_drv_twis_t const * const p_instance,
void * const p_buf,
size_t size)
{
ret_code_t err_code;
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type * const p_reg = m_const_inst[instNr].p_reg;
nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[instNr];
/* Check power state*/
if (p_var_inst->state != NRF_DRV_STATE_POWERED_ON)
{
err_code = NRF_ERROR_INVALID_STATE;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
/* Check data address */
if (!nrf_drv_is_in_RAM(p_buf))
{
err_code = NRF_ERROR_INVALID_ADDR;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
/* Check data size */
if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size)
{
err_code = NRF_ERROR_INVALID_LENGTH;
NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
nrf_twis_rx_prepare(p_reg, (uint8_t *)p_buf, (nrf_twis_amount_t)size);
err_code = NRF_SUCCESS;
NRF_LOG_INFO("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code));
return err_code;
}
size_t nrf_drv_twis_rx_amount(nrf_drv_twis_t const * const p_instance)
{
uint8_t instNr = p_instance->instNr;
NRF_TWIS_Type const * const p_reg = m_const_inst[instNr].p_reg;
return nrf_twis_rx_amount_get(p_reg);
}
bool nrf_drv_twis_is_busy(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_preprocess_status(p_instance->instNr);
return NRF_DRV_TWIS_SUBSTATE_IDLE != m_var_inst[(p_instance->instNr)].substate;
}
bool nrf_drv_twis_is_waiting_tx_buff(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_preprocess_status(p_instance->instNr);
return NRF_DRV_TWIS_SUBSTATE_READ_WAITING == m_var_inst[(p_instance->instNr)].substate;
}
bool nrf_drv_twis_is_waiting_rx_buff(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_preprocess_status(p_instance->instNr);
return NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING == m_var_inst[(p_instance->instNr)].substate;
}
bool nrf_drv_twis_is_pending_tx(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_preprocess_status(p_instance->instNr);
return NRF_DRV_TWIS_SUBSTATE_READ_PENDING == m_var_inst[(p_instance->instNr)].substate;
}
bool nrf_drv_twis_is_pending_rx(nrf_drv_twis_t const * const p_instance)
{
nrf_drv_twis_preprocess_status(p_instance->instNr);
return NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING == m_var_inst[(p_instance->instNr)].substate;
}
#endif // TWIS_COUNT
#endif // NRF_MODULE_ENABLED(TWIS)

View File

@@ -0,0 +1,396 @@
/**
* Copyright (c) 2015 - 2017, 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, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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 Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRF_DRV_TWIS_H__
#define NRF_DRV_TWIS_H__
#include "sdk_config.h"
#include "nrf_drv_common.h"
#include "nrf_gpio.h"
#include "sdk_errors.h"
#include "nrf_twis.h"
#include <stdint.h>
#include "app_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@file
* @addtogroup nrf_twis Two Wire slave interface (TWIS)
* @ingroup nrf_drivers
* @brief Two Wire slave interface (TWIS) APIs.
*
*
* @defgroup nrf_drv_twis TWIS driver
* @{
* @ingroup nrf_twis
* @brief TWI slave APIs.
*/
/**
* @brief Event callback function event definitions.
*/
typedef enum
{
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 nrf_drv_twis_tx_prepare to give parameters for buffer.
*/
TWIS_EVT_READ_DONE, ///< Read request has finished - free any data
TWIS_EVT_READ_ERROR, ///< Read request finished with error
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 nrf_drv_twis_rx_prepare to give parameters for buffer.
*/
TWIS_EVT_WRITE_DONE, ///< Write request has finished - process data
TWIS_EVT_WRITE_ERROR, ///< Write request finished with error
TWIS_EVT_GENERAL_ERROR ///< Error that happens not inside WRITE or READ transaction
} nrf_drv_twis_evt_type_t;
/**
* @brief TWIS driver instance structure
*
* @note We only need instance number here so we could really use just a number
* that would be send to every driver function.
* But for compatibility reason this number is inserted into the structure.
*/
typedef struct
{
uint8_t instNr; /**< Instance number */
}nrf_drv_twis_t;
/**
* @brief TWIS driver event structure
*/
typedef struct
{
nrf_drv_twis_evt_type_t type; ///< Event type
union
{
bool buf_req; ///< Flag for @ref TWIS_EVT_READ_REQ and @ref TWIS_EVT_WRITE_REQ
/**< Information if transmission buffer requires to be prepared */
uint32_t tx_amount; ///< Data for @ref TWIS_EVT_READ_DONE
uint32_t rx_amount; ///< Data for @ref TWIS_EVT_WRITE_DONE
uint32_t error; ///< Data for @ref TWIS_EVT_GENERAL_ERROR
}data;
}nrf_drv_twis_evt_t;
/**
* @brief TWI slave event callback function type.
*
* @param[in] p_event Event information structure.
*/
typedef void (*nrf_drv_twis_event_handler_t)(nrf_drv_twis_evt_t const * 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
nrf_gpio_pin_pull_t scl_pull; //!< SCL pin pull
uint32_t sda; //!< SDA pin number
nrf_gpio_pin_pull_t sda_pull; //!< SDA pin pull
uint8_t interrupt_priority; //!< The priority of interrupt for the module to set
}nrf_drv_twis_config_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 becouse
* of possible future extension (eg. supporting timeouts and synchronous mode).
*/
typedef enum
{
NRF_DRV_TWIS_ERROR_OVERFLOW = NRF_TWIS_ERROR_OVERFLOW, /**< RX buffer overflow detected, and prevented */
NRF_DRV_TWIS_ERROR_DATA_NACK = NRF_TWIS_ERROR_DATA_NACK, /**< NACK sent after receiving a data byte */
NRF_DRV_TWIS_ERROR_OVERREAD = NRF_TWIS_ERROR_OVERREAD, /**< TX buffer over-read detected, and prevented */
NRF_DRV_TWIS_ERROR_UNEXPECTED_EVENT = 1 << 8 /**< Unexpected event detected by state machine */
}nrf_drv_twis_error_t;
/**
* @internal
* @brief Internal macro for creating TWIS driver instance
*
* Second level of indirection in creating the instance.
* Do not use this macro directly.
* Use @ref NRF_DRV_TWIS_INSTANCE instead.
*/
#define NRF_DRV_TWIS_INSTANCE_x(id) \
{ \
TWIS##id##_INSTANCE_INDEX \
}
/**
* @brief Macro for creating TWIS driver instance
*
* @param[in] id Instance index. Use 0 for TWIS0 and 1 for TWIS1
*/
#define NRF_DRV_TWIS_INSTANCE(id) NRF_DRV_TWIS_INSTANCE_x(id)
#define TWIS0_INSTANCE_INDEX 0
#define TWIS1_INSTANCE_INDEX TWIS0_INSTANCE_INDEX+TWIS0_ENABLED
/**
* @brief Generate default configuration for TWIS driver instance
*/
#define NRF_DRV_TWIS_DEFAULT_CONFIG \
{ \
.addr = { TWIS_DEFAULT_CONFIG_ADDR0, TWIS_DEFAULT_CONFIG_ADDR1 }, \
.scl = 31, \
.scl_pull = (nrf_gpio_pin_pull_t)TWIS_DEFAULT_CONFIG_SCL_PULL, \
.sda = 31, \
.sda_pull = (nrf_gpio_pin_pull_t)TWIS_DEFAULT_CONFIG_SDA_PULL, \
.interrupt_priority = 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 nrf_drv_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 Initial configuration.
* @param[in] event_handler Event handler provided by the user.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_INVALID_STATE If the driver is already initialized.
* @retval NRF_ERROR_BUSY If some other peripheral with the same
* instance ID is already in use. This is
* possible only if PERIPHERAL_RESOURCE_SHARING_ENABLED
* is set to a value other than zero.
*/
ret_code_t nrf_drv_twis_init(
nrf_drv_twis_t const * const p_instance,
nrf_drv_twis_config_t const * p_config,
nrf_drv_twis_event_handler_t const 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 nrf_drv_twis_uninit even before initialization.
* Actually @ref nrf_drv_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 nrf_drv_twis_uninit(nrf_drv_twis_t const * 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 nrf_drv_twis_enable and @ref nrf_drv_twis_disable functions.
* They do not change any configuration registers.
*
* @param p_instance Pointer to the driver instance structure.
*/
void nrf_drv_twis_enable(nrf_drv_twis_t const * const p_instance);
/**
* @brief Disable TWIS instance
*
* Disabling TWIS instance gives possibility to turn off the TWIS while
* holding configuration done by @ref nrf_drv_twis_init
*
* @param p_instance Pointer to the driver instance structure.
*/
void nrf_drv_twis_disable(nrf_drv_twis_t const * 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 nrf_drv_twis_error_t
* @attention
* This function clears error state and flags.
*/
uint32_t nrf_drv_twis_error_get_and_clear(nrf_drv_twis_t const * const p_instance);
/**
* @brief Prepare data for sending
*
* This function should be used in response for @ref TWIS_EVT_READ_REQ event.
*
* @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 NRF_SUCCESS Preparation finished properly
* @retval NRF_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM
* @retval NRF_ERROR_INVALID_LENGTH Wrong value in @em size parameter
* @retval NRF_ERROR_INVALID_STATE Module not initialized or not enabled
*/
ret_code_t nrf_drv_twis_tx_prepare(
nrf_drv_twis_t const * const p_instance,
void const * 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 TWIS_EVT_READ_DONE or @ref TWIS_EVT_READ_ERROR events.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @return Number of bytes sent.
*/
size_t nrf_drv_twis_tx_amount(nrf_drv_twis_t const * const p_instance);
/**
* @brief Prepare data for receiving
*
* This function should be used in response for @ref TWIS_EVT_WRITE_REQ event.
*
* @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 NRF_SUCCESS Preparation finished properly
* @retval NRF_ERROR_INVALID_ADDR Given @em p_buf is not placed inside the RAM
* @retval NRF_ERROR_INVALID_LENGTH Wrong value in @em size parameter
* @retval NRF_ERROR_INVALID_STATE Module not initialized or not enabled
*/
ret_code_t nrf_drv_twis_rx_prepare(
nrf_drv_twis_t const * const p_instance,
void * const p_buf,
size_t size);
/**
* @brief Get number of received bytes
*
* Function returns number of bytes received.
* This function may be called after @ref TWIS_EVT_WRITE_DONE or @ref TWIS_EVT_WRITE_ERROR events.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @return Number of bytes received.
*/
size_t nrf_drv_twis_rx_amount(nrf_drv_twis_t const * 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 nrf_drv_twis_is_busy(nrf_drv_twis_t const * 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 nrf_drv_twis_tx_prepare function call.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true Driver waits for @ref nrf_drv_twis_tx_prepare
* @retval false Driver is not in the state where it waits for preparing tx buffer.
*/
bool nrf_drv_twis_is_waiting_tx_buff(nrf_drv_twis_t const * 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 nrf_drv_twis_rx_prepare function call.
*
* @param[in] p_instance Pointer to the driver instance structure.
*
* @retval true Driver waits for @ref nrf_drv_twis_rx_prepare
* @retval false Driver is not in the state where it waits for preparing rx buffer.
*/
bool nrf_drv_twis_is_waiting_rx_buff(nrf_drv_twis_t const * 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 nrf_drv_twis_is_pending_tx(nrf_drv_twis_t const * 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 nrf_drv_twis_is_pending_rx(nrf_drv_twis_t const * const p_instance);
/** @} */ /* End of lib_twis_drv group */
#ifdef __cplusplus
}
#endif
#endif /* NRF_DRV_TWIS_H__ */

View File

@@ -0,0 +1,20 @@
/**
* @file
* @brief Xmacro file with contains enumeration of TWIS instances to implement
*
* Use this file everywhere where anything has to be generated for all active TWIS instances.
* Xmacro format:
*
* @code
X(n)
* @endcode
*
* Where @em n is number of the instance itself (0 for NRF_TWIS0).
*/
#if (TWIS0_ENABLED == 1)
X(0)
#endif
#if (TWIS1_ENABLED == 1)
X(1)
#endif
#undef X