mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

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

Committer:
mbed_official
Date:
Fri Jul 17 09:15:10 2015 +0100
Revision:
592:a274ee790e56
Parent:
579:53297373a894
Synchronized with git revision e7144f83a8d75df80c4877936b6ffe552b0be9e6

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

More API implementation for SAMR21

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 579:53297373a894 1 #include "i2c_master.h"
mbed_official 579:53297373a894 2
mbed_official 579:53297373a894 3 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 4 # include "i2c_master_interrupt.h"
mbed_official 579:53297373a894 5 #endif
mbed_official 579:53297373a894 6
mbed_official 579:53297373a894 7 /* Forward declaration */
mbed_official 579:53297373a894 8 enum status_code _i2c_master_wait_for_bus(
mbed_official 579:53297373a894 9 struct i2c_master_module *const module);
mbed_official 579:53297373a894 10
mbed_official 579:53297373a894 11 enum status_code _i2c_master_address_response(
mbed_official 579:53297373a894 12 struct i2c_master_module *const module);
mbed_official 579:53297373a894 13
mbed_official 579:53297373a894 14 enum status_code _i2c_master_send_hs_master_code(
mbed_official 579:53297373a894 15 struct i2c_master_module *const module,
mbed_official 579:53297373a894 16 uint8_t hs_master_code);
mbed_official 579:53297373a894 17
mbed_official 579:53297373a894 18 #if !defined(__DOXYGEN__)
mbed_official 579:53297373a894 19
mbed_official 579:53297373a894 20 /**
mbed_official 579:53297373a894 21 * \internal Sets configurations to module
mbed_official 579:53297373a894 22 *
mbed_official 579:53297373a894 23 * \param[out] module Pointer to software module structure
mbed_official 579:53297373a894 24 * \param[in] config Configuration structure with configurations to set
mbed_official 579:53297373a894 25 *
mbed_official 579:53297373a894 26 * \return Status of setting configuration.
mbed_official 579:53297373a894 27 * \retval STATUS_OK If module was configured correctly
mbed_official 579:53297373a894 28 * \retval STATUS_ERR_ALREADY_INITIALIZED If setting other GCLK generator than
mbed_official 579:53297373a894 29 * previously set
mbed_official 579:53297373a894 30 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE If given baudrate is not compatible
mbed_official 579:53297373a894 31 * with set GCLK frequency
mbed_official 579:53297373a894 32 */
mbed_official 579:53297373a894 33 static enum status_code _i2c_master_set_config(
mbed_official 579:53297373a894 34 struct i2c_master_module *const module,
mbed_official 579:53297373a894 35 const struct i2c_master_config *const config)
mbed_official 579:53297373a894 36 {
mbed_official 579:53297373a894 37 /* Sanity check arguments. */
mbed_official 579:53297373a894 38 Assert(module);
mbed_official 579:53297373a894 39 Assert(module->hw);
mbed_official 579:53297373a894 40 Assert(config);
mbed_official 579:53297373a894 41
mbed_official 579:53297373a894 42 /* Temporary variables. */
mbed_official 579:53297373a894 43 uint32_t tmp_ctrla;
mbed_official 579:53297373a894 44 int32_t tmp_baud;
mbed_official 579:53297373a894 45 int32_t tmp_baud_hs;
mbed_official 579:53297373a894 46 enum status_code tmp_status_code = STATUS_OK;
mbed_official 579:53297373a894 47
mbed_official 579:53297373a894 48 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 49 Sercom *const sercom_hw = module->hw;
mbed_official 579:53297373a894 50
mbed_official 579:53297373a894 51 uint8_t sercom_index = _sercom_get_sercom_inst_index(sercom_hw);
mbed_official 579:53297373a894 52
mbed_official 579:53297373a894 53 /* Pin configuration */
mbed_official 579:53297373a894 54 struct system_pinmux_config pin_conf;
mbed_official 579:53297373a894 55 system_pinmux_get_config_defaults(&pin_conf);
mbed_official 579:53297373a894 56
mbed_official 579:53297373a894 57 uint32_t pad0 = config->pinmux_pad0;
mbed_official 579:53297373a894 58 uint32_t pad1 = config->pinmux_pad1;
mbed_official 579:53297373a894 59
mbed_official 579:53297373a894 60 /* SERCOM PAD0 - SDA */
mbed_official 579:53297373a894 61 if (pad0 == PINMUX_DEFAULT) {
mbed_official 579:53297373a894 62 pad0 = _sercom_get_default_pad(sercom_hw, 0);
mbed_official 579:53297373a894 63 }
mbed_official 579:53297373a894 64 pin_conf.mux_position = pad0 & 0xFFFF;
mbed_official 579:53297373a894 65 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
mbed_official 579:53297373a894 66 system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);
mbed_official 579:53297373a894 67
mbed_official 579:53297373a894 68 /* SERCOM PAD1 - SCL */
mbed_official 579:53297373a894 69 if (pad1 == PINMUX_DEFAULT) {
mbed_official 579:53297373a894 70 pad1 = _sercom_get_default_pad(sercom_hw, 1);
mbed_official 579:53297373a894 71 }
mbed_official 579:53297373a894 72 pin_conf.mux_position = pad1 & 0xFFFF;
mbed_official 579:53297373a894 73 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
mbed_official 579:53297373a894 74 system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);
mbed_official 579:53297373a894 75
mbed_official 579:53297373a894 76 /* Save timeout on unknown bus state in software module. */
mbed_official 579:53297373a894 77 module->unknown_bus_state_timeout = config->unknown_bus_state_timeout;
mbed_official 579:53297373a894 78
mbed_official 579:53297373a894 79 /* Save timeout on buffer write. */
mbed_official 579:53297373a894 80 module->buffer_timeout = config->buffer_timeout;
mbed_official 579:53297373a894 81
mbed_official 579:53297373a894 82 /* Set whether module should run in standby. */
mbed_official 579:53297373a894 83 if (config->run_in_standby || system_is_debugger_present()) {
mbed_official 579:53297373a894 84 tmp_ctrla = SERCOM_I2CM_CTRLA_RUNSTDBY;
mbed_official 579:53297373a894 85 } else {
mbed_official 579:53297373a894 86 tmp_ctrla = 0;
mbed_official 579:53297373a894 87 }
mbed_official 579:53297373a894 88
mbed_official 579:53297373a894 89 /* Check and set start data hold timeout. */
mbed_official 579:53297373a894 90 if (config->start_hold_time != I2C_MASTER_START_HOLD_TIME_DISABLED) {
mbed_official 579:53297373a894 91 tmp_ctrla |= config->start_hold_time;
mbed_official 579:53297373a894 92 }
mbed_official 579:53297373a894 93
mbed_official 579:53297373a894 94 /* Check and set transfer speed */
mbed_official 579:53297373a894 95 tmp_ctrla |= config->transfer_speed;
mbed_official 579:53297373a894 96
mbed_official 579:53297373a894 97 /* Check and set SCL low timeout. */
mbed_official 579:53297373a894 98 if (config->scl_low_timeout) {
mbed_official 579:53297373a894 99 tmp_ctrla |= SERCOM_I2CM_CTRLA_LOWTOUTEN;
mbed_official 579:53297373a894 100 }
mbed_official 579:53297373a894 101
mbed_official 579:53297373a894 102 /* Check and set inactive bus timeout. */
mbed_official 579:53297373a894 103 if (config->inactive_timeout != I2C_MASTER_INACTIVE_TIMEOUT_DISABLED) {
mbed_official 579:53297373a894 104 tmp_ctrla |= config->inactive_timeout;
mbed_official 579:53297373a894 105 }
mbed_official 579:53297373a894 106
mbed_official 579:53297373a894 107 /* Check and set SCL clock stretch mode. */
mbed_official 579:53297373a894 108 if (config->scl_stretch_only_after_ack_bit) {
mbed_official 579:53297373a894 109 tmp_ctrla |= SERCOM_I2CM_CTRLA_SCLSM;
mbed_official 579:53297373a894 110 }
mbed_official 579:53297373a894 111
mbed_official 579:53297373a894 112 /* Check and set slave SCL low extend timeout. */
mbed_official 579:53297373a894 113 if (config->slave_scl_low_extend_timeout) {
mbed_official 579:53297373a894 114 tmp_ctrla |= SERCOM_I2CM_CTRLA_SEXTTOEN;
mbed_official 579:53297373a894 115 }
mbed_official 579:53297373a894 116
mbed_official 579:53297373a894 117 /* Check and set master SCL low extend timeout. */
mbed_official 579:53297373a894 118 if (config->master_scl_low_extend_timeout) {
mbed_official 579:53297373a894 119 tmp_ctrla |= SERCOM_I2CM_CTRLA_MEXTTOEN;
mbed_official 579:53297373a894 120 }
mbed_official 579:53297373a894 121
mbed_official 579:53297373a894 122 /* Write config to register CTRLA. */
mbed_official 579:53297373a894 123 i2c_module->CTRLA.reg |= tmp_ctrla;
mbed_official 579:53297373a894 124
mbed_official 579:53297373a894 125 /* Set configurations in CTRLB. */
mbed_official 579:53297373a894 126 i2c_module->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
mbed_official 579:53297373a894 127
mbed_official 579:53297373a894 128 /* Find and set baudrate. */
mbed_official 579:53297373a894 129 tmp_baud = (int32_t)(div_ceil(
mbed_official 579:53297373a894 130 system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index),
mbed_official 579:53297373a894 131 (2000*(config->baud_rate))) - 5);
mbed_official 579:53297373a894 132
mbed_official 579:53297373a894 133 /* Check that baudrate is supported at current speed. */
mbed_official 579:53297373a894 134 if (tmp_baud > 255 || tmp_baud < 0) {
mbed_official 579:53297373a894 135 /* Baud rate not supported. */
mbed_official 579:53297373a894 136 tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
mbed_official 579:53297373a894 137 } else {
mbed_official 579:53297373a894 138 /* Find baudrate for high speed */
mbed_official 579:53297373a894 139 tmp_baud_hs = (int32_t)(div_ceil(
mbed_official 579:53297373a894 140 system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index),
mbed_official 579:53297373a894 141 (2000*(config->baud_rate_high_speed))) - 1);
mbed_official 579:53297373a894 142
mbed_official 579:53297373a894 143 /* Check that baudrate is supported at current speed. */
mbed_official 579:53297373a894 144 if (tmp_baud_hs > 255 || tmp_baud_hs < 0) {
mbed_official 579:53297373a894 145 /* Baud rate not supported. */
mbed_official 579:53297373a894 146 tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
mbed_official 579:53297373a894 147 }
mbed_official 579:53297373a894 148 }
mbed_official 579:53297373a894 149 if (tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE) {
mbed_official 579:53297373a894 150 /* Baud rate acceptable. */
mbed_official 579:53297373a894 151 i2c_module->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud) |
mbed_official 579:53297373a894 152 SERCOM_I2CM_BAUD_HSBAUD(tmp_baud_hs);
mbed_official 579:53297373a894 153 }
mbed_official 579:53297373a894 154
mbed_official 579:53297373a894 155 return tmp_status_code;
mbed_official 579:53297373a894 156 }
mbed_official 579:53297373a894 157 #endif /* __DOXYGEN__ */
mbed_official 579:53297373a894 158
mbed_official 579:53297373a894 159 /**
mbed_official 579:53297373a894 160 * \brief Initializes the requested I<SUP>2</SUP>C hardware module
mbed_official 579:53297373a894 161 *
mbed_official 579:53297373a894 162 * Initializes the SERCOM I<SUP>2</SUP>C master device requested and sets the provided
mbed_official 579:53297373a894 163 * software module struct. Run this function before any further use of
mbed_official 579:53297373a894 164 * the driver.
mbed_official 579:53297373a894 165 *
mbed_official 579:53297373a894 166 * \param[out] module Pointer to software module struct
mbed_official 579:53297373a894 167 * \param[in] hw Pointer to the hardware instance
mbed_official 579:53297373a894 168 * \param[in] config Pointer to the configuration struct
mbed_official 579:53297373a894 169 *
mbed_official 579:53297373a894 170 * \return Status of initialization.
mbed_official 579:53297373a894 171 * \retval STATUS_OK Module initiated correctly
mbed_official 579:53297373a894 172 * \retval STATUS_ERR_DENIED If module is enabled
mbed_official 579:53297373a894 173 * \retval STATUS_BUSY If module is busy resetting
mbed_official 579:53297373a894 174 * \retval STATUS_ERR_ALREADY_INITIALIZED If setting other GCLK generator than
mbed_official 579:53297373a894 175 * previously set
mbed_official 579:53297373a894 176 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE If given baudrate is not compatible
mbed_official 579:53297373a894 177 * with set GCLK frequency
mbed_official 579:53297373a894 178 *
mbed_official 579:53297373a894 179 */
mbed_official 579:53297373a894 180 enum status_code i2c_master_init(
mbed_official 579:53297373a894 181 struct i2c_master_module *const module,
mbed_official 579:53297373a894 182 Sercom *const hw,
mbed_official 579:53297373a894 183 const struct i2c_master_config *const config)
mbed_official 579:53297373a894 184 {
mbed_official 579:53297373a894 185 /* Sanity check arguments. */
mbed_official 579:53297373a894 186 Assert(module);
mbed_official 579:53297373a894 187 Assert(hw);
mbed_official 579:53297373a894 188 Assert(config);
mbed_official 579:53297373a894 189
mbed_official 579:53297373a894 190 /* Initialize software module */
mbed_official 579:53297373a894 191 module->hw = hw;
mbed_official 579:53297373a894 192
mbed_official 579:53297373a894 193 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 194
mbed_official 579:53297373a894 195 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 579:53297373a894 196 #if (SAML21)
mbed_official 579:53297373a894 197 uint32_t pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 579:53297373a894 198 #else
mbed_official 579:53297373a894 199 uint32_t pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
mbed_official 579:53297373a894 200 #endif
mbed_official 579:53297373a894 201 uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 579:53297373a894 202
mbed_official 579:53297373a894 203 /* Turn on module in PM */
mbed_official 579:53297373a894 204 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 579:53297373a894 205
mbed_official 579:53297373a894 206 /* Set up the GCLK for the module */
mbed_official 579:53297373a894 207 struct system_gclk_chan_config gclk_chan_conf;
mbed_official 579:53297373a894 208 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
mbed_official 579:53297373a894 209 gclk_chan_conf.source_generator = config->generator_source;
mbed_official 579:53297373a894 210 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
mbed_official 579:53297373a894 211 system_gclk_chan_enable(gclk_index);
mbed_official 579:53297373a894 212 sercom_set_gclk_generator(config->generator_source, false);
mbed_official 579:53297373a894 213
mbed_official 579:53297373a894 214 /* Check if module is enabled. */
mbed_official 579:53297373a894 215 if (i2c_module->CTRLA.reg & SERCOM_I2CM_CTRLA_ENABLE) {
mbed_official 579:53297373a894 216 return STATUS_ERR_DENIED;
mbed_official 579:53297373a894 217 }
mbed_official 579:53297373a894 218
mbed_official 579:53297373a894 219 /* Check if reset is in progress. */
mbed_official 579:53297373a894 220 if (i2c_module->CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST) {
mbed_official 579:53297373a894 221 return STATUS_BUSY;
mbed_official 579:53297373a894 222 }
mbed_official 579:53297373a894 223
mbed_official 579:53297373a894 224 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 225 /* Get sercom instance index and register callback. */
mbed_official 579:53297373a894 226 uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
mbed_official 579:53297373a894 227 _sercom_set_handler(instance_index, _i2c_master_interrupt_handler);
mbed_official 579:53297373a894 228 _sercom_instances[instance_index] = module;
mbed_official 579:53297373a894 229
mbed_official 579:53297373a894 230 /* Initialize values in module. */
mbed_official 579:53297373a894 231 module->registered_callback = 0;
mbed_official 579:53297373a894 232 module->enabled_callback = 0;
mbed_official 579:53297373a894 233 module->buffer_length = 0;
mbed_official 579:53297373a894 234 module->buffer_remaining = 0;
mbed_official 579:53297373a894 235
mbed_official 579:53297373a894 236 module->status = STATUS_OK;
mbed_official 579:53297373a894 237 module->buffer = NULL;
mbed_official 579:53297373a894 238 #endif
mbed_official 579:53297373a894 239
mbed_official 579:53297373a894 240 /* Set sercom module to operate in I2C master mode. */
mbed_official 579:53297373a894 241 i2c_module->CTRLA.reg = SERCOM_I2CM_CTRLA_MODE(0x5);
mbed_official 579:53297373a894 242
mbed_official 579:53297373a894 243 /* Set config and return status. */
mbed_official 579:53297373a894 244 return _i2c_master_set_config(module, config);
mbed_official 579:53297373a894 245 }
mbed_official 579:53297373a894 246
mbed_official 579:53297373a894 247 /**
mbed_official 579:53297373a894 248 * \brief Resets the hardware module
mbed_official 579:53297373a894 249 *
mbed_official 579:53297373a894 250 * Reset the module to hardware defaults.
mbed_official 579:53297373a894 251 *
mbed_official 579:53297373a894 252 * \param[in,out] module Pointer to software module structure
mbed_official 579:53297373a894 253 */
mbed_official 579:53297373a894 254 void i2c_master_reset(struct i2c_master_module *const module)
mbed_official 579:53297373a894 255 {
mbed_official 579:53297373a894 256 /* Sanity check arguments */
mbed_official 579:53297373a894 257 Assert(module);
mbed_official 579:53297373a894 258 Assert(module->hw);
mbed_official 579:53297373a894 259
mbed_official 579:53297373a894 260 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 261
mbed_official 579:53297373a894 262 /* Wait for sync */
mbed_official 579:53297373a894 263 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 264
mbed_official 579:53297373a894 265 /* Disable module */
mbed_official 579:53297373a894 266 i2c_master_disable(module);
mbed_official 579:53297373a894 267
mbed_official 579:53297373a894 268 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 269 /* Clear all pending interrupts */
mbed_official 579:53297373a894 270 system_interrupt_enter_critical_section();
mbed_official 579:53297373a894 271 system_interrupt_clear_pending(_sercom_get_interrupt_vector(module->hw));
mbed_official 579:53297373a894 272 system_interrupt_leave_critical_section();
mbed_official 579:53297373a894 273 #endif
mbed_official 579:53297373a894 274
mbed_official 579:53297373a894 275 /* Wait for sync */
mbed_official 579:53297373a894 276 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 277
mbed_official 579:53297373a894 278 /* Reset module */
mbed_official 579:53297373a894 279 i2c_module->CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
mbed_official 579:53297373a894 280 }
mbed_official 579:53297373a894 281
mbed_official 579:53297373a894 282 #if !defined(__DOXYGEN__)
mbed_official 579:53297373a894 283 /**
mbed_official 579:53297373a894 284 * \internal
mbed_official 579:53297373a894 285 * Address response. Called when address is answered or timed out.
mbed_official 579:53297373a894 286 *
mbed_official 579:53297373a894 287 * \param[in,out] module Pointer to software module structure
mbed_official 579:53297373a894 288 *
mbed_official 579:53297373a894 289 * \return Status of address response.
mbed_official 579:53297373a894 290 * \retval STATUS_OK No error has occurred
mbed_official 579:53297373a894 291 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 292 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 293 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 294 * acknowledged the address
mbed_official 579:53297373a894 295 */
mbed_official 579:53297373a894 296 enum status_code _i2c_master_address_response(
mbed_official 579:53297373a894 297 struct i2c_master_module *const module)
mbed_official 579:53297373a894 298 {
mbed_official 579:53297373a894 299 /* Sanity check arguments */
mbed_official 579:53297373a894 300 Assert(module);
mbed_official 579:53297373a894 301 Assert(module->hw);
mbed_official 579:53297373a894 302
mbed_official 579:53297373a894 303 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 304
mbed_official 579:53297373a894 305 /* Check for error and ignore bus-error; workaround for BUSSTATE stuck in
mbed_official 579:53297373a894 306 * BUSY */
mbed_official 579:53297373a894 307 if (i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB) {
mbed_official 579:53297373a894 308
mbed_official 579:53297373a894 309 /* Clear write interrupt flag */
mbed_official 579:53297373a894 310 i2c_module->INTFLAG.reg = SERCOM_I2CM_INTFLAG_SB;
mbed_official 579:53297373a894 311
mbed_official 579:53297373a894 312 /* Check arbitration. */
mbed_official 579:53297373a894 313 if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_ARBLOST) {
mbed_official 579:53297373a894 314 /* Return packet collision. */
mbed_official 579:53297373a894 315 return STATUS_ERR_PACKET_COLLISION;
mbed_official 579:53297373a894 316 }
mbed_official 579:53297373a894 317 /* Check that slave responded with ack. */
mbed_official 579:53297373a894 318 } else if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
mbed_official 579:53297373a894 319 /* Slave busy. Issue ack and stop command. */
mbed_official 579:53297373a894 320 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 579:53297373a894 321
mbed_official 579:53297373a894 322 /* Return bad address value. */
mbed_official 579:53297373a894 323 return STATUS_ERR_BAD_ADDRESS;
mbed_official 579:53297373a894 324 }
mbed_official 579:53297373a894 325
mbed_official 579:53297373a894 326 return STATUS_OK;
mbed_official 579:53297373a894 327 }
mbed_official 579:53297373a894 328
mbed_official 579:53297373a894 329 /**
mbed_official 579:53297373a894 330 * \internal
mbed_official 579:53297373a894 331 * Waits for answer on bus.
mbed_official 579:53297373a894 332 *
mbed_official 579:53297373a894 333 * \param[in,out] module Pointer to software module structure
mbed_official 579:53297373a894 334 *
mbed_official 579:53297373a894 335 * \return Status of bus.
mbed_official 579:53297373a894 336 * \retval STATUS_OK If given response from slave device
mbed_official 579:53297373a894 337 * \retval STATUS_ERR_TIMEOUT If no response was given within specified timeout
mbed_official 579:53297373a894 338 * period
mbed_official 579:53297373a894 339 */
mbed_official 579:53297373a894 340 enum status_code _i2c_master_wait_for_bus(
mbed_official 579:53297373a894 341 struct i2c_master_module *const module)
mbed_official 579:53297373a894 342 {
mbed_official 579:53297373a894 343 /* Sanity check arguments */
mbed_official 579:53297373a894 344 Assert(module);
mbed_official 579:53297373a894 345 Assert(module->hw);
mbed_official 579:53297373a894 346
mbed_official 579:53297373a894 347 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 348
mbed_official 579:53297373a894 349 /* Wait for reply. */
mbed_official 579:53297373a894 350 uint16_t timeout_counter = 0;
mbed_official 579:53297373a894 351 while (!(i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) &&
mbed_official 579:53297373a894 352 !(i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB)) {
mbed_official 579:53297373a894 353
mbed_official 579:53297373a894 354 /* Check timeout condition. */
mbed_official 579:53297373a894 355 if (++timeout_counter >= module->buffer_timeout) {
mbed_official 579:53297373a894 356 return STATUS_ERR_TIMEOUT;
mbed_official 579:53297373a894 357 }
mbed_official 579:53297373a894 358 }
mbed_official 579:53297373a894 359 return STATUS_OK;
mbed_official 579:53297373a894 360 }
mbed_official 579:53297373a894 361 #endif /* __DOXYGEN__ */
mbed_official 579:53297373a894 362
mbed_official 579:53297373a894 363 /**
mbed_official 579:53297373a894 364 * \internal
mbed_official 579:53297373a894 365 * Send master code for high speed transfer.
mbed_official 579:53297373a894 366 *
mbed_official 579:53297373a894 367 * \param[in,out] module Pointer to software module structure
mbed_official 579:53297373a894 368 * \param[in] hs_master_code 8-bit master code (0000 1XXX)
mbed_official 579:53297373a894 369 *
mbed_official 579:53297373a894 370 * \return Status of bus.
mbed_official 579:53297373a894 371 * \retval STATUS_OK No error happen
mbed_official 579:53297373a894 372 */
mbed_official 579:53297373a894 373 enum status_code _i2c_master_send_hs_master_code(
mbed_official 579:53297373a894 374 struct i2c_master_module *const module,
mbed_official 579:53297373a894 375 uint8_t hs_master_code)
mbed_official 579:53297373a894 376 {
mbed_official 579:53297373a894 377 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 378 /* Return value. */
mbed_official 579:53297373a894 379 enum status_code tmp_status;
mbed_official 579:53297373a894 380
mbed_official 579:53297373a894 381 /* Set NACK for high speed code */
mbed_official 579:53297373a894 382 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 383 /* Send high speed code */
mbed_official 579:53297373a894 384 i2c_module->ADDR.reg = hs_master_code;
mbed_official 579:53297373a894 385 /* Wait for response on bus. */
mbed_official 579:53297373a894 386 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 387 /* Clear write interrupt flag */
mbed_official 579:53297373a894 388 i2c_module->INTFLAG.reg = SERCOM_I2CM_INTENCLR_MB;
mbed_official 579:53297373a894 389
mbed_official 579:53297373a894 390 return tmp_status;
mbed_official 579:53297373a894 391 }
mbed_official 579:53297373a894 392
mbed_official 579:53297373a894 393
mbed_official 579:53297373a894 394 /**
mbed_official 579:53297373a894 395 * \internal
mbed_official 579:53297373a894 396 * Starts blocking read operation.
mbed_official 579:53297373a894 397 *
mbed_official 579:53297373a894 398 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 399 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 400 *
mbed_official 579:53297373a894 401 * \return Status of reading packet.
mbed_official 579:53297373a894 402 * \retval STATUS_OK The packet was read successfully
mbed_official 579:53297373a894 403 * \retval STATUS_ERR_TIMEOUT If no response was given within
mbed_official 579:53297373a894 404 * specified timeout period
mbed_official 579:53297373a894 405 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 406 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 407 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 408 * acknowledged the address
mbed_official 579:53297373a894 409 *
mbed_official 579:53297373a894 410 */
mbed_official 579:53297373a894 411 static enum status_code _i2c_master_read_packet(
mbed_official 579:53297373a894 412 struct i2c_master_module *const module,
mbed_official 579:53297373a894 413 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 414 {
mbed_official 579:53297373a894 415 /* Sanity check arguments */
mbed_official 579:53297373a894 416 Assert(module);
mbed_official 579:53297373a894 417 Assert(module->hw);
mbed_official 579:53297373a894 418 Assert(packet);
mbed_official 579:53297373a894 419
mbed_official 579:53297373a894 420 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 421
mbed_official 579:53297373a894 422 /* Return value. */
mbed_official 579:53297373a894 423 enum status_code tmp_status;
mbed_official 579:53297373a894 424 uint16_t tmp_data_length = packet->data_length;
mbed_official 579:53297373a894 425
mbed_official 579:53297373a894 426 /* Written buffer counter. */
mbed_official 579:53297373a894 427 uint16_t counter = 0;
mbed_official 579:53297373a894 428
mbed_official 579:53297373a894 429 bool sclsm_flag = i2c_module->CTRLA.bit.SCLSM;
mbed_official 579:53297373a894 430
mbed_official 579:53297373a894 431 /* Switch to high speed mode */
mbed_official 579:53297373a894 432 if (packet->high_speed) {
mbed_official 579:53297373a894 433 _i2c_master_send_hs_master_code(module, packet->hs_master_code);
mbed_official 579:53297373a894 434 }
mbed_official 579:53297373a894 435
mbed_official 579:53297373a894 436 /* Set action to ACK. */
mbed_official 579:53297373a894 437 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 438
mbed_official 579:53297373a894 439 /* Set address and direction bit. Will send start command on bus. */
mbed_official 579:53297373a894 440 if (packet->ten_bit_address) {
mbed_official 579:53297373a894 441 /*
mbed_official 579:53297373a894 442 * Write ADDR.ADDR[10:1] with the 10-bit address. ADDR.TENBITEN must
mbed_official 579:53297373a894 443 * be set and read/write bit (ADDR.ADDR[0]) equal to 0.
mbed_official 579:53297373a894 444 */
mbed_official 579:53297373a894 445 i2c_module->ADDR.reg = (packet->address << 1) |
mbed_official 579:53297373a894 446 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 579:53297373a894 447 SERCOM_I2CM_ADDR_TENBITEN;
mbed_official 579:53297373a894 448
mbed_official 579:53297373a894 449 /* Wait for response on bus. */
mbed_official 579:53297373a894 450 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 451
mbed_official 579:53297373a894 452 /* Set action to ack. */
mbed_official 579:53297373a894 453 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 454
mbed_official 579:53297373a894 455 /* Check for address response error unless previous error is
mbed_official 579:53297373a894 456 * detected. */
mbed_official 579:53297373a894 457 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 458 tmp_status = _i2c_master_address_response(module);
mbed_official 579:53297373a894 459 }
mbed_official 579:53297373a894 460
mbed_official 579:53297373a894 461 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 462 /*
mbed_official 579:53297373a894 463 * Write ADDR[7:0] register to 鈥10 address[9:8] 1鈥
mbed_official 579:53297373a894 464 * ADDR.TENBITEN must be cleared
mbed_official 579:53297373a894 465 */
mbed_official 579:53297373a894 466 i2c_module->ADDR.reg = (((packet->address >> 8) | 0x78) << 1) |
mbed_official 579:53297373a894 467 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 579:53297373a894 468 I2C_TRANSFER_READ;
mbed_official 579:53297373a894 469 } else {
mbed_official 579:53297373a894 470 return tmp_status;
mbed_official 579:53297373a894 471 }
mbed_official 579:53297373a894 472 } else {
mbed_official 579:53297373a894 473 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_READ |
mbed_official 579:53297373a894 474 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
mbed_official 579:53297373a894 475 }
mbed_official 579:53297373a894 476
mbed_official 579:53297373a894 477 /* Wait for response on bus. */
mbed_official 579:53297373a894 478 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 479
mbed_official 579:53297373a894 480 /* Set action to ack. */
mbed_official 579:53297373a894 481 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 482
mbed_official 579:53297373a894 483 /* Check for address response error unless previous error is
mbed_official 579:53297373a894 484 * detected. */
mbed_official 579:53297373a894 485 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 486 tmp_status = _i2c_master_address_response(module);
mbed_official 579:53297373a894 487 }
mbed_official 579:53297373a894 488
mbed_official 579:53297373a894 489 /* Check that no error has occurred. */
mbed_official 579:53297373a894 490 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 491 /* Read data buffer. */
mbed_official 579:53297373a894 492 while (tmp_data_length--) {
mbed_official 579:53297373a894 493 /* Check that bus ownership is not lost. */
mbed_official 579:53297373a894 494 if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) {
mbed_official 579:53297373a894 495 return STATUS_ERR_PACKET_COLLISION;
mbed_official 579:53297373a894 496 }
mbed_official 579:53297373a894 497
mbed_official 579:53297373a894 498 if (((!sclsm_flag) && (tmp_data_length == 0)) ||
mbed_official 579:53297373a894 499 ((sclsm_flag) && (tmp_data_length == 1))) {
mbed_official 579:53297373a894 500 /* Set action to NACK */
mbed_official 579:53297373a894 501 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 502 } else {
mbed_official 579:53297373a894 503 /* Save data to buffer. */
mbed_official 579:53297373a894 504 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 505 packet->data[counter++] = i2c_module->DATA.reg;
mbed_official 579:53297373a894 506 /* Wait for response. */
mbed_official 579:53297373a894 507 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 508 }
mbed_official 579:53297373a894 509
mbed_official 579:53297373a894 510 /* Check for error. */
mbed_official 579:53297373a894 511 if (tmp_status != STATUS_OK) {
mbed_official 579:53297373a894 512 break;
mbed_official 579:53297373a894 513 }
mbed_official 579:53297373a894 514 }
mbed_official 579:53297373a894 515
mbed_official 579:53297373a894 516 if (module->send_stop) {
mbed_official 579:53297373a894 517 /* Send stop command unless arbitration is lost. */
mbed_official 579:53297373a894 518 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 519 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 579:53297373a894 520 }
mbed_official 579:53297373a894 521
mbed_official 579:53297373a894 522 /* Save last data to buffer. */
mbed_official 579:53297373a894 523 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 524 packet->data[counter] = i2c_module->DATA.reg;
mbed_official 579:53297373a894 525 }
mbed_official 579:53297373a894 526
mbed_official 579:53297373a894 527 return tmp_status;
mbed_official 579:53297373a894 528 }
mbed_official 579:53297373a894 529
mbed_official 579:53297373a894 530 /**
mbed_official 579:53297373a894 531 * \brief Reads data packet from slave
mbed_official 579:53297373a894 532 *
mbed_official 579:53297373a894 533 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
mbed_official 579:53297373a894 534 * bus and sends a stop condition when finished.
mbed_official 579:53297373a894 535 *
mbed_official 579:53297373a894 536 * \note This will stall the device from any other operation. For
mbed_official 579:53297373a894 537 * interrupt-driven operation, see \ref i2c_master_read_packet_job.
mbed_official 579:53297373a894 538 *
mbed_official 579:53297373a894 539 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 540 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 541 *
mbed_official 579:53297373a894 542 * \return Status of reading packet.
mbed_official 579:53297373a894 543 * \retval STATUS_OK The packet was read successfully
mbed_official 579:53297373a894 544 * \retval STATUS_ERR_TIMEOUT If no response was given within
mbed_official 579:53297373a894 545 * specified timeout period
mbed_official 579:53297373a894 546 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 547 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 548 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 549 * acknowledged the address
mbed_official 579:53297373a894 550 */
mbed_official 579:53297373a894 551 enum status_code i2c_master_read_packet_wait(
mbed_official 579:53297373a894 552 struct i2c_master_module *const module,
mbed_official 579:53297373a894 553 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 554 {
mbed_official 579:53297373a894 555 /* Sanity check */
mbed_official 579:53297373a894 556 Assert(module);
mbed_official 579:53297373a894 557 Assert(module->hw);
mbed_official 579:53297373a894 558 Assert(packet);
mbed_official 579:53297373a894 559
mbed_official 579:53297373a894 560 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 561 /* Check if the I2C module is busy with a job. */
mbed_official 579:53297373a894 562 if (module->buffer_remaining > 0) {
mbed_official 579:53297373a894 563 return STATUS_BUSY;
mbed_official 579:53297373a894 564 }
mbed_official 579:53297373a894 565 #endif
mbed_official 579:53297373a894 566
mbed_official 579:53297373a894 567 module->send_stop = true;
mbed_official 579:53297373a894 568
mbed_official 579:53297373a894 569 return _i2c_master_read_packet(module, packet);
mbed_official 579:53297373a894 570 }
mbed_official 579:53297373a894 571
mbed_official 579:53297373a894 572 /**
mbed_official 579:53297373a894 573 * \brief Reads data packet from slave without sending a stop condition when done
mbed_official 579:53297373a894 574 *
mbed_official 579:53297373a894 575 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
mbed_official 579:53297373a894 576 * bus without sending a stop condition when done, thus retaining ownership of
mbed_official 579:53297373a894 577 * the bus when done. To end the transaction, a
mbed_official 579:53297373a894 578 * \ref i2c_master_read_packet_wait "read" or
mbed_official 579:53297373a894 579 * \ref i2c_master_write_packet_wait "write" with stop condition must be
mbed_official 579:53297373a894 580 * performed.
mbed_official 579:53297373a894 581 *
mbed_official 579:53297373a894 582 * \note This will stall the device from any other operation. For
mbed_official 579:53297373a894 583 * interrupt-driven operation, see \ref i2c_master_read_packet_job.
mbed_official 579:53297373a894 584 *
mbed_official 579:53297373a894 585 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 586 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 587 *
mbed_official 579:53297373a894 588 * \return Status of reading packet.
mbed_official 579:53297373a894 589 * \retval STATUS_OK The packet was read successfully
mbed_official 579:53297373a894 590 * \retval STATUS_ERR_TIMEOUT If no response was given within
mbed_official 579:53297373a894 591 * specified timeout period
mbed_official 579:53297373a894 592 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 593 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 594 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 595 * acknowledged the address
mbed_official 579:53297373a894 596 */
mbed_official 579:53297373a894 597 enum status_code i2c_master_read_packet_wait_no_stop(
mbed_official 579:53297373a894 598 struct i2c_master_module *const module,
mbed_official 579:53297373a894 599 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 600 {
mbed_official 579:53297373a894 601 /* Sanity check */
mbed_official 579:53297373a894 602 Assert(module);
mbed_official 579:53297373a894 603 Assert(module->hw);
mbed_official 579:53297373a894 604 Assert(packet);
mbed_official 579:53297373a894 605
mbed_official 579:53297373a894 606 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 607 /* Check if the I2C module is busy with a job. */
mbed_official 579:53297373a894 608 if (module->buffer_remaining > 0) {
mbed_official 579:53297373a894 609 return STATUS_BUSY;
mbed_official 579:53297373a894 610 }
mbed_official 579:53297373a894 611 #endif
mbed_official 579:53297373a894 612
mbed_official 579:53297373a894 613 module->send_stop = false;
mbed_official 579:53297373a894 614
mbed_official 579:53297373a894 615 return _i2c_master_read_packet(module, packet);
mbed_official 579:53297373a894 616 }
mbed_official 579:53297373a894 617
mbed_official 579:53297373a894 618 /**
mbed_official 579:53297373a894 619 * \internal
mbed_official 579:53297373a894 620 * Starts blocking write operation.
mbed_official 579:53297373a894 621 *
mbed_official 579:53297373a894 622 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 623 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 624 *
mbed_official 579:53297373a894 625 * \return Status of reading packet.
mbed_official 579:53297373a894 626 * \retval STATUS_OK The packet was read successfully
mbed_official 579:53297373a894 627 * \retval STATUS_ERR_TIMEOUT If no response was given within
mbed_official 579:53297373a894 628 * specified timeout period
mbed_official 579:53297373a894 629 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 630 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 631 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 632 * acknowledged the address
mbed_official 579:53297373a894 633 */
mbed_official 579:53297373a894 634 static enum status_code _i2c_master_write_packet(
mbed_official 579:53297373a894 635 struct i2c_master_module *const module,
mbed_official 579:53297373a894 636 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 637 {
mbed_official 579:53297373a894 638 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 639
mbed_official 579:53297373a894 640 /* Return value. */
mbed_official 579:53297373a894 641 enum status_code tmp_status;
mbed_official 579:53297373a894 642 uint16_t tmp_data_length = packet->data_length;
mbed_official 579:53297373a894 643
mbed_official 579:53297373a894 644 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 645
mbed_official 579:53297373a894 646 /* Switch to high speed mode */
mbed_official 579:53297373a894 647 if (packet->high_speed) {
mbed_official 579:53297373a894 648 _i2c_master_send_hs_master_code(module, packet->hs_master_code);
mbed_official 579:53297373a894 649 }
mbed_official 579:53297373a894 650
mbed_official 579:53297373a894 651 /* Set action to ACK. */
mbed_official 579:53297373a894 652 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 579:53297373a894 653
mbed_official 579:53297373a894 654 /* Set address and direction bit. Will send start command on bus. */
mbed_official 579:53297373a894 655 if (packet->ten_bit_address) {
mbed_official 579:53297373a894 656 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
mbed_official 579:53297373a894 657 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 579:53297373a894 658 SERCOM_I2CM_ADDR_TENBITEN;
mbed_official 579:53297373a894 659 } else {
mbed_official 579:53297373a894 660 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
mbed_official 579:53297373a894 661 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
mbed_official 579:53297373a894 662 }
mbed_official 579:53297373a894 663 /* Wait for response on bus. */
mbed_official 579:53297373a894 664 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 665
mbed_official 579:53297373a894 666 /* Check for address response error unless previous error is
mbed_official 579:53297373a894 667 * detected. */
mbed_official 579:53297373a894 668 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 669 tmp_status = _i2c_master_address_response(module);
mbed_official 579:53297373a894 670 }
mbed_official 579:53297373a894 671
mbed_official 579:53297373a894 672 /* Check that no error has occurred. */
mbed_official 579:53297373a894 673 if (tmp_status == STATUS_OK) {
mbed_official 579:53297373a894 674 /* Buffer counter. */
mbed_official 579:53297373a894 675 uint16_t buffer_counter = 0;
mbed_official 579:53297373a894 676
mbed_official 579:53297373a894 677 /* Write data buffer. */
mbed_official 579:53297373a894 678 while (tmp_data_length--) {
mbed_official 579:53297373a894 679 /* Check that bus ownership is not lost. */
mbed_official 579:53297373a894 680 if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) {
mbed_official 579:53297373a894 681 return STATUS_ERR_PACKET_COLLISION;
mbed_official 579:53297373a894 682 }
mbed_official 579:53297373a894 683
mbed_official 579:53297373a894 684 /* Write byte to slave. */
mbed_official 579:53297373a894 685 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 686 i2c_module->DATA.reg = packet->data[buffer_counter++];
mbed_official 579:53297373a894 687
mbed_official 579:53297373a894 688 /* Wait for response. */
mbed_official 579:53297373a894 689 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 579:53297373a894 690
mbed_official 579:53297373a894 691 /* Check for error. */
mbed_official 579:53297373a894 692 if (tmp_status != STATUS_OK) {
mbed_official 579:53297373a894 693 break;
mbed_official 579:53297373a894 694 }
mbed_official 579:53297373a894 695
mbed_official 579:53297373a894 696 /* Check for NACK from slave. */
mbed_official 579:53297373a894 697 if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
mbed_official 579:53297373a894 698 /* Return bad data value. */
mbed_official 579:53297373a894 699 tmp_status = STATUS_ERR_OVERFLOW;
mbed_official 579:53297373a894 700 break;
mbed_official 579:53297373a894 701 }
mbed_official 579:53297373a894 702 }
mbed_official 579:53297373a894 703
mbed_official 579:53297373a894 704 if (module->send_stop) {
mbed_official 579:53297373a894 705 /* Stop command */
mbed_official 579:53297373a894 706 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 707 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 579:53297373a894 708 }
mbed_official 579:53297373a894 709 }
mbed_official 579:53297373a894 710
mbed_official 579:53297373a894 711 return tmp_status;
mbed_official 579:53297373a894 712 }
mbed_official 579:53297373a894 713
mbed_official 579:53297373a894 714 /**
mbed_official 579:53297373a894 715 * \brief Writes data packet to slave
mbed_official 579:53297373a894 716 *
mbed_official 579:53297373a894 717 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
mbed_official 579:53297373a894 718 * and sends a stop condition when finished.
mbed_official 579:53297373a894 719 *
mbed_official 579:53297373a894 720 * \note This will stall the device from any other operation. For
mbed_official 579:53297373a894 721 * interrupt-driven operation, see \ref i2c_master_read_packet_job.
mbed_official 579:53297373a894 722 *
mbed_official 579:53297373a894 723 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 724 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 725 *
mbed_official 579:53297373a894 726 * \return Status of reading packet.
mbed_official 579:53297373a894 727 * \retval STATUS_OK If packet was read
mbed_official 579:53297373a894 728 * \retval STATUS_BUSY If master module is busy with a job
mbed_official 579:53297373a894 729 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 730 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 731 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 732 * acknowledged the address
mbed_official 579:53297373a894 733 * \retval STATUS_ERR_TIMEOUT If timeout occurred
mbed_official 579:53297373a894 734 * \retval STATUS_ERR_OVERFLOW If slave did not acknowledge last sent
mbed_official 579:53297373a894 735 * data, indicating that slave does not
mbed_official 579:53297373a894 736 * want more data and was not able to read
mbed_official 579:53297373a894 737 * last data sent
mbed_official 579:53297373a894 738 */
mbed_official 579:53297373a894 739 enum status_code i2c_master_write_packet_wait(
mbed_official 579:53297373a894 740 struct i2c_master_module *const module,
mbed_official 579:53297373a894 741 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 742 {
mbed_official 579:53297373a894 743 /* Sanity check */
mbed_official 579:53297373a894 744 Assert(module);
mbed_official 579:53297373a894 745 Assert(module->hw);
mbed_official 579:53297373a894 746 Assert(packet);
mbed_official 579:53297373a894 747
mbed_official 579:53297373a894 748 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 749 /* Check if the I2C module is busy with a job */
mbed_official 579:53297373a894 750 if (module->buffer_remaining > 0) {
mbed_official 579:53297373a894 751 return STATUS_BUSY;
mbed_official 579:53297373a894 752 }
mbed_official 579:53297373a894 753 #endif
mbed_official 579:53297373a894 754
mbed_official 579:53297373a894 755 module->send_stop = true;
mbed_official 579:53297373a894 756
mbed_official 579:53297373a894 757 return _i2c_master_write_packet(module, packet);
mbed_official 579:53297373a894 758 }
mbed_official 579:53297373a894 759
mbed_official 579:53297373a894 760 /**
mbed_official 579:53297373a894 761 * \brief Writes data packet to slave without sending a stop condition when done
mbed_official 579:53297373a894 762 *
mbed_official 579:53297373a894 763 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
mbed_official 579:53297373a894 764 * without sending a stop condition, thus retaining ownership of the bus when
mbed_official 579:53297373a894 765 * done. To end the transaction, a \ref i2c_master_read_packet_wait "read" or
mbed_official 579:53297373a894 766 * \ref i2c_master_write_packet_wait "write" with stop condition or sending a
mbed_official 579:53297373a894 767 * stop with the \ref i2c_master_send_stop function must be performed.
mbed_official 579:53297373a894 768 *
mbed_official 579:53297373a894 769 * \note This will stall the device from any other operation. For
mbed_official 579:53297373a894 770 * interrupt-driven operation, see \ref i2c_master_read_packet_job.
mbed_official 579:53297373a894 771 *
mbed_official 579:53297373a894 772 * \param[in,out] module Pointer to software module struct
mbed_official 579:53297373a894 773 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 579:53297373a894 774 *
mbed_official 579:53297373a894 775 * \return Status of reading packet.
mbed_official 579:53297373a894 776 * \retval STATUS_OK If packet was read
mbed_official 579:53297373a894 777 * \retval STATUS_BUSY If master module is busy
mbed_official 579:53297373a894 778 * \retval STATUS_ERR_DENIED If error on bus
mbed_official 579:53297373a894 779 * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
mbed_official 579:53297373a894 780 * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
mbed_official 579:53297373a894 781 * acknowledged the address
mbed_official 579:53297373a894 782 * \retval STATUS_ERR_TIMEOUT If timeout occurred
mbed_official 579:53297373a894 783 * \retval STATUS_ERR_OVERFLOW If slave did not acknowledge last sent
mbed_official 579:53297373a894 784 * data, indicating that slave do not want
mbed_official 579:53297373a894 785 * more data
mbed_official 579:53297373a894 786 */
mbed_official 579:53297373a894 787 enum status_code i2c_master_write_packet_wait_no_stop(
mbed_official 579:53297373a894 788 struct i2c_master_module *const module,
mbed_official 579:53297373a894 789 struct i2c_master_packet *const packet)
mbed_official 579:53297373a894 790 {
mbed_official 579:53297373a894 791 /* Sanity check */
mbed_official 579:53297373a894 792 Assert(module);
mbed_official 579:53297373a894 793 Assert(module->hw);
mbed_official 579:53297373a894 794 Assert(packet);
mbed_official 579:53297373a894 795
mbed_official 579:53297373a894 796 #if I2C_MASTER_CALLBACK_MODE == true
mbed_official 579:53297373a894 797 /* Check if the I2C module is busy with a job */
mbed_official 579:53297373a894 798 if (module->buffer_remaining > 0) {
mbed_official 579:53297373a894 799 return STATUS_BUSY;
mbed_official 579:53297373a894 800 }
mbed_official 579:53297373a894 801 #endif
mbed_official 579:53297373a894 802
mbed_official 579:53297373a894 803 module->send_stop = false;
mbed_official 579:53297373a894 804
mbed_official 579:53297373a894 805 return _i2c_master_write_packet(module, packet);
mbed_official 579:53297373a894 806 }
mbed_official 579:53297373a894 807
mbed_official 579:53297373a894 808 /**
mbed_official 579:53297373a894 809 * \brief Sends stop condition on bus
mbed_official 579:53297373a894 810 *
mbed_official 579:53297373a894 811 * Sends a stop condition on bus.
mbed_official 579:53297373a894 812 *
mbed_official 579:53297373a894 813 * \note This function can only be used after the
mbed_official 579:53297373a894 814 * \ref i2c_master_write_packet_wait_no_stop function. If a stop condition
mbed_official 579:53297373a894 815 * is to be sent after a read, the \ref i2c_master_read_packet_wait
mbed_official 579:53297373a894 816 * function must be used.
mbed_official 579:53297373a894 817 *
mbed_official 579:53297373a894 818 * \param[in] module Pointer to the software instance struct
mbed_official 579:53297373a894 819 */
mbed_official 579:53297373a894 820 void i2c_master_send_stop(struct i2c_master_module *const module)
mbed_official 579:53297373a894 821 {
mbed_official 579:53297373a894 822 /* Sanity check */
mbed_official 579:53297373a894 823 Assert(module);
mbed_official 579:53297373a894 824 Assert(module->hw);
mbed_official 579:53297373a894 825
mbed_official 579:53297373a894 826 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 579:53297373a894 827
mbed_official 579:53297373a894 828 /* Send stop command */
mbed_official 579:53297373a894 829 _i2c_master_wait_for_sync(module);
mbed_official 579:53297373a894 830 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 579:53297373a894 831 }