mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
mbed_official
Date:
Mon Nov 09 13:30:11 2015 +0000
Revision:
18:da299f395b9e
Parent:
targets/hal/TARGET_Atmel/TARGET_SAM_CortexM0P/drivers/sercom/i2c/i2c_samd21_r21_d10_d11_l21/i2c_slave.c@15:a81a8d6c1dfe
Synchronized with git revision f605825f66bb2e462ff7dbc5fb4ed2dbe979d1c3

Full URL: https://github.com/mbedmicro/mbed/commit/f605825f66bb2e462ff7dbc5fb4ed2dbe979d1c3/

Added support for SAML21

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 15:a81a8d6c1dfe 1 /**
mbed_official 15:a81a8d6c1dfe 2 * \file
mbed_official 15:a81a8d6c1dfe 3 *
mbed_official 15:a81a8d6c1dfe 4 * \brief SAM I2C Slave Driver
mbed_official 15:a81a8d6c1dfe 5 *
mbed_official 15:a81a8d6c1dfe 6 * Copyright (C) 2013-2015 Atmel Corporation. All rights reserved.
mbed_official 15:a81a8d6c1dfe 7 *
mbed_official 15:a81a8d6c1dfe 8 * \asf_license_start
mbed_official 15:a81a8d6c1dfe 9 *
mbed_official 15:a81a8d6c1dfe 10 * \page License
mbed_official 15:a81a8d6c1dfe 11 *
mbed_official 15:a81a8d6c1dfe 12 * Redistribution and use in source and binary forms, with or without
mbed_official 15:a81a8d6c1dfe 13 * modification, are permitted provided that the following conditions are met:
mbed_official 15:a81a8d6c1dfe 14 *
mbed_official 15:a81a8d6c1dfe 15 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 15:a81a8d6c1dfe 16 * this list of conditions and the following disclaimer.
mbed_official 15:a81a8d6c1dfe 17 *
mbed_official 15:a81a8d6c1dfe 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 15:a81a8d6c1dfe 19 * this list of conditions and the following disclaimer in the documentation
mbed_official 15:a81a8d6c1dfe 20 * and/or other materials provided with the distribution.
mbed_official 15:a81a8d6c1dfe 21 *
mbed_official 15:a81a8d6c1dfe 22 * 3. The name of Atmel may not be used to endorse or promote products derived
mbed_official 15:a81a8d6c1dfe 23 * from this software without specific prior written permission.
mbed_official 15:a81a8d6c1dfe 24 *
mbed_official 15:a81a8d6c1dfe 25 * 4. This software may only be redistributed and used in connection with an
mbed_official 15:a81a8d6c1dfe 26 * Atmel microcontroller product.
mbed_official 15:a81a8d6c1dfe 27 *
mbed_official 15:a81a8d6c1dfe 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
mbed_official 15:a81a8d6c1dfe 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 15:a81a8d6c1dfe 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
mbed_official 15:a81a8d6c1dfe 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
mbed_official 15:a81a8d6c1dfe 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mbed_official 15:a81a8d6c1dfe 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
mbed_official 15:a81a8d6c1dfe 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
mbed_official 15:a81a8d6c1dfe 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
mbed_official 15:a81a8d6c1dfe 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
mbed_official 15:a81a8d6c1dfe 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
mbed_official 15:a81a8d6c1dfe 38 * POSSIBILITY OF SUCH DAMAGE.
mbed_official 15:a81a8d6c1dfe 39 *
mbed_official 15:a81a8d6c1dfe 40 * \asf_license_stop
mbed_official 15:a81a8d6c1dfe 41 *
mbed_official 15:a81a8d6c1dfe 42 */
mbed_official 15:a81a8d6c1dfe 43 /*
mbed_official 15:a81a8d6c1dfe 44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
mbed_official 15:a81a8d6c1dfe 45 */
mbed_official 15:a81a8d6c1dfe 46
mbed_official 15:a81a8d6c1dfe 47 #include "i2c_slave.h"
mbed_official 15:a81a8d6c1dfe 48 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 49 # include "i2c_slave_interrupt.h"
mbed_official 15:a81a8d6c1dfe 50 #endif
mbed_official 15:a81a8d6c1dfe 51
mbed_official 15:a81a8d6c1dfe 52 /**
mbed_official 15:a81a8d6c1dfe 53 * \internal Sets configuration to module
mbed_official 15:a81a8d6c1dfe 54 *
mbed_official 15:a81a8d6c1dfe 55 * \param[out] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 56 * \param[in] config Configuration structure with configurations to set
mbed_official 15:a81a8d6c1dfe 57 *
mbed_official 15:a81a8d6c1dfe 58 * \return Status of setting configuration.
mbed_official 15:a81a8d6c1dfe 59 * \retval STATUS_OK Module was configured correctly
mbed_official 15:a81a8d6c1dfe 60 * \retval STATUS_ERR_ALREADY_INITIALIZED If setting other GCLK generator than
mbed_official 15:a81a8d6c1dfe 61 * previously set
mbed_official 15:a81a8d6c1dfe 62 */
mbed_official 15:a81a8d6c1dfe 63 static enum status_code _i2c_slave_set_config(
mbed_official 15:a81a8d6c1dfe 64 struct i2c_slave_module *const module,
mbed_official 15:a81a8d6c1dfe 65 const struct i2c_slave_config *const config)
mbed_official 15:a81a8d6c1dfe 66 {
mbed_official 15:a81a8d6c1dfe 67 uint32_t tmp_ctrla;
mbed_official 15:a81a8d6c1dfe 68
mbed_official 15:a81a8d6c1dfe 69 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 70 Assert(module);
mbed_official 15:a81a8d6c1dfe 71 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 72 Assert(config);
mbed_official 15:a81a8d6c1dfe 73
mbed_official 15:a81a8d6c1dfe 74 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 75 Sercom *const sercom_hw = module->hw;
mbed_official 15:a81a8d6c1dfe 76
mbed_official 15:a81a8d6c1dfe 77 module->buffer_timeout = config->buffer_timeout;
mbed_official 15:a81a8d6c1dfe 78 module->ten_bit_address = config->ten_bit_address;
mbed_official 15:a81a8d6c1dfe 79
mbed_official 15:a81a8d6c1dfe 80 struct system_pinmux_config pin_conf;
mbed_official 15:a81a8d6c1dfe 81 system_pinmux_get_config_defaults(&pin_conf);
mbed_official 15:a81a8d6c1dfe 82
mbed_official 15:a81a8d6c1dfe 83 uint32_t pad0 = config->pinmux_pad0;
mbed_official 15:a81a8d6c1dfe 84 uint32_t pad1 = config->pinmux_pad1;
mbed_official 15:a81a8d6c1dfe 85
mbed_official 15:a81a8d6c1dfe 86 /* SERCOM PAD0 - SDA */
mbed_official 15:a81a8d6c1dfe 87 if (pad0 == PINMUX_DEFAULT) {
mbed_official 15:a81a8d6c1dfe 88 pad0 = _sercom_get_default_pad(sercom_hw, 0);
mbed_official 15:a81a8d6c1dfe 89 }
mbed_official 15:a81a8d6c1dfe 90 pin_conf.mux_position = pad0 & 0xFFFF;
mbed_official 15:a81a8d6c1dfe 91 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
mbed_official 15:a81a8d6c1dfe 92 system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);
mbed_official 15:a81a8d6c1dfe 93
mbed_official 15:a81a8d6c1dfe 94 /* SERCOM PAD1 - SCL */
mbed_official 15:a81a8d6c1dfe 95 if (pad1 == PINMUX_DEFAULT) {
mbed_official 15:a81a8d6c1dfe 96 pad1 = _sercom_get_default_pad(sercom_hw, 1);
mbed_official 15:a81a8d6c1dfe 97 }
mbed_official 15:a81a8d6c1dfe 98 pin_conf.mux_position = pad1 & 0xFFFF;
mbed_official 15:a81a8d6c1dfe 99 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
mbed_official 15:a81a8d6c1dfe 100 system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);
mbed_official 15:a81a8d6c1dfe 101
mbed_official 15:a81a8d6c1dfe 102 /* Prepare config to write to register CTRLA */
mbed_official 15:a81a8d6c1dfe 103 if (config->run_in_standby || system_is_debugger_present()) {
mbed_official 15:a81a8d6c1dfe 104 tmp_ctrla = SERCOM_I2CS_CTRLA_RUNSTDBY;
mbed_official 15:a81a8d6c1dfe 105 } else {
mbed_official 15:a81a8d6c1dfe 106 tmp_ctrla = 0;
mbed_official 15:a81a8d6c1dfe 107 }
mbed_official 15:a81a8d6c1dfe 108
mbed_official 15:a81a8d6c1dfe 109 tmp_ctrla |= ((uint32_t)config->sda_hold_time |
mbed_official 15:a81a8d6c1dfe 110 config->transfer_speed |
mbed_official 15:a81a8d6c1dfe 111 (config->scl_low_timeout << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos) |
mbed_official 15:a81a8d6c1dfe 112 (config->scl_stretch_only_after_ack_bit << SERCOM_I2CS_CTRLA_SCLSM_Pos) |
mbed_official 15:a81a8d6c1dfe 113 (config->slave_scl_low_extend_timeout << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos));
mbed_official 15:a81a8d6c1dfe 114
mbed_official 15:a81a8d6c1dfe 115 i2c_hw->CTRLA.reg |= tmp_ctrla;
mbed_official 15:a81a8d6c1dfe 116
mbed_official 15:a81a8d6c1dfe 117 /* Set CTRLB configuration */
mbed_official 15:a81a8d6c1dfe 118 i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN | config->address_mode;
mbed_official 15:a81a8d6c1dfe 119
mbed_official 15:a81a8d6c1dfe 120 i2c_hw->ADDR.reg = config->address << SERCOM_I2CS_ADDR_ADDR_Pos |
mbed_official 15:a81a8d6c1dfe 121 config->address_mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos |
mbed_official 15:a81a8d6c1dfe 122 config->ten_bit_address << SERCOM_I2CS_ADDR_TENBITEN_Pos |
mbed_official 15:a81a8d6c1dfe 123 config->enable_general_call_address << SERCOM_I2CS_ADDR_GENCEN_Pos;
mbed_official 15:a81a8d6c1dfe 124
mbed_official 15:a81a8d6c1dfe 125 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 126 }
mbed_official 15:a81a8d6c1dfe 127
mbed_official 15:a81a8d6c1dfe 128 /**
mbed_official 15:a81a8d6c1dfe 129 * \brief Initializes the requested I<SUP>2</SUP>C hardware module
mbed_official 15:a81a8d6c1dfe 130 *
mbed_official 15:a81a8d6c1dfe 131 * Initializes the SERCOM I<SUP>2</SUP>C Slave device requested and sets the provided
mbed_official 15:a81a8d6c1dfe 132 * software module struct. Run this function before any further use of
mbed_official 15:a81a8d6c1dfe 133 * the driver.
mbed_official 15:a81a8d6c1dfe 134 *
mbed_official 15:a81a8d6c1dfe 135 * \param[out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 136 * \param[in] hw Pointer to the hardware instance
mbed_official 15:a81a8d6c1dfe 137 * \param[in] config Pointer to the configuration struct
mbed_official 15:a81a8d6c1dfe 138 *
mbed_official 15:a81a8d6c1dfe 139 * \return Status of initialization.
mbed_official 15:a81a8d6c1dfe 140 * \retval STATUS_OK Module initiated correctly
mbed_official 15:a81a8d6c1dfe 141 * \retval STATUS_ERR_DENIED If module is enabled
mbed_official 15:a81a8d6c1dfe 142 * \retval STATUS_BUSY If module is busy resetting
mbed_official 15:a81a8d6c1dfe 143 * \retval STATUS_ERR_ALREADY_INITIALIZED If setting other GCLK generator than
mbed_official 15:a81a8d6c1dfe 144 * previously set
mbed_official 15:a81a8d6c1dfe 145 */
mbed_official 15:a81a8d6c1dfe 146 enum status_code i2c_slave_init(
mbed_official 15:a81a8d6c1dfe 147 struct i2c_slave_module *const module,
mbed_official 15:a81a8d6c1dfe 148 Sercom *const hw,
mbed_official 15:a81a8d6c1dfe 149 const struct i2c_slave_config *const config)
mbed_official 15:a81a8d6c1dfe 150 {
mbed_official 15:a81a8d6c1dfe 151 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 152 Assert(module);
mbed_official 15:a81a8d6c1dfe 153 Assert(hw);
mbed_official 15:a81a8d6c1dfe 154 Assert(config);
mbed_official 15:a81a8d6c1dfe 155
mbed_official 15:a81a8d6c1dfe 156 /* Initialize software module */
mbed_official 15:a81a8d6c1dfe 157 module->hw = hw;
mbed_official 15:a81a8d6c1dfe 158
mbed_official 15:a81a8d6c1dfe 159 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 160
mbed_official 15:a81a8d6c1dfe 161 /* Check if module is enabled. */
mbed_official 15:a81a8d6c1dfe 162 if (i2c_hw->CTRLA.reg & SERCOM_I2CS_CTRLA_ENABLE) {
mbed_official 15:a81a8d6c1dfe 163 return STATUS_ERR_DENIED;
mbed_official 15:a81a8d6c1dfe 164 }
mbed_official 15:a81a8d6c1dfe 165
mbed_official 15:a81a8d6c1dfe 166 /* Check if reset is in progress. */
mbed_official 15:a81a8d6c1dfe 167 if (i2c_hw->CTRLA.reg & SERCOM_I2CS_CTRLA_SWRST) {
mbed_official 15:a81a8d6c1dfe 168 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 169 }
mbed_official 15:a81a8d6c1dfe 170
mbed_official 15:a81a8d6c1dfe 171 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 15:a81a8d6c1dfe 172 uint32_t pm_index, gclk_index;
mbed_official 15:a81a8d6c1dfe 173 #if (SAML21) || (SAMC20) || (SAMC21)
mbed_official 15:a81a8d6c1dfe 174 #if (SAML21)
mbed_official 15:a81a8d6c1dfe 175 if (sercom_index == 5) {
mbed_official 15:a81a8d6c1dfe 176 pm_index = MCLK_APBDMASK_SERCOM5_Pos;
mbed_official 15:a81a8d6c1dfe 177 gclk_index = SERCOM5_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 178 } else {
mbed_official 15:a81a8d6c1dfe 179 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 15:a81a8d6c1dfe 180 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 181 }
mbed_official 15:a81a8d6c1dfe 182 #else
mbed_official 15:a81a8d6c1dfe 183 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 15:a81a8d6c1dfe 184 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 185 #endif
mbed_official 15:a81a8d6c1dfe 186 #else
mbed_official 15:a81a8d6c1dfe 187 pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
mbed_official 15:a81a8d6c1dfe 188 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 189 #endif
mbed_official 15:a81a8d6c1dfe 190
mbed_official 15:a81a8d6c1dfe 191 /* Turn on module in PM */
mbed_official 15:a81a8d6c1dfe 192 #if (SAML21)
mbed_official 15:a81a8d6c1dfe 193 if (sercom_index == 5) {
mbed_official 15:a81a8d6c1dfe 194 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
mbed_official 15:a81a8d6c1dfe 195 } else {
mbed_official 15:a81a8d6c1dfe 196 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 15:a81a8d6c1dfe 197 }
mbed_official 15:a81a8d6c1dfe 198 #else
mbed_official 15:a81a8d6c1dfe 199 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 15:a81a8d6c1dfe 200 #endif
mbed_official 15:a81a8d6c1dfe 201
mbed_official 15:a81a8d6c1dfe 202 /* Set up the GCLK for the module */
mbed_official 15:a81a8d6c1dfe 203 struct system_gclk_chan_config gclk_chan_conf;
mbed_official 15:a81a8d6c1dfe 204 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
mbed_official 15:a81a8d6c1dfe 205 gclk_chan_conf.source_generator = config->generator_source;
mbed_official 15:a81a8d6c1dfe 206 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
mbed_official 15:a81a8d6c1dfe 207 system_gclk_chan_enable(gclk_index);
mbed_official 15:a81a8d6c1dfe 208 sercom_set_gclk_generator(config->generator_source, false);
mbed_official 15:a81a8d6c1dfe 209
mbed_official 15:a81a8d6c1dfe 210 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 211 /* Get sercom instance index. */
mbed_official 15:a81a8d6c1dfe 212 uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 15:a81a8d6c1dfe 213
mbed_official 15:a81a8d6c1dfe 214 /* Save software module in interrupt handler. */
mbed_official 15:a81a8d6c1dfe 215 _sercom_set_handler(instance_index, _i2c_slave_interrupt_handler);
mbed_official 15:a81a8d6c1dfe 216
mbed_official 15:a81a8d6c1dfe 217 /* Save software module. */
mbed_official 15:a81a8d6c1dfe 218 _sercom_instances[instance_index] = module;
mbed_official 15:a81a8d6c1dfe 219
mbed_official 15:a81a8d6c1dfe 220 /* Initialize values in module. */
mbed_official 15:a81a8d6c1dfe 221 module->registered_callback = 0;
mbed_official 15:a81a8d6c1dfe 222 module->enabled_callback = 0;
mbed_official 15:a81a8d6c1dfe 223 module->buffer_length = 0;
mbed_official 15:a81a8d6c1dfe 224 module->nack_on_address = config->enable_nack_on_address;
mbed_official 15:a81a8d6c1dfe 225 #endif
mbed_official 15:a81a8d6c1dfe 226
mbed_official 15:a81a8d6c1dfe 227 /* Set SERCOM module to operate in I2C slave mode. */
mbed_official 15:a81a8d6c1dfe 228 i2c_hw->CTRLA.reg = SERCOM_I2CS_CTRLA_MODE(0x4);
mbed_official 15:a81a8d6c1dfe 229
mbed_official 15:a81a8d6c1dfe 230 /* Set config and return status. */
mbed_official 15:a81a8d6c1dfe 231 return _i2c_slave_set_config(module, config);
mbed_official 15:a81a8d6c1dfe 232 }
mbed_official 15:a81a8d6c1dfe 233
mbed_official 15:a81a8d6c1dfe 234 /**
mbed_official 15:a81a8d6c1dfe 235 * \brief Resets the hardware module
mbed_official 15:a81a8d6c1dfe 236 *
mbed_official 15:a81a8d6c1dfe 237 * This will reset the module to hardware defaults.
mbed_official 15:a81a8d6c1dfe 238 *
mbed_official 15:a81a8d6c1dfe 239 * \param[in,out] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 240 */
mbed_official 15:a81a8d6c1dfe 241 void i2c_slave_reset(
mbed_official 15:a81a8d6c1dfe 242 struct i2c_slave_module *const module)
mbed_official 15:a81a8d6c1dfe 243 {
mbed_official 15:a81a8d6c1dfe 244 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 245 Assert(module);
mbed_official 15:a81a8d6c1dfe 246 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 247
mbed_official 15:a81a8d6c1dfe 248 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 249
mbed_official 15:a81a8d6c1dfe 250 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 251 /* Reset module instance. */
mbed_official 15:a81a8d6c1dfe 252 module->registered_callback = 0;
mbed_official 15:a81a8d6c1dfe 253 module->enabled_callback = 0;
mbed_official 15:a81a8d6c1dfe 254 module->buffer_length = 0;
mbed_official 15:a81a8d6c1dfe 255 module->buffer_remaining = 0;
mbed_official 15:a81a8d6c1dfe 256 module->buffer = NULL;
mbed_official 15:a81a8d6c1dfe 257 #endif
mbed_official 15:a81a8d6c1dfe 258
mbed_official 15:a81a8d6c1dfe 259 /* Disable module */
mbed_official 15:a81a8d6c1dfe 260 i2c_slave_disable(module);
mbed_official 15:a81a8d6c1dfe 261
mbed_official 15:a81a8d6c1dfe 262 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 263 /* Clear all pending interrupts. */
mbed_official 15:a81a8d6c1dfe 264 system_interrupt_enter_critical_section();
mbed_official 15:a81a8d6c1dfe 265 system_interrupt_clear_pending(_sercom_get_interrupt_vector(module->hw));
mbed_official 15:a81a8d6c1dfe 266 system_interrupt_leave_critical_section();
mbed_official 15:a81a8d6c1dfe 267 #endif
mbed_official 15:a81a8d6c1dfe 268
mbed_official 15:a81a8d6c1dfe 269 /* Wait for sync. */
mbed_official 15:a81a8d6c1dfe 270 _i2c_slave_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 271
mbed_official 15:a81a8d6c1dfe 272 /* Reset module. */
mbed_official 15:a81a8d6c1dfe 273 i2c_hw->CTRLA.reg = SERCOM_I2CS_CTRLA_SWRST;
mbed_official 15:a81a8d6c1dfe 274 }
mbed_official 15:a81a8d6c1dfe 275
mbed_official 15:a81a8d6c1dfe 276 /**
mbed_official 15:a81a8d6c1dfe 277 * \internal Waits for answer on bus
mbed_official 15:a81a8d6c1dfe 278 *
mbed_official 15:a81a8d6c1dfe 279 * \param[in] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 280 *
mbed_official 15:a81a8d6c1dfe 281 * \return Status of bus.
mbed_official 15:a81a8d6c1dfe 282 * \retval STATUS_OK If given response from slave device
mbed_official 15:a81a8d6c1dfe 283 * \retval STATUS_ERR_TIMEOUT If no response was given within specified timeout
mbed_official 15:a81a8d6c1dfe 284 * period
mbed_official 15:a81a8d6c1dfe 285 */
mbed_official 15:a81a8d6c1dfe 286 static enum status_code _i2c_slave_wait_for_bus(
mbed_official 15:a81a8d6c1dfe 287 struct i2c_slave_module *const module)
mbed_official 15:a81a8d6c1dfe 288 {
mbed_official 15:a81a8d6c1dfe 289 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 290 Assert(module);
mbed_official 15:a81a8d6c1dfe 291 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 292
mbed_official 15:a81a8d6c1dfe 293 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 294
mbed_official 15:a81a8d6c1dfe 295 /* Wait for reply. */
mbed_official 15:a81a8d6c1dfe 296 uint16_t timeout_counter = 0;
mbed_official 15:a81a8d6c1dfe 297 while ((!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY)) &&
mbed_official 15:a81a8d6c1dfe 298 (!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC)) &&
mbed_official 15:a81a8d6c1dfe 299 (!(i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH))) {
mbed_official 15:a81a8d6c1dfe 300
mbed_official 15:a81a8d6c1dfe 301 /* Check timeout condition. */
mbed_official 15:a81a8d6c1dfe 302 if (++timeout_counter >= module->buffer_timeout) {
mbed_official 15:a81a8d6c1dfe 303 return STATUS_ERR_TIMEOUT;
mbed_official 15:a81a8d6c1dfe 304 }
mbed_official 15:a81a8d6c1dfe 305 }
mbed_official 15:a81a8d6c1dfe 306 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 307 }
mbed_official 15:a81a8d6c1dfe 308
mbed_official 15:a81a8d6c1dfe 309 /**
mbed_official 15:a81a8d6c1dfe 310 * \brief Writes a packet to the master
mbed_official 15:a81a8d6c1dfe 311 *
mbed_official 15:a81a8d6c1dfe 312 * Writes a packet to the master. This will wait for the master to issue
mbed_official 15:a81a8d6c1dfe 313 * a request.
mbed_official 15:a81a8d6c1dfe 314 *
mbed_official 15:a81a8d6c1dfe 315 * \param[in] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 316 * \param[in] packet Packet to write to master
mbed_official 15:a81a8d6c1dfe 317 *
mbed_official 15:a81a8d6c1dfe 318 * \return Status of packet write.
mbed_official 15:a81a8d6c1dfe 319 * \retval STATUS_OK Packet was written successfully
mbed_official 15:a81a8d6c1dfe 320 * \retval STATUS_ERR_DENIED Start condition not received, another
mbed_official 15:a81a8d6c1dfe 321 * interrupt flag is set
mbed_official 15:a81a8d6c1dfe 322 * \retval STATUS_ERR_IO There was an error in the previous transfer
mbed_official 15:a81a8d6c1dfe 323 * \retval STATUS_ERR_BAD_FORMAT Master wants to write data
mbed_official 15:a81a8d6c1dfe 324 * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) was provided
mbed_official 15:a81a8d6c1dfe 325 * \retval STATUS_ERR_BUSY The I<SUP>2</SUP>C module is busy with a job
mbed_official 15:a81a8d6c1dfe 326 * \retval STATUS_ERR_ERR_OVERFLOW Master NACKed before entire packet was
mbed_official 15:a81a8d6c1dfe 327 * transferred
mbed_official 15:a81a8d6c1dfe 328 * \retval STATUS_ERR_TIMEOUT No response was given within the timeout
mbed_official 15:a81a8d6c1dfe 329 * period
mbed_official 15:a81a8d6c1dfe 330 */
mbed_official 15:a81a8d6c1dfe 331 enum status_code i2c_slave_write_packet_wait(
mbed_official 15:a81a8d6c1dfe 332 struct i2c_slave_module *const module,
mbed_official 15:a81a8d6c1dfe 333 struct i2c_slave_packet *const packet)
mbed_official 15:a81a8d6c1dfe 334 {
mbed_official 15:a81a8d6c1dfe 335 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 336 Assert(module);
mbed_official 15:a81a8d6c1dfe 337 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 338 Assert(packet);
mbed_official 15:a81a8d6c1dfe 339
mbed_official 15:a81a8d6c1dfe 340 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 341
mbed_official 15:a81a8d6c1dfe 342 uint16_t length = packet->data_length;
mbed_official 15:a81a8d6c1dfe 343
mbed_official 15:a81a8d6c1dfe 344 if (length == 0) {
mbed_official 15:a81a8d6c1dfe 345 return STATUS_ERR_INVALID_ARG;
mbed_official 15:a81a8d6c1dfe 346 }
mbed_official 15:a81a8d6c1dfe 347
mbed_official 15:a81a8d6c1dfe 348 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 349 /* Check if the module is busy with a job or AMATCH is enabled */
mbed_official 15:a81a8d6c1dfe 350 if (module->buffer_remaining > 0 ||
mbed_official 15:a81a8d6c1dfe 351 (i2c_hw->INTENSET.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 352 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 353 }
mbed_official 15:a81a8d6c1dfe 354 #endif
mbed_official 15:a81a8d6c1dfe 355
mbed_official 15:a81a8d6c1dfe 356 enum status_code status;
mbed_official 15:a81a8d6c1dfe 357 /* Wait for master to send address packet */
mbed_official 15:a81a8d6c1dfe 358 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 359
mbed_official 15:a81a8d6c1dfe 360 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 361 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 362 return status;
mbed_official 15:a81a8d6c1dfe 363 }
mbed_official 15:a81a8d6c1dfe 364 if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 365 /* Not address interrupt, something is wrong */
mbed_official 15:a81a8d6c1dfe 366 return STATUS_ERR_DENIED;
mbed_official 15:a81a8d6c1dfe 367 }
mbed_official 15:a81a8d6c1dfe 368
mbed_official 15:a81a8d6c1dfe 369 if (module->ten_bit_address) {
mbed_official 15:a81a8d6c1dfe 370 /* ACK the first address */
mbed_official 15:a81a8d6c1dfe 371 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 372 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
mbed_official 15:a81a8d6c1dfe 373
mbed_official 15:a81a8d6c1dfe 374 /* Wait for address interrupt */
mbed_official 15:a81a8d6c1dfe 375 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 376
mbed_official 15:a81a8d6c1dfe 377 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 378 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 379 return STATUS_ERR_TIMEOUT;
mbed_official 15:a81a8d6c1dfe 380 }
mbed_official 15:a81a8d6c1dfe 381
mbed_official 15:a81a8d6c1dfe 382 if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 383 /* Not address interrupt, something is wrong */
mbed_official 15:a81a8d6c1dfe 384 return STATUS_ERR_DENIED;
mbed_official 15:a81a8d6c1dfe 385 }
mbed_official 15:a81a8d6c1dfe 386 }
mbed_official 15:a81a8d6c1dfe 387
mbed_official 15:a81a8d6c1dfe 388 /* Check if there was an error in last transfer */
mbed_official 15:a81a8d6c1dfe 389 if (i2c_hw->STATUS.reg & (SERCOM_I2CS_STATUS_BUSERR |
mbed_official 15:a81a8d6c1dfe 390 SERCOM_I2CS_STATUS_COLL | SERCOM_I2CS_STATUS_LOWTOUT)) {
mbed_official 15:a81a8d6c1dfe 391 return STATUS_ERR_IO;
mbed_official 15:a81a8d6c1dfe 392 }
mbed_official 15:a81a8d6c1dfe 393
mbed_official 15:a81a8d6c1dfe 394 /* Check direction */
mbed_official 15:a81a8d6c1dfe 395 if (!(i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
mbed_official 15:a81a8d6c1dfe 396 /* Write request from master, send NACK and return */
mbed_official 15:a81a8d6c1dfe 397 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 398 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
mbed_official 15:a81a8d6c1dfe 399 return STATUS_ERR_BAD_FORMAT;
mbed_official 15:a81a8d6c1dfe 400 }
mbed_official 15:a81a8d6c1dfe 401
mbed_official 15:a81a8d6c1dfe 402 /* Read request from master, ACK address */
mbed_official 15:a81a8d6c1dfe 403 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 404 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
mbed_official 15:a81a8d6c1dfe 405
mbed_official 15:a81a8d6c1dfe 406 uint16_t i = 0;
mbed_official 15:a81a8d6c1dfe 407
mbed_official 15:a81a8d6c1dfe 408 /* Wait for data interrupt */
mbed_official 15:a81a8d6c1dfe 409 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 410 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 411 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 412 return status;
mbed_official 15:a81a8d6c1dfe 413 }
mbed_official 15:a81a8d6c1dfe 414
mbed_official 15:a81a8d6c1dfe 415 while (length--) {
mbed_official 15:a81a8d6c1dfe 416 /* Write data */
mbed_official 15:a81a8d6c1dfe 417 _i2c_slave_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 418 i2c_hw->DATA.reg = packet->data[i++];
mbed_official 15:a81a8d6c1dfe 419
mbed_official 15:a81a8d6c1dfe 420 /* Wait for response from master */
mbed_official 15:a81a8d6c1dfe 421 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 422
mbed_official 15:a81a8d6c1dfe 423 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 424 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 425 return status;
mbed_official 15:a81a8d6c1dfe 426 }
mbed_official 15:a81a8d6c1dfe 427
mbed_official 15:a81a8d6c1dfe 428 if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_RXNACK &&
mbed_official 15:a81a8d6c1dfe 429 length !=0) {
mbed_official 15:a81a8d6c1dfe 430 /* NACK from master, abort */
mbed_official 15:a81a8d6c1dfe 431 /* Release line */
mbed_official 15:a81a8d6c1dfe 432 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02);
mbed_official 15:a81a8d6c1dfe 433
mbed_official 15:a81a8d6c1dfe 434 return STATUS_ERR_OVERFLOW;
mbed_official 15:a81a8d6c1dfe 435 }
mbed_official 15:a81a8d6c1dfe 436 /* ACK from master, continue writing */
mbed_official 15:a81a8d6c1dfe 437 }
mbed_official 15:a81a8d6c1dfe 438
mbed_official 15:a81a8d6c1dfe 439 /* Release line */
mbed_official 15:a81a8d6c1dfe 440 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02);
mbed_official 15:a81a8d6c1dfe 441
mbed_official 15:a81a8d6c1dfe 442 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 443 }
mbed_official 15:a81a8d6c1dfe 444
mbed_official 15:a81a8d6c1dfe 445 /**
mbed_official 15:a81a8d6c1dfe 446 * \brief Reads a packet from the master
mbed_official 15:a81a8d6c1dfe 447 *
mbed_official 15:a81a8d6c1dfe 448 * Reads a packet from the master. This will wait for the master to issue a
mbed_official 15:a81a8d6c1dfe 449 * request.
mbed_official 15:a81a8d6c1dfe 450 *
mbed_official 15:a81a8d6c1dfe 451 * \param[in] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 452 * \param[out] packet Packet to read from master
mbed_official 15:a81a8d6c1dfe 453 *
mbed_official 15:a81a8d6c1dfe 454 * \return Status of packet read.
mbed_official 15:a81a8d6c1dfe 455 * \retval STATUS_OK Packet was read successfully
mbed_official 15:a81a8d6c1dfe 456 * \retval STATUS_ABORTED Master sent stop condition or repeated
mbed_official 15:a81a8d6c1dfe 457 * start before specified length of bytes
mbed_official 15:a81a8d6c1dfe 458 * was received
mbed_official 15:a81a8d6c1dfe 459 * \retval STATUS_ERR_IO There was an error in the previous transfer
mbed_official 15:a81a8d6c1dfe 460 * \retval STATUS_ERR_DENIED Start condition not received, another
mbed_official 15:a81a8d6c1dfe 461 * interrupt flag is set
mbed_official 15:a81a8d6c1dfe 462 * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) was provided
mbed_official 15:a81a8d6c1dfe 463 * \retval STATUS_ERR_BUSY The I<SUP>2</SUP>C module is busy with a job
mbed_official 15:a81a8d6c1dfe 464 * \retval STATUS_ERR_BAD_FORMAT Master wants to read data
mbed_official 15:a81a8d6c1dfe 465 * \retval STATUS_ERR_ERR_OVERFLOW Last byte received overflows buffer
mbed_official 15:a81a8d6c1dfe 466 */
mbed_official 15:a81a8d6c1dfe 467 enum status_code i2c_slave_read_packet_wait(
mbed_official 15:a81a8d6c1dfe 468 struct i2c_slave_module *const module,
mbed_official 15:a81a8d6c1dfe 469 struct i2c_slave_packet *const packet)
mbed_official 15:a81a8d6c1dfe 470 {
mbed_official 15:a81a8d6c1dfe 471 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 472 Assert(module);
mbed_official 15:a81a8d6c1dfe 473 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 474 Assert(packet);
mbed_official 15:a81a8d6c1dfe 475
mbed_official 15:a81a8d6c1dfe 476 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 477
mbed_official 15:a81a8d6c1dfe 478 uint16_t length = packet->data_length;
mbed_official 15:a81a8d6c1dfe 479
mbed_official 15:a81a8d6c1dfe 480 if (length == 0) {
mbed_official 15:a81a8d6c1dfe 481 return STATUS_ERR_INVALID_ARG;
mbed_official 15:a81a8d6c1dfe 482 }
mbed_official 15:a81a8d6c1dfe 483
mbed_official 15:a81a8d6c1dfe 484 #if I2C_SLAVE_CALLBACK_MODE == true
mbed_official 15:a81a8d6c1dfe 485 /* Check if the module is busy with a job or AMATCH is enabled */
mbed_official 15:a81a8d6c1dfe 486 if (module->buffer_remaining > 0 ||
mbed_official 15:a81a8d6c1dfe 487 (i2c_hw->INTENSET.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 488 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 489 }
mbed_official 15:a81a8d6c1dfe 490 #endif
mbed_official 15:a81a8d6c1dfe 491
mbed_official 15:a81a8d6c1dfe 492 enum status_code status;
mbed_official 15:a81a8d6c1dfe 493
mbed_official 15:a81a8d6c1dfe 494 /* Wait for master to send address packet */
mbed_official 15:a81a8d6c1dfe 495 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 496 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 497 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 498 return status;
mbed_official 15:a81a8d6c1dfe 499 }
mbed_official 15:a81a8d6c1dfe 500
mbed_official 15:a81a8d6c1dfe 501 if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 502 /* Not address interrupt, something is wrong */
mbed_official 15:a81a8d6c1dfe 503 return STATUS_ERR_DENIED;
mbed_official 15:a81a8d6c1dfe 504 }
mbed_official 15:a81a8d6c1dfe 505
mbed_official 15:a81a8d6c1dfe 506 /* Check if there was an error in the last transfer */
mbed_official 15:a81a8d6c1dfe 507 if (i2c_hw->STATUS.reg & (SERCOM_I2CS_STATUS_BUSERR |
mbed_official 15:a81a8d6c1dfe 508 SERCOM_I2CS_STATUS_COLL | SERCOM_I2CS_STATUS_LOWTOUT)) {
mbed_official 15:a81a8d6c1dfe 509 return STATUS_ERR_IO;
mbed_official 15:a81a8d6c1dfe 510 }
mbed_official 15:a81a8d6c1dfe 511 /* Check direction */
mbed_official 15:a81a8d6c1dfe 512 if ((i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
mbed_official 15:a81a8d6c1dfe 513 /* Read request from master, send NACK and return */
mbed_official 15:a81a8d6c1dfe 514 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 515 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
mbed_official 15:a81a8d6c1dfe 516 return STATUS_ERR_BAD_FORMAT;
mbed_official 15:a81a8d6c1dfe 517 }
mbed_official 15:a81a8d6c1dfe 518
mbed_official 15:a81a8d6c1dfe 519 /* Write request from master, ACK address */
mbed_official 15:a81a8d6c1dfe 520 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 521 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
mbed_official 15:a81a8d6c1dfe 522
mbed_official 15:a81a8d6c1dfe 523 uint16_t i = 0;
mbed_official 15:a81a8d6c1dfe 524 while (length--) {
mbed_official 15:a81a8d6c1dfe 525
mbed_official 15:a81a8d6c1dfe 526 /* Wait for next byte or stop condition */
mbed_official 15:a81a8d6c1dfe 527 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 528 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 529 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 530 return status;
mbed_official 15:a81a8d6c1dfe 531 }
mbed_official 15:a81a8d6c1dfe 532
mbed_official 15:a81a8d6c1dfe 533 if ((i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) ||
mbed_official 15:a81a8d6c1dfe 534 i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
mbed_official 15:a81a8d6c1dfe 535 /* Master sent stop condition, or repeated start, read done */
mbed_official 15:a81a8d6c1dfe 536 /* Clear stop flag */
mbed_official 15:a81a8d6c1dfe 537 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
mbed_official 15:a81a8d6c1dfe 538 return STATUS_ABORTED;
mbed_official 15:a81a8d6c1dfe 539 }
mbed_official 15:a81a8d6c1dfe 540
mbed_official 15:a81a8d6c1dfe 541 /* Read data */
mbed_official 15:a81a8d6c1dfe 542 _i2c_slave_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 543 packet->data[i++] = i2c_hw->DATA.reg;
mbed_official 15:a81a8d6c1dfe 544
mbed_official 15:a81a8d6c1dfe 545 }
mbed_official 15:a81a8d6c1dfe 546
mbed_official 15:a81a8d6c1dfe 547 /* Packet read done, wait for packet to NACK, Stop or repeated start */
mbed_official 15:a81a8d6c1dfe 548 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 549
mbed_official 15:a81a8d6c1dfe 550 if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY) {
mbed_official 15:a81a8d6c1dfe 551 /* Buffer is full, send NACK */
mbed_official 15:a81a8d6c1dfe 552 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 553 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2);
mbed_official 15:a81a8d6c1dfe 554 }
mbed_official 15:a81a8d6c1dfe 555 if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) {
mbed_official 15:a81a8d6c1dfe 556 /* Clear stop flag */
mbed_official 15:a81a8d6c1dfe 557 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
mbed_official 15:a81a8d6c1dfe 558 }
mbed_official 15:a81a8d6c1dfe 559 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 560 }
mbed_official 15:a81a8d6c1dfe 561
mbed_official 15:a81a8d6c1dfe 562 /**
mbed_official 15:a81a8d6c1dfe 563 * \brief Waits for a start condition on the bus
mbed_official 15:a81a8d6c1dfe 564 *
mbed_official 15:a81a8d6c1dfe 565 * \note This function is only available for 7-bit slave addressing.
mbed_official 15:a81a8d6c1dfe 566 *
mbed_official 15:a81a8d6c1dfe 567 * Waits for the master to issue a start condition on the bus.
mbed_official 15:a81a8d6c1dfe 568 * Note that this function does not check for errors in the last transfer,
mbed_official 15:a81a8d6c1dfe 569 * this will be discovered when reading or writing.
mbed_official 15:a81a8d6c1dfe 570 *
mbed_official 15:a81a8d6c1dfe 571 * \param[in] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 572 *
mbed_official 15:a81a8d6c1dfe 573 * \return Direction of the current transfer, when in slave mode.
mbed_official 15:a81a8d6c1dfe 574 * \retval I2C_SLAVE_DIRECTION_NONE No request from master within timeout
mbed_official 15:a81a8d6c1dfe 575 * period
mbed_official 15:a81a8d6c1dfe 576 * \retval I2C_SLAVE_DIRECTION_READ Write request from master
mbed_official 15:a81a8d6c1dfe 577 * \retval I2C_SLAVE_DIRECTION_WRITE Read request from master
mbed_official 15:a81a8d6c1dfe 578 */
mbed_official 15:a81a8d6c1dfe 579 enum i2c_slave_direction i2c_slave_get_direction_wait(
mbed_official 15:a81a8d6c1dfe 580 struct i2c_slave_module *const module)
mbed_official 15:a81a8d6c1dfe 581 {
mbed_official 15:a81a8d6c1dfe 582 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 583 Assert(module);
mbed_official 15:a81a8d6c1dfe 584 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 585
mbed_official 15:a81a8d6c1dfe 586 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 587
mbed_official 15:a81a8d6c1dfe 588 enum status_code status;
mbed_official 15:a81a8d6c1dfe 589
mbed_official 15:a81a8d6c1dfe 590 /* Wait for address interrupt */
mbed_official 15:a81a8d6c1dfe 591 status = _i2c_slave_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 592
mbed_official 15:a81a8d6c1dfe 593 if (status != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 594 /* Timeout, return */
mbed_official 15:a81a8d6c1dfe 595 return I2C_SLAVE_DIRECTION_NONE;
mbed_official 15:a81a8d6c1dfe 596 }
mbed_official 15:a81a8d6c1dfe 597
mbed_official 15:a81a8d6c1dfe 598 if (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH)) {
mbed_official 15:a81a8d6c1dfe 599 /* Not address interrupt, something is wrong */
mbed_official 15:a81a8d6c1dfe 600 return I2C_SLAVE_DIRECTION_NONE;
mbed_official 15:a81a8d6c1dfe 601 }
mbed_official 15:a81a8d6c1dfe 602
mbed_official 15:a81a8d6c1dfe 603 /* Check direction */
mbed_official 15:a81a8d6c1dfe 604 if ((i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR)) {
mbed_official 15:a81a8d6c1dfe 605 /* Read request from master */
mbed_official 15:a81a8d6c1dfe 606 return I2C_SLAVE_DIRECTION_WRITE;
mbed_official 15:a81a8d6c1dfe 607 } else {
mbed_official 15:a81a8d6c1dfe 608 /* Write request from master */
mbed_official 15:a81a8d6c1dfe 609 return I2C_SLAVE_DIRECTION_READ;
mbed_official 15:a81a8d6c1dfe 610 }
mbed_official 15:a81a8d6c1dfe 611 }
mbed_official 15:a81a8d6c1dfe 612
mbed_official 15:a81a8d6c1dfe 613 /**
mbed_official 15:a81a8d6c1dfe 614 * \brief Retrieves the current module status
mbed_official 15:a81a8d6c1dfe 615 *
mbed_official 15:a81a8d6c1dfe 616 * Checks the status of the module and returns it as a bitmask of status
mbed_official 15:a81a8d6c1dfe 617 * flags.
mbed_official 15:a81a8d6c1dfe 618 *
mbed_official 15:a81a8d6c1dfe 619 * \param[in] module Pointer to the I<SUP>2</SUP>C slave software device struct
mbed_official 15:a81a8d6c1dfe 620 *
mbed_official 15:a81a8d6c1dfe 621 * \return Bitmask of status flags.
mbed_official 15:a81a8d6c1dfe 622 *
mbed_official 15:a81a8d6c1dfe 623 * \retval I2C_SLAVE_STATUS_ADDRESS_MATCH A valid address has been received
mbed_official 15:a81a8d6c1dfe 624 * \retval I2C_SLAVE_STATUS_DATA_READY A I<SUP>2</SUP>C slave byte transmission is
mbed_official 15:a81a8d6c1dfe 625 * successfully completed
mbed_official 15:a81a8d6c1dfe 626 * \retval I2C_SLAVE_STATUS_STOP_RECEIVED A stop condition is detected for a
mbed_official 15:a81a8d6c1dfe 627 * transaction being processed
mbed_official 15:a81a8d6c1dfe 628 * \retval I2C_SLAVE_STATUS_CLOCK_HOLD The slave is holding the SCL line
mbed_official 15:a81a8d6c1dfe 629 * low
mbed_official 15:a81a8d6c1dfe 630 * \retval I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT An SCL low time-out has occurred
mbed_official 15:a81a8d6c1dfe 631 * \retval I2C_SLAVE_STATUS_REPEATED_START Indicates a repeated start, only
mbed_official 15:a81a8d6c1dfe 632 * valid if \ref
mbed_official 15:a81a8d6c1dfe 633 * I2C_SLAVE_STATUS_ADDRESS_MATCH is
mbed_official 15:a81a8d6c1dfe 634 * set
mbed_official 15:a81a8d6c1dfe 635 * \retval I2C_SLAVE_STATUS_RECEIVED_NACK The last data packet sent was not
mbed_official 15:a81a8d6c1dfe 636 * acknowledged
mbed_official 15:a81a8d6c1dfe 637 * \retval I2C_SLAVE_STATUS_COLLISION The I<SUP>2</SUP>C slave was not able to
mbed_official 15:a81a8d6c1dfe 638 * transmit a high data or NACK bit
mbed_official 15:a81a8d6c1dfe 639 * \retval I2C_SLAVE_STATUS_BUS_ERROR An illegal bus condition has
mbed_official 15:a81a8d6c1dfe 640 * occurred on the bus
mbed_official 15:a81a8d6c1dfe 641 */
mbed_official 15:a81a8d6c1dfe 642 uint32_t i2c_slave_get_status(
mbed_official 15:a81a8d6c1dfe 643 struct i2c_slave_module *const module)
mbed_official 15:a81a8d6c1dfe 644 {
mbed_official 15:a81a8d6c1dfe 645 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 646 Assert(module);
mbed_official 15:a81a8d6c1dfe 647 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 648
mbed_official 15:a81a8d6c1dfe 649 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 650
mbed_official 15:a81a8d6c1dfe 651 uint8_t intflags = i2c_hw->INTFLAG.reg;
mbed_official 15:a81a8d6c1dfe 652 uint8_t status = i2c_hw->STATUS.reg;
mbed_official 15:a81a8d6c1dfe 653 uint32_t status_flags = 0;
mbed_official 15:a81a8d6c1dfe 654
mbed_official 15:a81a8d6c1dfe 655 /* Check Address Match flag */
mbed_official 15:a81a8d6c1dfe 656 if (intflags & SERCOM_I2CS_INTFLAG_AMATCH) {
mbed_official 15:a81a8d6c1dfe 657 status_flags |= I2C_SLAVE_STATUS_ADDRESS_MATCH;
mbed_official 15:a81a8d6c1dfe 658 }
mbed_official 15:a81a8d6c1dfe 659 /* Check Data Ready flag */
mbed_official 15:a81a8d6c1dfe 660 if (intflags & SERCOM_I2CS_INTFLAG_DRDY) {
mbed_official 15:a81a8d6c1dfe 661 status_flags |= I2C_SLAVE_STATUS_DATA_READY;
mbed_official 15:a81a8d6c1dfe 662 }
mbed_official 15:a81a8d6c1dfe 663 /* Check Stop flag */
mbed_official 15:a81a8d6c1dfe 664 if (intflags & SERCOM_I2CS_INTFLAG_PREC) {
mbed_official 15:a81a8d6c1dfe 665 status_flags |= I2C_SLAVE_STATUS_STOP_RECEIVED;
mbed_official 15:a81a8d6c1dfe 666 }
mbed_official 15:a81a8d6c1dfe 667 /* Check Clock Hold */
mbed_official 15:a81a8d6c1dfe 668 if (status & SERCOM_I2CS_STATUS_CLKHOLD) {
mbed_official 15:a81a8d6c1dfe 669 status_flags |= I2C_SLAVE_STATUS_CLOCK_HOLD;
mbed_official 15:a81a8d6c1dfe 670 }
mbed_official 15:a81a8d6c1dfe 671 /* Check SCL Low Timeout */
mbed_official 15:a81a8d6c1dfe 672 if (status & SERCOM_I2CS_STATUS_LOWTOUT) {
mbed_official 15:a81a8d6c1dfe 673 status_flags |= I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT;
mbed_official 15:a81a8d6c1dfe 674 }
mbed_official 15:a81a8d6c1dfe 675 /* Check Repeated Start */
mbed_official 15:a81a8d6c1dfe 676 if (status & SERCOM_I2CS_STATUS_SR) {
mbed_official 15:a81a8d6c1dfe 677 status_flags |= I2C_SLAVE_STATUS_REPEATED_START;
mbed_official 15:a81a8d6c1dfe 678 }
mbed_official 15:a81a8d6c1dfe 679 /* Check Received Not Acknowledge */
mbed_official 15:a81a8d6c1dfe 680 if (status & SERCOM_I2CS_STATUS_RXNACK) {
mbed_official 15:a81a8d6c1dfe 681 status_flags |= I2C_SLAVE_STATUS_RECEIVED_NACK;
mbed_official 15:a81a8d6c1dfe 682 }
mbed_official 15:a81a8d6c1dfe 683 /* Check Transmit Collision */
mbed_official 15:a81a8d6c1dfe 684 if (status & SERCOM_I2CS_STATUS_COLL) {
mbed_official 15:a81a8d6c1dfe 685 status_flags |= I2C_SLAVE_STATUS_COLLISION;
mbed_official 15:a81a8d6c1dfe 686 }
mbed_official 15:a81a8d6c1dfe 687 /* Check Bus Error */
mbed_official 15:a81a8d6c1dfe 688 if (status & SERCOM_I2CS_STATUS_BUSERR) {
mbed_official 15:a81a8d6c1dfe 689 status_flags |= I2C_SLAVE_STATUS_BUS_ERROR;
mbed_official 15:a81a8d6c1dfe 690 }
mbed_official 15:a81a8d6c1dfe 691
mbed_official 15:a81a8d6c1dfe 692 return status_flags;
mbed_official 15:a81a8d6c1dfe 693 }
mbed_official 15:a81a8d6c1dfe 694
mbed_official 15:a81a8d6c1dfe 695 /**
mbed_official 15:a81a8d6c1dfe 696 * \brief Clears a module status flag
mbed_official 15:a81a8d6c1dfe 697 *
mbed_official 15:a81a8d6c1dfe 698 * Clears the given status flag of the module.
mbed_official 15:a81a8d6c1dfe 699 *
mbed_official 15:a81a8d6c1dfe 700 * \note Not all status flags can be cleared.
mbed_official 15:a81a8d6c1dfe 701 *
mbed_official 15:a81a8d6c1dfe 702 * \param[in] module Pointer to the I<SUP>2</SUP>C software device struct
mbed_official 15:a81a8d6c1dfe 703 * \param[in] status_flags Bit mask of status flags to clear
mbed_official 15:a81a8d6c1dfe 704 *
mbed_official 15:a81a8d6c1dfe 705 */
mbed_official 15:a81a8d6c1dfe 706 void i2c_slave_clear_status(
mbed_official 15:a81a8d6c1dfe 707 struct i2c_slave_module *const module,
mbed_official 15:a81a8d6c1dfe 708 uint32_t status_flags)
mbed_official 15:a81a8d6c1dfe 709 {
mbed_official 15:a81a8d6c1dfe 710 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 711 Assert(module);
mbed_official 15:a81a8d6c1dfe 712 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 713
mbed_official 15:a81a8d6c1dfe 714 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
mbed_official 15:a81a8d6c1dfe 715
mbed_official 15:a81a8d6c1dfe 716 /* Clear Address Match flag */
mbed_official 15:a81a8d6c1dfe 717 if (status_flags & I2C_SLAVE_STATUS_ADDRESS_MATCH) {
mbed_official 15:a81a8d6c1dfe 718 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
mbed_official 15:a81a8d6c1dfe 719 }
mbed_official 15:a81a8d6c1dfe 720 /* Clear Data Ready flag */
mbed_official 15:a81a8d6c1dfe 721 if (status_flags & I2C_SLAVE_STATUS_DATA_READY) {
mbed_official 15:a81a8d6c1dfe 722 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_DRDY;
mbed_official 15:a81a8d6c1dfe 723 }
mbed_official 15:a81a8d6c1dfe 724 /* Clear Stop flag */
mbed_official 15:a81a8d6c1dfe 725 if (status_flags & I2C_SLAVE_STATUS_STOP_RECEIVED) {
mbed_official 15:a81a8d6c1dfe 726 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
mbed_official 15:a81a8d6c1dfe 727 }
mbed_official 15:a81a8d6c1dfe 728 /* Clear SCL Low Timeout */
mbed_official 15:a81a8d6c1dfe 729 if (status_flags & I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT) {
mbed_official 15:a81a8d6c1dfe 730 i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_LOWTOUT;
mbed_official 15:a81a8d6c1dfe 731 }
mbed_official 15:a81a8d6c1dfe 732 /* Clear Transmit Collision */
mbed_official 15:a81a8d6c1dfe 733 if (status_flags & I2C_SLAVE_STATUS_COLLISION) {
mbed_official 15:a81a8d6c1dfe 734 i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_COLL;
mbed_official 15:a81a8d6c1dfe 735 }
mbed_official 15:a81a8d6c1dfe 736 /* Clear Bus Error */
mbed_official 15:a81a8d6c1dfe 737 if (status_flags & I2C_SLAVE_STATUS_BUS_ERROR) {
mbed_official 15:a81a8d6c1dfe 738 i2c_hw->STATUS.reg = SERCOM_I2CS_STATUS_BUSERR;
mbed_official 15:a81a8d6c1dfe 739 }
mbed_official 15:a81a8d6c1dfe 740 }