mbed library sources

Fork of mbed-src by mbed official

Revision:
613:bc40b8d2aec4
Parent:
612:fba1c7dc54c0
Child:
614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/sercom/i2c/i2c_samd21_r21_d10_d11_l21/i2c_slave.c	Tue Aug 18 15:00:09 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,674 +0,0 @@
-#include "i2c_slave.h"
-#if I2C_SLAVE_CALLBACK_MODE == true
-#  include "i2c_slave_interrupt.h"
-#endif
-
-/**
- * \internal Sets configuration to module
- *
- * \param[out] module  Pointer to software module structure
- * \param[in]  config  Configuration structure with configurations to set
- *
- * \return Status of setting configuration.
- * \retval STATUS_OK                       Module was configured correctly
- * \retval STATUS_ERR_ALREADY_INITIALIZED  If setting other GCLK generator than
- *                                         previously set
- */
-static enum status_code _i2c_slave_set_config(
-    struct i2c_slave_module *const module,
-    const struct i2c_slave_config *const config)
-{
-    uint32_t tmp_ctrla;
-
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-    Assert(config);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-    Sercom *const sercom_hw = module->hw;
-
-    module->buffer_timeout = config->buffer_timeout;
-    module->ten_bit_address = config->ten_bit_address;
-
-    struct system_pinmux_config pin_conf;
-    system_pinmux_get_config_defaults(&pin_conf);
-
-    uint32_t pad0 = config->pinmux_pad0;
-    uint32_t pad1 = config->pinmux_pad1;
-
-    /* SERCOM PAD0 - SDA */
-    if (pad0 == PINMUX_DEFAULT) {
-        pad0 = _sercom_get_default_pad(sercom_hw, 0);
-    }
-    pin_conf.mux_position = pad0 & 0xFFFF;
-    pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
-    system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);
-
-    /* SERCOM PAD1 - SCL */
-    if (pad1 == PINMUX_DEFAULT) {
-        pad1 = _sercom_get_default_pad(sercom_hw, 1);
-    }
-    pin_conf.mux_position = pad1 & 0xFFFF;
-    pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
-    system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);
-
-    /* Prepare config to write to register CTRLA */
-    if (config->run_in_standby || system_is_debugger_present()) {
-        tmp_ctrla = SERCOM_I2CS_CTRLA_RUNSTDBY;
-    } else {
-        tmp_ctrla = 0;
-    }
-
-    tmp_ctrla |= ((uint32_t)config->sda_hold_time |
-                  config->transfer_speed |
-                  (config->scl_low_timeout << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos) |
-                  (config->scl_stretch_only_after_ack_bit << SERCOM_I2CS_CTRLA_SCLSM_Pos) |
-                  (config->slave_scl_low_extend_timeout << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos));
-
-    i2c_hw->CTRLA.reg |= tmp_ctrla;
-
-    /* Set CTRLB configuration */
-    i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN | config->address_mode;
-
-    i2c_hw->ADDR.reg = config->address << SERCOM_I2CS_ADDR_ADDR_Pos |
-                       config->address_mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos |
-                       config->ten_bit_address << SERCOM_I2CS_ADDR_TENBITEN_Pos |
-                       config->enable_general_call_address << SERCOM_I2CS_ADDR_GENCEN_Pos;
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Initializes the requested I<SUP>2</SUP>C hardware module
- *
- * Initializes the SERCOM I<SUP>2</SUP>C Slave device requested and sets the provided
- * software module struct.  Run this function before any further use of
- * the driver.
- *
- * \param[out] module  Pointer to software module struct
- * \param[in]  hw      Pointer to the hardware instance
- * \param[in]  config  Pointer to the configuration struct
- *
- * \return Status of initialization.
- * \retval STATUS_OK                       Module initiated correctly
- * \retval STATUS_ERR_DENIED               If module is enabled
- * \retval STATUS_BUSY                     If module is busy resetting
- * \retval STATUS_ERR_ALREADY_INITIALIZED  If setting other GCLK generator than
- *                                         previously set
- */
-enum status_code i2c_slave_init(
-    struct i2c_slave_module *const module,
-    Sercom *const hw,
-    const struct i2c_slave_config *const config)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(hw);
-    Assert(config);
-
-    /* Initialize software module */
-    module->hw = hw;
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    /* Check if module is enabled. */
-    if (i2c_hw->CTRLA.reg & SERCOM_I2CS_CTRLA_ENABLE) {
-        return STATUS_ERR_DENIED;
-    }
-
-    /* Check if reset is in progress. */
-    if (i2c_hw->CTRLA.reg & SERCOM_I2CS_CTRLA_SWRST) {
-        return STATUS_BUSY;
-    }
-
-    uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
-#if (SAML21)
-    uint32_t pm_index     = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
-#else
-    uint32_t pm_index     = sercom_index + PM_APBCMASK_SERCOM0_Pos;
-#endif
-    uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
-
-    /* Turn on module in PM */
-    system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
-
-    /* Set up the GCLK for the module */
-    struct system_gclk_chan_config gclk_chan_conf;
-    system_gclk_chan_get_config_defaults(&gclk_chan_conf);
-    gclk_chan_conf.source_generator = config->generator_source;
-    system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
-    system_gclk_chan_enable(gclk_index);
-    sercom_set_gclk_generator(config->generator_source, false);
-
-#if I2C_SLAVE_CALLBACK_MODE == true
-    /* Get sercom instance index. */
-    uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
-
-    /* Save software module in interrupt handler. */
-    _sercom_set_handler(instance_index, _i2c_slave_interrupt_handler);
-
-    /* Save software module. */
-    _sercom_instances[instance_index] = module;
-
-    /* Initialize values in module. */
-    module->registered_callback = 0;
-    module->enabled_callback = 0;
-    module->buffer_length = 0;
-    module->nack_on_address = config->enable_nack_on_address;
-#endif
-
-    /* Set SERCOM module to operate in I2C slave mode. */
-    i2c_hw->CTRLA.reg = SERCOM_I2CS_CTRLA_MODE(0x4);
-
-    /* Set config and return status. */
-    return _i2c_slave_set_config(module, config);
-}
-
-/**
- * \brief Resets the hardware module
- *
- * This will reset the module to hardware defaults.
- *
- * \param[in,out] module  Pointer to software module structure
- */
-void i2c_slave_reset(
-    struct i2c_slave_module *const module)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-#if I2C_SLAVE_CALLBACK_MODE == true
-    /* Reset module instance. */
-    module->registered_callback = 0;
-    module->enabled_callback = 0;
-    module->buffer_length = 0;
-    module->buffer_remaining = 0;
-    module->buffer = NULL;
-#endif
-
-    /* Disable module */
-    i2c_slave_disable(module);
-
-#if I2C_SLAVE_CALLBACK_MODE == true
-    /* Clear all pending interrupts. */
-    system_interrupt_enter_critical_section();
-    system_interrupt_clear_pending(_sercom_get_interrupt_vector(module->hw));
-    system_interrupt_leave_critical_section();
-#endif
-
-    /* Wait for sync. */
-    _i2c_slave_wait_for_sync(module);
-
-    /* Reset module. */
-    i2c_hw->CTRLA.reg = SERCOM_I2CS_CTRLA_SWRST;
-}
-
-/**
- * \internal Waits for answer on bus
- *
- * \param[in]  module  Pointer to software module structure
- *
- * \return Status of bus.
- * \retval STATUS_OK           If given response from slave device
- * \retval STATUS_ERR_TIMEOUT  If no response was given within specified timeout
- *                             period
- */
-static enum status_code _i2c_slave_wait_for_bus(
-    struct i2c_slave_module *const module)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-
-    SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
-    /* Wait for reply. */
-    uint16_t timeout_counter = 0;
-    while ((!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY)) &&
-            (!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC)) &&
-            (!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH))) {
-
-        /* Check timeout condition. */
-        if (++timeout_counter >= module->buffer_timeout) {
-            return STATUS_ERR_TIMEOUT;
-        }
-    }
-    return STATUS_OK;
-}
-
-/**
- * \brief Writes a packet to the master
- *
- * Writes a packet to the master. This will wait for the master to issue
- * a request.
- *
- * \param[in]  module  Pointer to software module structure
- * \param[in]  packet  Packet to write to master
- *
- * \return Status of packet write.
- * \retval STATUS_OK                Packet was written successfully
- * \retval STATUS_ERR_DENIED        Start condition not received, another
- *                                  interrupt flag is set
- * \retval STATUS_ERR_IO            There was an error in the previous transfer
- * \retval STATUS_ERR_BAD_FORMAT    Master wants to write data
- * \retval STATUS_ERR_INVALID_ARG   Invalid argument(s) was provided
- * \retval STATUS_ERR_BUSY          The I<SUP>2</SUP>C module is busy with a job
- * \retval STATUS_ERR_ERR_OVERFLOW  Master NACKed before entire packet was
- *                                  transferred
- * \retval STATUS_ERR_TIMEOUT       No response was given within the timeout
- *                                  period
- */
-enum status_code i2c_slave_write_packet_wait(
-    struct i2c_slave_module *const module,
-    struct i2c_slave_packet *const packet)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-    Assert(packet);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    uint16_t length = packet->data_length;
-
-    if (length == 0) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-#if I2C_SLAVE_CALLBACK_MODE == true
-    /* Check if the module is busy with a job or AMATCH is enabled */
-    if (module->buffer_remaining > 0 ||
-            (i2c_hw->INTENSET.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-        return STATUS_BUSY;
-    }
-#endif
-
-    enum status_code status;
-    /* Wait for master to send address packet */
-    status = _i2c_slave_wait_for_bus(module);
-
-    if (status != STATUS_OK) {
-        /* Timeout, return */
-        return status;
-    }
-    if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-        /* Not address interrupt, something is wrong */
-        return STATUS_ERR_DENIED;
-    }
-
-    if (module->ten_bit_address) {
-        /* ACK the first address */
-        i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
-
-        /* Wait for address interrupt */
-        status = _i2c_slave_wait_for_bus(module);
-
-        if (status != STATUS_OK) {
-            /* Timeout, return */
-            return STATUS_ERR_TIMEOUT;
-        }
-
-        if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-            /* Not address interrupt, something is wrong */
-            return STATUS_ERR_DENIED;
-        }
-    }
-
-    /* Check if there was an error in last transfer */
-    if (i2c_hw->STATUS.reg & (SERCOM_I2CS_STATUS_BUSERR |
-                              SERCOM_I2CS_STATUS_COLL | SERCOM_I2CS_STATUS_LOWTOUT)) {
-        return STATUS_ERR_IO;
-    }
-
-    /* Check direction */
-    if (!(i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
-        /* Write request from master, send NACK and return */
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
-        return STATUS_ERR_BAD_FORMAT;
-    }
-
-    /* Read request from master, ACK address */
-    i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
-    i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
-
-    uint16_t i = 0;
-
-    /* Wait for data interrupt */
-    status = _i2c_slave_wait_for_bus(module);
-    if (status != STATUS_OK) {
-        /* Timeout, return */
-        return status;
-    }
-
-    while (length--) {
-        /* Write data */
-        _i2c_slave_wait_for_sync(module);
-        i2c_hw->DATA.reg = packet->data[i++];
-
-        /* Wait for response from master */
-        status = _i2c_slave_wait_for_bus(module);
-
-        if (status != STATUS_OK) {
-            /* Timeout, return */
-            return status;
-        }
-
-        if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_RXNACK &&
-                length !=0) {
-            /* NACK from master, abort */
-            /* Release line */
-            i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02);
-
-            return STATUS_ERR_OVERFLOW;
-        }
-        /* ACK from master, continue writing */
-    }
-
-    /* Release line */
-    i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02);
-
-    return STATUS_OK;
-}
-
-/**
- * \brief Reads a packet from the master
- *
- * Reads a packet from the master. This will wait for the master to issue a
- * request.
- *
- * \param[in]  module  Pointer to software module structure
- * \param[out] packet  Packet to read from master
- *
- * \return Status of packet read.
- * \retval STATUS_OK                Packet was read successfully
- * \retval STATUS_ABORTED           Master sent stop condition or repeated
- *                                  start before specified length of bytes
- *                                  was received
- * \retval STATUS_ERR_IO            There was an error in the previous transfer
- * \retval STATUS_ERR_DENIED        Start condition not received, another
- *                                  interrupt flag is set
- * \retval STATUS_ERR_INVALID_ARG   Invalid argument(s) was provided
- * \retval STATUS_ERR_BUSY          The I<SUP>2</SUP>C module is busy with a job
- * \retval STATUS_ERR_BAD_FORMAT    Master wants to read data
- * \retval STATUS_ERR_ERR_OVERFLOW  Last byte received overflows buffer
- */
-enum status_code i2c_slave_read_packet_wait(
-    struct i2c_slave_module *const module,
-    struct i2c_slave_packet *const packet)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-    Assert(packet);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    uint16_t length = packet->data_length;
-
-    if (length == 0) {
-        return STATUS_ERR_INVALID_ARG;
-    }
-
-#if I2C_SLAVE_CALLBACK_MODE == true
-    /* Check if the module is busy with a job or AMATCH is enabled */
-    if (module->buffer_remaining > 0 ||
-            (i2c_hw->INTENSET.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-        return STATUS_BUSY;
-    }
-#endif
-
-    enum status_code status;
-
-    /* Wait for master to send address packet */
-    status = _i2c_slave_wait_for_bus(module);
-    if (status != STATUS_OK) {
-        /* Timeout, return */
-        return status;
-    }
-
-    if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-        /* Not address interrupt, something is wrong */
-        return STATUS_ERR_DENIED;
-    }
-
-    /* Check if there was an error in the last transfer */
-    if (i2c_hw->STATUS.reg & (SERCOM_I2CS_STATUS_BUSERR |
-                              SERCOM_I2CS_STATUS_COLL | SERCOM_I2CS_STATUS_LOWTOUT)) {
-        return STATUS_ERR_IO;
-    }
-    /* Check direction */
-    if ((i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
-        /* Read request from master, send NACK and return */
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
-        return STATUS_ERR_BAD_FORMAT;
-    }
-
-    /* Write request from master, ACK address */
-    i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
-    i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
-
-    uint16_t i = 0;
-    while (length--) {
-
-        /* Wait for next byte or stop condition */
-        status = _i2c_slave_wait_for_bus(module);
-        if (status != STATUS_OK) {
-            /* Timeout, return */
-            return status;
-        }
-
-        if ((i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) ||
-                i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
-            /* Master sent stop condition, or repeated start, read done */
-            /* Clear stop flag */
-            i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
-            return STATUS_ABORTED;
-        }
-
-        /* Read data */
-        _i2c_slave_wait_for_sync(module);
-        packet->data[i++] = i2c_hw->DATA.reg;
-
-    }
-
-    /* Packet read done, wait for packet to NACK, Stop or repeated start */
-    status = _i2c_slave_wait_for_bus(module);
-
-    if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY) {
-        /* Buffer is full, send NACK */
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
-        i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2);
-    }
-    if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) {
-        /* Clear stop flag */
-        i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
-    }
-    return STATUS_OK;
-}
-
-/**
- * \brief Waits for a start condition on the bus
- *
- * \note This function is only available for 7-bit slave addressing.
- *
- * Waits for the master to issue a start condition on the bus.
- * Note that this function does not check for errors in the last transfer,
- * this will be discovered when reading or writing.
- *
- * \param[in]  module  Pointer to software module structure
- *
- * \return Direction of the current transfer, when in slave mode.
- * \retval I2C_SLAVE_DIRECTION_NONE   No request from master within timeout
- *                                    period
- * \retval I2C_SLAVE_DIRECTION_READ   Write request from master
- * \retval I2C_SLAVE_DIRECTION_WRITE  Read request from master
- */
-enum i2c_slave_direction i2c_slave_get_direction_wait(
-    struct i2c_slave_module *const module)
-{
-    /* Sanity check arguments. */
-    Assert(module);
-    Assert(module->hw);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    enum status_code status;
-
-    /* Wait for address interrupt */
-    status = _i2c_slave_wait_for_bus(module);
-
-    if (status != STATUS_OK) {
-        /* Timeout, return */
-        return I2C_SLAVE_DIRECTION_NONE;
-    }
-
-    if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
-        /* Not address interrupt, something is wrong */
-        return I2C_SLAVE_DIRECTION_NONE;
-    }
-
-    /* Check direction */
-    if ((i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
-        /* Read request from master */
-        return I2C_SLAVE_DIRECTION_WRITE;
-    } else {
-        /* Write request from master */
-        return I2C_SLAVE_DIRECTION_READ;
-    }
-}
-
-/**
- * \brief Retrieves the current module status
- *
- * Checks the status of the module and returns it as a bitmask of status
- * flags.
- *
- * \param[in] module      Pointer to the I<SUP>2</SUP>C slave software device struct
- *
- * \return Bitmask of status flags.
- *
- * \retval I2C_SLAVE_STATUS_ADDRESS_MATCH   A valid address has been received
- * \retval I2C_SLAVE_STATUS_DATA_READY      A I<SUP>2</SUP>C slave byte transmission is
- *                                          successfully completed
- * \retval I2C_SLAVE_STATUS_STOP_RECEIVED   A stop condition is detected for a
- *                                          transaction being processed
- * \retval I2C_SLAVE_STATUS_CLOCK_HOLD      The slave is holding the SCL line
- *                                          low
- * \retval I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT An SCL low time-out has occurred
- * \retval I2C_SLAVE_STATUS_REPEATED_START  Indicates a repeated start, only
- *                                          valid if \ref
- *                                          I2C_SLAVE_STATUS_ADDRESS_MATCH is
- *                                          set
- * \retval I2C_SLAVE_STATUS_RECEIVED_NACK   The last data packet sent was not
- *                                          acknowledged
- * \retval I2C_SLAVE_STATUS_COLLISION       The I<SUP>2</SUP>C slave was not able to
- *                                          transmit a high data or NACK bit
- * \retval I2C_SLAVE_STATUS_BUS_ERROR       An illegal bus condition has
- *                                          occurred on the bus
- */
-uint32_t i2c_slave_get_status(
-    struct i2c_slave_module *const module)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    uint8_t intflags = i2c_hw->INTFLAG.reg;
-    uint8_t status = i2c_hw->STATUS.reg;
-    uint32_t status_flags = 0;
-
-    /* Check Address Match flag */
-    if (intflags & SERCOM_I2CS_INTFLAG_AMATCH) {
-        status_flags |= I2C_SLAVE_STATUS_ADDRESS_MATCH;
-    }
-    /* Check Data Ready flag */
-    if (intflags & SERCOM_I2CS_INTFLAG_DRDY) {
-        status_flags |= I2C_SLAVE_STATUS_DATA_READY;
-    }
-    /* Check Stop flag */
-    if (intflags & SERCOM_I2CS_INTFLAG_PREC) {
-        status_flags |= I2C_SLAVE_STATUS_STOP_RECEIVED;
-    }
-    /* Check Clock Hold */
-    if (status & SERCOM_I2CS_STATUS_CLKHOLD) {
-        status_flags |= I2C_SLAVE_STATUS_CLOCK_HOLD;
-    }
-    /* Check SCL Low Timeout */
-    if (status & SERCOM_I2CS_STATUS_LOWTOUT) {
-        status_flags |= I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT;
-    }
-    /* Check Repeated Start */
-    if (status & SERCOM_I2CS_STATUS_SR) {
-        status_flags |= I2C_SLAVE_STATUS_REPEATED_START;
-    }
-    /* Check Received Not Acknowledge */
-    if (status & SERCOM_I2CS_STATUS_RXNACK) {
-        status_flags |= I2C_SLAVE_STATUS_RECEIVED_NACK;
-    }
-    /* Check Transmit Collision */
-    if (status & SERCOM_I2CS_STATUS_COLL) {
-        status_flags |= I2C_SLAVE_STATUS_COLLISION;
-    }
-    /* Check Bus Error */
-    if (status & SERCOM_I2CS_STATUS_BUSERR) {
-        status_flags |= I2C_SLAVE_STATUS_BUS_ERROR;
-    }
-
-    return status_flags;
-}
-
-/**
- * \brief Clears a module status flag
- *
- * Clears the given status flag of the module.
- *
- * \note Not all status flags can be cleared.
- *
- * \param[in] module         Pointer to the I<SUP>2</SUP>C software device struct
- * \param[in] status_flags   Bit mask of status flags to clear
- *
- */
-void i2c_slave_clear_status(
-    struct i2c_slave_module *const module,
-    uint32_t status_flags)
-{
-    /* Sanity check arguments */
-    Assert(module);
-    Assert(module->hw);
-
-    SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
-    /* Clear Address Match flag */
-    if (status_flags & I2C_SLAVE_STATUS_ADDRESS_MATCH) {
-        i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
-    }
-    /* Clear Data Ready flag */
-    if (status_flags & I2C_SLAVE_STATUS_DATA_READY) {
-        i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_DRDY;
-    }
-    /* Clear Stop flag */
-    if (status_flags & I2C_SLAVE_STATUS_STOP_RECEIVED) {
-        i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
-    }
-    /* Clear SCL Low Timeout */
-    if (status_flags & I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT) {
-        i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_LOWTOUT;
-    }
-    /* Clear Transmit Collision */
-    if (status_flags & I2C_SLAVE_STATUS_COLLISION) {
-        i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_COLL;
-    }
-    /* Clear Bus Error */
-    if (status_flags & I2C_SLAVE_STATUS_BUS_ERROR) {
-        i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_BUSERR;
-    }
-}