The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Dependents:   hello SerialTestv11 SerialTestv12 Sierpinski ... more

mbed 2

This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.

Revision:
171:3a7713b1edbc
Parent:
111:4336505e4b1c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TARGET_SAMD21J18A/TOOLCHAIN_ARM_MICRO/i2c_slave.h	Thu Nov 08 11:45:42 2018 +0000
@@ -0,0 +1,749 @@
+/**
+ * \file
+ *
+ * \brief SAM SERCOM I2C Slave Driver
+ *
+ * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef I2C_SLAVE_H_INCLUDED
+#define I2C_SLAVE_H_INCLUDED
+
+#include "i2c_common.h"
+#include <sercom.h>
+#include <pinmux.h>
+
+#if I2C_SLAVE_CALLBACK_MODE == true
+#  include <sercom_interrupt.h>
+#endif
+
+#ifndef PINMUX_DEFAULT
+#  define PINMUX_DEFAULT 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup asfdoc_sam0_sercom_i2c_group
+ *
+ * @{
+ *
+ */
+
+/**
+ * \name I2C Slave Status Flags
+ *
+ * I<SUP>2</SUP>C slave status flags, returned by \ref i2c_slave_get_status() and cleared
+ * by \ref i2c_slave_clear_status().
+ * @{
+ */
+
+/** Address Match.
+ * \note Should only be cleared internally by driver.
+ */
+#define I2C_SLAVE_STATUS_ADDRESS_MATCH     (1UL << 0)
+/** Data Ready. */
+#define I2C_SLAVE_STATUS_DATA_READY        (1UL << 1)
+/** Stop Received. */
+#define I2C_SLAVE_STATUS_STOP_RECEIVED     (1UL << 2)
+/** Clock Hold.
+ * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
+ * set.
+ */
+#define I2C_SLAVE_STATUS_CLOCK_HOLD        (1UL << 3)
+/** SCL Low Timeout. */
+#define I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT   (1UL << 4)
+/** Repeated Start.
+ * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
+ * set.
+ */
+#define I2C_SLAVE_STATUS_REPEATED_START    (1UL << 5)
+/** Received not acknowledge.
+ * \note Cannot be cleared.
+ */
+#define I2C_SLAVE_STATUS_RECEIVED_NACK     (1UL << 6)
+/** Transmit Collision. */
+#define I2C_SLAVE_STATUS_COLLISION         (1UL << 7)
+/** Bus error. */
+#define I2C_SLAVE_STATUS_BUS_ERROR         (1UL << 8)
+
+/** @} */
+
+/**
+ * \brief I<SUP>2</SUP>C slave packet for read/write
+ *
+ * Structure to be used when transferring I<SUP>2</SUP>C slave packets.
+ */
+struct i2c_slave_packet {
+    /** Length of data array. */
+    uint16_t data_length;
+    /** Data array containing all data to be transferred. */
+    uint8_t *data;
+};
+
+#if I2C_SLAVE_CALLBACK_MODE == true
+/**
+* \brief Callback types
+*
+* The available callback types for the I<SUP>2</SUP>C slave.
+*/
+enum i2c_slave_callback {
+    /** Callback for packet write complete. */
+    I2C_SLAVE_CALLBACK_WRITE_COMPLETE,
+    /** Callback for packet read complete. */
+    I2C_SLAVE_CALLBACK_READ_COMPLETE,
+    /**
+     * Callback for read request from master - can be used to
+     * issue a write.
+     */
+    I2C_SLAVE_CALLBACK_READ_REQUEST,
+    /**
+     * Callback for write request from master - can be used to issue a read.
+     */
+    I2C_SLAVE_CALLBACK_WRITE_REQUEST,
+    /** Callback for error. */
+    I2C_SLAVE_CALLBACK_ERROR,
+    /**
+     * Callback for error in last transfer. Discovered on a new address
+     * interrupt.
+     */
+    I2C_SLAVE_CALLBACK_ERROR_LAST_TRANSFER,
+#  if !defined(__DOXYGEN__)
+    /** Total number of callbacks. */
+    _I2C_SLAVE_CALLBACK_N,
+#  endif
+};
+
+#  if !defined(__DOXYGEN__)
+/** Software module prototype. */
+struct i2c_slave_module;
+
+/** Callback type. */
+typedef void (*i2c_slave_callback_t)(
+    struct i2c_slave_module *const module);
+#  endif
+#endif
+
+/**
+ * \brief Enum for the possible SDA hold times with respect to the negative
+ * edge of SCL
+ *
+ * Enum for the possible SDA hold times with respect to the negative edge
+ * of SCL.
+ */
+enum i2c_slave_sda_hold_time {
+    /** SDA hold time disabled. */
+    I2C_SLAVE_SDA_HOLD_TIME_DISABLED =
+        ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((0) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
+    /** SDA hold time 50ns - 100ns. */
+    I2C_SLAVE_SDA_HOLD_TIME_50NS_100NS =
+        ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((1) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
+    /** SDA hold time 300ns - 600ns. */
+    I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS =
+        ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((2) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
+    /** SDA hold time 400ns - 800ns. */
+    I2C_SLAVE_SDA_HOLD_TIME_400NS_800NS =
+        ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((3) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
+};
+
+/**
+ * \brief Enum for the possible address modes
+ *
+ * Enum for the possible address modes.
+ */
+enum i2c_slave_address_mode {
+    /** Address match on address_mask used as a mask to address. */
+    I2C_SLAVE_ADDRESS_MODE_MASK = SERCOM_I2CS_CTRLB_AMODE(0),
+    /** Address math on both address and address_mask. */
+    I2C_SLAVE_ADDRESS_MODE_TWO_ADDRESSES = SERCOM_I2CS_CTRLB_AMODE(1),
+    /**
+     * Address match on range of addresses between and including address and
+     * address_mask.
+     */
+    I2C_SLAVE_ADDRESS_MODE_RANGE = SERCOM_I2CS_CTRLB_AMODE(2),
+};
+
+/**
+ * \brief Enum for the direction of a request
+ *
+ * Enum for the direction of a request.
+ */
+enum i2c_slave_direction {
+    /** Read. */
+    I2C_SLAVE_DIRECTION_READ,
+    /** Write. */
+    I2C_SLAVE_DIRECTION_WRITE,
+    /** No direction. */
+    I2C_SLAVE_DIRECTION_NONE,
+};
+
+#ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
+/**
+ * \brief Enum for the transfer speed
+ *
+ * Enum for the transfer speed.
+ */
+enum i2c_slave_transfer_speed {
+    /** Standard-mode (Sm) up to 100KHz and Fast-mode (Fm) up to 400KHz. */
+    I2C_SLAVE_SPEED_STANDARD_AND_FAST = SERCOM_I2CS_CTRLA_SPEED(0),
+    /** Fast-mode Plus (Fm+) up to 1MHz. */
+    I2C_SLAVE_SPEED_FAST_MODE_PLUS = SERCOM_I2CS_CTRLA_SPEED(1),
+    /** High-speed mode (Hs-mode) up to 3.4MHz. */
+    I2C_SLAVE_SPEED_HIGH_SPEED = SERCOM_I2CS_CTRLA_SPEED(2),
+};
+#endif
+
+/**
+ * \brief SERCOM I<SUP>2</SUP>C Slave driver software device instance structure.
+ *
+ * SERCOM I<SUP>2</SUP>C Slave driver software instance structure, used to
+ * retain software state information of an associated hardware module instance.
+ *
+ * \note The fields of this structure should not be altered by the user
+ *       application; they are reserved for module-internal use only.
+ */
+struct i2c_slave_module {
+#if !defined(__DOXYGEN__)
+    /** Hardware instance initialized for the struct. */
+    Sercom *hw;
+    /** Module lock. */
+    volatile bool locked;
+    /** Timeout value for polled functions. */
+    uint16_t buffer_timeout;
+#  ifdef FEATURE_I2C_10_BIT_ADDRESS
+    /** Using 10-bit addressing for the slave. */
+    bool ten_bit_address;
+#  endif
+#  if I2C_SLAVE_CALLBACK_MODE == true
+    /** Nack on address match. */
+    bool nack_on_address;
+    /** Pointers to callback functions. */
+    volatile i2c_slave_callback_t callbacks[_I2C_SLAVE_CALLBACK_N];
+    /** Mask for registered callbacks. */
+    volatile uint8_t registered_callback;
+    /** Mask for enabled callbacks. */
+    volatile uint8_t enabled_callback;
+    /** The total number of bytes to transfer. */
+    volatile uint16_t buffer_length;
+    /**
+     * Counter used for bytes left to send in write and to count number of
+     * obtained bytes in read.
+     */
+    uint16_t buffer_remaining;
+    /** Data buffer for packet write and read. */
+    volatile uint8_t *buffer;
+    /** Save direction of request from master. 1 = read, 0 = write. */
+    volatile enum i2c_transfer_direction transfer_direction;
+    /** Status for status read back in error callback. */
+    volatile enum status_code status;
+#  endif
+#endif
+};
+
+/**
+ * \brief Configuration structure for the I<SUP>2</SUP>C Slave device
+ *
+ * This is the configuration structure for the I<SUP>2</SUP>C Slave device. It is used
+ * as an argument for \ref i2c_slave_init to provide the desired
+ * configurations for the module. The structure should be initialized using the
+ * \ref i2c_slave_get_config_defaults.
+ */
+struct i2c_slave_config {
+    /** Set to enable the SCL low timeout. */
+    bool enable_scl_low_timeout;
+    /** SDA hold time with respect to the negative edge of SCL. */
+    enum i2c_slave_sda_hold_time sda_hold_time;
+    /** Timeout to wait for master in polled functions. */
+    uint16_t buffer_timeout;
+    /** Addressing mode. */
+    enum i2c_slave_address_mode address_mode;
+    /** Address or upper limit of address range. */
+    uint16_t address;
+    /** Address mask, second address or lower limit of address range. */
+    uint16_t address_mask;
+#ifdef FEATURE_I2C_10_BIT_ADDRESS
+    /** Enable 10-bit addressing. */
+    bool ten_bit_address;
+#endif
+    /**
+     * Enable general call address recognition (general call address
+     * is defined as 0000000 with direction bit 0).
+     */
+    bool enable_general_call_address;
+
+#ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
+    /** Transfer speed mode. */
+    enum i2c_slave_transfer_speed transfer_speed;
+#endif
+
+#if I2C_SLAVE_CALLBACK_MODE == true
+    /**
+     * Enable NACK on address match (this can be changed after initialization
+     * via the \ref i2c_slave_enable_nack_on_address and
+     * \ref i2c_slave_disable_nack_on_address functions).
+     */
+    bool enable_nack_on_address;
+#endif
+    /** GCLK generator to use as clock source. */
+    enum gclk_generator generator_source;
+    /** Set to keep module active in sleep modes. */
+    bool run_in_standby;
+    /** PAD0 (SDA) pinmux. */
+    uint32_t pinmux_pad0;
+    /** PAD1 (SCL) pinmux. */
+    uint32_t pinmux_pad1;
+    /** Set to enable SCL low time-out. */
+    bool scl_low_timeout;
+#ifdef FEATURE_I2C_SCL_STRETCH_MODE
+    /** Set to enable SCL stretch only after ACK bit (required for high speed). */
+    bool scl_stretch_only_after_ack_bit;
+#endif
+#ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
+    /** Set to enable slave SCL low extend time-out. */
+    bool slave_scl_low_extend_timeout;
+#endif
+};
+
+
+/**
+ * \name Lock/Unlock
+ * @{
+ */
+
+/**
+ * \brief Attempt to get lock on driver instance
+ *
+ * This function checks the instance's lock, which indicates whether or not it
+ * is currently in use, and sets the lock if it was not already set.
+ *
+ * The purpose of this is to enable exclusive access to driver instances, so
+ * that, e.g., transactions by different services will not interfere with each
+ * other.
+ *
+ * \param[in,out] module Pointer to the driver instance to lock
+ *
+ * \retval STATUS_OK If the module was locked
+ * \retval STATUS_BUSY If the module was already locked
+ */
+static inline enum status_code i2c_slave_lock(
+    struct i2c_slave_module *const module)
+{
+    enum status_code status;
+
+    system_interrupt_enter_critical_section();
+
+    if (module->locked) {
+        status = STATUS_BUSY;
+    } else {
+        module->locked = true;
+        status = STATUS_OK;
+    }
+
+    system_interrupt_leave_critical_section();
+
+    return status;
+}
+
+/**
+ * \brief Unlock driver instance
+ *
+ * This function clears the instance lock, indicating that it is available for
+ * use.
+ *
+ * \param[in,out] module Pointer to the driver instance to lock
+ *
+ * \retval STATUS_OK If the module was locked
+ * \retval STATUS_BUSY If the module was already locked
+ */
+static inline void i2c_slave_unlock(struct i2c_slave_module *const module)
+{
+    module->locked = false;
+}
+
+/** @} */
+
+/**
+ * \name Configuration and Initialization
+ * @{
+ */
+
+/**
+ * \brief Returns the synchronization status of the module
+ *
+ * Returns the synchronization status of the module.
+ *
+ * \param[out] module  Pointer to software module structure
+ *
+ * \return Status of the synchronization.
+ * \retval true   Module is busy synchronizing
+ * \retval false  Module is not synchronizing
+ */
+static inline bool i2c_slave_is_syncing(
+    const struct i2c_slave_module *const module)
+{
+    /* Sanity check */
+    Assert(module);
+    Assert(module->hw);
+
+    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
+
+    /* Return sync status */
+#if defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_1)
+    return (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_SYNCBUSY);
+#elif defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_2)
+    return (i2c_hw->SYNCBUSY.reg & SERCOM_I2CS_SYNCBUSY_MASK);
+#else
+#  error Unknown SERCOM SYNCBUSY scheme!
+#endif
+}
+
+#if !defined(__DOXYGEN__)
+/**
+ * \internal Wait for hardware module to sync
+ *
+ * \param[in]  module  Pointer to software module structure
+ */
+static void _i2c_slave_wait_for_sync(
+    const struct i2c_slave_module *const module)
+{
+    /* Sanity check. */
+    Assert(module);
+
+    while (i2c_slave_is_syncing(module)) {
+        /* Wait for I2C module to sync */
+    }
+}
+#endif
+
+///@cond INTERNAL
+/**
+ * \internal Workaround for errata 13574
+ * Instead set ACK/NACK of CTRLB
+ *
+ * This errata exist in part revisions of SAMD20/D21
+ * D10/D11/L21/DAx/C20/C21, but workaround can be works in all
+ * revision of those device. As this function operation
+ * should be use less cpu time as possible, so caller
+ * function can ignore to check revision number, and use
+ * this workaround in all revision of those device.
+ *
+ * \param[in,out] module  Pointer to software module structure
+ * \param[in] send_ack true send ACK, false send NACK
+ */
+static inline void _i2c_slave_set_ctrlb_ackact(
+    struct i2c_slave_module *const module,
+    bool send_ack)
+{
+    Assert(module);
+    Assert(module->hw);
+
+    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
+
+#if (SAMD20 || SAMD21 || SAMD10 || SAMD11 || SAML21 || SAMDA1 || SAMC20 || SAMC21)
+    /* Workaround, Following two write are atomic */
+    system_interrupt_enter_critical_section();
+    i2c_hw->STATUS.reg = 0;
+
+    if (send_ack == true) {
+        i2c_hw->CTRLB.reg = 0;
+    } else {
+        i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_ACKACT;
+    }
+    system_interrupt_leave_critical_section();
+#else
+    /* Normal operation */
+    if (send_ack == true) {
+        i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
+    } else {
+        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
+    }
+#endif
+    return;
+}
+
+/**
+ * \internal Workaround for SAM0 errata 13574,
+ * instead Set CMD3 of CTRLB
+ *
+ * This errata exist in part revisions of SAMD20/D21
+ * D10/D11/L21/DAx/C20/C21, but workaround can be works in all
+ * revision of those device. As this function operation
+ * should be use less cpu time as possible, so caller
+ * function can ignore to check revision number, and use
+ * this workaround in all revision of those device.
+ *
+ * \param[in,out] module  Pointer to software module structure
+ */
+static inline void _i2c_slave_set_ctrlb_cmd3(
+    struct i2c_slave_module *const module)
+{
+    Assert(module);
+    Assert(module->hw);
+
+    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
+
+#if (SAMD20 || SAMD21 || SAMD10 || SAMD11 || SAML21 || SAMDA1 || SAMC20 || SAMC21)
+    /* Workaround */
+    /*
+     * Below code instead i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
+     * CMD=0x3 clears all interrupts, so to keep the result similar
+     * PREC is cleared if it was set
+     */
+    if (i2c_hw->INTFLAG.bit.PREC) {
+        i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
+    }
+    i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
+#else
+    /* Normal operation */
+    i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
+#endif
+    return;
+}
+///@endcond
+
+/**
+ * \brief Gets the I<SUP>2</SUP>C slave default configurations
+ *
+ * This will initialize the configuration structure to known default values.
+ *
+ * The default configuration is as follows:
+ * - Disable SCL low timeout
+ * - 300ns - 600ns SDA hold time
+ * - Buffer timeout = 65535
+ * - Address with mask
+ * - Address = 0
+ * - Address mask = 0 (one single address)
+ * - General call address disabled
+ * - Address nack disabled if the interrupt driver is used
+ * - GCLK generator 0
+ * - Do not run in standby
+ * - PINMUX_DEFAULT for SERCOM pads
+ *
+ * Those default configuration only available if the device supports it:
+ * - Not using 10-bit addressing
+ * - Standard-mode and Fast-mode transfer speed
+ * - SCL stretch disabled
+ * - slave SCL low extend time-out disabled
+ *
+ * \param[out] config  Pointer to configuration structure to be initialized
+ */
+static inline void i2c_slave_get_config_defaults(
+    struct i2c_slave_config *const config)
+{
+    /*Sanity check argument. */
+    Assert(config);
+    config->enable_scl_low_timeout = false;
+    config->sda_hold_time = I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS;
+    config->buffer_timeout = 65535;
+    config->address_mode = I2C_SLAVE_ADDRESS_MODE_MASK;
+    config->address = 0;
+    config->address_mask = 0;
+#ifdef FEATURE_I2C_10_BIT_ADDRESS
+    config->ten_bit_address = false;
+#endif
+    config->enable_general_call_address = false;
+#ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
+    config->transfer_speed = I2C_SLAVE_SPEED_STANDARD_AND_FAST;
+#endif
+#if I2C_SLAVE_CALLBACK_MODE == true
+    config->enable_nack_on_address = false;
+#endif
+    config->generator_source = GCLK_GENERATOR_0;
+    config->run_in_standby = false;
+    config->pinmux_pad0 = PINMUX_DEFAULT;
+    config->pinmux_pad1 = PINMUX_DEFAULT;
+    config->scl_low_timeout  = false;
+#ifdef FEATURE_I2C_SCL_STRETCH_MODE
+    config->scl_stretch_only_after_ack_bit = false;
+#endif
+#ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
+    config->slave_scl_low_extend_timeout   = false;
+#endif
+}
+
+enum status_code i2c_slave_init(struct i2c_slave_module *const module,
+                                Sercom *const hw,
+                                const struct i2c_slave_config *const config);
+
+/**
+ * \brief Enables the I<SUP>2</SUP>C module
+ *
+ * This will enable the requested I<SUP>2</SUP>C module.
+ *
+ * \param[in]  module Pointer to the software module struct
+ */
+static inline void i2c_slave_enable(
+    const struct i2c_slave_module *const module)
+{
+    /* Sanity check of arguments. */
+    Assert(module);
+    Assert(module->hw);
+
+    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
+
+#if I2C_SLAVE_CALLBACK_MODE == true
+    /* Enable global interrupt for module */
+    system_interrupt_enable(_sercom_get_interrupt_vector(module->hw));
+#endif
+
+    /* Wait for module to sync */
+    _i2c_slave_wait_for_sync(module);
+
+    /* Enable module */
+    i2c_hw->CTRLA.reg |= SERCOM_I2CS_CTRLA_ENABLE;
+}
+
+
+/**
+ * \brief Disables the I<SUP>2</SUP>C module
+ *
+ * This will disable the I<SUP>2</SUP>C module specified in the provided software module
+ * structure.
+ *
+ * \param[in]  module  Pointer to the software module struct
+ */
+static inline void i2c_slave_disable(
+    const struct i2c_slave_module *const module)
+{
+    /* Sanity check of arguments. */
+    Assert(module);
+    Assert(module->hw);
+
+    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
+
+#if I2C_SLAVE_CALLBACK_MODE == true
+    /* Disable interrupts */
+    i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTENSET_PREC |
+                           SERCOM_I2CS_INTENSET_AMATCH | SERCOM_I2CS_INTENSET_DRDY;
+
+    /* Clear interrupt flags */
+    i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC | SERCOM_I2CS_INTFLAG_AMATCH |
+                          SERCOM_I2CS_INTFLAG_DRDY;
+
+    /* Disable global interrupt for module */
+    system_interrupt_disable(_sercom_get_interrupt_vector(module->hw));
+#endif
+
+    /* Wait for module to sync */
+    _i2c_slave_wait_for_sync(module);
+
+    /* Disable module */
+    i2c_hw->CTRLA.reg &= ~SERCOM_I2CS_CTRLA_ENABLE;
+}
+
+void i2c_slave_reset(
+    struct i2c_slave_module *const module);
+
+/** @} */
+
+/**
+ * \name Read and Write
+ * @{
+ */
+
+enum status_code i2c_slave_write_packet_wait(
+    struct i2c_slave_module *const module,
+    struct i2c_slave_packet *const packet);
+enum status_code i2c_slave_read_packet_wait(
+    struct i2c_slave_module *const module,
+    struct i2c_slave_packet *const packet);
+enum i2c_slave_direction i2c_slave_get_direction_wait(
+    struct i2c_slave_module *const module);
+
+/** @} */
+
+/**
+ * \name Status Management
+ * @{
+ */
+uint32_t i2c_slave_get_status(
+    struct i2c_slave_module *const module);
+void i2c_slave_clear_status(
+    struct i2c_slave_module *const module,
+    uint32_t status_flags);
+/** @} */
+
+#ifdef FEATURE_I2C_DMA_SUPPORT
+/**
+ * \name SERCOM I2C Slave with DMA Interfaces
+ * @{
+ */
+
+/**
+ * \brief Read SERCOM I<SUP>2</SUP>C interrupt status.
+ *
+ * Read I<SUP>2</SUP>C interrupt status for DMA transfer.
+ *
+ * \param[in,out] module Pointer to the driver instance to lock
+ *
+ */
+static inline uint8_t i2c_slave_dma_read_interrupt_status(struct i2c_slave_module *const module)
+{
+    return (uint8_t)module->hw->I2CS.INTFLAG.reg;
+}
+
+/**
+ * \brief Write SERCOM I<SUP>2</SUP>C interrupt status.
+ *
+ * Write I<SUP>2</SUP>C interrupt status for DMA transfer.
+ *
+ * \param[in,out] module Pointer to the driver instance to lock
+ * \param[in] flag Interrupt flag status
+ *
+ */
+static inline void i2c_slave_dma_write_interrupt_status(struct i2c_slave_module *const module,
+        uint8_t flag)
+{
+    module->hw->I2CS.INTFLAG.reg = flag;
+}
+
+/** @} */
+#endif
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* I2C_SLAVE_H_INCLUDED */