You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/02/27 02:26:39 UTC
[37/51] [abbrv] [partial] incubator-mynewt-larva git commit: Arduino
zero BSP and Atmel MCU in a different repository.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master_interrupt.c
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master_interrupt.c b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master_interrupt.c
deleted file mode 100755
index 10dfcdf..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master_interrupt.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/**
- * \file
- *
- * \brief SAM I2C Master Interrupt Driver
- *
- * Copyright (C) 2012-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>
- */
-
-#include "i2c_master_interrupt.h"
-
-extern enum status_code _i2c_master_wait_for_bus(
- struct i2c_master_module *const module);
-
-extern enum status_code _i2c_master_address_response(
- struct i2c_master_module *const module);
-
-extern enum status_code _i2c_master_send_hs_master_code(
- struct i2c_master_module *const module,
- uint8_t hs_master_code);;
-
-/**
- * \internal
- * Read next data. Used by interrupt handler to get next data byte from slave.
- *
- * \param[in,out] module Pointer to software module structure
- */
-static void _i2c_master_read(
- struct i2c_master_module *const module)
-{
- /* Sanity check arguments. */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
- bool sclsm_flag = i2c_module->CTRLA.bit.SCLSM;
-
- /* Find index to save next value in buffer */
- uint16_t buffer_index = module->buffer_length;
- buffer_index -= module->buffer_remaining;
-
- module->buffer_remaining--;
-
- if (sclsm_flag) {
- if (module->send_nack && module->buffer_remaining == 1) {
- /* Set action to NACK. */
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
- }
- } else {
- if (module->send_nack && module->buffer_remaining == 0) {
- /* Set action to NACK. */
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
- }
- }
-
- if (module->buffer_remaining == 0) {
- if (module->send_stop) {
- /* Send stop condition */
- _i2c_master_wait_for_sync(module);
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
- }
- }
-
- /* Read byte from slave and put in buffer */
- _i2c_master_wait_for_sync(module);
- module->buffer[buffer_index] = i2c_module->DATA.reg;
-}
-
-/**
- * \internal
- *
- * Write next data. Used by interrupt handler to send next data byte to slave.
- *
- * \param[in,out] module Pointer to software module structure
- */
-static void _i2c_master_write(struct i2c_master_module *const module)
-{
- /* Sanity check arguments. */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
- /* Check for ack from slave */
- if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
- {
- /* Set status */
- module->status = STATUS_ERR_OVERFLOW;
- /* Do not write more data */
- return;
- }
-
- /* Find index to get next byte in buffer */
- uint16_t buffer_index = module->buffer_length;
- buffer_index -= module->buffer_remaining;
-
- module->buffer_remaining--;
-
- /* Write byte from buffer to slave */
- _i2c_master_wait_for_sync(module);
- i2c_module->DATA.reg = module->buffer[buffer_index];
-}
-
-/**
- * \internal
- * Acts on slave address response. Checks for errors concerning master->slave
- * handshake.
- *
- * \param[in,out] module Pointer to software module structure
- */
-static void _i2c_master_async_address_response(
- struct i2c_master_module *const module)
-{
- /* Sanity check arguments. */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
- /* Check for error. Ignore bus-error; workaround for bus state stuck in
- * BUSY.
- */
- if (i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB)
- {
- /* Clear write interrupt flag */
- i2c_module->INTFLAG.reg = SERCOM_I2CM_INTENCLR_MB;
-
- /* Check arbitration */
- if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_ARBLOST) {
- /* Return busy */
- module->status = STATUS_ERR_PACKET_COLLISION;
- }
- } else if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
- /* Return bad address value */
- module->status = STATUS_ERR_BAD_ADDRESS;
- module->buffer_remaining = 0;
-
- if (module->send_stop) {
- /* Send stop condition */
- _i2c_master_wait_for_sync(module);
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
- }
- }
-
- module->buffer_length = module->buffer_remaining;
-
- /* Check for status OK. */
- if (module->status == STATUS_BUSY) {
- /* Call function based on transfer direction. */
- if (module->transfer_direction == I2C_TRANSFER_WRITE) {
- _i2c_master_write(module);
- } else {
- _i2c_master_read(module);
- }
- }
-}
-
-/**
- * \brief Registers callback for the specified callback type
- *
- * Associates the given callback function with the
- * specified callback type.
- *
- * To enable the callback, the \ref i2c_master_enable_callback function
- * must be used.
- *
- * \param[in,out] module Pointer to the software module struct
- * \param[in] callback Pointer to the function desired for the
- * specified callback
- * \param[in] callback_type Callback type to register
- */
-void i2c_master_register_callback(
- struct i2c_master_module *const module,
- const i2c_master_callback_t callback,
- enum i2c_master_callback callback_type)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(callback);
-
- /* Register callback */
- module->callbacks[callback_type] = callback;
-
- /* Set corresponding bit to set callback as registered */
- module->registered_callback |= (1 << callback_type);
-}
-
-/**
- * \brief Unregisters callback for the specified callback type
- *
- * When called, the currently registered callback for the given callback type
- * will be removed.
- *
- * \param[in,out] module Pointer to the software module struct
- * \param[in] callback_type Specifies the callback type to unregister
- */
-void i2c_master_unregister_callback(
- struct i2c_master_module *const module,
- enum i2c_master_callback callback_type)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
-
- /* Register callback */
- module->callbacks[callback_type] = NULL;
-
- /* Clear corresponding bit to set callback as unregistered */
- module->registered_callback &= ~(1 << callback_type);
-}
-
-/**
- * \internal
- * Starts a read bytes operation.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_master_read_bytes(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
- /* Save packet to software module */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->transfer_direction = I2C_TRANSFER_READ;
- module->status = STATUS_BUSY;
- module->send_stop = false;
- module->send_nack = false;
-
- /* Enable interrupts */
- i2c_module->INTENSET.reg =
- SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
-
- return STATUS_OK;
-}
-
-/**
- * \internal
- * Starts a read packet operation.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-static enum status_code _i2c_master_read_packet(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
- enum status_code tmp_status;
-
- /* Save packet to software module */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->transfer_direction = I2C_TRANSFER_READ;
- module->status = STATUS_BUSY;
-
- /* Switch to high speed mode */
- if (packet->high_speed) {
- _i2c_master_send_hs_master_code(module, packet->hs_master_code);
- }
-
- /* Set action to ACK. */
- i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
-
- if (packet->ten_bit_address) {
- /*
- * Write ADDR.ADDR[10:1] with the 10-bit address. ADDR.TENBITEN must
- * be set and read/write bit (ADDR.ADDR[0]) equal to 0.
- */
- i2c_module->ADDR.reg = (packet->address << 1) |
- (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
- SERCOM_I2CM_ADDR_TENBITEN;
-
- /* Wait for response on bus. */
- tmp_status = _i2c_master_wait_for_bus(module);
-
- /* Set action to ack. */
- i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
-
- /* Check for address response error unless previous error is
- * detected. */
- if (tmp_status == STATUS_OK) {
- tmp_status = _i2c_master_address_response(module);
- }
-
- if (tmp_status == STATUS_OK) {
- /* Enable interrupts */
- i2c_module->INTENSET.reg =
- SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
-
- /*
- * Write ADDR[7:0] register to "11110 address[9:8] 1"
- * ADDR.TENBITEN must be cleared
- */
- i2c_module->ADDR.reg = (((packet->address >> 8) | 0x78) << 1) |
- (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
- I2C_TRANSFER_READ;
- } else {
- return tmp_status;
- }
- } else {
- /* Enable interrupts */
- i2c_module->INTENSET.reg =
- SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
-
- /* Set address and direction bit. Will send start command on bus */
- i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_READ |
- (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
- }
-
- return STATUS_OK;
-}
-
-/**
- * \brief Initiates a read packet operation
- *
- * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
- * bus. This is the non-blocking equivalent of \ref i2c_master_read_packet_wait.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_master_read_packet_job(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy with a job */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Make sure we send STOP */
- module->send_stop = true;
- module->send_nack = true;
- /* Start reading */
- return _i2c_master_read_packet(module, packet);
-}
-
-/**
- * \brief Initiates a read packet operation without sending a STOP condition when done
- *
- * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C bus without
- * sending a stop condition, thus retaining ownership of the bus when done.
- * To end the transaction, a \ref i2c_master_read_packet_wait "read" or
- * \ref i2c_master_write_packet_wait "write" with stop condition must be
- * performed.
- *
- * This is the non-blocking equivalent of \ref i2c_master_read_packet_wait_no_stop.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another operation
- */
-enum status_code i2c_master_read_packet_job_no_stop(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy with a job */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Make sure we don't send STOP */
- module->send_stop = false;
- module->send_nack = true;
- /* Start reading */
- return _i2c_master_read_packet(module, packet);
-}
-
-/**
- * \brief Initiates a read packet operation without sending a NACK signal and a
- * STOP condition when done
- *
- * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C bus without
- * sending a nack and a stop condition, thus retaining ownership of the bus when done.
- * To end the transaction, a \ref i2c_master_read_packet_wait "read" or
- * \ref i2c_master_write_packet_wait "write" with stop condition must be
- * performed.
- *
- * This is the non-blocking equivalent of \ref i2c_master_read_packet_wait_no_stop.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another operation
- */
-enum status_code i2c_master_read_packet_job_no_nack(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy with a job */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Make sure we don't send STOP */
- module->send_stop = false;
- module->send_nack = false;
- /* Start reading */
- return _i2c_master_read_packet(module, packet);
-}
-
-/**
- * \internal
- * Starts a write bytes operation.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting write I<SUP>2</SUP>C bytes.
- * \retval STATUS_OK If writing was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_master_write_bytes(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
- /* Save packet to software module */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->transfer_direction = I2C_TRANSFER_WRITE;
- module->status = STATUS_BUSY;
- module->send_stop = false;
- module->send_nack = false;
-
- /* Enable interrupts */
- i2c_module->INTENSET.reg =
- SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
-
- return STATUS_OK;
-}
-
-/**
- * \internal Initiates a write packet operation
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting writing I<SUP>2</SUP>C packet job.
- * \retval STATUS_OK If writing was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-static enum status_code _i2c_master_write_packet(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
-
- /* Switch to high speed mode */
- if (packet->high_speed) {
- _i2c_master_send_hs_master_code(module, packet->hs_master_code);
- }
-
- /* Set action to ACK. */
- i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
-
- /* Save packet to software module */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->transfer_direction = I2C_TRANSFER_WRITE;
- module->status = STATUS_BUSY;
-
- /* Enable interrupts */
- i2c_module->INTENSET.reg =
- SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
-
- /* Set address and direction bit, will send start command on bus */
- if (packet->ten_bit_address) {
- i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
- (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
- SERCOM_I2CM_ADDR_TENBITEN;
- } else {
- i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
- (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
- }
-
- return STATUS_OK;
-}
-
-/**
- * \brief Initiates a write packet operation
- *
- * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C
- * bus. This is the non-blocking equivalent of \ref i2c_master_write_packet_wait.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting writing I<SUP>2</SUP>C packet job.
- * \retval STATUS_OK If writing was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_master_write_packet_job(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy with another job. */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Make sure we send STOP at end*/
- module->send_stop = true;
- module->send_nack = true;
- /* Start write operation */
- return _i2c_master_write_packet(module, packet);
-}
-
-/**
- * \brief Initiates a write packet operation without sending a STOP condition when done
- *
- * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
- * without sending a stop condition, thus retaining ownership of the bus when
- * done. To end the transaction, a \ref i2c_master_read_packet_wait "read" or
- * \ref i2c_master_write_packet_wait "write" with stop condition or sending
- * a stop with the \ref i2c_master_send_stop function must be performed.
- *
- * This is the non-blocking equivalent of \ref i2c_master_write_packet_wait_no_stop.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting writing I<SUP>2</SUP>C packet job.
- * \retval STATUS_OK If writing was started successfully
- * \retval STATUS_BUSY If module is currently busy with another
- */
-enum status_code i2c_master_write_packet_job_no_stop(
- struct i2c_master_module *const module,
- struct i2c_master_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy with another job. */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Do not send stop condition when done */
- module->send_stop = false;
- module->send_nack = true;
- /* Start write operation */
- return _i2c_master_write_packet(module, packet);
-}
-
-/**
- * \internal
- * Interrupt handler for I<SUP>2</SUP>C master.
- *
- * \param[in] instance SERCOM instance that triggered the interrupt
- */
-void _i2c_master_interrupt_handler(
- uint8_t instance)
-{
- /* Get software module for callback handling */
- struct i2c_master_module *module =
- (struct i2c_master_module*)_sercom_instances[instance];
-
- Assert(module);
-
- SercomI2cm *const i2c_module = &(module->hw->I2CM);
- bool sclsm_flag = i2c_module->CTRLA.bit.SCLSM;
-
- /* Combine callback registered and enabled masks */
- uint8_t callback_mask = module->enabled_callback;
- callback_mask &= module->registered_callback;
-
- /* Check if the module should respond to address ack */
- if ((module->buffer_length <= 0) && (module->buffer_remaining > 0)) {
- /* Call function for address response */
- _i2c_master_async_address_response(module);
-
- /* Check if buffer write is done */
- } else if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
- (module->status == STATUS_BUSY) &&
- (module->transfer_direction == I2C_TRANSFER_WRITE)) {
- /* Stop packet operation */
- i2c_module->INTENCLR.reg =
- SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
-
- module->buffer_length = 0;
- module->status = STATUS_OK;
-
- if (module->send_stop) {
- /* Send stop condition */
- _i2c_master_wait_for_sync(module);
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
- } else {
- /* Clear write interrupt flag */
- i2c_module->INTFLAG.reg = SERCOM_I2CM_INTFLAG_MB;
- }
-
- if (callback_mask & (1 << I2C_MASTER_CALLBACK_WRITE_COMPLETE)) {
- module->callbacks[I2C_MASTER_CALLBACK_WRITE_COMPLETE](module);
- }
-
- /* Continue buffer write/read */
- } else if ((module->buffer_length > 0) && (module->buffer_remaining > 0)){
- /* Check that bus ownership is not lost */
- if ((!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) &&
- (!(sclsm_flag && (module->buffer_remaining == 1)))) {
- module->status = STATUS_ERR_PACKET_COLLISION;
- } else if (module->transfer_direction == I2C_TRANSFER_WRITE) {
- _i2c_master_write(module);
- } else {
- _i2c_master_read(module);
- }
- }
-
- /* Check if read buffer transfer is complete */
- if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
- (module->status == STATUS_BUSY) &&
- (module->transfer_direction == I2C_TRANSFER_READ)) {
-
- /* Clear read interrupt flag */
- if (i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB) {
- i2c_module->INTFLAG.reg = SERCOM_I2CM_INTFLAG_SB;
- }
- /* Stop packet operation */
- i2c_module->INTENCLR.reg =
- SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
- module->buffer_length = 0;
- module->status = STATUS_OK;
-
- /* Call appropriate callback if enabled and registered */
- if ((callback_mask & (1 << I2C_MASTER_CALLBACK_READ_COMPLETE))
- && (module->transfer_direction == I2C_TRANSFER_READ)) {
- module->callbacks[I2C_MASTER_CALLBACK_READ_COMPLETE](module);
- } else if ((callback_mask & (1 << I2C_MASTER_CALLBACK_WRITE_COMPLETE))
- && (module->transfer_direction == I2C_TRANSFER_WRITE)) {
- module->callbacks[I2C_MASTER_CALLBACK_WRITE_COMPLETE](module);
- }
- }
-
- /* Check for error */
- if ((module->status != STATUS_BUSY) && (module->status != STATUS_OK)) {
- /* Stop packet operation */
- i2c_module->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB |
- SERCOM_I2CM_INTENCLR_SB;
-
- module->buffer_length = 0;
- module->buffer_remaining = 0;
-
- /* Send nack and stop command unless arbitration is lost */
- if ((module->status != STATUS_ERR_PACKET_COLLISION) &&
- module->send_stop) {
- _i2c_master_wait_for_sync(module);
- i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT |
- SERCOM_I2CM_CTRLB_CMD(3);
- }
-
- /* Call error callback if enabled and registered */
- if (callback_mask & (1 << I2C_MASTER_CALLBACK_ERROR)) {
- module->callbacks[I2C_MASTER_CALLBACK_ERROR](module);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave.c
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave.c b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave.c
deleted file mode 100755
index 4bb968d..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/**
- * \file
- *
- * \brief SAM 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>
- */
-
-#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;
- }
-
- /* Check and set SCL clock stretch mode. */
- if (config->scl_stretch_only_after_ack_bit || (config->transfer_speed == I2C_SLAVE_SPEED_HIGH_SPEED)) {
- tmp_ctrla |= SERCOM_I2CM_CTRLA_SCLSM;
- }
-
- tmp_ctrla |= ((uint32_t)config->sda_hold_time |
- config->transfer_speed |
- (config->scl_low_timeout << SERCOM_I2CS_CTRLA_LOWTOUTEN_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);
- uint32_t pm_index, gclk_index;
-#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
-#if (SAML21)
- if (sercom_index == 5) {
- pm_index = MCLK_APBDMASK_SERCOM5_Pos;
- gclk_index = SERCOM5_GCLK_ID_CORE;
- } else {
- pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
- }
-#else
- pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-#endif
-#else
- pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
- gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
-#endif
-
- /* Turn on module in PM */
-#if (SAML21)
- if (sercom_index == 5) {
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
- } else {
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
- }
-#else
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
-#endif
-
- /* 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 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;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave_interrupt.c
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave_interrupt.c b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave_interrupt.c
deleted file mode 100755
index 0a6f234..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_sam0/i2c_slave_interrupt.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/**
- * \file
- *
- * \brief SAM I2C Slave Interrupt 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>
- */
-
-#include "i2c_slave_interrupt.h"
-
-/**
- * \brief Enables sending of NACK on address match
- *
- * Enables sending of NACK on address match, thus discarding
- * any incoming transaction.
- *
- * \param[in,out] module Pointer to software module structure
- */
-void i2c_slave_enable_nack_on_address(
- struct i2c_slave_module *const module)
-{
- /* Sanity check arguments. */
- Assert(module);
-
- module->nack_on_address = true;
-}
-
-/**
- * \brief Disables sending NACK on address match
- *
- * Disables sending of NACK on address match, thus
- * acknowledging incoming transactions.
- *
- * \param[in,out] module Pointer to software module structure
- */
-void i2c_slave_disable_nack_on_address(
- struct i2c_slave_module *const module)
-{
- /* Sanity check arguments. */
- Assert(module);
-
- module->nack_on_address = false;
-}
-
-/**
- * \internal
- * Reads next data. Used by interrupt handler to get next data byte from master.
- *
- * \param[in,out] module Pointer to software module structure
- */
-static void _i2c_slave_read(
- struct i2c_slave_module *const module)
-{
- SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
- /* Read byte from master and put in buffer. */
- *(module->buffer++) = i2c_hw->DATA.reg;
-
- /*Decrement remaining buffer length */
- module->buffer_remaining--;
-}
-
-/**
- * \internal
- * Writes next data. Used by interrupt handler to send next data byte to master.
- *
- * \param[in,out] module Pointer to software module structure
- */
-static void _i2c_slave_write(
- struct i2c_slave_module *const module)
-{
- SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
- /* Write byte from buffer to master */
- i2c_hw->DATA.reg = *(module->buffer++);
-
- /*Decrement remaining buffer length */
- module->buffer_remaining--;
-}
-
-/**
- * \brief Registers callback for the specified callback type
- *
- * Associates the given callback function with the
- * specified callback type. To enable the callback, the
- * \ref i2c_slave_enable_callback function must be used.
- *
- * \param[in,out] module Pointer to the software module struct
- * \param[in] callback Pointer to the function desired for the
- * specified callback
- * \param[in] callback_type Callback type to register
- */
-void i2c_slave_register_callback(
- struct i2c_slave_module *const module,
- i2c_slave_callback_t callback,
- enum i2c_slave_callback callback_type)
-{
- /* Sanity check. */
- Assert(module);
- Assert(module->hw);
- Assert(callback);
-
- /* Register callback. */
- module->callbacks[callback_type] = callback;
-
- /* Set corresponding bit to set callback as initiated. */
- module->registered_callback |= (1 << callback_type);
-}
-
-/**
- * \brief Unregisters callback for the specified callback type
- *
- * Removes the currently registered callback for the given callback
- * type.
- *
- * \param[in,out] module Pointer to the software module struct
- * \param[in] callback_type Callback type to unregister
- */
-void i2c_slave_unregister_callback(
- struct i2c_slave_module *const module,
- enum i2c_slave_callback callback_type)
-{
- /* Sanity check. */
- Assert(module);
- Assert(module->hw);
-
- /* Register callback. */
- module->callbacks[callback_type] = NULL;
-
- /* Set corresponding bit to set callback as initiated. */
- module->registered_callback &= ~(1 << callback_type);
-}
-
-/**
- * \brief Initiates a reads packet operation
- *
- * Reads a data packet from the master. A write request must be initiated by
- * the master before the packet can be read.
- *
- * The \ref I2C_SLAVE_CALLBACK_WRITE_REQUEST callback can be used to call this
- * function.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting asynchronously reading I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If reading was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_slave_read_packet_job(
- struct i2c_slave_module *const module,
- struct i2c_slave_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy doing async operation. */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Save packet to software module. */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->buffer_length = packet->data_length;
- module->status = STATUS_BUSY;
-
- /* Enable interrupts */
- SercomI2cs *const i2c_hw = &(module->hw->I2CS);
- i2c_hw->INTENSET.reg = SERCOM_I2CS_INTFLAG_AMATCH |
- SERCOM_I2CS_INTFLAG_DRDY | SERCOM_I2CS_INTFLAG_PREC;
-
- /* Read will begin when master initiates the transfer */
- return STATUS_OK;
-}
-
-/**
- * \brief Initiates a write packet operation
- *
- * Writes a data packet to the master. A read request must be initiated by
- * the master before the packet can be written.
- *
- * The \ref I2C_SLAVE_CALLBACK_READ_REQUEST callback can be used to call this
- * function.
- *
- * \param[in,out] module Pointer to software module struct
- * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
- *
- * \return Status of starting writing I<SUP>2</SUP>C packet.
- * \retval STATUS_OK If writing was started successfully
- * \retval STATUS_BUSY If module is currently busy with another transfer
- */
-enum status_code i2c_slave_write_packet_job(
- struct i2c_slave_module *const module,
- struct i2c_slave_packet *const packet)
-{
- /* Sanity check */
- Assert(module);
- Assert(module->hw);
- Assert(packet);
-
- /* Check if the I2C module is busy doing async operation. */
- if (module->buffer_remaining > 0) {
- return STATUS_BUSY;
- }
-
- /* Save packet to software module. */
- module->buffer = packet->data;
- module->buffer_remaining = packet->data_length;
- module->buffer_length = packet->data_length;
- module->status = STATUS_BUSY;
-
- /* Enable interrupts */
- SercomI2cs *const i2c_hw = &(module->hw->I2CS);
- i2c_hw->INTENSET.reg = SERCOM_I2CS_INTFLAG_AMATCH |
- SERCOM_I2CS_INTFLAG_DRDY | SERCOM_I2CS_INTFLAG_PREC;
-
- return STATUS_OK;
-}
-
-/**
- * \internal Interrupt handler for I<SUP>2</SUP>C slave
- *
- * \param[in] instance Sercom instance that triggered the interrupt
- */
-void _i2c_slave_interrupt_handler(
- uint8_t instance)
-{
- /* Get software module for callback handling. */
- struct i2c_slave_module *module =
- (struct i2c_slave_module*)_sercom_instances[instance];
-
- Assert(module);
-
- SercomI2cs *const i2c_hw = &(module->hw->I2CS);
-
- /* Combine callback registered and enabled masks. */
- uint8_t callback_mask = module->enabled_callback;
- callback_mask &= module->registered_callback;
-
-
- if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
- /* Address match */
- /* Check if last transfer is done - repeated start */
- if (module->buffer_length != module->buffer_remaining &&
- module->transfer_direction == I2C_TRANSFER_WRITE) {
-
- module->status = STATUS_OK;
- module->buffer_length = 0;
- module->buffer_remaining = 0;
-
- if ((callback_mask & (1 << I2C_SLAVE_CALLBACK_READ_COMPLETE))) {
- module->callbacks[I2C_SLAVE_CALLBACK_READ_COMPLETE](module);
- }
- } else if (module->buffer_length != module->buffer_remaining &&
- module->transfer_direction == I2C_TRANSFER_READ) {
- module->status = STATUS_OK;
- module->buffer_length = 0;
- module->buffer_remaining = 0;
-
- if ((callback_mask & (1 << I2C_SLAVE_CALLBACK_WRITE_COMPLETE))) {
- module->callbacks[I2C_SLAVE_CALLBACK_WRITE_COMPLETE](module);
- }
- }
-
- if (i2c_hw->STATUS.reg & (SERCOM_I2CS_STATUS_BUSERR |
- SERCOM_I2CS_STATUS_COLL | SERCOM_I2CS_STATUS_LOWTOUT)) {
- /* An error occurred in last packet transfer */
- module->status = STATUS_ERR_IO;
-
- if ((callback_mask & (1 << I2C_SLAVE_CALLBACK_ERROR_LAST_TRANSFER))) {
- module->callbacks[I2C_SLAVE_CALLBACK_ERROR_LAST_TRANSFER](module);
- }
- }
- if (module->nack_on_address) {
- /* NACK address, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, false);
- } else if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR) {
- /* Set transfer direction in module instance */
- module->transfer_direction = I2C_TRANSFER_READ;
-
- /* Read request from master */
- if (callback_mask & (1 << I2C_SLAVE_CALLBACK_READ_REQUEST)) {
- module->callbacks[I2C_SLAVE_CALLBACK_READ_REQUEST](module);
- }
-
- if (module->buffer_length == 0) {
- /* Data buffer not set up, NACK address, workaround 13574*/
- _i2c_slave_set_ctrlb_ackact(module, false);
- } else {
- /* ACK address, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, true);
- }
- } else {
- /* Set transfer direction in dev inst */
- module->transfer_direction = I2C_TRANSFER_WRITE;
-
- /* Write request from master */
- if (callback_mask & (1 << I2C_SLAVE_CALLBACK_WRITE_REQUEST)) {
- module->callbacks[I2C_SLAVE_CALLBACK_WRITE_REQUEST](module);
- }
-
- if (module->buffer_length == 0) {
- /* Data buffer not set up, NACK address, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, false);
- } else {
- /* ACK address, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, true);
- }
- }
-
- /* ACK or NACK address, Workaround 13574 */
- _i2c_slave_set_ctrlb_cmd3(module);
-
- /* ACK next incoming packet, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, true);
-
- } else if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) {
- /* Stop condition on bus - current transfer done */
-
- /* Clear Stop interrupt */
- i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
-
- /* Disable interrupts */
- i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTFLAG_PREC | SERCOM_I2CS_INTFLAG_DRDY;
-
- if (!((module->enabled_callback & (1 << I2C_SLAVE_CALLBACK_READ_REQUEST))
- || (module->enabled_callback == (1 << I2C_SLAVE_CALLBACK_WRITE_REQUEST)))) {
- /* Disable address match if read/write request is not enabled */
- i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTFLAG_AMATCH;
- }
-
- if (!(module->status == STATUS_ERR_OVERFLOW || module->status == STATUS_ERR_IO)) {
- module->status = STATUS_OK;
- module->buffer_length = 0;
- module->buffer_remaining = 0;
-
- /* Call appropriate callback if enabled and registered */
- if ((callback_mask & (1 << I2C_SLAVE_CALLBACK_READ_COMPLETE))
- && (module->transfer_direction == I2C_TRANSFER_WRITE)) {
- /* Read from master complete */
- module->callbacks[I2C_SLAVE_CALLBACK_READ_COMPLETE](module);
- } else if ((callback_mask & (1 << I2C_SLAVE_CALLBACK_WRITE_COMPLETE))
- && (module->transfer_direction == I2C_TRANSFER_READ)) {
- /* Write to master complete */
- module->callbacks[I2C_SLAVE_CALLBACK_WRITE_COMPLETE](module);
- }
- }
- } else if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY) {
- /* Check if buffer is full, or NACK from master */
- if (module->buffer_remaining <= 0 ||
- (module->transfer_direction == I2C_TRANSFER_READ &&
- (module->buffer_length > module->buffer_remaining) &&
- (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_RXNACK))) {
-
- module->buffer_remaining = 0;
- module->buffer_length = 0;
-
- if (module->transfer_direction == I2C_TRANSFER_WRITE) {
- /* Buffer is full, send NACK, workaround 13574 */
- _i2c_slave_set_ctrlb_ackact(module, false);
- i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2);
-
- /* Set status, new character in DATA register will overflow
- * buffer */
- module->status = STATUS_ERR_OVERFLOW;
-
- if (callback_mask & (1 << I2C_SLAVE_CALLBACK_ERROR)) {
- /* Read complete */
- module->callbacks[I2C_SLAVE_CALLBACK_ERROR](module);
- }
- } else {
- /* Release SCL and wait for new start condition */
- _i2c_slave_set_ctrlb_ackact(module, false);
- i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2);
-
- /* Transfer successful */
- module->status = STATUS_OK;
-
- /* Disable interrupts */
- i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTFLAG_DRDY;
- }
-
- /* Continue buffer write/read */
- } else if (module->buffer_length > 0 && module->buffer_remaining > 0) {
- /* Call function based on transfer direction */
- if (module->transfer_direction == I2C_TRANSFER_WRITE) {
- _i2c_slave_read(module);
- } else {
- _i2c_slave_write(module);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a280628a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_slave.h
----------------------------------------------------------------------
diff --git a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_slave.h b/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_slave.h
deleted file mode 100755
index 239fb9d..0000000
--- a/hw/mcu/atmel/samd21xx/src/sam0/drivers/sercom/i2c/i2c_slave.h
+++ /dev/null
@@ -1,753 +0,0 @@
-/**
- * \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 I<SUP>2</SUP>C module to sync */
- }
-}
-#endif
-
-///@cond INTERNAL
-/**
- * \internal Workaround for errata 13574
- * Instead set ACK/NACK of CTRLB
- *
- * This errata exist in part revisions of SAM D20/D21/D09
- * D10/D11/L21/L22/DA1/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 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAMDA1 || \
- SAML22 || 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 SAM D20/D21/D09
- * D10/D11/L21/DA1/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 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAML22 || \
- 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 */