You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/07/27 23:13:58 UTC

[29/51] [partial] incubator-mynewt-core git commit: add stm32 and nordic sdks based on new structure

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.c
new file mode 100644
index 0000000..d13f9a2
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.c
@@ -0,0 +1,972 @@
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+#include "nrf_drv_twi.h"
+#include "nrf_drv_common.h"
+#include "nrf_gpio.h"
+#include "nrf_assert.h"
+#include "app_util_platform.h"
+#include "nrf_delay.h"
+
+#include <stdio.h>
+
+#define TWI0_IRQ_HANDLER    SPI0_TWI0_IRQHandler
+#define TWI1_IRQ_HANDLER    SPI1_TWI1_IRQHandler
+
+#if (defined(TWIM_IN_USE) && defined(TWI_IN_USE))
+    // TWIM and TWI combined
+    #define CODE_FOR_TWIM(code) if (p_instance->use_easy_dma) { code }
+    #define CODE_FOR_TWI(code)  else { code }
+#elif (defined(TWIM_IN_USE) && !defined(TWI_IN_USE))
+    // TWIM only
+    #define CODE_FOR_TWIM(code) { code }
+    #define CODE_FOR_TWI(code)
+#elif (!defined(TWIM_IN_USE) && defined(TWI_IN_USE))
+    // TWI only
+    #define CODE_FOR_TWIM(code)
+    #define CODE_FOR_TWI(code)  { code }
+#else
+    #error "Wrong configuration."
+#endif
+
+// All interrupt flags
+#define DISABLE_ALL  0xFFFFFFFF
+
+#define SCL_PIN_CONF        ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)    \
+                            | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)   \
+                            | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)    \
+                            | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)   \
+                            | (GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos))
+
+#define SDA_PIN_CONF        SCL_PIN_CONF
+
+#define SCL_PIN_CONF_CLR    ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)    \
+                            | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)   \
+                            | (GPIO_PIN_CNF_PULL_Pullup    << GPIO_PIN_CNF_PULL_Pos)    \
+                            | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)   \
+                            | (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos))
+
+#define SDA_PIN_CONF_CLR    SCL_PIN_CONF_CLR
+
+// Control block - driver instance local data.
+typedef struct
+{
+    nrf_drv_twi_evt_handler_t handler;
+    void *                    p_context;
+    volatile uint32_t         int_mask;
+    nrf_drv_twi_xfer_desc_t   xfer_desc;
+    uint32_t                  flags;
+    uint8_t *                 p_curr_buf;
+    uint8_t                   curr_length;
+    bool                      curr_no_stop;
+    nrf_drv_state_t           state;
+    bool                      error;
+    volatile bool             busy;
+    bool                      repeated;
+    uint8_t                   bytes_transferred;
+} twi_control_block_t;
+
+static twi_control_block_t m_cb[TWI_COUNT];
+
+static nrf_drv_twi_config_t const m_default_config[TWI_COUNT] = {
+#if TWI0_ENABLED
+    NRF_DRV_TWI_DEFAULT_CONFIG(0),
+#endif
+#if TWI1_ENABLED
+    NRF_DRV_TWI_DEFAULT_CONFIG(1),
+#endif
+};
+
+#if PERIPHERAL_RESOURCE_SHARING_ENABLED
+    #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n
+    #define IRQ_HANDLER(n)      static void IRQ_HANDLER_NAME(n)(void)
+
+    #if TWI0_ENABLED
+        IRQ_HANDLER(0);
+    #endif
+    #if TWI1_ENABLED
+        IRQ_HANDLER(1);
+    #endif
+    static nrf_drv_irq_handler_t const m_irq_handlers[TWI_COUNT] = {
+    #if TWI0_ENABLED
+        IRQ_HANDLER_NAME(0),
+    #endif
+    #if TWI1_ENABLED
+        IRQ_HANDLER_NAME(1),
+    #endif
+    };
+#else
+    #define IRQ_HANDLER(n) void SPI##n##_TWI##n##_IRQHandler(void)
+#endif // PERIPHERAL_RESOURCE_SHARING_ENABLED
+
+static void twi_clear_bus(nrf_drv_twi_t const * const p_instance,
+                          nrf_drv_twi_config_t const * p_config)
+{
+    NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_CONF;
+    NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_CONF;
+
+    nrf_gpio_pin_set(p_config->scl);
+    nrf_gpio_pin_set(p_config->sda);
+
+    NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_CONF_CLR;
+    NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_CONF_CLR;
+
+    nrf_delay_us(4);
+
+    for(int i = 0; i < 9; i++)
+    {
+        if (nrf_gpio_pin_read(p_config->sda))
+        {
+            if(i == 0)
+            {
+                return;
+            }
+            else
+            {
+                break;
+            }
+        }
+        nrf_gpio_pin_clear(p_config->scl);
+        nrf_delay_us(4);
+        nrf_gpio_pin_set(p_config->scl);
+        nrf_delay_us(4);
+    }
+    nrf_gpio_pin_clear(p_config->sda);
+    nrf_delay_us(4);
+    nrf_gpio_pin_set(p_config->sda);
+}
+
+ret_code_t nrf_drv_twi_init(nrf_drv_twi_t const *        p_instance,
+                            nrf_drv_twi_config_t const * p_config,
+                            nrf_drv_twi_evt_handler_t    event_handler,
+                            void *                       p_context)
+{
+    twi_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
+
+    if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+    if (p_config == NULL)
+    {
+        p_config = &m_default_config[p_instance->drv_inst_idx];
+    }
+
+#if PERIPHERAL_RESOURCE_SHARING_ENABLED
+    if (nrf_drv_common_per_res_acquire(p_instance->reg.p_twi,
+            m_irq_handlers[p_instance->drv_inst_idx]) != NRF_SUCCESS)
+    {
+        return NRF_ERROR_BUSY;
+    }
+#endif // PERIPHERAL_RESOURCE_SHARING_ENABLED
+
+    p_cb->handler   = event_handler;
+    p_cb->p_context = p_context;
+    p_cb->int_mask  = 0;
+    p_cb->repeated  = false;
+    p_cb->busy      = false;
+
+    twi_clear_bus(p_instance, p_config);
+
+    /* To secure correct signal levels on the pins used by the TWI
+       master when the system is in OFF mode, and when the TWI master is
+       disabled, these pins must be configured in the GPIO peripheral.
+    */
+    NRF_GPIO->PIN_CNF[p_config->scl] = SCL_PIN_CONF;
+    NRF_GPIO->PIN_CNF[p_config->sda] = SDA_PIN_CONF;
+
+    CODE_FOR_TWIM
+    (
+        NRF_TWIM_Type * p_twim = p_instance->reg.p_twim;
+        nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
+        nrf_twim_frequency_set(p_twim,
+            (nrf_twim_frequency_t)p_config->frequency);
+    )
+    CODE_FOR_TWI
+    (
+        NRF_TWI_Type * p_twi = p_instance->reg.p_twi;
+        nrf_twi_pins_set(p_twi, p_config->scl, p_config->sda);
+        nrf_twi_frequency_set(p_twi,
+            (nrf_twi_frequency_t)p_config->frequency);
+    )
+
+    if (p_cb->handler)
+    {
+        CODE_FOR_TWIM
+        (
+            nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twim),
+                p_config->interrupt_priority);
+        )
+        CODE_FOR_TWI
+        (
+            nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twi),
+                p_config->interrupt_priority);
+        )
+    }
+
+    p_cb->state = NRF_DRV_STATE_INITIALIZED;
+
+    return NRF_SUCCESS;
+}
+
+void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance)
+{
+    twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    if (p_cb->handler)
+    {
+        CODE_FOR_TWIM
+        (
+            nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twim));
+        )
+        CODE_FOR_TWI
+        (
+            nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)p_instance->reg.p_twi));
+        )
+    }
+    nrf_drv_twi_disable(p_instance);
+
+#if PERIPHERAL_RESOURCE_SHARING_ENABLED
+    nrf_drv_common_per_res_release(p_instance->reg.p_twi);
+#endif
+
+    p_cb->state = NRF_DRV_STATE_UNINITIALIZED;
+}
+
+void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance)
+{
+    twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state == NRF_DRV_STATE_INITIALIZED);
+
+    CODE_FOR_TWIM
+    (
+        NRF_TWIM_Type * p_twim = p_instance->reg.p_twim;
+
+        nrf_twim_enable(p_twim);
+    )
+    CODE_FOR_TWI
+    (
+        NRF_TWI_Type * p_twi = p_instance->reg.p_twi;
+
+        nrf_twi_enable(p_twi);
+    )
+
+    p_cb->state = NRF_DRV_STATE_POWERED_ON;
+}
+
+void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance)
+{
+    twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
+
+    CODE_FOR_TWIM
+    (
+        NRF_TWIM_Type * p_twim = p_instance->reg.p_twim;
+        p_cb->int_mask = 0;
+        nrf_twim_int_disable(p_twim, DISABLE_ALL);
+        nrf_twim_shorts_disable(p_twim, DISABLE_ALL);
+        nrf_twim_disable(p_twim);
+    )
+    CODE_FOR_TWI
+    (
+        NRF_TWI_Type * p_twi = p_instance->reg.p_twi;
+        nrf_twi_int_disable(p_twi, DISABLE_ALL);
+        nrf_twi_shorts_disable(p_twi, DISABLE_ALL);
+        nrf_twi_disable(p_twi);
+    )
+
+    p_cb->state = NRF_DRV_STATE_INITIALIZED;
+}
+
+#ifdef TWI_IN_USE
+static bool twi_send_byte(NRF_TWI_Type  * p_twi,
+                          uint8_t const * p_data,
+                          uint8_t         length,
+                          uint8_t       * p_bytes_transferred,
+                          bool            no_stop)
+{
+    if (*p_bytes_transferred < length)
+    {
+        nrf_twi_txd_set(p_twi, p_data[*p_bytes_transferred]);
+        ++(*p_bytes_transferred);
+    }
+    else
+    {
+        if (no_stop)
+        {
+            nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
+            return false;
+        }
+        else
+        {
+            nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+        }
+    }
+    return true;
+}
+
+static void twi_receive_byte(NRF_TWI_Type * p_twi,
+                             uint8_t      * p_data,
+                             uint8_t        length,
+                             uint8_t      * p_bytes_transferred)
+{
+    if (*p_bytes_transferred < length)
+    {
+        p_data[*p_bytes_transferred] = nrf_twi_rxd_get(p_twi);
+
+        ++(*p_bytes_transferred);
+
+        if (*p_bytes_transferred == length-1)
+        {
+            nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
+        }
+        else if (*p_bytes_transferred == length)
+        {
+            return;
+        }
+
+        nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+    }
+}
+
+static bool twi_transfer(NRF_TWI_Type  * p_twi,
+                         bool          * p_error,
+                         uint8_t       * p_bytes_transferred,
+                         uint8_t       * p_data,
+                         uint8_t         length,
+                         bool            no_stop)
+{
+    bool do_stop_check;
+
+    if ((*p_error == true) || (*p_bytes_transferred == length))
+    {
+        do_stop_check = true;
+    }
+    else
+    {
+        do_stop_check = false;
+    }
+
+    if (*p_error)
+    {
+        nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+        nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+        nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+    }
+    else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+    {
+        nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+        nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+        *p_error = true;
+    }
+    else
+    {
+        if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_TXDSENT))
+        {
+            nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+            if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+            {
+                nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+                nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+                *p_error = true;
+            }
+            else
+            {
+                if (!twi_send_byte(p_twi, p_data, length, p_bytes_transferred, no_stop))
+                {
+                    return false;
+                }
+            }
+        }
+        else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_RXDREADY))
+        {
+            nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+            if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
+            {
+                nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+                nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
+                *p_error = true;
+            }
+            else
+            {
+                twi_receive_byte(p_twi, p_data, length, p_bytes_transferred);
+            }
+        }
+    }
+
+    if (do_stop_check && nrf_twi_event_check(p_twi, NRF_TWI_EVENT_STOPPED))
+    {
+        nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+        return false;
+    }
+
+    return true;
+}
+
+static ret_code_t twi_tx_start_transfer(twi_control_block_t * p_cb,
+                                        NRF_TWI_Type *        p_twi,
+                                        uint8_t const *       p_data,
+                                        uint8_t               length,
+                                        bool                  no_stop)
+{
+    ret_code_t ret_code = NRF_SUCCESS;
+
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+    nrf_twi_shorts_set(p_twi, 0);
+
+    p_cb->bytes_transferred = 0;
+    p_cb->error             = false;
+
+    // In case TWI is suspended resume its operation.
+    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX);
+
+    (void)twi_send_byte(p_twi, p_data, length, &p_cb->bytes_transferred, no_stop);
+
+    if (p_cb->handler)
+    {
+        p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK   |
+                        NRF_TWI_INT_ERROR_MASK     |
+                        NRF_TWI_INT_TXDSENT_MASK   |
+                        NRF_TWI_INT_RXDREADY_MASK;
+        nrf_twi_int_enable(p_twi, p_cb->int_mask);
+    }
+    else
+    {
+        while (twi_transfer(p_twi, &p_cb->error, &p_cb->bytes_transferred, (uint8_t *)p_data, length, no_stop))
+        {}
+
+        if (p_cb->error)
+        {
+            ret_code = NRF_ERROR_INTERNAL;
+        }
+    }
+    return ret_code;
+}
+
+static ret_code_t twi_rx_start_transfer(twi_control_block_t * p_cb,
+                                        NRF_TWI_Type *        p_twi,
+                                        uint8_t const *       p_data,
+                                        uint8_t               length)
+{
+    ret_code_t ret_code = NRF_SUCCESS;
+
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
+    nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
+
+    p_cb->bytes_transferred = 0;
+    p_cb->error             = false;
+
+    if (length == 1)
+    {
+        nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
+    }
+    else
+    {
+        nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
+    }
+    // In case TWI is suspended resume its operation.
+    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
+    nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);
+
+    if (p_cb->handler)
+    {
+        p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK   |
+                        NRF_TWI_INT_ERROR_MASK     |
+                        NRF_TWI_INT_TXDSENT_MASK   |
+                        NRF_TWI_INT_RXDREADY_MASK;
+        nrf_twi_int_enable(p_twi, p_cb->int_mask);
+    }
+    else
+    {
+        while (twi_transfer(p_twi, &p_cb->error, &p_cb->bytes_transferred, (uint8_t*)p_data, length, false))
+        {}
+
+        if (p_cb->error)
+        {
+            ret_code = NRF_ERROR_INTERNAL;
+        }
+    }
+    return ret_code;
+}
+
+__STATIC_INLINE ret_code_t twi_xfer(twi_control_block_t           * p_cb,
+                                    NRF_TWI_Type                  * p_twi,
+                                    nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
+                                    uint32_t                        flags)
+{
+    ret_code_t ret = NRF_SUCCESS;
+
+    /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
+    nrf_twi_int_disable(p_twi, DISABLE_ALL);
+
+    if (p_cb->busy)
+    {
+        nrf_twi_int_enable(p_twi, p_cb->int_mask);
+        return NRF_ERROR_BUSY;
+    }
+    else
+    {
+        p_cb->busy = (NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ? false : true;
+    }
+
+    if (flags & NRF_DRV_TWI_FLAG_HOLD_XFER)
+    {
+        return NRF_ERROR_NOT_SUPPORTED;
+    }
+
+    p_cb->flags       = flags;
+    p_cb->xfer_desc   = *p_xfer_desc;
+    p_cb->curr_length = p_xfer_desc->primary_length;
+    p_cb->p_curr_buf  = p_xfer_desc->p_primary_buf;
+    nrf_twi_address_set(p_twi, p_xfer_desc->address);
+
+    if (p_xfer_desc->type != NRF_DRV_TWI_XFER_RX)
+    {
+        p_cb->curr_no_stop = ((p_xfer_desc->type == NRF_DRV_TWI_XFER_TX) &&
+                             !(flags & NRF_DRV_TWI_FLAG_TX_NO_STOP)) ? false : true;
+        ret = twi_tx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length, p_cb->curr_no_stop);
+    }
+    else
+    {
+        p_cb->curr_no_stop = false;
+        ret = twi_rx_start_transfer(p_cb, p_twi, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+    }
+    if (p_cb->handler == NULL)
+    {
+        p_cb->busy = false;
+    }
+    return ret;
+}
+#endif
+
+#ifdef TWIM_IN_USE
+__STATIC_INLINE void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
+{
+    if (NRF_DRV_TWI_FLAG_TX_POSTINC & flags)
+    {
+        nrf_twim_tx_list_enable(p_twim);
+    }
+    else
+    {
+        nrf_twim_tx_list_disable(p_twim);
+    }
+
+    if (NRF_DRV_TWI_FLAG_RX_POSTINC & flags)
+    {
+        nrf_twim_rx_list_enable(p_twim);
+    }
+    else
+    {
+        nrf_twim_rx_list_disable(p_twim);
+    }
+#ifndef NRF52_PAN_46
+#endif
+}
+__STATIC_INLINE ret_code_t twim_xfer(twi_control_block_t           * p_cb,
+                                     NRF_TWIM_Type                 * p_twim,
+                                     nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
+                                     uint32_t                        flags)
+{
+    ret_code_t ret = NRF_SUCCESS;
+    nrf_twim_task_t  start_task = NRF_TWIM_TASK_STARTTX;
+    nrf_twim_event_t evt_to_wait = NRF_TWIM_EVENT_STOPPED;
+
+    if (!nrf_drv_is_in_RAM(p_xfer_desc->p_primary_buf))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+    /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
+    nrf_twim_int_disable(p_twim, DISABLE_ALL);
+    if (p_cb->busy)
+    {
+        nrf_twim_int_enable(p_twim, p_cb->int_mask);
+        return NRF_ERROR_BUSY;
+    }
+    else
+    {
+
+        p_cb->busy = ((NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ||
+                      (NRF_DRV_TWI_FLAG_REPEATED_XFER & flags)) ? false: true;
+    }
+
+    p_cb->xfer_desc = *p_xfer_desc;
+    p_cb->repeated = (flags & NRF_DRV_TWI_FLAG_REPEATED_XFER) ? true : false;
+    nrf_twim_address_set(p_twim, p_xfer_desc->address);
+
+    nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
+    nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+
+    twim_list_enable_handle(p_twim, flags);
+    switch (p_xfer_desc->type)
+    {
+    case NRF_DRV_TWI_XFER_TXTX:
+        ASSERT(!(flags & NRF_DRV_TWI_FLAG_REPEATED_XFER));
+        ASSERT(!(flags & NRF_DRV_TWI_FLAG_HOLD_XFER));
+        ASSERT(!(flags & NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER));
+        if (!nrf_drv_is_in_RAM(p_xfer_desc->p_secondary_buf))
+        {
+            return NRF_ERROR_INVALID_ADDR;
+        }
+        nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
+        nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+        nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+        nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
+        while(!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
+        {}
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
+        nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
+        p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
+        break;
+    case NRF_DRV_TWI_XFER_TXRX:
+        nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+        nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
+        nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
+                                    NRF_TWIM_SHORT_LASTRX_STOP_MASK);
+        p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+        break;
+    case NRF_DRV_TWI_XFER_TX:
+        nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+        if (NRF_DRV_TWI_FLAG_TX_NO_STOP & flags)
+        {
+            nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
+            p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
+            nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+            evt_to_wait = NRF_TWIM_EVENT_SUSPENDED;
+        }
+        else
+        {
+            nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
+            p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+        }
+        nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+        break;
+    case NRF_DRV_TWI_XFER_RX:
+        nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
+        nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
+        p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+        start_task = NRF_TWIM_TASK_STARTRX;
+        nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+        break;
+    default:
+        ret = NRF_ERROR_INVALID_PARAM;
+        break;
+    }
+
+    if (!(flags & NRF_DRV_TWI_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRF_DRV_TWI_XFER_TXTX))
+    {
+        nrf_twim_task_trigger(p_twim, start_task);
+    }
+
+    if (p_cb->handler)
+    {
+        if (flags & NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER)
+        {
+            p_cb->int_mask = NRF_TWIM_INT_ERROR_MASK;
+        }
+        nrf_twim_int_enable(p_twim, p_cb->int_mask);
+    }
+    else
+    {
+        while (!nrf_twim_event_check(p_twim, evt_to_wait))
+        {
+            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
+            {
+                nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+                nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+                nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
+                evt_to_wait = NRF_TWIM_EVENT_STOPPED;
+            }
+        }
+
+        uint32_t errorsrc =  nrf_twim_errorsrc_get_and_clear(p_twim);
+
+        p_cb->busy = false;
+
+        if (errorsrc)
+        {
+            ret = NRF_ERROR_INTERNAL;
+        }
+    }
+    return ret;
+}
+#endif
+
+ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t           const * p_instance,
+                            nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
+                            uint32_t                        flags)
+{
+    ret_code_t ret = NRF_SUCCESS;
+    twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+
+    // TXRX and TXTX transfers are support only in non-blocking mode.
+    ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXRX)));
+    ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRF_DRV_TWI_XFER_TXTX)));
+
+    CODE_FOR_TWIM
+    (
+        ret = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->reg.p_twim, p_xfer_desc, flags);
+    )
+    CODE_FOR_TWI
+    (
+        if ( (NRF_DRV_TWI_FLAG_TX_POSTINC | NRF_DRV_TWI_FLAG_RX_POSTINC) & flags)
+        {
+            return NRF_ERROR_NOT_SUPPORTED;
+        }
+        ret = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->reg.p_twi, p_xfer_desc, flags);
+    )
+    return ret;
+}
+
+ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance,
+                          uint8_t               address,
+                          uint8_t const *       p_data,
+                          uint8_t               length,
+                          bool                  no_stop)
+{
+    nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length);
+
+    return nrf_drv_twi_xfer(p_instance, &xfer, no_stop ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0);
+}
+
+ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance,
+                          uint8_t               address,
+                          uint8_t *             p_data,
+                          uint8_t               length)
+{
+    nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_RX(address, p_data, length);
+    return nrf_drv_twi_xfer(p_instance, &xfer, 0);
+}
+
+uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance)
+{
+    CODE_FOR_TWIM
+    (
+        ASSERT(false);
+        return 0;
+    )
+    CODE_FOR_TWI
+    (
+        return m_cb[p_instance->drv_inst_idx].bytes_transferred;
+    )
+}
+uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, nrf_drv_twi_xfer_type_t xfer_type)
+{
+    CODE_FOR_TWIM
+    (
+        return (uint32_t)nrf_twim_task_address_get(p_instance->reg.p_twim,
+            (xfer_type != NRF_DRV_TWI_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
+    )
+    CODE_FOR_TWI
+    (
+        return (uint32_t)nrf_twi_task_address_get(p_instance->reg.p_twi,
+                (xfer_type != NRF_DRV_TWI_XFER_RX) ? NRF_TWI_TASK_STARTTX : NRF_TWI_TASK_STARTRX);
+    )
+}
+
+uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance)
+{
+    CODE_FOR_TWIM
+    (
+        return (uint32_t)nrf_twim_event_address_get(p_instance->reg.p_twim, NRF_TWIM_EVENT_STOPPED);
+    )
+    CODE_FOR_TWI
+    (
+        return (uint32_t)nrf_twi_event_address_get(p_instance->reg.p_twi, NRF_TWI_EVENT_STOPPED);
+    )
+}
+
+#ifdef TWIM_IN_USE
+static void irq_handler_twim(NRF_TWIM_Type * p_twim, twi_control_block_t * p_cb)
+{
+    ASSERT(p_cb->handler);
+
+    if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
+    {
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
+        if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
+        {
+            nrf_twim_int_disable(p_twim, p_cb->int_mask);
+            p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
+            nrf_twim_int_enable(p_twim, p_cb->int_mask);
+
+            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
+            return;
+        }
+    }
+
+    nrf_drv_twi_evt_t event;
+
+    if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
+    {
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
+        event.xfer_desc = p_cb->xfer_desc;
+        if (p_cb->error)
+        {
+
+            event.xfer_desc.primary_length = (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_RX) ?
+                (uint8_t)nrf_twim_rxd_amount_get(p_twim) : (uint8_t)nrf_twim_txd_amount_get(p_twim);
+            event.xfer_desc.secondary_length = (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX) ?
+                (uint8_t)nrf_twim_rxd_amount_get(p_twim) : (uint8_t)nrf_twim_txd_amount_get(p_twim);
+
+        }
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
+        if (!p_cb->repeated || p_cb->error)
+        {
+            nrf_twim_shorts_set(p_twim, 0);
+            p_cb->int_mask = 0;
+            nrf_twim_int_disable(p_twim, DISABLE_ALL);
+        }
+    }
+    else
+    {
+        nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
+        if (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
+        {
+            event.xfer_desc = p_cb->xfer_desc;
+            if (!p_cb->repeated)
+            {
+                nrf_twim_shorts_set(p_twim, 0);
+                p_cb->int_mask = 0;
+                nrf_twim_int_disable(p_twim, DISABLE_ALL);
+            }
+        }
+        else
+        {
+            nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
+            p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
+            nrf_twim_int_disable(p_twim, DISABLE_ALL);
+            nrf_twim_int_enable(p_twim, p_cb->int_mask);
+            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
+            nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
+            return;
+        }
+    }
+
+    uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
+    if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
+    {
+        event.type = NRF_DRV_TWI_EVT_ADDRESS_NACK;
+    }
+    else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
+    {
+        event.type = NRF_DRV_TWI_EVT_DATA_NACK;
+    }
+    else
+    {
+        event.type = NRF_DRV_TWI_EVT_DONE;
+    }
+
+    if (!p_cb->repeated)
+    {
+        p_cb->busy = false;
+    }
+    p_cb->handler(&event, p_cb->p_context);
+}
+#endif // TWIM_IN_USE
+
+#ifdef TWI_IN_USE
+static void irq_handler_twi(NRF_TWI_Type * p_twi, twi_control_block_t * p_cb)
+{
+    ASSERT(p_cb->handler);
+
+    if (twi_transfer(p_twi, &p_cb->error, &p_cb->bytes_transferred, p_cb->p_curr_buf, p_cb->curr_length, p_cb->curr_no_stop ))
+    {
+        return;
+    }
+
+    if (!p_cb->error &&
+        ((p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX) ||
+         (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)) &&
+        p_cb->p_curr_buf == p_cb->xfer_desc.p_primary_buf)
+    {
+        p_cb->p_curr_buf   = p_cb->xfer_desc.p_secondary_buf;
+        p_cb->curr_length  = p_cb->xfer_desc.secondary_length;
+        p_cb->curr_no_stop = (p_cb->flags & NRF_DRV_TWI_FLAG_TX_NO_STOP);
+
+        if (p_cb->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)
+        {
+            (void)twi_tx_start_transfer(p_cb, p_twi, p_cb->p_curr_buf, p_cb->curr_length, p_cb->curr_no_stop);
+        }
+        else
+        {
+            (void)twi_rx_start_transfer(p_cb, p_twi, p_cb->p_curr_buf, p_cb->curr_length);
+        }
+    }
+    else
+    {
+        nrf_drv_twi_evt_t event;
+        event.xfer_desc = p_cb->xfer_desc;
+
+        if (p_cb->error)
+        {
+            uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
+            if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
+            {
+                event.type = NRF_DRV_TWI_EVT_ADDRESS_NACK;
+            }
+            else if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
+            {
+                event.type = NRF_DRV_TWI_EVT_DATA_NACK;
+            }
+        }
+        else
+        {
+            event.type = NRF_DRV_TWI_EVT_DONE;
+        }
+
+        p_cb->busy = false;
+
+        if (!(NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER & p_cb->flags))
+        {
+            p_cb->handler(&event, p_cb->p_context);
+        }
+    }
+
+}
+#endif // TWI_IN_USE
+
+#if TWI0_ENABLED
+IRQ_HANDLER(0)
+{
+    #if (TWI0_USE_EASY_DMA == 1) && defined(NRF52)
+        irq_handler_twim(NRF_TWIM0,
+    #else
+        irq_handler_twi(NRF_TWI0,
+    #endif
+            &m_cb[TWI0_INSTANCE_INDEX]);
+}
+#endif // TWI0_ENABLED
+
+#if TWI1_ENABLED
+IRQ_HANDLER(1)
+{
+    #if (TWI1_USE_EASY_DMA == 1)
+        irq_handler_twim(NRF_TWIM1,
+    #else
+        irq_handler_twi(NRF_TWI1,
+    #endif
+            &m_cb[TWI1_INSTANCE_INDEX]);
+}
+#endif // TWI1_ENABLED

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.h b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.h
new file mode 100644
index 0000000..e4e67ec
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twi_master/nrf_drv_twi.h
@@ -0,0 +1,384 @@
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/**
+ *
+ * @defgroup nrf_twi Two-wire interface (TWI)
+ * @ingroup nrf_drivers
+ * @brief Two-wire interface (TWI) APIs.
+ *
+ * @defgroup nrf_twi_master TWI master HAL and driver
+ * @ingroup nrf_twi
+ * @brief TWI master APIs.
+ * @details The TWI and TWIM HALs provide basic APIs for accessing the registers of the TWI and TWIM peripherals, respectively. 
+ *
+ * The TWI master driver provides APIs on a higher level.
+ *
+ */
+
+#ifndef NRF_DRV_TWI_H__
+#define NRF_DRV_TWI_H__
+
+#include "nordic_common.h"
+#include "nrf_drv_config.h"
+
+// This set of macros makes it possible to exclude parts of code when one type
+// of supported peripherals is not used.
+#if ((TWI0_ENABLED == 1 && TWI0_USE_EASY_DMA == 1) || \
+     (TWI1_ENABLED == 1 && TWI1_USE_EASY_DMA == 1))
+    #define TWIM_IN_USE
+#endif
+#if ((TWI0_ENABLED == 1 && TWI0_USE_EASY_DMA != 1) || \
+     (TWI1_ENABLED == 1 && TWI1_USE_EASY_DMA != 1))
+    #define TWI_IN_USE
+#endif
+
+#include "nrf_twi.h"
+#ifdef TWIM_IN_USE
+    #include "nrf_twim.h"
+#endif
+#include "sdk_errors.h"
+
+#if defined(NRF52)
+    #define NRF_DRV_TWI_PERIPHERAL(id)           \
+        (CONCAT_3(TWI, id, _USE_EASY_DMA) == 1 ? \
+            (void *)CONCAT_2(NRF_TWIM, id)       \
+          : (void *)CONCAT_2(NRF_TWI, id))
+#else
+    #define NRF_DRV_TWI_PERIPHERAL(id)  (void *)CONCAT_2(NRF_TWI, id)
+#endif
+
+/**
+ * @defgroup nrf_drv_twi TWI master driver
+ * @{
+ * @ingroup nrf_twi_master
+ * @brief   Multi-instance TWI master driver.
+ */
+
+/**
+ * @brief Structure for the TWI master driver instance.
+ */
+typedef struct
+{
+    union
+    {
+#ifdef TWIM_IN_USE
+        NRF_TWIM_Type * p_twim; ///< Pointer to a structure with TWIM registers.
+#endif
+        NRF_TWI_Type  * p_twi;  ///< Pointer to a structure with TWI registers.
+    } reg;
+    uint8_t drv_inst_idx; ///< Driver instance index.
+    bool    use_easy_dma; ///< True if the peripheral with EasyDMA (TWIM) shall be used.
+} nrf_drv_twi_t;
+
+/**
+ * @brief Macro for creating a TWI master driver instance.
+ */
+#define NRF_DRV_TWI_INSTANCE(id)                        \
+{                                                       \
+    .reg          = {NRF_DRV_TWI_PERIPHERAL(id)},       \
+    .drv_inst_idx = CONCAT_3(TWI, id, _INSTANCE_INDEX), \
+    .use_easy_dma = CONCAT_3(TWI, id, _USE_EASY_DMA)    \
+}
+
+/**
+ * @brief Structure for the TWI master driver instance configuration.
+ */
+typedef struct
+{
+    uint32_t            scl;                ///< SCL pin number.
+    uint32_t            sda;                ///< SDA pin number.
+    nrf_twi_frequency_t frequency;          ///< TWI frequency.
+    uint8_t             interrupt_priority; ///< Interrupt priority.
+} nrf_drv_twi_config_t;
+
+/**
+ * @brief TWI master driver instance default configuration.
+ */
+#define NRF_DRV_TWI_DEFAULT_CONFIG(id)                            \
+{                                                                 \
+    .frequency          = CONCAT_3(TWI, id, _CONFIG_FREQUENCY),   \
+    .scl                = CONCAT_3(TWI, id, _CONFIG_SCL),         \
+    .sda                = CONCAT_3(TWI, id, _CONFIG_SDA),         \
+    .interrupt_priority = CONCAT_3(TWI, id, _CONFIG_IRQ_PRIORITY) \
+}
+
+#define NRF_DRV_TWI_FLAG_TX_POSTINC          (1UL << 0) /**< TX buffer address incremented after transfer. */
+#define NRF_DRV_TWI_FLAG_RX_POSTINC          (1UL << 1) /**< RX buffer address incremented after transfer. */
+#define NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */
+#define NRF_DRV_TWI_FLAG_HOLD_XFER           (1UL << 3) /**< Set up the transfer but do not start it. */
+#define NRF_DRV_TWI_FLAG_REPEATED_XFER       (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */
+#define NRF_DRV_TWI_FLAG_TX_NO_STOP          (1UL << 5) /**< Flag indicating that the TX transfer will not end with a stop condition. */
+
+/**
+ * @brief TWI master driver event types.
+ */
+typedef enum
+{
+    NRF_DRV_TWI_EVT_DONE,         ///< Transfer completed event.
+    NRF_DRV_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
+    NRF_DRV_TWI_EVT_DATA_NACK     ///< Error event: NACK received after sending a data byte.
+} nrf_drv_twi_evt_type_t;
+
+/**
+ * @brief TWI master driver transfer types.
+ */
+typedef enum
+{
+    NRF_DRV_TWI_XFER_TX,          ///< TX transfer.
+    NRF_DRV_TWI_XFER_RX,          ///< RX transfer.
+    NRF_DRV_TWI_XFER_TXRX,        ///< TX transfer followed by RX transfer with repeated start.
+    NRF_DRV_TWI_XFER_TXTX         ///< TX transfer followed by TX transfer with repeated start.
+} nrf_drv_twi_xfer_type_t;
+
+/**
+ * @brief Structure for a TWI transfer descriptor.
+ */
+typedef struct
+{
+    nrf_drv_twi_xfer_type_t type;             ///< Type of transfer.
+    uint8_t                 address;          ///< Slave address.
+    uint8_t                 primary_length;   ///< Number of bytes transferred.
+    uint8_t                 secondary_length; ///< Number of bytes transferred.
+    uint8_t *               p_primary_buf;    ///< Pointer to transferred data.
+    uint8_t *               p_secondary_buf;  ///< Pointer to transferred data.
+} nrf_drv_twi_xfer_desc_t;
+
+
+/**@brief Macro for setting the TX transfer descriptor. */
+#define NRF_DRV_TWI_XFER_DESC_TX(addr, p_data, length)                 \
+    {                                                                  \
+        .type = NRF_DRV_TWI_XFER_TX,                                   \
+        .address = addr,                                               \
+        .primary_length = length,                                      \
+        .p_primary_buf  = p_data,                                      \
+    }
+
+/**@brief Macro for setting the RX transfer descriptor. */
+#define NRF_DRV_TWI_XFER_DESC_RX(addr, p_data, length)                 \
+    {                                                                  \
+        .type = NRF_DRV_TWI_XFER_RX,                                   \
+        .address = addr,                                               \
+        .primary_length = length,                                      \
+        .p_primary_buf  = p_data,                                      \
+    }
+
+/**@brief Macro for setting the TXRX transfer descriptor. */
+#define NRF_DRV_TWI_XFER_DESC_TXRX(addr, p_tx, tx_len, p_rx, rx_len)   \
+    {                                                                  \
+        .type = NRF_DRV_TWI_XFER_TXRX,                                 \
+        .address = addr,                                               \
+        .primary_length   = tx_len,                                    \
+        .secondary_length = rx_len,                                    \
+        .p_primary_buf    = p_tx,                                      \
+        .p_secondary_buf  = p_rx,                                      \
+    }
+
+/**@brief Macro for setting the TXTX transfer descriptor. */
+#define NRF_DRV_TWI_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \
+    {                                                                  \
+        .type = NRF_DRV_TWI_XFER_TXTX,                                 \
+        .address = addr,                                               \
+        .primary_length   = tx_len,                                    \
+        .secondary_length = tx_len2,                                   \
+        .p_primary_buf    = p_tx,                                      \
+        .p_secondary_buf  = p_tx2,                                     \
+    }
+
+/**
+ * @brief Structure for a TWI event.
+ */
+typedef struct
+{
+    nrf_drv_twi_evt_type_t  type;      ///< Event type.
+    nrf_drv_twi_xfer_desc_t xfer_desc; ///< Transfer details.
+} nrf_drv_twi_evt_t;
+
+/**
+ * @brief TWI event handler prototype.
+ */
+typedef void (* nrf_drv_twi_evt_handler_t)(nrf_drv_twi_evt_t const * p_event,
+                                           void *                    p_context);
+
+/**
+ * @brief Function for initializing the TWI instance.
+ *
+ * @param[in] p_instance      TWI instance.
+ * @param[in] p_config        Initial configuration. If NULL, the default configuration is used.
+ * @param[in] event_handler   Event handler provided by the user. If NULL, blocking mode is enabled.
+ * @param[in] p_context       Context passed to event handler.
+ *
+ * @retval NRF_SUCCESS             If initialization was successful.
+ * @retval NRF_ERROR_INVALID_STATE If the driver is in invalid state.
+ * @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_twi_init(nrf_drv_twi_t const *        p_instance,
+                            nrf_drv_twi_config_t const * p_config,
+                            nrf_drv_twi_evt_handler_t    event_handler,
+                            void *                       p_context);
+
+/**
+ * @brief Function for uninitializing the TWI instance.
+ *
+ * @param[in] p_instance  TWI instance.
+ */
+void nrf_drv_twi_uninit(nrf_drv_twi_t const * p_instance);
+
+/**
+ * @brief Function for enabling the TWI instance.
+ *
+ * @param[in] p_instance  TWI instance.
+ */
+void nrf_drv_twi_enable(nrf_drv_twi_t const * p_instance);
+
+/**
+ * @brief Function for disabling the TWI instance.
+ *
+ * @param[in] p_instance  TWI instance.
+ */
+void nrf_drv_twi_disable(nrf_drv_twi_t const * p_instance);
+
+/**
+ * @brief Function for sending data to a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRF_ERROR_BUSY.
+ *
+ * @param[in] p_instance TWI instance.
+ * @param[in] address    Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data     Pointer to a transmit buffer.
+ * @param[in] length     Number of bytes to send.
+ * @param[in] no_stop    If set, the stop condition is not generated on the bus
+ *                       after the transfer has completed successfully (allowing
+ *                       for a repeated start in the next transfer).
+ *
+ * @retval NRF_SUCCESS        If the procedure was successful.
+ * @retval NRF_ERROR_BUSY     If the driver is not ready for a new transfer.
+ * @retval NRF_ERROR_INTERNAL If an error was detected by hardware.
+ */
+ret_code_t nrf_drv_twi_tx(nrf_drv_twi_t const * p_instance,
+                          uint8_t               address,
+                          uint8_t const *       p_data,
+                          uint8_t               length,
+                          bool                  no_stop);
+
+/**
+ * @brief Function for reading data from a TWI slave.
+ *
+ * The transmission will be stopped when an error occurs. If a transfer is ongoing,
+ * the function returns the error code @ref NRF_ERROR_BUSY. 
+ *
+ * @param[in] p_instance TWI instance.
+ * @param[in] address    Address of a specific slave device (only 7 LSB).
+ * @param[in] p_data     Pointer to a receive buffer.
+ * @param[in] length     Number of bytes to be received.
+ *
+ * @retval NRF_SUCCESS             If the procedure was successful.
+ * @retval NRF_ERROR_BUSY          If the driver is not ready for a new transfer.
+ * @retval NRF_ERROR_INTERNAL      If an error was detected by hardware.
+ */
+ret_code_t nrf_drv_twi_rx(nrf_drv_twi_t const * p_instance,
+                          uint8_t               address,
+                          uint8_t *             p_data,
+                          uint8_t               length);
+
+/**
+ * @brief Function for preparing a TWI transfer.
+ *
+ * The following transfer types can be configured (@ref nrf_drv_twi_xfer_desc_t::type):
+ * - @ref NRF_DRV_TWI_XFER_TXRX<span></span>: Write operation followed by a read operation (without STOP condition in between).
+ * - @ref NRF_DRV_TWI_XFER_TXTX<span></span>: Write operation followed by a write operation (without STOP condition in between).
+ * - @ref NRF_DRV_TWI_XFER_TX<span></span>:   Write operation (with or without STOP condition).
+ * - @ref NRF_DRV_TWI_XFER_RX<span></span>:   Read operation  (with STOP condition).
+ *
+ * Additional options are provided using the flags parameter:
+ * - @ref NRF_DRV_TWI_FLAG_TX_POSTINC and @ref NRF_DRV_TWI_FLAG_RX_POSTINC<span></span>: Post-incrementation of buffer addresses. Supported only by TWIM.
+ * - @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER<span></span>: No user event handler after transfer completion. In most cases, this also means no interrupt at the end of the transfer.
+ * - @ref NRF_DRV_TWI_FLAG_HOLD_XFER<span></span>: Driver is not starting the transfer. Use this flag if the transfer is triggered externally by PPI. Supported only by TWIM.
+ *   Use @ref nrf_drv_twi_start_task_get to get the address of the start task.
+ * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER<span></span>: Prepare for repeated transfers. You can set up a number of transfers that will be triggered externally (for example by PPI).
+ *   An example is a TXRX transfer with the options @ref NRF_DRV_TWI_FLAG_RX_POSTINC, @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER, and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER.
+ *   After the transfer is set up, a set of transfers can be triggered by PPI that will read, for example, the same register of an
+ *   external component and put it into a RAM buffer without any interrupts. @ref nrf_drv_twi_stopped_event_get can be used to get the
+ *   address of the STOPPED event, which can be used to count the number of transfers. If @ref NRF_DRV_TWI_FLAG_REPEATED_XFER is used,
+ *   the driver does not set the instance into busy state, so you must ensure that the next transfers are set up
+ *   when TWIM is not active. Supported only by TWIM.
+ * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP<span></span>: No stop condition after TX transfer.
+ *
+ * @note
+ * Some flag combinations are invalid:
+ * - @ref NRF_DRV_TWI_FLAG_TX_NO_STOP with @ref nrf_drv_twi_xfer_desc_t::type different than @ref NRF_DRV_TWI_XFER_TX
+ * - @ref NRF_DRV_TWI_FLAG_REPEATED_XFER with @ref nrf_drv_twi_xfer_desc_t::type set to @ref NRF_DRV_TWI_XFER_TXTX
+ *
+ * If @ref nrf_drv_twi_xfer_desc_t::type is set to @ref NRF_DRV_TWI_XFER_TX and the @ref NRF_DRV_TWI_FLAG_TX_NO_STOP and @ref NRF_DRV_TWI_FLAG_REPEATED_XFER
+ * flags are set, two tasks must be used to trigger a transfer: TASKS_RESUME followed by TASKS_STARTTX. If no stop condition is generated,
+ * TWIM is in SUSPENDED state. Therefore, it must be resumed before the transfer can be started.
+ *
+ * @note
+ * This function should be used only if the instance is configured to work in non-blocking mode. If the function is used in blocking mode, the driver asserts.
+ * @note If you are using this function with TWI, the only supported flag is @ref NRF_DRV_TWI_FLAG_TX_NO_STOP. All other flags require TWIM.
+  *
+ * @param[in] p_instance        TWI instance.
+ * @param[in] p_xfer_desc       Pointer to the transfer descriptor.
+ * @param[in] flags             Transfer options (0 for default settings).
+ *
+ * @retval NRF_SUCCESS             If the procedure was successful.
+ * @retval NRF_ERROR_BUSY          If the driver is not ready for a new transfer.
+ * @retval NRF_ERROR_NOT_SUPPORTED If the provided parameters are not supported.
+ */
+ret_code_t nrf_drv_twi_xfer(nrf_drv_twi_t           const * p_instance,
+                            nrf_drv_twi_xfer_desc_t const * p_xfer_desc,
+                            uint32_t                        flags);
+
+/**
+ * @brief Function for getting the transferred data count.
+ *
+ * This function provides valid results only in legacy mode.
+ *
+ * @param[in] p_instance TWI instance.
+ *
+ * @return     Data count.
+ */
+uint32_t nrf_drv_twi_data_count_get(nrf_drv_twi_t const * const p_instance);
+
+/**
+ * @brief Function for returning the address of a TWI/TWIM start task.
+ *
+ * This function should be used if @ref nrf_drv_twi_xfer was called with the flag @ref NRF_DRV_TWI_FLAG_HOLD_XFER.
+ * In that case, the transfer is not started by the driver, but it must be started externally by PPI.
+ *
+ * @param[in]  p_instance TWI instance.
+ * @param[in]  xfer_type  Transfer type used in the last call of the @ref nrf_drv_twi_xfer function.
+ *
+ * @return     Start task address (TX or RX) depending on the value of xfer_type.
+ */
+uint32_t nrf_drv_twi_start_task_get(nrf_drv_twi_t const * p_instance, nrf_drv_twi_xfer_type_t xfer_type);
+
+/**
+ * @brief Function for returning the address of a STOPPED TWI/TWIM event.
+ *
+ * A STOPPED event can be used to detect the end of a transfer if the @ref NRF_DRV_TWI_FLAG_NO_XFER_EVT_HANDLER
+ * option is used.
+ *
+ * @param[in]  p_instance  TWI instance.
+ *
+ * @return     STOPPED event address.
+ */
+uint32_t nrf_drv_twi_stopped_event_get(nrf_drv_twi_t const * p_instance);
+/**
+ *@}
+ **/
+
+#endif // NRF_DRV_TWI_H__

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f06c2d2b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twis_slave/nrf_drv_twis.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twis_slave/nrf_drv_twis.c b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twis_slave/nrf_drv_twis.c
new file mode 100644
index 0000000..21f98ed
--- /dev/null
+++ b/hw/mcu/nordic/src/ext/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/twis_slave/nrf_drv_twis.c
@@ -0,0 +1,881 @@
+/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+#include "nrf_drv_twis.h"
+#include "nrf_assert.h"
+#include "nordic_common.h"
+#include "app_util_platform.h"
+#include "nrf_gpio.h"
+
+#if TWIS_COUNT == 0
+#error "TWIS driver included but none of TWIS devices is activated in the configuration file"
+#endif
+
+/**
+ * @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[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[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 PERIPHERAL_RESOURCE_SHARING_ENABLED
+    #define IRQ_HANDLER_NAME(n) irq_handler_for_instance_##n
+    #define IRQ_HANDLER(n)      static void IRQ_HANDLER_NAME(n)(void)
+
+    #if TWIS0_ENABLED
+        IRQ_HANDLER(0);
+    #endif
+    #if TWIS1_ENABLED
+        IRQ_HANDLER(1);
+    #endif
+    static nrf_drv_irq_handler_t const m_irq_handlers[TWIS_COUNT] = {
+    #if TWIS0_ENABLED
+        IRQ_HANDLER_NAME(0),
+    #endif
+    #if TWIS1_ENABLED
+        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 // PERIPHERAL_RESOURCE_SHARING_ENABLED
+
+/**
+ * @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[TWIS_COUNT];
+
+/**
+ * @brief Default configuration
+ *
+ * Array with default configurations for each driver instance.
+ */
+static const nrf_drv_twis_config_t m_config_default[TWIS_COUNT] =
+{
+    #define X(n) NRF_DRV_TWIS_DEFAULT_CONFIG(n),
+    #include "nrf_drv_twis_inst.def"
+};
+
+/**
+ * @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_cfg(pin,
+                 NRF_GPIO_PIN_DIR_INPUT,
+                 NRF_GPIO_PIN_INPUT_DISCONNECT,
+                 NRF_GPIO_PIN_NOPULL,
+                 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_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_inst,
+        nrf_drv_twis_config_t   const * p_config,
+        nrf_drv_twis_event_handler_t    const event_handler)
+{
+    uint8_t instNr = p_inst->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;
+
+    if( m_var_inst[instNr].state != NRF_DRV_STATE_UNINITIALIZED)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+#if PERIPHERAL_RESOURCE_SHARING_ENABLED
+    if (nrf_drv_common_per_res_acquire(p_reg, m_irq_handlers[instNr]) !=
+            NRF_SUCCESS)
+    {
+        return NRF_ERROR_BUSY;
+    }
+#endif
+
+    if(NULL == p_config)
+    {
+        p_config = &m_config_default[instNr];
+    }
+
+    if(!TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
+    {
+        nrf_drv_twis_swreset(p_reg);
+    }
+    
+    nrf_drv_twis_config_pin(p_config->scl);
+    nrf_drv_twis_config_pin(p_config->sda);
+
+    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;
+    return NRF_SUCCESS;
+}
+
+
+void nrf_drv_twis_uninit(nrf_drv_twis_t const * const p_inst)
+{
+    uint8_t instNr = p_inst->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 PERIPHERAL_RESOURCE_SHARING_ENABLED
+    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_inst)
+{
+    uint8_t instNr = p_inst->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_inst)
+{
+    uint8_t instNr = p_inst->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 \u2013 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_inst)
+{
+    nrf_drv_twis_var_inst_t * const p_var_inst = &m_var_inst[p_inst->instNr];
+    nrf_drv_twis_preprocess_status(p_inst->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_inst,
+        void const * const p_buf,
+        size_t size)
+{
+    uint8_t instNr = p_inst->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)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+    /* Check data address */
+    if(!nrf_drv_is_in_RAM(p_buf))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+    /* Check data size */
+    if((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size)
+    {
+        return NRF_ERROR_INVALID_LENGTH;
+    }
+
+    nrf_twis_tx_prepare(p_reg, (uint8_t const *)p_buf, (nrf_twis_amount_t)size);
+    return NRF_SUCCESS;
+
+}
+
+
+size_t nrf_drv_twis_tx_amount(nrf_drv_twis_t const * const p_inst)
+{
+    uint8_t instNr = p_inst->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_inst,
+        void * const p_buf,
+        size_t size)
+{
+    uint8_t instNr = p_inst->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)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+    /* Check data address */
+    if(!nrf_drv_is_in_RAM(p_buf))
+    {
+        return NRF_ERROR_INVALID_ADDR;
+    }
+    /* Check data size */
+    if((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size)
+    {
+        return NRF_ERROR_INVALID_LENGTH;
+    }
+
+    nrf_twis_rx_prepare(p_reg, (uint8_t *)p_buf, (nrf_twis_amount_t)size);
+    return NRF_SUCCESS;
+}
+
+
+size_t nrf_drv_twis_rx_amount(nrf_drv_twis_t const * const p_inst)
+{
+    uint8_t instNr = p_inst->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_inst)
+{
+    nrf_drv_twis_preprocess_status(p_inst->instNr);
+    return NRF_DRV_TWIS_SUBSTATE_IDLE != m_var_inst[(p_inst->instNr)].substate;
+}
+
+bool nrf_drv_twis_is_waiting_tx_buff(nrf_drv_twis_t const * const p_inst)
+{
+    nrf_drv_twis_preprocess_status(p_inst->instNr);
+    return NRF_DRV_TWIS_SUBSTATE_READ_WAITING == m_var_inst[(p_inst->instNr)].substate;
+}
+
+bool nrf_drv_twis_is_waiting_rx_buff(nrf_drv_twis_t const * const p_inst)
+{
+    nrf_drv_twis_preprocess_status(p_inst->instNr);
+    return NRF_DRV_TWIS_SUBSTATE_WRITE_WAITING == m_var_inst[(p_inst->instNr)].substate;
+}
+
+bool nrf_drv_twis_is_pending_tx(nrf_drv_twis_t const * const p_inst)
+{
+    nrf_drv_twis_preprocess_status(p_inst->instNr);
+    return NRF_DRV_TWIS_SUBSTATE_READ_PENDING == m_var_inst[(p_inst->instNr)].substate;
+}
+
+bool nrf_drv_twis_is_pending_rx(nrf_drv_twis_t const * const p_inst)
+{
+    nrf_drv_twis_preprocess_status(p_inst->instNr);
+    return NRF_DRV_TWIS_SUBSTATE_WRITE_PENDING == m_var_inst[(p_inst->instNr)].substate;
+}