mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
mbed_official
Date:
Wed Nov 04 16:30:11 2015 +0000
Revision:
15:a81a8d6c1dfe
Synchronized with git revision 46af745ef4405614c3fa49abbd9a706a362ea514

Full URL: https://github.com/mbedmicro/mbed/commit/46af745ef4405614c3fa49abbd9a706a362ea514/

Renamed TARGET_SAM_CortexM0+ to TARGET_SAM_CortexM0P for compatiblity with online compiler

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 Master Interrupt Driver
mbed_official 15:a81a8d6c1dfe 5 *
mbed_official 15:a81a8d6c1dfe 6 * Copyright (C) 2012-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_master_interrupt.h"
mbed_official 15:a81a8d6c1dfe 48
mbed_official 15:a81a8d6c1dfe 49 extern enum status_code _i2c_master_wait_for_bus(
mbed_official 15:a81a8d6c1dfe 50 struct i2c_master_module *const module);
mbed_official 15:a81a8d6c1dfe 51
mbed_official 15:a81a8d6c1dfe 52 extern enum status_code _i2c_master_address_response(
mbed_official 15:a81a8d6c1dfe 53 struct i2c_master_module *const module);
mbed_official 15:a81a8d6c1dfe 54
mbed_official 15:a81a8d6c1dfe 55 extern enum status_code _i2c_master_send_hs_master_code(
mbed_official 15:a81a8d6c1dfe 56 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 57 uint8_t hs_master_code);;
mbed_official 15:a81a8d6c1dfe 58
mbed_official 15:a81a8d6c1dfe 59 /**
mbed_official 15:a81a8d6c1dfe 60 * \internal
mbed_official 15:a81a8d6c1dfe 61 * Read next data. Used by interrupt handler to get next data byte from slave.
mbed_official 15:a81a8d6c1dfe 62 *
mbed_official 15:a81a8d6c1dfe 63 * \param[in,out] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 64 */
mbed_official 15:a81a8d6c1dfe 65 static void _i2c_master_read(
mbed_official 15:a81a8d6c1dfe 66 struct i2c_master_module *const module)
mbed_official 15:a81a8d6c1dfe 67 {
mbed_official 15:a81a8d6c1dfe 68 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 69 Assert(module);
mbed_official 15:a81a8d6c1dfe 70 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 71
mbed_official 15:a81a8d6c1dfe 72 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 73 bool sclsm_flag = i2c_module->CTRLA.bit.SCLSM;
mbed_official 15:a81a8d6c1dfe 74
mbed_official 15:a81a8d6c1dfe 75 /* Find index to save next value in buffer */
mbed_official 15:a81a8d6c1dfe 76 uint16_t buffer_index = module->buffer_length;
mbed_official 15:a81a8d6c1dfe 77 buffer_index -= module->buffer_remaining;
mbed_official 15:a81a8d6c1dfe 78
mbed_official 15:a81a8d6c1dfe 79 module->buffer_remaining--;
mbed_official 15:a81a8d6c1dfe 80
mbed_official 15:a81a8d6c1dfe 81 if (sclsm_flag) {
mbed_official 15:a81a8d6c1dfe 82 if (module->send_nack && module->buffer_remaining == 1) {
mbed_official 15:a81a8d6c1dfe 83 /* Set action to NACK. */
mbed_official 15:a81a8d6c1dfe 84 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 85 }
mbed_official 15:a81a8d6c1dfe 86 } else {
mbed_official 15:a81a8d6c1dfe 87 if (module->send_nack && module->buffer_remaining == 0) {
mbed_official 15:a81a8d6c1dfe 88 /* Set action to NACK. */
mbed_official 15:a81a8d6c1dfe 89 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 90 }
mbed_official 15:a81a8d6c1dfe 91 }
mbed_official 15:a81a8d6c1dfe 92
mbed_official 15:a81a8d6c1dfe 93 if (module->buffer_remaining == 0) {
mbed_official 15:a81a8d6c1dfe 94 if (module->send_stop) {
mbed_official 15:a81a8d6c1dfe 95 /* Send stop condition */
mbed_official 15:a81a8d6c1dfe 96 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 97 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 15:a81a8d6c1dfe 98 }
mbed_official 15:a81a8d6c1dfe 99 }
mbed_official 15:a81a8d6c1dfe 100
mbed_official 15:a81a8d6c1dfe 101 /* Read byte from slave and put in buffer */
mbed_official 15:a81a8d6c1dfe 102 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 103 module->buffer[buffer_index] = i2c_module->DATA.reg;
mbed_official 15:a81a8d6c1dfe 104 }
mbed_official 15:a81a8d6c1dfe 105
mbed_official 15:a81a8d6c1dfe 106 /**
mbed_official 15:a81a8d6c1dfe 107 * \internal
mbed_official 15:a81a8d6c1dfe 108 *
mbed_official 15:a81a8d6c1dfe 109 * Write next data. Used by interrupt handler to send next data byte to slave.
mbed_official 15:a81a8d6c1dfe 110 *
mbed_official 15:a81a8d6c1dfe 111 * \param[in,out] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 112 */
mbed_official 15:a81a8d6c1dfe 113 static void _i2c_master_write(struct i2c_master_module *const module)
mbed_official 15:a81a8d6c1dfe 114 {
mbed_official 15:a81a8d6c1dfe 115 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 116 Assert(module);
mbed_official 15:a81a8d6c1dfe 117 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 118
mbed_official 15:a81a8d6c1dfe 119 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 120
mbed_official 15:a81a8d6c1dfe 121 /* Check for ack from slave */
mbed_official 15:a81a8d6c1dfe 122 if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
mbed_official 15:a81a8d6c1dfe 123 /* Set status */
mbed_official 15:a81a8d6c1dfe 124 module->status = STATUS_ERR_OVERFLOW;
mbed_official 15:a81a8d6c1dfe 125 /* Do not write more data */
mbed_official 15:a81a8d6c1dfe 126 return;
mbed_official 15:a81a8d6c1dfe 127 }
mbed_official 15:a81a8d6c1dfe 128
mbed_official 15:a81a8d6c1dfe 129 /* Find index to get next byte in buffer */
mbed_official 15:a81a8d6c1dfe 130 uint16_t buffer_index = module->buffer_length;
mbed_official 15:a81a8d6c1dfe 131 buffer_index -= module->buffer_remaining;
mbed_official 15:a81a8d6c1dfe 132
mbed_official 15:a81a8d6c1dfe 133 module->buffer_remaining--;
mbed_official 15:a81a8d6c1dfe 134
mbed_official 15:a81a8d6c1dfe 135 /* Write byte from buffer to slave */
mbed_official 15:a81a8d6c1dfe 136 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 137 i2c_module->DATA.reg = module->buffer[buffer_index];
mbed_official 15:a81a8d6c1dfe 138 }
mbed_official 15:a81a8d6c1dfe 139
mbed_official 15:a81a8d6c1dfe 140 /**
mbed_official 15:a81a8d6c1dfe 141 * \internal
mbed_official 15:a81a8d6c1dfe 142 * Acts on slave address response. Checks for errors concerning master->slave
mbed_official 15:a81a8d6c1dfe 143 * handshake.
mbed_official 15:a81a8d6c1dfe 144 *
mbed_official 15:a81a8d6c1dfe 145 * \param[in,out] module Pointer to software module structure
mbed_official 15:a81a8d6c1dfe 146 */
mbed_official 15:a81a8d6c1dfe 147 static void _i2c_master_async_address_response(
mbed_official 15:a81a8d6c1dfe 148 struct i2c_master_module *const module)
mbed_official 15:a81a8d6c1dfe 149 {
mbed_official 15:a81a8d6c1dfe 150 /* Sanity check arguments. */
mbed_official 15:a81a8d6c1dfe 151 Assert(module);
mbed_official 15:a81a8d6c1dfe 152 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 153
mbed_official 15:a81a8d6c1dfe 154 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 155
mbed_official 15:a81a8d6c1dfe 156 /* Check for error. Ignore bus-error; workaround for bus state stuck in
mbed_official 15:a81a8d6c1dfe 157 * BUSY.
mbed_official 15:a81a8d6c1dfe 158 */
mbed_official 15:a81a8d6c1dfe 159 if (i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) {
mbed_official 15:a81a8d6c1dfe 160 /* Clear write interrupt flag */
mbed_official 15:a81a8d6c1dfe 161 i2c_module->INTFLAG.reg = SERCOM_I2CM_INTENCLR_MB;
mbed_official 15:a81a8d6c1dfe 162
mbed_official 15:a81a8d6c1dfe 163 /* Check arbitration */
mbed_official 15:a81a8d6c1dfe 164 if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_ARBLOST) {
mbed_official 15:a81a8d6c1dfe 165 /* Return busy */
mbed_official 15:a81a8d6c1dfe 166 module->status = STATUS_ERR_PACKET_COLLISION;
mbed_official 15:a81a8d6c1dfe 167 }
mbed_official 15:a81a8d6c1dfe 168 } else if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
mbed_official 15:a81a8d6c1dfe 169 /* Return bad address value */
mbed_official 15:a81a8d6c1dfe 170 module->status = STATUS_ERR_BAD_ADDRESS;
mbed_official 15:a81a8d6c1dfe 171 module->buffer_remaining = 0;
mbed_official 15:a81a8d6c1dfe 172
mbed_official 15:a81a8d6c1dfe 173 if (module->send_stop) {
mbed_official 15:a81a8d6c1dfe 174 /* Send stop condition */
mbed_official 15:a81a8d6c1dfe 175 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 176 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 15:a81a8d6c1dfe 177 }
mbed_official 15:a81a8d6c1dfe 178 }
mbed_official 15:a81a8d6c1dfe 179
mbed_official 15:a81a8d6c1dfe 180 module->buffer_length = module->buffer_remaining;
mbed_official 15:a81a8d6c1dfe 181
mbed_official 15:a81a8d6c1dfe 182 /* Check for status OK. */
mbed_official 15:a81a8d6c1dfe 183 if (module->status == STATUS_BUSY) {
mbed_official 15:a81a8d6c1dfe 184 /* Call function based on transfer direction. */
mbed_official 15:a81a8d6c1dfe 185 if (module->transfer_direction == I2C_TRANSFER_WRITE) {
mbed_official 15:a81a8d6c1dfe 186 _i2c_master_write(module);
mbed_official 15:a81a8d6c1dfe 187 } else {
mbed_official 15:a81a8d6c1dfe 188 _i2c_master_read(module);
mbed_official 15:a81a8d6c1dfe 189 }
mbed_official 15:a81a8d6c1dfe 190 }
mbed_official 15:a81a8d6c1dfe 191 }
mbed_official 15:a81a8d6c1dfe 192
mbed_official 15:a81a8d6c1dfe 193 /**
mbed_official 15:a81a8d6c1dfe 194 * \brief Registers callback for the specified callback type
mbed_official 15:a81a8d6c1dfe 195 *
mbed_official 15:a81a8d6c1dfe 196 * Associates the given callback function with the
mbed_official 15:a81a8d6c1dfe 197 * specified callback type.
mbed_official 15:a81a8d6c1dfe 198 *
mbed_official 15:a81a8d6c1dfe 199 * To enable the callback, the \ref i2c_master_enable_callback function
mbed_official 15:a81a8d6c1dfe 200 * must be used.
mbed_official 15:a81a8d6c1dfe 201 *
mbed_official 15:a81a8d6c1dfe 202 * \param[in,out] module Pointer to the software module struct
mbed_official 15:a81a8d6c1dfe 203 * \param[in] callback Pointer to the function desired for the
mbed_official 15:a81a8d6c1dfe 204 * specified callback
mbed_official 15:a81a8d6c1dfe 205 * \param[in] callback_type Callback type to register
mbed_official 15:a81a8d6c1dfe 206 */
mbed_official 15:a81a8d6c1dfe 207 void i2c_master_register_callback(
mbed_official 15:a81a8d6c1dfe 208 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 209 const i2c_master_callback_t callback,
mbed_official 15:a81a8d6c1dfe 210 enum i2c_master_callback callback_type)
mbed_official 15:a81a8d6c1dfe 211 {
mbed_official 15:a81a8d6c1dfe 212 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 213 Assert(module);
mbed_official 15:a81a8d6c1dfe 214 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 215 Assert(callback);
mbed_official 15:a81a8d6c1dfe 216
mbed_official 15:a81a8d6c1dfe 217 /* Register callback */
mbed_official 15:a81a8d6c1dfe 218 module->callbacks[callback_type] = callback;
mbed_official 15:a81a8d6c1dfe 219
mbed_official 15:a81a8d6c1dfe 220 /* Set corresponding bit to set callback as registered */
mbed_official 15:a81a8d6c1dfe 221 module->registered_callback |= (1 << callback_type);
mbed_official 15:a81a8d6c1dfe 222 }
mbed_official 15:a81a8d6c1dfe 223
mbed_official 15:a81a8d6c1dfe 224 /**
mbed_official 15:a81a8d6c1dfe 225 * \brief Unregisters callback for the specified callback type
mbed_official 15:a81a8d6c1dfe 226 *
mbed_official 15:a81a8d6c1dfe 227 * When called, the currently registered callback for the given callback type
mbed_official 15:a81a8d6c1dfe 228 * will be removed.
mbed_official 15:a81a8d6c1dfe 229 *
mbed_official 15:a81a8d6c1dfe 230 * \param[in,out] module Pointer to the software module struct
mbed_official 15:a81a8d6c1dfe 231 * \param[in] callback_type Specifies the callback type to unregister
mbed_official 15:a81a8d6c1dfe 232 */
mbed_official 15:a81a8d6c1dfe 233 void i2c_master_unregister_callback(
mbed_official 15:a81a8d6c1dfe 234 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 235 enum i2c_master_callback callback_type)
mbed_official 15:a81a8d6c1dfe 236 {
mbed_official 15:a81a8d6c1dfe 237 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 238 Assert(module);
mbed_official 15:a81a8d6c1dfe 239 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 240
mbed_official 15:a81a8d6c1dfe 241 /* Register callback */
mbed_official 15:a81a8d6c1dfe 242 module->callbacks[callback_type] = NULL;
mbed_official 15:a81a8d6c1dfe 243
mbed_official 15:a81a8d6c1dfe 244 /* Clear corresponding bit to set callback as unregistered */
mbed_official 15:a81a8d6c1dfe 245 module->registered_callback &= ~(1 << callback_type);
mbed_official 15:a81a8d6c1dfe 246 }
mbed_official 15:a81a8d6c1dfe 247
mbed_official 15:a81a8d6c1dfe 248 /**
mbed_official 15:a81a8d6c1dfe 249 * \internal
mbed_official 15:a81a8d6c1dfe 250 * Starts a read bytes operation.
mbed_official 15:a81a8d6c1dfe 251 *
mbed_official 15:a81a8d6c1dfe 252 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 253 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 254 *
mbed_official 15:a81a8d6c1dfe 255 * \return Status of starting reading I<SUP>2</SUP>C packet.
mbed_official 15:a81a8d6c1dfe 256 * \retval STATUS_OK If reading was started successfully
mbed_official 15:a81a8d6c1dfe 257 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 258 */
mbed_official 15:a81a8d6c1dfe 259 enum status_code i2c_master_read_bytes(
mbed_official 15:a81a8d6c1dfe 260 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 261 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 262 {
mbed_official 15:a81a8d6c1dfe 263 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 264 Assert(module);
mbed_official 15:a81a8d6c1dfe 265 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 266
mbed_official 15:a81a8d6c1dfe 267 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 268
mbed_official 15:a81a8d6c1dfe 269 /* Save packet to software module */
mbed_official 15:a81a8d6c1dfe 270 module->buffer = packet->data;
mbed_official 15:a81a8d6c1dfe 271 module->buffer_remaining = packet->data_length;
mbed_official 15:a81a8d6c1dfe 272 module->transfer_direction = I2C_TRANSFER_READ;
mbed_official 15:a81a8d6c1dfe 273 module->status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 274 module->send_stop = false;
mbed_official 15:a81a8d6c1dfe 275 module->send_nack = false;
mbed_official 15:a81a8d6c1dfe 276
mbed_official 15:a81a8d6c1dfe 277 /* Enable interrupts */
mbed_official 15:a81a8d6c1dfe 278 i2c_module->INTENSET.reg =
mbed_official 15:a81a8d6c1dfe 279 SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
mbed_official 15:a81a8d6c1dfe 280
mbed_official 15:a81a8d6c1dfe 281 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 282 }
mbed_official 15:a81a8d6c1dfe 283
mbed_official 15:a81a8d6c1dfe 284 /**
mbed_official 15:a81a8d6c1dfe 285 * \internal
mbed_official 15:a81a8d6c1dfe 286 * Starts a read packet operation.
mbed_official 15:a81a8d6c1dfe 287 *
mbed_official 15:a81a8d6c1dfe 288 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 289 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 290 *
mbed_official 15:a81a8d6c1dfe 291 * \return Status of starting reading I<SUP>2</SUP>C packet.
mbed_official 15:a81a8d6c1dfe 292 * \retval STATUS_OK If reading was started successfully
mbed_official 15:a81a8d6c1dfe 293 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 294 */
mbed_official 15:a81a8d6c1dfe 295 static enum status_code _i2c_master_read_packet(
mbed_official 15:a81a8d6c1dfe 296 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 297 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 298 {
mbed_official 15:a81a8d6c1dfe 299 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 300 Assert(module);
mbed_official 15:a81a8d6c1dfe 301 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 302
mbed_official 15:a81a8d6c1dfe 303 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 304 enum status_code tmp_status;
mbed_official 15:a81a8d6c1dfe 305
mbed_official 15:a81a8d6c1dfe 306 /* Save packet to software module */
mbed_official 15:a81a8d6c1dfe 307 module->buffer = packet->data;
mbed_official 15:a81a8d6c1dfe 308 module->buffer_remaining = packet->data_length;
mbed_official 15:a81a8d6c1dfe 309 module->transfer_direction = I2C_TRANSFER_READ;
mbed_official 15:a81a8d6c1dfe 310 module->status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 311
mbed_official 15:a81a8d6c1dfe 312 /* Switch to high speed mode */
mbed_official 15:a81a8d6c1dfe 313 if (packet->high_speed) {
mbed_official 15:a81a8d6c1dfe 314 _i2c_master_send_hs_master_code(module, packet->hs_master_code);
mbed_official 15:a81a8d6c1dfe 315 }
mbed_official 15:a81a8d6c1dfe 316
mbed_official 15:a81a8d6c1dfe 317 /* Set action to ACK. */
mbed_official 15:a81a8d6c1dfe 318 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 319
mbed_official 15:a81a8d6c1dfe 320 if (packet->ten_bit_address) {
mbed_official 15:a81a8d6c1dfe 321 /*
mbed_official 15:a81a8d6c1dfe 322 * Write ADDR.ADDR[10:1] with the 10-bit address. ADDR.TENBITEN must
mbed_official 15:a81a8d6c1dfe 323 * be set and read/write bit (ADDR.ADDR[0]) equal to 0.
mbed_official 15:a81a8d6c1dfe 324 */
mbed_official 15:a81a8d6c1dfe 325 i2c_module->ADDR.reg = (packet->address << 1) |
mbed_official 15:a81a8d6c1dfe 326 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 15:a81a8d6c1dfe 327 SERCOM_I2CM_ADDR_TENBITEN;
mbed_official 15:a81a8d6c1dfe 328
mbed_official 15:a81a8d6c1dfe 329 /* Wait for response on bus. */
mbed_official 15:a81a8d6c1dfe 330 tmp_status = _i2c_master_wait_for_bus(module);
mbed_official 15:a81a8d6c1dfe 331
mbed_official 15:a81a8d6c1dfe 332 /* Set action to ack. */
mbed_official 15:a81a8d6c1dfe 333 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 334
mbed_official 15:a81a8d6c1dfe 335 /* Check for address response error unless previous error is
mbed_official 15:a81a8d6c1dfe 336 * detected. */
mbed_official 15:a81a8d6c1dfe 337 if (tmp_status == STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 338 tmp_status = _i2c_master_address_response(module);
mbed_official 15:a81a8d6c1dfe 339 }
mbed_official 15:a81a8d6c1dfe 340
mbed_official 15:a81a8d6c1dfe 341 if (tmp_status == STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 342 /* Enable interrupts */
mbed_official 15:a81a8d6c1dfe 343 i2c_module->INTENSET.reg =
mbed_official 15:a81a8d6c1dfe 344 SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
mbed_official 15:a81a8d6c1dfe 345
mbed_official 15:a81a8d6c1dfe 346 /*
mbed_official 15:a81a8d6c1dfe 347 * Write ADDR[7:0] register to "11110 address[9:8] 1"
mbed_official 15:a81a8d6c1dfe 348 * ADDR.TENBITEN must be cleared
mbed_official 15:a81a8d6c1dfe 349 */
mbed_official 15:a81a8d6c1dfe 350 i2c_module->ADDR.reg = (((packet->address >> 8) | 0x78) << 1) |
mbed_official 15:a81a8d6c1dfe 351 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 15:a81a8d6c1dfe 352 I2C_TRANSFER_READ;
mbed_official 15:a81a8d6c1dfe 353 } else {
mbed_official 15:a81a8d6c1dfe 354 return tmp_status;
mbed_official 15:a81a8d6c1dfe 355 }
mbed_official 15:a81a8d6c1dfe 356 } else {
mbed_official 15:a81a8d6c1dfe 357 /* Enable interrupts */
mbed_official 15:a81a8d6c1dfe 358 i2c_module->INTENSET.reg =
mbed_official 15:a81a8d6c1dfe 359 SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
mbed_official 15:a81a8d6c1dfe 360
mbed_official 15:a81a8d6c1dfe 361 /* Set address and direction bit. Will send start command on bus */
mbed_official 15:a81a8d6c1dfe 362 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_READ |
mbed_official 15:a81a8d6c1dfe 363 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
mbed_official 15:a81a8d6c1dfe 364 }
mbed_official 15:a81a8d6c1dfe 365
mbed_official 15:a81a8d6c1dfe 366 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 367 }
mbed_official 15:a81a8d6c1dfe 368
mbed_official 15:a81a8d6c1dfe 369 /**
mbed_official 15:a81a8d6c1dfe 370 * \brief Initiates a read packet operation
mbed_official 15:a81a8d6c1dfe 371 *
mbed_official 15:a81a8d6c1dfe 372 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
mbed_official 15:a81a8d6c1dfe 373 * bus. This is the non-blocking equivalent of \ref i2c_master_read_packet_wait.
mbed_official 15:a81a8d6c1dfe 374 *
mbed_official 15:a81a8d6c1dfe 375 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 376 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 377 *
mbed_official 15:a81a8d6c1dfe 378 * \return Status of starting reading I<SUP>2</SUP>C packet.
mbed_official 15:a81a8d6c1dfe 379 * \retval STATUS_OK If reading was started successfully
mbed_official 15:a81a8d6c1dfe 380 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 381 */
mbed_official 15:a81a8d6c1dfe 382 enum status_code i2c_master_read_packet_job(
mbed_official 15:a81a8d6c1dfe 383 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 384 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 385 {
mbed_official 15:a81a8d6c1dfe 386 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 387 Assert(module);
mbed_official 15:a81a8d6c1dfe 388 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 389 Assert(packet);
mbed_official 15:a81a8d6c1dfe 390
mbed_official 15:a81a8d6c1dfe 391 /* Check if the I2C module is busy with a job */
mbed_official 15:a81a8d6c1dfe 392 if (module->buffer_remaining > 0) {
mbed_official 15:a81a8d6c1dfe 393 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 394 }
mbed_official 15:a81a8d6c1dfe 395
mbed_official 15:a81a8d6c1dfe 396 /* Make sure we send STOP */
mbed_official 15:a81a8d6c1dfe 397 module->send_stop = true;
mbed_official 15:a81a8d6c1dfe 398 module->send_nack = true;
mbed_official 15:a81a8d6c1dfe 399 /* Start reading */
mbed_official 15:a81a8d6c1dfe 400 return _i2c_master_read_packet(module, packet);
mbed_official 15:a81a8d6c1dfe 401 }
mbed_official 15:a81a8d6c1dfe 402
mbed_official 15:a81a8d6c1dfe 403 /**
mbed_official 15:a81a8d6c1dfe 404 * \brief Initiates a read packet operation without sending a STOP condition when done
mbed_official 15:a81a8d6c1dfe 405 *
mbed_official 15:a81a8d6c1dfe 406 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C bus without
mbed_official 15:a81a8d6c1dfe 407 * sending a stop condition, thus retaining ownership of the bus when done.
mbed_official 15:a81a8d6c1dfe 408 * To end the transaction, a \ref i2c_master_read_packet_wait "read" or
mbed_official 15:a81a8d6c1dfe 409 * \ref i2c_master_write_packet_wait "write" with stop condition must be
mbed_official 15:a81a8d6c1dfe 410 * performed.
mbed_official 15:a81a8d6c1dfe 411 *
mbed_official 15:a81a8d6c1dfe 412 * This is the non-blocking equivalent of \ref i2c_master_read_packet_wait_no_stop.
mbed_official 15:a81a8d6c1dfe 413 *
mbed_official 15:a81a8d6c1dfe 414 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 415 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 416 *
mbed_official 15:a81a8d6c1dfe 417 * \return Status of starting reading I<SUP>2</SUP>C packet.
mbed_official 15:a81a8d6c1dfe 418 * \retval STATUS_OK If reading was started successfully
mbed_official 15:a81a8d6c1dfe 419 * \retval STATUS_BUSY If module is currently busy with another operation
mbed_official 15:a81a8d6c1dfe 420 */
mbed_official 15:a81a8d6c1dfe 421 enum status_code i2c_master_read_packet_job_no_stop(
mbed_official 15:a81a8d6c1dfe 422 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 423 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 424 {
mbed_official 15:a81a8d6c1dfe 425 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 426 Assert(module);
mbed_official 15:a81a8d6c1dfe 427 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 428 Assert(packet);
mbed_official 15:a81a8d6c1dfe 429
mbed_official 15:a81a8d6c1dfe 430 /* Check if the I2C module is busy with a job */
mbed_official 15:a81a8d6c1dfe 431 if (module->buffer_remaining > 0) {
mbed_official 15:a81a8d6c1dfe 432 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 433 }
mbed_official 15:a81a8d6c1dfe 434
mbed_official 15:a81a8d6c1dfe 435 /* Make sure we don't send STOP */
mbed_official 15:a81a8d6c1dfe 436 module->send_stop = false;
mbed_official 15:a81a8d6c1dfe 437 module->send_nack = true;
mbed_official 15:a81a8d6c1dfe 438 /* Start reading */
mbed_official 15:a81a8d6c1dfe 439 return _i2c_master_read_packet(module, packet);
mbed_official 15:a81a8d6c1dfe 440 }
mbed_official 15:a81a8d6c1dfe 441
mbed_official 15:a81a8d6c1dfe 442 /**
mbed_official 15:a81a8d6c1dfe 443 * \brief Initiates a read packet operation without sending a NACK signal and a
mbed_official 15:a81a8d6c1dfe 444 * STOP condition when done
mbed_official 15:a81a8d6c1dfe 445 *
mbed_official 15:a81a8d6c1dfe 446 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C bus without
mbed_official 15:a81a8d6c1dfe 447 * sending a nack and a stop condition, thus retaining ownership of the bus when done.
mbed_official 15:a81a8d6c1dfe 448 * To end the transaction, a \ref i2c_master_read_packet_wait "read" or
mbed_official 15:a81a8d6c1dfe 449 * \ref i2c_master_write_packet_wait "write" with stop condition must be
mbed_official 15:a81a8d6c1dfe 450 * performed.
mbed_official 15:a81a8d6c1dfe 451 *
mbed_official 15:a81a8d6c1dfe 452 * This is the non-blocking equivalent of \ref i2c_master_read_packet_wait_no_stop.
mbed_official 15:a81a8d6c1dfe 453 *
mbed_official 15:a81a8d6c1dfe 454 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 455 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 456 *
mbed_official 15:a81a8d6c1dfe 457 * \return Status of starting reading I<SUP>2</SUP>C packet.
mbed_official 15:a81a8d6c1dfe 458 * \retval STATUS_OK If reading was started successfully
mbed_official 15:a81a8d6c1dfe 459 * \retval STATUS_BUSY If module is currently busy with another operation
mbed_official 15:a81a8d6c1dfe 460 */
mbed_official 15:a81a8d6c1dfe 461 enum status_code i2c_master_read_packet_job_no_nack(
mbed_official 15:a81a8d6c1dfe 462 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 463 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 464 {
mbed_official 15:a81a8d6c1dfe 465 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 466 Assert(module);
mbed_official 15:a81a8d6c1dfe 467 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 468 Assert(packet);
mbed_official 15:a81a8d6c1dfe 469
mbed_official 15:a81a8d6c1dfe 470 /* Check if the I2C module is busy with a job */
mbed_official 15:a81a8d6c1dfe 471 if (module->buffer_remaining > 0) {
mbed_official 15:a81a8d6c1dfe 472 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 473 }
mbed_official 15:a81a8d6c1dfe 474
mbed_official 15:a81a8d6c1dfe 475 /* Make sure we don't send STOP */
mbed_official 15:a81a8d6c1dfe 476 module->send_stop = false;
mbed_official 15:a81a8d6c1dfe 477 module->send_nack = false;
mbed_official 15:a81a8d6c1dfe 478 /* Start reading */
mbed_official 15:a81a8d6c1dfe 479 return _i2c_master_read_packet(module, packet);
mbed_official 15:a81a8d6c1dfe 480 }
mbed_official 15:a81a8d6c1dfe 481
mbed_official 15:a81a8d6c1dfe 482 /**
mbed_official 15:a81a8d6c1dfe 483 * \internal
mbed_official 15:a81a8d6c1dfe 484 * Starts a write bytes operation.
mbed_official 15:a81a8d6c1dfe 485 *
mbed_official 15:a81a8d6c1dfe 486 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 487 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 488 *
mbed_official 15:a81a8d6c1dfe 489 * \return Status of starting write I<SUP>2</SUP>C bytes.
mbed_official 15:a81a8d6c1dfe 490 * \retval STATUS_OK If writing was started successfully
mbed_official 15:a81a8d6c1dfe 491 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 492 */
mbed_official 15:a81a8d6c1dfe 493 enum status_code i2c_master_write_bytes(
mbed_official 15:a81a8d6c1dfe 494 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 495 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 496 {
mbed_official 15:a81a8d6c1dfe 497 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 498 Assert(module);
mbed_official 15:a81a8d6c1dfe 499 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 500
mbed_official 15:a81a8d6c1dfe 501 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 502
mbed_official 15:a81a8d6c1dfe 503 /* Save packet to software module */
mbed_official 15:a81a8d6c1dfe 504 module->buffer = packet->data;
mbed_official 15:a81a8d6c1dfe 505 module->buffer_remaining = packet->data_length;
mbed_official 15:a81a8d6c1dfe 506 module->transfer_direction = I2C_TRANSFER_WRITE;
mbed_official 15:a81a8d6c1dfe 507 module->status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 508 module->send_stop = false;
mbed_official 15:a81a8d6c1dfe 509 module->send_nack = false;
mbed_official 15:a81a8d6c1dfe 510
mbed_official 15:a81a8d6c1dfe 511 /* Enable interrupts */
mbed_official 15:a81a8d6c1dfe 512 i2c_module->INTENSET.reg =
mbed_official 15:a81a8d6c1dfe 513 SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
mbed_official 15:a81a8d6c1dfe 514
mbed_official 15:a81a8d6c1dfe 515 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 516 }
mbed_official 15:a81a8d6c1dfe 517
mbed_official 15:a81a8d6c1dfe 518 /**
mbed_official 15:a81a8d6c1dfe 519 * \internal Initiates a write packet operation
mbed_official 15:a81a8d6c1dfe 520 *
mbed_official 15:a81a8d6c1dfe 521 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 522 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 523 *
mbed_official 15:a81a8d6c1dfe 524 * \return Status of starting writing I<SUP>2</SUP>C packet job.
mbed_official 15:a81a8d6c1dfe 525 * \retval STATUS_OK If writing was started successfully
mbed_official 15:a81a8d6c1dfe 526 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 527 */
mbed_official 15:a81a8d6c1dfe 528 static enum status_code _i2c_master_write_packet(
mbed_official 15:a81a8d6c1dfe 529 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 530 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 531 {
mbed_official 15:a81a8d6c1dfe 532 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 533 Assert(module);
mbed_official 15:a81a8d6c1dfe 534 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 535
mbed_official 15:a81a8d6c1dfe 536 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 537
mbed_official 15:a81a8d6c1dfe 538 /* Switch to high speed mode */
mbed_official 15:a81a8d6c1dfe 539 if (packet->high_speed) {
mbed_official 15:a81a8d6c1dfe 540 _i2c_master_send_hs_master_code(module, packet->hs_master_code);
mbed_official 15:a81a8d6c1dfe 541 }
mbed_official 15:a81a8d6c1dfe 542
mbed_official 15:a81a8d6c1dfe 543 /* Set action to ACK. */
mbed_official 15:a81a8d6c1dfe 544 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
mbed_official 15:a81a8d6c1dfe 545
mbed_official 15:a81a8d6c1dfe 546 /* Save packet to software module */
mbed_official 15:a81a8d6c1dfe 547 module->buffer = packet->data;
mbed_official 15:a81a8d6c1dfe 548 module->buffer_remaining = packet->data_length;
mbed_official 15:a81a8d6c1dfe 549 module->transfer_direction = I2C_TRANSFER_WRITE;
mbed_official 15:a81a8d6c1dfe 550 module->status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 551
mbed_official 15:a81a8d6c1dfe 552 /* Enable interrupts */
mbed_official 15:a81a8d6c1dfe 553 i2c_module->INTENSET.reg =
mbed_official 15:a81a8d6c1dfe 554 SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB;
mbed_official 15:a81a8d6c1dfe 555
mbed_official 15:a81a8d6c1dfe 556 /* Set address and direction bit, will send start command on bus */
mbed_official 15:a81a8d6c1dfe 557 if (packet->ten_bit_address) {
mbed_official 15:a81a8d6c1dfe 558 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
mbed_official 15:a81a8d6c1dfe 559 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos) |
mbed_official 15:a81a8d6c1dfe 560 SERCOM_I2CM_ADDR_TENBITEN;
mbed_official 15:a81a8d6c1dfe 561 } else {
mbed_official 15:a81a8d6c1dfe 562 i2c_module->ADDR.reg = (packet->address << 1) | I2C_TRANSFER_WRITE |
mbed_official 15:a81a8d6c1dfe 563 (packet->high_speed << SERCOM_I2CM_ADDR_HS_Pos);
mbed_official 15:a81a8d6c1dfe 564 }
mbed_official 15:a81a8d6c1dfe 565
mbed_official 15:a81a8d6c1dfe 566 return STATUS_OK;
mbed_official 15:a81a8d6c1dfe 567 }
mbed_official 15:a81a8d6c1dfe 568
mbed_official 15:a81a8d6c1dfe 569 /**
mbed_official 15:a81a8d6c1dfe 570 * \brief Initiates a write packet operation
mbed_official 15:a81a8d6c1dfe 571 *
mbed_official 15:a81a8d6c1dfe 572 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C
mbed_official 15:a81a8d6c1dfe 573 * bus. This is the non-blocking equivalent of \ref i2c_master_write_packet_wait.
mbed_official 15:a81a8d6c1dfe 574 *
mbed_official 15:a81a8d6c1dfe 575 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 576 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 577 *
mbed_official 15:a81a8d6c1dfe 578 * \return Status of starting writing I<SUP>2</SUP>C packet job.
mbed_official 15:a81a8d6c1dfe 579 * \retval STATUS_OK If writing was started successfully
mbed_official 15:a81a8d6c1dfe 580 * \retval STATUS_BUSY If module is currently busy with another transfer
mbed_official 15:a81a8d6c1dfe 581 */
mbed_official 15:a81a8d6c1dfe 582 enum status_code i2c_master_write_packet_job(
mbed_official 15:a81a8d6c1dfe 583 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 584 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 585 {
mbed_official 15:a81a8d6c1dfe 586 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 587 Assert(module);
mbed_official 15:a81a8d6c1dfe 588 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 589 Assert(packet);
mbed_official 15:a81a8d6c1dfe 590
mbed_official 15:a81a8d6c1dfe 591 /* Check if the I2C module is busy with another job. */
mbed_official 15:a81a8d6c1dfe 592 if (module->buffer_remaining > 0) {
mbed_official 15:a81a8d6c1dfe 593 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 594 }
mbed_official 15:a81a8d6c1dfe 595
mbed_official 15:a81a8d6c1dfe 596 /* Make sure we send STOP at end*/
mbed_official 15:a81a8d6c1dfe 597 module->send_stop = true;
mbed_official 15:a81a8d6c1dfe 598 module->send_nack = true;
mbed_official 15:a81a8d6c1dfe 599 /* Start write operation */
mbed_official 15:a81a8d6c1dfe 600 return _i2c_master_write_packet(module, packet);
mbed_official 15:a81a8d6c1dfe 601 }
mbed_official 15:a81a8d6c1dfe 602
mbed_official 15:a81a8d6c1dfe 603 /**
mbed_official 15:a81a8d6c1dfe 604 * \brief Initiates a write packet operation without sending a STOP condition when done
mbed_official 15:a81a8d6c1dfe 605 *
mbed_official 15:a81a8d6c1dfe 606 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
mbed_official 15:a81a8d6c1dfe 607 * without sending a stop condition, thus retaining ownership of the bus when
mbed_official 15:a81a8d6c1dfe 608 * done. To end the transaction, a \ref i2c_master_read_packet_wait "read" or
mbed_official 15:a81a8d6c1dfe 609 * \ref i2c_master_write_packet_wait "write" with stop condition or sending
mbed_official 15:a81a8d6c1dfe 610 * a stop with the \ref i2c_master_send_stop function must be performed.
mbed_official 15:a81a8d6c1dfe 611 *
mbed_official 15:a81a8d6c1dfe 612 * This is the non-blocking equivalent of \ref i2c_master_write_packet_wait_no_stop.
mbed_official 15:a81a8d6c1dfe 613 *
mbed_official 15:a81a8d6c1dfe 614 * \param[in,out] module Pointer to software module struct
mbed_official 15:a81a8d6c1dfe 615 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
mbed_official 15:a81a8d6c1dfe 616 *
mbed_official 15:a81a8d6c1dfe 617 * \return Status of starting writing I<SUP>2</SUP>C packet job.
mbed_official 15:a81a8d6c1dfe 618 * \retval STATUS_OK If writing was started successfully
mbed_official 15:a81a8d6c1dfe 619 * \retval STATUS_BUSY If module is currently busy with another
mbed_official 15:a81a8d6c1dfe 620 */
mbed_official 15:a81a8d6c1dfe 621 enum status_code i2c_master_write_packet_job_no_stop(
mbed_official 15:a81a8d6c1dfe 622 struct i2c_master_module *const module,
mbed_official 15:a81a8d6c1dfe 623 struct i2c_master_packet *const packet)
mbed_official 15:a81a8d6c1dfe 624 {
mbed_official 15:a81a8d6c1dfe 625 /* Sanity check */
mbed_official 15:a81a8d6c1dfe 626 Assert(module);
mbed_official 15:a81a8d6c1dfe 627 Assert(module->hw);
mbed_official 15:a81a8d6c1dfe 628 Assert(packet);
mbed_official 15:a81a8d6c1dfe 629
mbed_official 15:a81a8d6c1dfe 630 /* Check if the I2C module is busy with another job. */
mbed_official 15:a81a8d6c1dfe 631 if (module->buffer_remaining > 0) {
mbed_official 15:a81a8d6c1dfe 632 return STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 633 }
mbed_official 15:a81a8d6c1dfe 634
mbed_official 15:a81a8d6c1dfe 635 /* Do not send stop condition when done */
mbed_official 15:a81a8d6c1dfe 636 module->send_stop = false;
mbed_official 15:a81a8d6c1dfe 637 module->send_nack = true;
mbed_official 15:a81a8d6c1dfe 638 /* Start write operation */
mbed_official 15:a81a8d6c1dfe 639 return _i2c_master_write_packet(module, packet);
mbed_official 15:a81a8d6c1dfe 640 }
mbed_official 15:a81a8d6c1dfe 641
mbed_official 15:a81a8d6c1dfe 642 /**
mbed_official 15:a81a8d6c1dfe 643 * \internal
mbed_official 15:a81a8d6c1dfe 644 * Interrupt handler for I<SUP>2</SUP>C master.
mbed_official 15:a81a8d6c1dfe 645 *
mbed_official 15:a81a8d6c1dfe 646 * \param[in] instance SERCOM instance that triggered the interrupt
mbed_official 15:a81a8d6c1dfe 647 */
mbed_official 15:a81a8d6c1dfe 648 void _i2c_master_interrupt_handler(
mbed_official 15:a81a8d6c1dfe 649 uint8_t instance)
mbed_official 15:a81a8d6c1dfe 650 {
mbed_official 15:a81a8d6c1dfe 651 /* Get software module for callback handling */
mbed_official 15:a81a8d6c1dfe 652 struct i2c_master_module *module =
mbed_official 15:a81a8d6c1dfe 653 (struct i2c_master_module*)_sercom_instances[instance];
mbed_official 15:a81a8d6c1dfe 654
mbed_official 15:a81a8d6c1dfe 655 Assert(module);
mbed_official 15:a81a8d6c1dfe 656
mbed_official 15:a81a8d6c1dfe 657 SercomI2cm *const i2c_module = &(module->hw->I2CM);
mbed_official 15:a81a8d6c1dfe 658 bool sclsm_flag = i2c_module->CTRLA.bit.SCLSM;
mbed_official 15:a81a8d6c1dfe 659
mbed_official 15:a81a8d6c1dfe 660 /* Combine callback registered and enabled masks */
mbed_official 15:a81a8d6c1dfe 661 uint8_t callback_mask = module->enabled_callback;
mbed_official 15:a81a8d6c1dfe 662 callback_mask &= module->registered_callback;
mbed_official 15:a81a8d6c1dfe 663
mbed_official 15:a81a8d6c1dfe 664 /* Check if the module should respond to address ack */
mbed_official 15:a81a8d6c1dfe 665 if ((module->buffer_length <= 0) && (module->buffer_remaining > 0)) {
mbed_official 15:a81a8d6c1dfe 666 /* Call function for address response */
mbed_official 15:a81a8d6c1dfe 667 _i2c_master_async_address_response(module);
mbed_official 15:a81a8d6c1dfe 668
mbed_official 15:a81a8d6c1dfe 669 /* Check if buffer write is done */
mbed_official 15:a81a8d6c1dfe 670 } else if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
mbed_official 15:a81a8d6c1dfe 671 (module->status == STATUS_BUSY) &&
mbed_official 15:a81a8d6c1dfe 672 (module->transfer_direction == I2C_TRANSFER_WRITE)) {
mbed_official 15:a81a8d6c1dfe 673 /* Stop packet operation */
mbed_official 15:a81a8d6c1dfe 674 i2c_module->INTENCLR.reg =
mbed_official 15:a81a8d6c1dfe 675 SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
mbed_official 15:a81a8d6c1dfe 676
mbed_official 15:a81a8d6c1dfe 677 module->buffer_length = 0;
mbed_official 15:a81a8d6c1dfe 678 module->status = STATUS_OK;
mbed_official 15:a81a8d6c1dfe 679
mbed_official 15:a81a8d6c1dfe 680 if (module->send_stop) {
mbed_official 15:a81a8d6c1dfe 681 /* Send stop condition */
mbed_official 15:a81a8d6c1dfe 682 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 683 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 15:a81a8d6c1dfe 684 } else {
mbed_official 15:a81a8d6c1dfe 685 /* Clear write interrupt flag */
mbed_official 15:a81a8d6c1dfe 686 i2c_module->INTFLAG.reg = SERCOM_I2CM_INTFLAG_MB;
mbed_official 15:a81a8d6c1dfe 687 }
mbed_official 15:a81a8d6c1dfe 688
mbed_official 15:a81a8d6c1dfe 689 if (callback_mask & (1 << I2C_MASTER_CALLBACK_WRITE_COMPLETE)) {
mbed_official 15:a81a8d6c1dfe 690 module->callbacks[I2C_MASTER_CALLBACK_WRITE_COMPLETE](module);
mbed_official 15:a81a8d6c1dfe 691 }
mbed_official 15:a81a8d6c1dfe 692
mbed_official 15:a81a8d6c1dfe 693 /* Continue buffer write/read */
mbed_official 15:a81a8d6c1dfe 694 } else if ((module->buffer_length > 0) && (module->buffer_remaining > 0)) {
mbed_official 15:a81a8d6c1dfe 695 /* Check that bus ownership is not lost */
mbed_official 15:a81a8d6c1dfe 696 if ((!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) &&
mbed_official 15:a81a8d6c1dfe 697 (!(sclsm_flag && (module->buffer_remaining == 1)))) {
mbed_official 15:a81a8d6c1dfe 698 module->status = STATUS_ERR_PACKET_COLLISION;
mbed_official 15:a81a8d6c1dfe 699 } else if (module->transfer_direction == I2C_TRANSFER_WRITE) {
mbed_official 15:a81a8d6c1dfe 700 _i2c_master_write(module);
mbed_official 15:a81a8d6c1dfe 701 } else {
mbed_official 15:a81a8d6c1dfe 702 _i2c_master_read(module);
mbed_official 15:a81a8d6c1dfe 703 }
mbed_official 15:a81a8d6c1dfe 704 }
mbed_official 15:a81a8d6c1dfe 705
mbed_official 15:a81a8d6c1dfe 706 /* Check if read buffer transfer is complete */
mbed_official 15:a81a8d6c1dfe 707 if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
mbed_official 15:a81a8d6c1dfe 708 (module->status == STATUS_BUSY) &&
mbed_official 15:a81a8d6c1dfe 709 (module->transfer_direction == I2C_TRANSFER_READ)) {
mbed_official 15:a81a8d6c1dfe 710
mbed_official 15:a81a8d6c1dfe 711 /* Clear read interrupt flag */
mbed_official 15:a81a8d6c1dfe 712 if (i2c_module->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB) {
mbed_official 15:a81a8d6c1dfe 713 i2c_module->INTFLAG.reg = SERCOM_I2CM_INTFLAG_SB;
mbed_official 15:a81a8d6c1dfe 714 }
mbed_official 15:a81a8d6c1dfe 715 /* Stop packet operation */
mbed_official 15:a81a8d6c1dfe 716 i2c_module->INTENCLR.reg =
mbed_official 15:a81a8d6c1dfe 717 SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
mbed_official 15:a81a8d6c1dfe 718 module->buffer_length = 0;
mbed_official 15:a81a8d6c1dfe 719 module->status = STATUS_OK;
mbed_official 15:a81a8d6c1dfe 720
mbed_official 15:a81a8d6c1dfe 721 /* Call appropriate callback if enabled and registered */
mbed_official 15:a81a8d6c1dfe 722 if ((callback_mask & (1 << I2C_MASTER_CALLBACK_READ_COMPLETE))
mbed_official 15:a81a8d6c1dfe 723 && (module->transfer_direction == I2C_TRANSFER_READ)) {
mbed_official 15:a81a8d6c1dfe 724 module->callbacks[I2C_MASTER_CALLBACK_READ_COMPLETE](module);
mbed_official 15:a81a8d6c1dfe 725 } else if ((callback_mask & (1 << I2C_MASTER_CALLBACK_WRITE_COMPLETE))
mbed_official 15:a81a8d6c1dfe 726 && (module->transfer_direction == I2C_TRANSFER_WRITE)) {
mbed_official 15:a81a8d6c1dfe 727 module->callbacks[I2C_MASTER_CALLBACK_WRITE_COMPLETE](module);
mbed_official 15:a81a8d6c1dfe 728 }
mbed_official 15:a81a8d6c1dfe 729 }
mbed_official 15:a81a8d6c1dfe 730
mbed_official 15:a81a8d6c1dfe 731 /* Check for error */
mbed_official 15:a81a8d6c1dfe 732 if ((module->status != STATUS_BUSY) && (module->status != STATUS_OK)) {
mbed_official 15:a81a8d6c1dfe 733 /* Stop packet operation */
mbed_official 15:a81a8d6c1dfe 734 i2c_module->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB |
mbed_official 15:a81a8d6c1dfe 735 SERCOM_I2CM_INTENCLR_SB;
mbed_official 15:a81a8d6c1dfe 736
mbed_official 15:a81a8d6c1dfe 737 module->buffer_length = 0;
mbed_official 15:a81a8d6c1dfe 738 module->buffer_remaining = 0;
mbed_official 15:a81a8d6c1dfe 739
mbed_official 15:a81a8d6c1dfe 740 /* Send nack and stop command unless arbitration is lost */
mbed_official 15:a81a8d6c1dfe 741 if ((module->status != STATUS_ERR_PACKET_COLLISION) &&
mbed_official 15:a81a8d6c1dfe 742 module->send_stop) {
mbed_official 15:a81a8d6c1dfe 743 _i2c_master_wait_for_sync(module);
mbed_official 15:a81a8d6c1dfe 744 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT |
mbed_official 15:a81a8d6c1dfe 745 SERCOM_I2CM_CTRLB_CMD(3);
mbed_official 15:a81a8d6c1dfe 746 }
mbed_official 15:a81a8d6c1dfe 747
mbed_official 15:a81a8d6c1dfe 748 /* Call error callback if enabled and registered */
mbed_official 15:a81a8d6c1dfe 749 if (callback_mask & (1 << I2C_MASTER_CALLBACK_ERROR)) {
mbed_official 15:a81a8d6c1dfe 750 module->callbacks[I2C_MASTER_CALLBACK_ERROR](module);
mbed_official 15:a81a8d6c1dfe 751 }
mbed_official 15:a81a8d6c1dfe 752 }
mbed_official 15:a81a8d6c1dfe 753 }