Mouse code for the MacroRat
mbed-dev/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/i2c_api.c@18:6a4db94011d3, 2017-05-14 (annotated)
- Committer:
- sahilmgandhi
- Date:
- Sun May 14 23:18:57 2017 +0000
- Revision:
- 18:6a4db94011d3
Publishing again
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sahilmgandhi | 18:6a4db94011d3 | 1 | /* mbed Microcontroller Library |
sahilmgandhi | 18:6a4db94011d3 | 2 | * Copyright (c) 2006-2015 ARM Limited |
sahilmgandhi | 18:6a4db94011d3 | 3 | * |
sahilmgandhi | 18:6a4db94011d3 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
sahilmgandhi | 18:6a4db94011d3 | 5 | * you may not use this file except in compliance with the License. |
sahilmgandhi | 18:6a4db94011d3 | 6 | * You may obtain a copy of the License at |
sahilmgandhi | 18:6a4db94011d3 | 7 | * |
sahilmgandhi | 18:6a4db94011d3 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
sahilmgandhi | 18:6a4db94011d3 | 9 | * |
sahilmgandhi | 18:6a4db94011d3 | 10 | * Unless required by applicable law or agreed to in writing, software |
sahilmgandhi | 18:6a4db94011d3 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
sahilmgandhi | 18:6a4db94011d3 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
sahilmgandhi | 18:6a4db94011d3 | 13 | * See the License for the specific language governing permissions and |
sahilmgandhi | 18:6a4db94011d3 | 14 | * limitations under the License. |
sahilmgandhi | 18:6a4db94011d3 | 15 | */ |
sahilmgandhi | 18:6a4db94011d3 | 16 | #include "mbed_assert.h" |
sahilmgandhi | 18:6a4db94011d3 | 17 | #include "i2c_api.h" |
sahilmgandhi | 18:6a4db94011d3 | 18 | |
sahilmgandhi | 18:6a4db94011d3 | 19 | #include <math.h> |
sahilmgandhi | 18:6a4db94011d3 | 20 | |
sahilmgandhi | 18:6a4db94011d3 | 21 | #include "cmsis.h" |
sahilmgandhi | 18:6a4db94011d3 | 22 | #include "pinmap.h" |
sahilmgandhi | 18:6a4db94011d3 | 23 | #include "sercom.h" |
sahilmgandhi | 18:6a4db94011d3 | 24 | #include "i2c_master.h" |
sahilmgandhi | 18:6a4db94011d3 | 25 | #include "i2c_slave.h" |
sahilmgandhi | 18:6a4db94011d3 | 26 | |
sahilmgandhi | 18:6a4db94011d3 | 27 | #include "pinmap_function.h" |
sahilmgandhi | 18:6a4db94011d3 | 28 | |
sahilmgandhi | 18:6a4db94011d3 | 29 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 30 | #include "i2c_master_interrupt.h" |
sahilmgandhi | 18:6a4db94011d3 | 31 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 32 | |
sahilmgandhi | 18:6a4db94011d3 | 33 | |
sahilmgandhi | 18:6a4db94011d3 | 34 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 35 | #define pI2C_S(obj) (&obj->i2c) |
sahilmgandhi | 18:6a4db94011d3 | 36 | #else |
sahilmgandhi | 18:6a4db94011d3 | 37 | #define pI2C_S(obj) obj |
sahilmgandhi | 18:6a4db94011d3 | 38 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 39 | |
sahilmgandhi | 18:6a4db94011d3 | 40 | #define I2C_MASTER_DEFAULT_BAUD 100000 |
sahilmgandhi | 18:6a4db94011d3 | 41 | |
sahilmgandhi | 18:6a4db94011d3 | 42 | /** |
sahilmgandhi | 18:6a4db94011d3 | 43 | * \brief I2C modes enum |
sahilmgandhi | 18:6a4db94011d3 | 44 | * |
sahilmgandhi | 18:6a4db94011d3 | 45 | * I2C mode selection. |
sahilmgandhi | 18:6a4db94011d3 | 46 | */ |
sahilmgandhi | 18:6a4db94011d3 | 47 | enum i2c_mode { |
sahilmgandhi | 18:6a4db94011d3 | 48 | /** Master mode. */ |
sahilmgandhi | 18:6a4db94011d3 | 49 | I2C_MODE_MASTER = 0x5, |
sahilmgandhi | 18:6a4db94011d3 | 50 | /** Slave mode. */ |
sahilmgandhi | 18:6a4db94011d3 | 51 | I2C_MODE_SLAVE = 0x4, |
sahilmgandhi | 18:6a4db94011d3 | 52 | }; |
sahilmgandhi | 18:6a4db94011d3 | 53 | |
sahilmgandhi | 18:6a4db94011d3 | 54 | /* Extern Variables */ |
sahilmgandhi | 18:6a4db94011d3 | 55 | extern uint8_t g_sys_init; |
sahilmgandhi | 18:6a4db94011d3 | 56 | |
sahilmgandhi | 18:6a4db94011d3 | 57 | typedef void (*I2CHandler)(void); |
sahilmgandhi | 18:6a4db94011d3 | 58 | |
sahilmgandhi | 18:6a4db94011d3 | 59 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 60 | #define _SERCOM_INTERRUPT_HANDLERS(n, unused) (uint32_t)SERCOM##n##_Handler, |
sahilmgandhi | 18:6a4db94011d3 | 61 | |
sahilmgandhi | 18:6a4db94011d3 | 62 | /* To save the i2c objects */ |
sahilmgandhi | 18:6a4db94011d3 | 63 | static uint32_t i2c_instances[SERCOM_INST_NUM] = {0}; |
sahilmgandhi | 18:6a4db94011d3 | 64 | const uint32_t sercom_irq_handlers[SERCOM_INST_NUM] = { |
sahilmgandhi | 18:6a4db94011d3 | 65 | MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_HANDLERS, ~) |
sahilmgandhi | 18:6a4db94011d3 | 66 | }; |
sahilmgandhi | 18:6a4db94011d3 | 67 | |
sahilmgandhi | 18:6a4db94011d3 | 68 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 69 | |
sahilmgandhi | 18:6a4db94011d3 | 70 | /* Forward declaration */ |
sahilmgandhi | 18:6a4db94011d3 | 71 | enum status_code _i2c_master_wait_for_bus( |
sahilmgandhi | 18:6a4db94011d3 | 72 | struct i2c_master_module *const module); |
sahilmgandhi | 18:6a4db94011d3 | 73 | |
sahilmgandhi | 18:6a4db94011d3 | 74 | enum status_code _i2c_master_address_response( |
sahilmgandhi | 18:6a4db94011d3 | 75 | struct i2c_master_module *const module); |
sahilmgandhi | 18:6a4db94011d3 | 76 | |
sahilmgandhi | 18:6a4db94011d3 | 77 | enum status_code _i2c_master_send_hs_master_code( |
sahilmgandhi | 18:6a4db94011d3 | 78 | struct i2c_master_module *const module, |
sahilmgandhi | 18:6a4db94011d3 | 79 | uint8_t hs_master_code); |
sahilmgandhi | 18:6a4db94011d3 | 80 | |
sahilmgandhi | 18:6a4db94011d3 | 81 | /* Adding function from ASF for compatibility */ |
sahilmgandhi | 18:6a4db94011d3 | 82 | static enum status_code _i2c_slave_wait_for_bus( |
sahilmgandhi | 18:6a4db94011d3 | 83 | struct i2c_slave_module *const module) |
sahilmgandhi | 18:6a4db94011d3 | 84 | { |
sahilmgandhi | 18:6a4db94011d3 | 85 | /* Sanity check arguments. */ |
sahilmgandhi | 18:6a4db94011d3 | 86 | MBED_ASSERT(module); |
sahilmgandhi | 18:6a4db94011d3 | 87 | MBED_ASSERT(module->hw); |
sahilmgandhi | 18:6a4db94011d3 | 88 | |
sahilmgandhi | 18:6a4db94011d3 | 89 | SercomI2cs *const i2c_hw = &(module->hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 90 | |
sahilmgandhi | 18:6a4db94011d3 | 91 | /* Wait for reply. */ |
sahilmgandhi | 18:6a4db94011d3 | 92 | uint16_t timeout_counter = 0; |
sahilmgandhi | 18:6a4db94011d3 | 93 | while ((!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY)) && |
sahilmgandhi | 18:6a4db94011d3 | 94 | (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC)) && |
sahilmgandhi | 18:6a4db94011d3 | 95 | (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH))) { |
sahilmgandhi | 18:6a4db94011d3 | 96 | |
sahilmgandhi | 18:6a4db94011d3 | 97 | /* Check timeout condition. */ |
sahilmgandhi | 18:6a4db94011d3 | 98 | if (++timeout_counter >= module->buffer_timeout) { |
sahilmgandhi | 18:6a4db94011d3 | 99 | return STATUS_ERR_TIMEOUT; |
sahilmgandhi | 18:6a4db94011d3 | 100 | } |
sahilmgandhi | 18:6a4db94011d3 | 101 | } |
sahilmgandhi | 18:6a4db94011d3 | 102 | return STATUS_OK; |
sahilmgandhi | 18:6a4db94011d3 | 103 | } |
sahilmgandhi | 18:6a4db94011d3 | 104 | |
sahilmgandhi | 18:6a4db94011d3 | 105 | /** Initialize the I2C peripheral |
sahilmgandhi | 18:6a4db94011d3 | 106 | * |
sahilmgandhi | 18:6a4db94011d3 | 107 | * Configures the pins used by I2C, sets a default format and frequency, and enables the peripheral |
sahilmgandhi | 18:6a4db94011d3 | 108 | * @param[out] obj The I2C object to initialize |
sahilmgandhi | 18:6a4db94011d3 | 109 | * @param[in] sda The pin to use for SDA |
sahilmgandhi | 18:6a4db94011d3 | 110 | * @param[in] scl The pin to use for SCL |
sahilmgandhi | 18:6a4db94011d3 | 111 | * @return void |
sahilmgandhi | 18:6a4db94011d3 | 112 | */ |
sahilmgandhi | 18:6a4db94011d3 | 113 | void i2c_init(i2c_t *obj, PinName sda, PinName scl) |
sahilmgandhi | 18:6a4db94011d3 | 114 | { |
sahilmgandhi | 18:6a4db94011d3 | 115 | Sercom* hw; |
sahilmgandhi | 18:6a4db94011d3 | 116 | uint32_t mux_func; |
sahilmgandhi | 18:6a4db94011d3 | 117 | struct i2c_master_config config_i2c_master; |
sahilmgandhi | 18:6a4db94011d3 | 118 | |
sahilmgandhi | 18:6a4db94011d3 | 119 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 120 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 121 | MBED_ASSERT(sda != NC); |
sahilmgandhi | 18:6a4db94011d3 | 122 | MBED_ASSERT(scl != NC); |
sahilmgandhi | 18:6a4db94011d3 | 123 | |
sahilmgandhi | 18:6a4db94011d3 | 124 | if (g_sys_init == 0) { |
sahilmgandhi | 18:6a4db94011d3 | 125 | system_init(); |
sahilmgandhi | 18:6a4db94011d3 | 126 | g_sys_init = 1; |
sahilmgandhi | 18:6a4db94011d3 | 127 | } |
sahilmgandhi | 18:6a4db94011d3 | 128 | |
sahilmgandhi | 18:6a4db94011d3 | 129 | pI2C_S(obj)->pins[0] = sda; |
sahilmgandhi | 18:6a4db94011d3 | 130 | pI2C_S(obj)->pins[1] = scl; |
sahilmgandhi | 18:6a4db94011d3 | 131 | |
sahilmgandhi | 18:6a4db94011d3 | 132 | /* Calculate SERCOM instance from pins */ |
sahilmgandhi | 18:6a4db94011d3 | 133 | uint32_t sercom_index = pinmap_merge_sercom(sda, scl); |
sahilmgandhi | 18:6a4db94011d3 | 134 | if (sercom_index == (uint32_t)NC) { |
sahilmgandhi | 18:6a4db94011d3 | 135 | return; |
sahilmgandhi | 18:6a4db94011d3 | 136 | } |
sahilmgandhi | 18:6a4db94011d3 | 137 | hw = (Sercom*)pinmap_peripheral_sercom(NC, sercom_index); |
sahilmgandhi | 18:6a4db94011d3 | 138 | |
sahilmgandhi | 18:6a4db94011d3 | 139 | i2c_master_get_config_defaults(&config_i2c_master); |
sahilmgandhi | 18:6a4db94011d3 | 140 | |
sahilmgandhi | 18:6a4db94011d3 | 141 | /* SERCOM PAD0 - SDA */ |
sahilmgandhi | 18:6a4db94011d3 | 142 | mux_func = pinmap_function_sercom(sda, sercom_index); |
sahilmgandhi | 18:6a4db94011d3 | 143 | if (mux_func == (uint32_t)NC) return; |
sahilmgandhi | 18:6a4db94011d3 | 144 | config_i2c_master.pinmux_pad0 = (sda << 16) | (mux_func & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 145 | |
sahilmgandhi | 18:6a4db94011d3 | 146 | /* SERCOM PAD1 - SCL */ |
sahilmgandhi | 18:6a4db94011d3 | 147 | mux_func = pinmap_function_sercom(scl, sercom_index); |
sahilmgandhi | 18:6a4db94011d3 | 148 | if (mux_func == (uint32_t)NC) return; |
sahilmgandhi | 18:6a4db94011d3 | 149 | config_i2c_master.pinmux_pad1 = (scl << 16) | (mux_func & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 150 | |
sahilmgandhi | 18:6a4db94011d3 | 151 | /* Default baud rate is set to 100kHz */ |
sahilmgandhi | 18:6a4db94011d3 | 152 | pI2C_S(obj)->baud_rate = I2C_MASTER_DEFAULT_BAUD; |
sahilmgandhi | 18:6a4db94011d3 | 153 | config_i2c_master.baud_rate = pI2C_S(obj)->baud_rate / 1000; |
sahilmgandhi | 18:6a4db94011d3 | 154 | |
sahilmgandhi | 18:6a4db94011d3 | 155 | while(i2c_master_init(&pI2C_S(obj)->master, hw, &config_i2c_master) != STATUS_OK); |
sahilmgandhi | 18:6a4db94011d3 | 156 | pI2C_S(obj)->mode = I2C_MODE_MASTER; |
sahilmgandhi | 18:6a4db94011d3 | 157 | |
sahilmgandhi | 18:6a4db94011d3 | 158 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 159 | /* Save the i2c object */ |
sahilmgandhi | 18:6a4db94011d3 | 160 | i2c_instances[sercom_index] = (uint32_t)obj; |
sahilmgandhi | 18:6a4db94011d3 | 161 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 162 | |
sahilmgandhi | 18:6a4db94011d3 | 163 | i2c_master_enable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 164 | } |
sahilmgandhi | 18:6a4db94011d3 | 165 | |
sahilmgandhi | 18:6a4db94011d3 | 166 | /** Configure the I2C frequency. |
sahilmgandhi | 18:6a4db94011d3 | 167 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 168 | * @param hz Frequency in Hz |
sahilmgandhi | 18:6a4db94011d3 | 169 | */ |
sahilmgandhi | 18:6a4db94011d3 | 170 | void i2c_frequency(i2c_t *obj, int hz) |
sahilmgandhi | 18:6a4db94011d3 | 171 | { |
sahilmgandhi | 18:6a4db94011d3 | 172 | /* Temporary variables. */ |
sahilmgandhi | 18:6a4db94011d3 | 173 | int32_t baud_rate; |
sahilmgandhi | 18:6a4db94011d3 | 174 | int32_t tmp_baud; |
sahilmgandhi | 18:6a4db94011d3 | 175 | int32_t tmp_baud_hs; |
sahilmgandhi | 18:6a4db94011d3 | 176 | enum status_code tmp_status_code; |
sahilmgandhi | 18:6a4db94011d3 | 177 | |
sahilmgandhi | 18:6a4db94011d3 | 178 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 179 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 180 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 181 | |
sahilmgandhi | 18:6a4db94011d3 | 182 | /* Return if in Slave mode, slave do not have any baud to set */ |
sahilmgandhi | 18:6a4db94011d3 | 183 | if (pI2C_S(obj)->mode != I2C_MODE_MASTER) return; |
sahilmgandhi | 18:6a4db94011d3 | 184 | |
sahilmgandhi | 18:6a4db94011d3 | 185 | SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM); |
sahilmgandhi | 18:6a4db94011d3 | 186 | |
sahilmgandhi | 18:6a4db94011d3 | 187 | /* Disable I2C Module */ |
sahilmgandhi | 18:6a4db94011d3 | 188 | i2c_master_disable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 189 | |
sahilmgandhi | 18:6a4db94011d3 | 190 | baud_rate = hz / 1000; /* To kHz */ |
sahilmgandhi | 18:6a4db94011d3 | 191 | |
sahilmgandhi | 18:6a4db94011d3 | 192 | /* Give a dummy supported value */ |
sahilmgandhi | 18:6a4db94011d3 | 193 | pI2C_S(obj)->baud_rate_high_speed = I2C_MASTER_BAUD_RATE_3400KHZ; |
sahilmgandhi | 18:6a4db94011d3 | 194 | |
sahilmgandhi | 18:6a4db94011d3 | 195 | uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 196 | |
sahilmgandhi | 18:6a4db94011d3 | 197 | /* Find and set baudrate. */ |
sahilmgandhi | 18:6a4db94011d3 | 198 | tmp_baud = (int32_t)(div_ceil( |
sahilmgandhi | 18:6a4db94011d3 | 199 | system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index), (2000*(baud_rate))) - 5); |
sahilmgandhi | 18:6a4db94011d3 | 200 | |
sahilmgandhi | 18:6a4db94011d3 | 201 | /* Check that baudrate is supported at current speed. */ |
sahilmgandhi | 18:6a4db94011d3 | 202 | if (tmp_baud > 255 || tmp_baud < 0) { |
sahilmgandhi | 18:6a4db94011d3 | 203 | /* Baud rate not supported. */ |
sahilmgandhi | 18:6a4db94011d3 | 204 | tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE; |
sahilmgandhi | 18:6a4db94011d3 | 205 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 206 | /* Find baudrate for high speed */ |
sahilmgandhi | 18:6a4db94011d3 | 207 | tmp_baud_hs = (int32_t)(div_ceil( |
sahilmgandhi | 18:6a4db94011d3 | 208 | system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index), |
sahilmgandhi | 18:6a4db94011d3 | 209 | (2000*(pI2C_S(obj)->baud_rate_high_speed))) - 1); |
sahilmgandhi | 18:6a4db94011d3 | 210 | |
sahilmgandhi | 18:6a4db94011d3 | 211 | /* Check that baudrate is supported at current speed. */ |
sahilmgandhi | 18:6a4db94011d3 | 212 | if (tmp_baud_hs > 255 || tmp_baud_hs < 0) { |
sahilmgandhi | 18:6a4db94011d3 | 213 | /* Baud rate not supported. */ |
sahilmgandhi | 18:6a4db94011d3 | 214 | tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE; |
sahilmgandhi | 18:6a4db94011d3 | 215 | } |
sahilmgandhi | 18:6a4db94011d3 | 216 | } |
sahilmgandhi | 18:6a4db94011d3 | 217 | if (tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE) { |
sahilmgandhi | 18:6a4db94011d3 | 218 | /* Baud rate acceptable. */ |
sahilmgandhi | 18:6a4db94011d3 | 219 | i2c_module->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud) | SERCOM_I2CM_BAUD_HSBAUD(tmp_baud_hs); |
sahilmgandhi | 18:6a4db94011d3 | 220 | pI2C_S(obj)->baud_rate = hz; |
sahilmgandhi | 18:6a4db94011d3 | 221 | } |
sahilmgandhi | 18:6a4db94011d3 | 222 | |
sahilmgandhi | 18:6a4db94011d3 | 223 | /* Enable back the I2C Module */ |
sahilmgandhi | 18:6a4db94011d3 | 224 | i2c_master_enable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 225 | } |
sahilmgandhi | 18:6a4db94011d3 | 226 | |
sahilmgandhi | 18:6a4db94011d3 | 227 | /** Send START command. |
sahilmgandhi | 18:6a4db94011d3 | 228 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 229 | */ |
sahilmgandhi | 18:6a4db94011d3 | 230 | int i2c_start(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 231 | { |
sahilmgandhi | 18:6a4db94011d3 | 232 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 233 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 234 | |
sahilmgandhi | 18:6a4db94011d3 | 235 | if (pI2C_S(obj)->mode == I2C_MODE_MASTER) { |
sahilmgandhi | 18:6a4db94011d3 | 236 | pI2C_S(obj)->start_pending = 1; |
sahilmgandhi | 18:6a4db94011d3 | 237 | } |
sahilmgandhi | 18:6a4db94011d3 | 238 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 239 | } |
sahilmgandhi | 18:6a4db94011d3 | 240 | |
sahilmgandhi | 18:6a4db94011d3 | 241 | /** Send STOP command. |
sahilmgandhi | 18:6a4db94011d3 | 242 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 243 | */ |
sahilmgandhi | 18:6a4db94011d3 | 244 | int i2c_stop(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 245 | { |
sahilmgandhi | 18:6a4db94011d3 | 246 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 247 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 248 | |
sahilmgandhi | 18:6a4db94011d3 | 249 | if (pI2C_S(obj)->mode == I2C_MODE_MASTER) { |
sahilmgandhi | 18:6a4db94011d3 | 250 | /* Send STOP command */ |
sahilmgandhi | 18:6a4db94011d3 | 251 | i2c_master_send_stop(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 252 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 253 | SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 254 | /* Release line and wait for next start condition */ |
sahilmgandhi | 18:6a4db94011d3 | 255 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2); |
sahilmgandhi | 18:6a4db94011d3 | 256 | } |
sahilmgandhi | 18:6a4db94011d3 | 257 | |
sahilmgandhi | 18:6a4db94011d3 | 258 | pI2C_S(obj)->start_pending = 0; |
sahilmgandhi | 18:6a4db94011d3 | 259 | |
sahilmgandhi | 18:6a4db94011d3 | 260 | /* TODO: Wait till STOP is send */ |
sahilmgandhi | 18:6a4db94011d3 | 261 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 262 | } |
sahilmgandhi | 18:6a4db94011d3 | 263 | |
sahilmgandhi | 18:6a4db94011d3 | 264 | /** Blocking reading data. |
sahilmgandhi | 18:6a4db94011d3 | 265 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 266 | * @param address 7-bit address (last bit is 1) |
sahilmgandhi | 18:6a4db94011d3 | 267 | * @param data The buffer for receiving |
sahilmgandhi | 18:6a4db94011d3 | 268 | * @param length Number of bytes to read |
sahilmgandhi | 18:6a4db94011d3 | 269 | * @param stop Stop to be generated after the transfer is done |
sahilmgandhi | 18:6a4db94011d3 | 270 | * @return Number of read bytes |
sahilmgandhi | 18:6a4db94011d3 | 271 | */ |
sahilmgandhi | 18:6a4db94011d3 | 272 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) |
sahilmgandhi | 18:6a4db94011d3 | 273 | { |
sahilmgandhi | 18:6a4db94011d3 | 274 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 275 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 276 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 277 | |
sahilmgandhi | 18:6a4db94011d3 | 278 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 279 | |
sahilmgandhi | 18:6a4db94011d3 | 280 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 281 | if (i2c_active(obj)) { |
sahilmgandhi | 18:6a4db94011d3 | 282 | /* I2C is busy with a job */ |
sahilmgandhi | 18:6a4db94011d3 | 283 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 284 | } |
sahilmgandhi | 18:6a4db94011d3 | 285 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 286 | |
sahilmgandhi | 18:6a4db94011d3 | 287 | struct i2c_master_packet packet; |
sahilmgandhi | 18:6a4db94011d3 | 288 | packet.address = (address & 0xFF) >> 1; |
sahilmgandhi | 18:6a4db94011d3 | 289 | packet.data_length = length; |
sahilmgandhi | 18:6a4db94011d3 | 290 | packet.data = (uint8_t*)data; |
sahilmgandhi | 18:6a4db94011d3 | 291 | packet.ten_bit_address = false; |
sahilmgandhi | 18:6a4db94011d3 | 292 | packet.high_speed = false; |
sahilmgandhi | 18:6a4db94011d3 | 293 | |
sahilmgandhi | 18:6a4db94011d3 | 294 | if (stop) { |
sahilmgandhi | 18:6a4db94011d3 | 295 | tmp_status = i2c_master_read_packet_wait(&pI2C_S(obj)->master, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 296 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 297 | tmp_status = i2c_master_read_packet_wait_no_stop(&pI2C_S(obj)->master, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 298 | } |
sahilmgandhi | 18:6a4db94011d3 | 299 | |
sahilmgandhi | 18:6a4db94011d3 | 300 | if (tmp_status == STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 301 | return length; |
sahilmgandhi | 18:6a4db94011d3 | 302 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 303 | /* Currently, no way to track no of bytes received, so return 0 if fail */ |
sahilmgandhi | 18:6a4db94011d3 | 304 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 305 | } |
sahilmgandhi | 18:6a4db94011d3 | 306 | } |
sahilmgandhi | 18:6a4db94011d3 | 307 | |
sahilmgandhi | 18:6a4db94011d3 | 308 | /** Blocking sending data. |
sahilmgandhi | 18:6a4db94011d3 | 309 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 310 | * @param address 7-bit address (last bit is 0) |
sahilmgandhi | 18:6a4db94011d3 | 311 | * @param data The buffer for sending |
sahilmgandhi | 18:6a4db94011d3 | 312 | * @param length Number of bytes to write |
sahilmgandhi | 18:6a4db94011d3 | 313 | * @param stop Stop to be generated after the transfer is done |
sahilmgandhi | 18:6a4db94011d3 | 314 | * @return Number of written bytes |
sahilmgandhi | 18:6a4db94011d3 | 315 | */ |
sahilmgandhi | 18:6a4db94011d3 | 316 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) |
sahilmgandhi | 18:6a4db94011d3 | 317 | { |
sahilmgandhi | 18:6a4db94011d3 | 318 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 319 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 320 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 321 | |
sahilmgandhi | 18:6a4db94011d3 | 322 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 323 | |
sahilmgandhi | 18:6a4db94011d3 | 324 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 325 | if (i2c_active(obj)) { |
sahilmgandhi | 18:6a4db94011d3 | 326 | /* I2C is busy with a job */ |
sahilmgandhi | 18:6a4db94011d3 | 327 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 328 | } |
sahilmgandhi | 18:6a4db94011d3 | 329 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 330 | |
sahilmgandhi | 18:6a4db94011d3 | 331 | struct i2c_master_packet packet; |
sahilmgandhi | 18:6a4db94011d3 | 332 | packet.address = (address & 0xFF) >> 1; |
sahilmgandhi | 18:6a4db94011d3 | 333 | packet.data_length = length; |
sahilmgandhi | 18:6a4db94011d3 | 334 | packet.data = (uint8_t *)data; |
sahilmgandhi | 18:6a4db94011d3 | 335 | packet.ten_bit_address = false; |
sahilmgandhi | 18:6a4db94011d3 | 336 | packet.high_speed = false; |
sahilmgandhi | 18:6a4db94011d3 | 337 | |
sahilmgandhi | 18:6a4db94011d3 | 338 | if (stop) { |
sahilmgandhi | 18:6a4db94011d3 | 339 | tmp_status = i2c_master_write_packet_wait(&pI2C_S(obj)->master, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 340 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 341 | tmp_status = i2c_master_write_packet_wait_no_stop(&pI2C_S(obj)->master, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 342 | } |
sahilmgandhi | 18:6a4db94011d3 | 343 | |
sahilmgandhi | 18:6a4db94011d3 | 344 | if (tmp_status == STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 345 | return length; |
sahilmgandhi | 18:6a4db94011d3 | 346 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 347 | /* Currently, no way to track no of bytes transmitted, so return 0 if fail */ |
sahilmgandhi | 18:6a4db94011d3 | 348 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 349 | } |
sahilmgandhi | 18:6a4db94011d3 | 350 | } |
sahilmgandhi | 18:6a4db94011d3 | 351 | |
sahilmgandhi | 18:6a4db94011d3 | 352 | /** Reset I2C peripheral. |
sahilmgandhi | 18:6a4db94011d3 | 353 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 354 | */ |
sahilmgandhi | 18:6a4db94011d3 | 355 | void i2c_reset(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 356 | { |
sahilmgandhi | 18:6a4db94011d3 | 357 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 358 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 359 | |
sahilmgandhi | 18:6a4db94011d3 | 360 | /* Send STOP */ |
sahilmgandhi | 18:6a4db94011d3 | 361 | i2c_stop(obj); |
sahilmgandhi | 18:6a4db94011d3 | 362 | |
sahilmgandhi | 18:6a4db94011d3 | 363 | pI2C_S(obj)->start_pending = 0; |
sahilmgandhi | 18:6a4db94011d3 | 364 | } |
sahilmgandhi | 18:6a4db94011d3 | 365 | |
sahilmgandhi | 18:6a4db94011d3 | 366 | /** Write address preceded by START condition. |
sahilmgandhi | 18:6a4db94011d3 | 367 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 368 | * @param address Address to be placed |
sahilmgandhi | 18:6a4db94011d3 | 369 | * @param rw_flag read or write flag |
sahilmgandhi | 18:6a4db94011d3 | 370 | * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout. |
sahilmgandhi | 18:6a4db94011d3 | 371 | */ |
sahilmgandhi | 18:6a4db94011d3 | 372 | int i2c_write_address(i2c_t *obj, int address, int rw_flag) |
sahilmgandhi | 18:6a4db94011d3 | 373 | { |
sahilmgandhi | 18:6a4db94011d3 | 374 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 375 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 376 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 377 | |
sahilmgandhi | 18:6a4db94011d3 | 378 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 379 | SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM); |
sahilmgandhi | 18:6a4db94011d3 | 380 | |
sahilmgandhi | 18:6a4db94011d3 | 381 | _i2c_master_wait_for_sync(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 382 | |
sahilmgandhi | 18:6a4db94011d3 | 383 | /* Set action to ACK. */ |
sahilmgandhi | 18:6a4db94011d3 | 384 | i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 385 | |
sahilmgandhi | 18:6a4db94011d3 | 386 | /* Write 7-bit address + read/write flag */ |
sahilmgandhi | 18:6a4db94011d3 | 387 | i2c_module->ADDR.reg = ((address & 0x7F) << 1) | (rw_flag & 0x01) | (0 << SERCOM_I2CM_ADDR_HS_Pos); |
sahilmgandhi | 18:6a4db94011d3 | 388 | |
sahilmgandhi | 18:6a4db94011d3 | 389 | /* Wait for response on bus. */ |
sahilmgandhi | 18:6a4db94011d3 | 390 | tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 391 | /* Check for error. */ |
sahilmgandhi | 18:6a4db94011d3 | 392 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 393 | return I2C_ERROR_BUS_BUSY; |
sahilmgandhi | 18:6a4db94011d3 | 394 | } |
sahilmgandhi | 18:6a4db94011d3 | 395 | /* Check for address response error unless previous error is detected. */ |
sahilmgandhi | 18:6a4db94011d3 | 396 | tmp_status = _i2c_master_address_response(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 397 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 398 | return I2C_ERROR_NO_SLAVE; |
sahilmgandhi | 18:6a4db94011d3 | 399 | } |
sahilmgandhi | 18:6a4db94011d3 | 400 | |
sahilmgandhi | 18:6a4db94011d3 | 401 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 402 | } |
sahilmgandhi | 18:6a4db94011d3 | 403 | |
sahilmgandhi | 18:6a4db94011d3 | 404 | /** Read one byte. |
sahilmgandhi | 18:6a4db94011d3 | 405 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 406 | * @param last Acknowledge |
sahilmgandhi | 18:6a4db94011d3 | 407 | * @return The read byte |
sahilmgandhi | 18:6a4db94011d3 | 408 | */ |
sahilmgandhi | 18:6a4db94011d3 | 409 | int i2c_byte_read(i2c_t *obj, int last) |
sahilmgandhi | 18:6a4db94011d3 | 410 | { |
sahilmgandhi | 18:6a4db94011d3 | 411 | int data = -1; |
sahilmgandhi | 18:6a4db94011d3 | 412 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 413 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 414 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 415 | |
sahilmgandhi | 18:6a4db94011d3 | 416 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 417 | |
sahilmgandhi | 18:6a4db94011d3 | 418 | if (pI2C_S(obj)->mode == I2C_MODE_MASTER) { |
sahilmgandhi | 18:6a4db94011d3 | 419 | SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM); |
sahilmgandhi | 18:6a4db94011d3 | 420 | |
sahilmgandhi | 18:6a4db94011d3 | 421 | if (last) { |
sahilmgandhi | 18:6a4db94011d3 | 422 | /* Set action to nack. */ |
sahilmgandhi | 18:6a4db94011d3 | 423 | i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 424 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 425 | /* Set action to ack. */ |
sahilmgandhi | 18:6a4db94011d3 | 426 | i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 427 | } |
sahilmgandhi | 18:6a4db94011d3 | 428 | |
sahilmgandhi | 18:6a4db94011d3 | 429 | /* Check that bus ownership is not lost. */ |
sahilmgandhi | 18:6a4db94011d3 | 430 | if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) { |
sahilmgandhi | 18:6a4db94011d3 | 431 | return -1; /* Return invalid data*/ |
sahilmgandhi | 18:6a4db94011d3 | 432 | } |
sahilmgandhi | 18:6a4db94011d3 | 433 | |
sahilmgandhi | 18:6a4db94011d3 | 434 | /* Save data to buffer. */ |
sahilmgandhi | 18:6a4db94011d3 | 435 | _i2c_master_wait_for_sync(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 436 | data = i2c_module->DATA.reg; |
sahilmgandhi | 18:6a4db94011d3 | 437 | /* Wait for response. */ |
sahilmgandhi | 18:6a4db94011d3 | 438 | tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 439 | |
sahilmgandhi | 18:6a4db94011d3 | 440 | /* Check for error. */ |
sahilmgandhi | 18:6a4db94011d3 | 441 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 442 | return -1; /* Return invalid data*/ |
sahilmgandhi | 18:6a4db94011d3 | 443 | } |
sahilmgandhi | 18:6a4db94011d3 | 444 | |
sahilmgandhi | 18:6a4db94011d3 | 445 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 446 | #if DEVICE_I2CSLAVE |
sahilmgandhi | 18:6a4db94011d3 | 447 | SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 448 | |
sahilmgandhi | 18:6a4db94011d3 | 449 | /* Check direction */ |
sahilmgandhi | 18:6a4db94011d3 | 450 | if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR) { |
sahilmgandhi | 18:6a4db94011d3 | 451 | /* Write request from master, send NACK and return */ |
sahilmgandhi | 18:6a4db94011d3 | 452 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 453 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3); |
sahilmgandhi | 18:6a4db94011d3 | 454 | return -1; /* Return invalid data*/ |
sahilmgandhi | 18:6a4db94011d3 | 455 | } |
sahilmgandhi | 18:6a4db94011d3 | 456 | |
sahilmgandhi | 18:6a4db94011d3 | 457 | if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) { |
sahilmgandhi | 18:6a4db94011d3 | 458 | /* Request from master, Address not yet acknowledged */ |
sahilmgandhi | 18:6a4db94011d3 | 459 | i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 460 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3); |
sahilmgandhi | 18:6a4db94011d3 | 461 | i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH; |
sahilmgandhi | 18:6a4db94011d3 | 462 | } |
sahilmgandhi | 18:6a4db94011d3 | 463 | if (last) { |
sahilmgandhi | 18:6a4db94011d3 | 464 | /* Set action to nack. */ |
sahilmgandhi | 18:6a4db94011d3 | 465 | i2c_hw->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 466 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 467 | /* Set action to ack. */ |
sahilmgandhi | 18:6a4db94011d3 | 468 | i2c_hw->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 469 | } |
sahilmgandhi | 18:6a4db94011d3 | 470 | |
sahilmgandhi | 18:6a4db94011d3 | 471 | /* Wait for next byte or stop condition */ |
sahilmgandhi | 18:6a4db94011d3 | 472 | tmp_status = _i2c_slave_wait_for_bus(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 473 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 474 | /* Timeout, return */ |
sahilmgandhi | 18:6a4db94011d3 | 475 | return -1; |
sahilmgandhi | 18:6a4db94011d3 | 476 | } |
sahilmgandhi | 18:6a4db94011d3 | 477 | |
sahilmgandhi | 18:6a4db94011d3 | 478 | if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) { |
sahilmgandhi | 18:6a4db94011d3 | 479 | /* Master sent stop condition, or repeated start, read done */ |
sahilmgandhi | 18:6a4db94011d3 | 480 | /* Clear stop flag */ |
sahilmgandhi | 18:6a4db94011d3 | 481 | i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC; |
sahilmgandhi | 18:6a4db94011d3 | 482 | return -1; |
sahilmgandhi | 18:6a4db94011d3 | 483 | } |
sahilmgandhi | 18:6a4db94011d3 | 484 | |
sahilmgandhi | 18:6a4db94011d3 | 485 | /* Read data */ |
sahilmgandhi | 18:6a4db94011d3 | 486 | _i2c_slave_wait_for_sync(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 487 | data = i2c_hw->DATA.reg; |
sahilmgandhi | 18:6a4db94011d3 | 488 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 489 | } |
sahilmgandhi | 18:6a4db94011d3 | 490 | |
sahilmgandhi | 18:6a4db94011d3 | 491 | return data; |
sahilmgandhi | 18:6a4db94011d3 | 492 | } |
sahilmgandhi | 18:6a4db94011d3 | 493 | |
sahilmgandhi | 18:6a4db94011d3 | 494 | /** Write one byte. |
sahilmgandhi | 18:6a4db94011d3 | 495 | * @param obj The i2c object |
sahilmgandhi | 18:6a4db94011d3 | 496 | * @param data Byte to be written |
sahilmgandhi | 18:6a4db94011d3 | 497 | * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout. |
sahilmgandhi | 18:6a4db94011d3 | 498 | */ |
sahilmgandhi | 18:6a4db94011d3 | 499 | int i2c_byte_write(i2c_t *obj, int data) |
sahilmgandhi | 18:6a4db94011d3 | 500 | { |
sahilmgandhi | 18:6a4db94011d3 | 501 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 502 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 503 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 504 | |
sahilmgandhi | 18:6a4db94011d3 | 505 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 506 | |
sahilmgandhi | 18:6a4db94011d3 | 507 | data = data & 0xFF; |
sahilmgandhi | 18:6a4db94011d3 | 508 | |
sahilmgandhi | 18:6a4db94011d3 | 509 | if (pI2C_S(obj)->mode == I2C_MODE_MASTER) { |
sahilmgandhi | 18:6a4db94011d3 | 510 | SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM); |
sahilmgandhi | 18:6a4db94011d3 | 511 | |
sahilmgandhi | 18:6a4db94011d3 | 512 | if (pI2C_S(obj)->start_pending) { |
sahilmgandhi | 18:6a4db94011d3 | 513 | pI2C_S(obj)->start_pending = 0; |
sahilmgandhi | 18:6a4db94011d3 | 514 | /* Write address */ |
sahilmgandhi | 18:6a4db94011d3 | 515 | return i2c_write_address(obj, (data >> 1), (data & 0x01)); |
sahilmgandhi | 18:6a4db94011d3 | 516 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 517 | /* Write data */ |
sahilmgandhi | 18:6a4db94011d3 | 518 | /* Check that bus ownership is not lost. */ |
sahilmgandhi | 18:6a4db94011d3 | 519 | if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) { |
sahilmgandhi | 18:6a4db94011d3 | 520 | return I2C_ERROR_NO_SLAVE; |
sahilmgandhi | 18:6a4db94011d3 | 521 | } |
sahilmgandhi | 18:6a4db94011d3 | 522 | |
sahilmgandhi | 18:6a4db94011d3 | 523 | /* Write byte to slave. */ |
sahilmgandhi | 18:6a4db94011d3 | 524 | _i2c_master_wait_for_sync(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 525 | i2c_module->DATA.reg = data; |
sahilmgandhi | 18:6a4db94011d3 | 526 | |
sahilmgandhi | 18:6a4db94011d3 | 527 | /* Wait for response. */ |
sahilmgandhi | 18:6a4db94011d3 | 528 | tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 529 | /* Check for error. */ |
sahilmgandhi | 18:6a4db94011d3 | 530 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 531 | return I2C_ERROR_BUS_BUSY; |
sahilmgandhi | 18:6a4db94011d3 | 532 | } |
sahilmgandhi | 18:6a4db94011d3 | 533 | |
sahilmgandhi | 18:6a4db94011d3 | 534 | /* Check for NACK from slave. */ |
sahilmgandhi | 18:6a4db94011d3 | 535 | if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) { |
sahilmgandhi | 18:6a4db94011d3 | 536 | /* Return bad data value. */ |
sahilmgandhi | 18:6a4db94011d3 | 537 | return I2C_ERROR_NO_SLAVE; |
sahilmgandhi | 18:6a4db94011d3 | 538 | } |
sahilmgandhi | 18:6a4db94011d3 | 539 | } |
sahilmgandhi | 18:6a4db94011d3 | 540 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 541 | #if DEVICE_I2CSLAVE |
sahilmgandhi | 18:6a4db94011d3 | 542 | SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 543 | |
sahilmgandhi | 18:6a4db94011d3 | 544 | if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) { |
sahilmgandhi | 18:6a4db94011d3 | 545 | /* Read request from master, Address not yet acknowledged */ |
sahilmgandhi | 18:6a4db94011d3 | 546 | i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT; |
sahilmgandhi | 18:6a4db94011d3 | 547 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3); |
sahilmgandhi | 18:6a4db94011d3 | 548 | i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH; |
sahilmgandhi | 18:6a4db94011d3 | 549 | } |
sahilmgandhi | 18:6a4db94011d3 | 550 | |
sahilmgandhi | 18:6a4db94011d3 | 551 | /* Write data */ |
sahilmgandhi | 18:6a4db94011d3 | 552 | _i2c_slave_wait_for_sync(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 553 | i2c_hw->DATA.reg = data; |
sahilmgandhi | 18:6a4db94011d3 | 554 | |
sahilmgandhi | 18:6a4db94011d3 | 555 | /* Wait for response from master */ |
sahilmgandhi | 18:6a4db94011d3 | 556 | tmp_status = _i2c_slave_wait_for_bus(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 557 | |
sahilmgandhi | 18:6a4db94011d3 | 558 | if (tmp_status != STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 559 | /* Timeout, return */ |
sahilmgandhi | 18:6a4db94011d3 | 560 | return I2C_ERROR_BUS_BUSY; |
sahilmgandhi | 18:6a4db94011d3 | 561 | } |
sahilmgandhi | 18:6a4db94011d3 | 562 | |
sahilmgandhi | 18:6a4db94011d3 | 563 | if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_RXNACK) { |
sahilmgandhi | 18:6a4db94011d3 | 564 | /* NACK from master, abort */ |
sahilmgandhi | 18:6a4db94011d3 | 565 | /* Release line */ |
sahilmgandhi | 18:6a4db94011d3 | 566 | i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02); |
sahilmgandhi | 18:6a4db94011d3 | 567 | |
sahilmgandhi | 18:6a4db94011d3 | 568 | return I2C_ERROR_NO_SLAVE; |
sahilmgandhi | 18:6a4db94011d3 | 569 | } |
sahilmgandhi | 18:6a4db94011d3 | 570 | #endif |
sahilmgandhi | 18:6a4db94011d3 | 571 | } |
sahilmgandhi | 18:6a4db94011d3 | 572 | |
sahilmgandhi | 18:6a4db94011d3 | 573 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 574 | } |
sahilmgandhi | 18:6a4db94011d3 | 575 | |
sahilmgandhi | 18:6a4db94011d3 | 576 | |
sahilmgandhi | 18:6a4db94011d3 | 577 | #if DEVICE_I2CSLAVE |
sahilmgandhi | 18:6a4db94011d3 | 578 | |
sahilmgandhi | 18:6a4db94011d3 | 579 | /** |
sahilmgandhi | 18:6a4db94011d3 | 580 | * \defgroup SynchI2C Synchronous I2C Hardware Abstraction Layer for slave |
sahilmgandhi | 18:6a4db94011d3 | 581 | * @{ |
sahilmgandhi | 18:6a4db94011d3 | 582 | */ |
sahilmgandhi | 18:6a4db94011d3 | 583 | |
sahilmgandhi | 18:6a4db94011d3 | 584 | /** Configure I2C as slave or master. |
sahilmgandhi | 18:6a4db94011d3 | 585 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 586 | * @param enable_slave configure I2C in slave mode or not |
sahilmgandhi | 18:6a4db94011d3 | 587 | * @return void |
sahilmgandhi | 18:6a4db94011d3 | 588 | */ |
sahilmgandhi | 18:6a4db94011d3 | 589 | void i2c_slave_mode(i2c_t *obj, int enable_slave) |
sahilmgandhi | 18:6a4db94011d3 | 590 | { |
sahilmgandhi | 18:6a4db94011d3 | 591 | int i; |
sahilmgandhi | 18:6a4db94011d3 | 592 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 593 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 594 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 595 | |
sahilmgandhi | 18:6a4db94011d3 | 596 | uint32_t mux_func[2]; |
sahilmgandhi | 18:6a4db94011d3 | 597 | uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 598 | for (i=0; i<2; i++) { |
sahilmgandhi | 18:6a4db94011d3 | 599 | mux_func[i] = pinmap_function_sercom(pI2C_S(obj)->pins[0], sercom_index); |
sahilmgandhi | 18:6a4db94011d3 | 600 | if (mux_func[i] == (uint32_t)NC) return; |
sahilmgandhi | 18:6a4db94011d3 | 601 | } |
sahilmgandhi | 18:6a4db94011d3 | 602 | |
sahilmgandhi | 18:6a4db94011d3 | 603 | if (enable_slave) { |
sahilmgandhi | 18:6a4db94011d3 | 604 | /* Disable I2C Master module if active */ |
sahilmgandhi | 18:6a4db94011d3 | 605 | i2c_master_disable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 606 | |
sahilmgandhi | 18:6a4db94011d3 | 607 | struct i2c_slave_config config_i2c_slave; |
sahilmgandhi | 18:6a4db94011d3 | 608 | i2c_slave_get_config_defaults(&config_i2c_slave); |
sahilmgandhi | 18:6a4db94011d3 | 609 | |
sahilmgandhi | 18:6a4db94011d3 | 610 | /* SERCOM PAD0 - SDA */ |
sahilmgandhi | 18:6a4db94011d3 | 611 | config_i2c_slave.pinmux_pad0 = (pI2C_S(obj)->pins[0] << 16) | (mux_func[0] & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 612 | /* SERCOM PAD1 - SCL */ |
sahilmgandhi | 18:6a4db94011d3 | 613 | config_i2c_slave.pinmux_pad1 = (pI2C_S(obj)->pins[1] << 16) | (mux_func[1] & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 614 | |
sahilmgandhi | 18:6a4db94011d3 | 615 | i2c_slave_init(&pI2C_S(obj)->slave, pI2C_S(obj)->master.hw, &config_i2c_slave); |
sahilmgandhi | 18:6a4db94011d3 | 616 | |
sahilmgandhi | 18:6a4db94011d3 | 617 | pI2C_S(obj)->mode = I2C_MODE_SLAVE; |
sahilmgandhi | 18:6a4db94011d3 | 618 | |
sahilmgandhi | 18:6a4db94011d3 | 619 | i2c_slave_enable(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 620 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 621 | if ((pI2C_S(obj)->master.hw) && (pI2C_S(obj)->mode == I2C_MODE_MASTER)) { |
sahilmgandhi | 18:6a4db94011d3 | 622 | /* Already configured, enable and return */ |
sahilmgandhi | 18:6a4db94011d3 | 623 | i2c_master_enable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 624 | return; |
sahilmgandhi | 18:6a4db94011d3 | 625 | } else if ((pI2C_S(obj)->slave.hw) && (pI2C_S(obj)->mode == I2C_MODE_SLAVE)) { |
sahilmgandhi | 18:6a4db94011d3 | 626 | /* Disable slave */ |
sahilmgandhi | 18:6a4db94011d3 | 627 | i2c_slave_disable(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 628 | } |
sahilmgandhi | 18:6a4db94011d3 | 629 | |
sahilmgandhi | 18:6a4db94011d3 | 630 | struct i2c_master_config config_i2c_master; |
sahilmgandhi | 18:6a4db94011d3 | 631 | /* SERCOM PAD0 - SDA */ |
sahilmgandhi | 18:6a4db94011d3 | 632 | config_i2c_master.pinmux_pad0 = (pI2C_S(obj)->pins[0] << 16) | (mux_func[0] & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 633 | /* SERCOM PAD1 - SCL */ |
sahilmgandhi | 18:6a4db94011d3 | 634 | config_i2c_master.pinmux_pad1 = (pI2C_S(obj)->pins[1] << 16) | (mux_func[1] & 0xFFFF); |
sahilmgandhi | 18:6a4db94011d3 | 635 | /* Baud rate */ |
sahilmgandhi | 18:6a4db94011d3 | 636 | config_i2c_master.baud_rate = pI2C_S(obj)->baud_rate / 1000; |
sahilmgandhi | 18:6a4db94011d3 | 637 | |
sahilmgandhi | 18:6a4db94011d3 | 638 | while(i2c_master_init(&pI2C_S(obj)->master, pI2C_S(obj)->master.hw, &config_i2c_master) != STATUS_OK); |
sahilmgandhi | 18:6a4db94011d3 | 639 | pI2C_S(obj)->mode = I2C_MODE_MASTER; |
sahilmgandhi | 18:6a4db94011d3 | 640 | |
sahilmgandhi | 18:6a4db94011d3 | 641 | i2c_master_enable(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 642 | } |
sahilmgandhi | 18:6a4db94011d3 | 643 | } |
sahilmgandhi | 18:6a4db94011d3 | 644 | |
sahilmgandhi | 18:6a4db94011d3 | 645 | /** Check to see if the I2C slave has been addressed. |
sahilmgandhi | 18:6a4db94011d3 | 646 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 647 | * @return The status - 1 - read addresses, 2 - write to all slaves, |
sahilmgandhi | 18:6a4db94011d3 | 648 | * 3 write addressed, 0 - the slave has not been addressed |
sahilmgandhi | 18:6a4db94011d3 | 649 | */ |
sahilmgandhi | 18:6a4db94011d3 | 650 | int i2c_slave_receive(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 651 | { |
sahilmgandhi | 18:6a4db94011d3 | 652 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 653 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 654 | MBED_ASSERT(pI2C_S(obj)->slave.hw); |
sahilmgandhi | 18:6a4db94011d3 | 655 | |
sahilmgandhi | 18:6a4db94011d3 | 656 | SercomI2cs *const i2c_module = &(pI2C_S(obj)->slave.hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 657 | |
sahilmgandhi | 18:6a4db94011d3 | 658 | if (i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) { |
sahilmgandhi | 18:6a4db94011d3 | 659 | if (i2c_module->STATUS.reg & SERCOM_I2CS_STATUS_DIR) { |
sahilmgandhi | 18:6a4db94011d3 | 660 | /* Slave is read addressed */ |
sahilmgandhi | 18:6a4db94011d3 | 661 | return 1; |
sahilmgandhi | 18:6a4db94011d3 | 662 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 663 | if (!(i2c_module->DATA.reg & 0xFF)) { |
sahilmgandhi | 18:6a4db94011d3 | 664 | /* General call address detected */ |
sahilmgandhi | 18:6a4db94011d3 | 665 | return 2; |
sahilmgandhi | 18:6a4db94011d3 | 666 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 667 | /* Slave is write addressed */ |
sahilmgandhi | 18:6a4db94011d3 | 668 | return 3; |
sahilmgandhi | 18:6a4db94011d3 | 669 | } |
sahilmgandhi | 18:6a4db94011d3 | 670 | } |
sahilmgandhi | 18:6a4db94011d3 | 671 | } |
sahilmgandhi | 18:6a4db94011d3 | 672 | |
sahilmgandhi | 18:6a4db94011d3 | 673 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 674 | } |
sahilmgandhi | 18:6a4db94011d3 | 675 | |
sahilmgandhi | 18:6a4db94011d3 | 676 | /** Blocking reading data. |
sahilmgandhi | 18:6a4db94011d3 | 677 | * @param obj The i2c slave object |
sahilmgandhi | 18:6a4db94011d3 | 678 | * @param data The buffer for receiving |
sahilmgandhi | 18:6a4db94011d3 | 679 | * @param length Number of bytes to read |
sahilmgandhi | 18:6a4db94011d3 | 680 | * @return Number of read bytes |
sahilmgandhi | 18:6a4db94011d3 | 681 | */ |
sahilmgandhi | 18:6a4db94011d3 | 682 | int i2c_slave_read(i2c_t *obj, char *data, int length) |
sahilmgandhi | 18:6a4db94011d3 | 683 | { |
sahilmgandhi | 18:6a4db94011d3 | 684 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 685 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 686 | MBED_ASSERT(pI2C_S(obj)->slave.hw); |
sahilmgandhi | 18:6a4db94011d3 | 687 | |
sahilmgandhi | 18:6a4db94011d3 | 688 | if (!data || !length) return 0; |
sahilmgandhi | 18:6a4db94011d3 | 689 | |
sahilmgandhi | 18:6a4db94011d3 | 690 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 691 | |
sahilmgandhi | 18:6a4db94011d3 | 692 | struct i2c_slave_packet packet; |
sahilmgandhi | 18:6a4db94011d3 | 693 | packet.data_length = length; |
sahilmgandhi | 18:6a4db94011d3 | 694 | packet.data = (uint8_t*)data; |
sahilmgandhi | 18:6a4db94011d3 | 695 | |
sahilmgandhi | 18:6a4db94011d3 | 696 | tmp_status = i2c_slave_read_packet_wait(&pI2C_S(obj)->slave, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 697 | |
sahilmgandhi | 18:6a4db94011d3 | 698 | if (tmp_status == STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 699 | return length; |
sahilmgandhi | 18:6a4db94011d3 | 700 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 701 | /* Currently, no way to track no of bytes transmitted, so return 0 */ |
sahilmgandhi | 18:6a4db94011d3 | 702 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 703 | } |
sahilmgandhi | 18:6a4db94011d3 | 704 | |
sahilmgandhi | 18:6a4db94011d3 | 705 | } |
sahilmgandhi | 18:6a4db94011d3 | 706 | |
sahilmgandhi | 18:6a4db94011d3 | 707 | /** Blocking writing data. |
sahilmgandhi | 18:6a4db94011d3 | 708 | * @param obj The i2c slave object |
sahilmgandhi | 18:6a4db94011d3 | 709 | * @param data The buffer for transmitting |
sahilmgandhi | 18:6a4db94011d3 | 710 | * @param length Number of bytes to write |
sahilmgandhi | 18:6a4db94011d3 | 711 | * @return Number of bytes written |
sahilmgandhi | 18:6a4db94011d3 | 712 | */ |
sahilmgandhi | 18:6a4db94011d3 | 713 | int i2c_slave_write(i2c_t *obj, const char *data, int length) |
sahilmgandhi | 18:6a4db94011d3 | 714 | { |
sahilmgandhi | 18:6a4db94011d3 | 715 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 716 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 717 | MBED_ASSERT(pI2C_S(obj)->slave.hw); |
sahilmgandhi | 18:6a4db94011d3 | 718 | |
sahilmgandhi | 18:6a4db94011d3 | 719 | if (!data || !length) return 0; |
sahilmgandhi | 18:6a4db94011d3 | 720 | |
sahilmgandhi | 18:6a4db94011d3 | 721 | enum status_code tmp_status; |
sahilmgandhi | 18:6a4db94011d3 | 722 | |
sahilmgandhi | 18:6a4db94011d3 | 723 | struct i2c_slave_packet packet; |
sahilmgandhi | 18:6a4db94011d3 | 724 | packet.data_length = length; |
sahilmgandhi | 18:6a4db94011d3 | 725 | packet.data = (uint8_t *)data; |
sahilmgandhi | 18:6a4db94011d3 | 726 | |
sahilmgandhi | 18:6a4db94011d3 | 727 | tmp_status = i2c_slave_write_packet_wait(&pI2C_S(obj)->slave, &packet); |
sahilmgandhi | 18:6a4db94011d3 | 728 | |
sahilmgandhi | 18:6a4db94011d3 | 729 | if (tmp_status == STATUS_OK) { |
sahilmgandhi | 18:6a4db94011d3 | 730 | return length; |
sahilmgandhi | 18:6a4db94011d3 | 731 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 732 | /* Currently, no way to track no of bytes transmitted, so return 0 */ |
sahilmgandhi | 18:6a4db94011d3 | 733 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 734 | } |
sahilmgandhi | 18:6a4db94011d3 | 735 | |
sahilmgandhi | 18:6a4db94011d3 | 736 | } |
sahilmgandhi | 18:6a4db94011d3 | 737 | |
sahilmgandhi | 18:6a4db94011d3 | 738 | /** Configure I2C slave address. |
sahilmgandhi | 18:6a4db94011d3 | 739 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 740 | * @param idx Currently not used |
sahilmgandhi | 18:6a4db94011d3 | 741 | * @param address The address to be set |
sahilmgandhi | 18:6a4db94011d3 | 742 | * @param mask Currently not used |
sahilmgandhi | 18:6a4db94011d3 | 743 | */ |
sahilmgandhi | 18:6a4db94011d3 | 744 | void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) |
sahilmgandhi | 18:6a4db94011d3 | 745 | { |
sahilmgandhi | 18:6a4db94011d3 | 746 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 747 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 748 | MBED_ASSERT(pI2C_S(obj)->slave.hw); |
sahilmgandhi | 18:6a4db94011d3 | 749 | |
sahilmgandhi | 18:6a4db94011d3 | 750 | /* Disable I2C Module */ |
sahilmgandhi | 18:6a4db94011d3 | 751 | i2c_slave_disable(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 752 | |
sahilmgandhi | 18:6a4db94011d3 | 753 | SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS); |
sahilmgandhi | 18:6a4db94011d3 | 754 | |
sahilmgandhi | 18:6a4db94011d3 | 755 | address = (address & 0xFF) >> 1; |
sahilmgandhi | 18:6a4db94011d3 | 756 | if (!mask) { |
sahilmgandhi | 18:6a4db94011d3 | 757 | mask = (0xFE >> 1); |
sahilmgandhi | 18:6a4db94011d3 | 758 | } |
sahilmgandhi | 18:6a4db94011d3 | 759 | /* Set the address and address mask */ |
sahilmgandhi | 18:6a4db94011d3 | 760 | i2c_hw->ADDR.reg = (address << SERCOM_I2CS_ADDR_ADDR_Pos) | |
sahilmgandhi | 18:6a4db94011d3 | 761 | (mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos) | |
sahilmgandhi | 18:6a4db94011d3 | 762 | (0 << SERCOM_I2CS_ADDR_TENBITEN_Pos) | |
sahilmgandhi | 18:6a4db94011d3 | 763 | (1 << SERCOM_I2CS_ADDR_GENCEN_Pos); |
sahilmgandhi | 18:6a4db94011d3 | 764 | |
sahilmgandhi | 18:6a4db94011d3 | 765 | /* Enable I2C Module */ |
sahilmgandhi | 18:6a4db94011d3 | 766 | i2c_slave_enable(&pI2C_S(obj)->slave); |
sahilmgandhi | 18:6a4db94011d3 | 767 | } |
sahilmgandhi | 18:6a4db94011d3 | 768 | |
sahilmgandhi | 18:6a4db94011d3 | 769 | #endif /* DEVICE_I2CSLAVE */ |
sahilmgandhi | 18:6a4db94011d3 | 770 | |
sahilmgandhi | 18:6a4db94011d3 | 771 | /**@}*/ |
sahilmgandhi | 18:6a4db94011d3 | 772 | |
sahilmgandhi | 18:6a4db94011d3 | 773 | #if DEVICE_I2C_ASYNCH |
sahilmgandhi | 18:6a4db94011d3 | 774 | |
sahilmgandhi | 18:6a4db94011d3 | 775 | /** |
sahilmgandhi | 18:6a4db94011d3 | 776 | * \defgroup AsynchI2C Asynchronous I2C Hardware Abstraction Layer |
sahilmgandhi | 18:6a4db94011d3 | 777 | * @{ |
sahilmgandhi | 18:6a4db94011d3 | 778 | */ |
sahilmgandhi | 18:6a4db94011d3 | 779 | |
sahilmgandhi | 18:6a4db94011d3 | 780 | /** |
sahilmgandhi | 18:6a4db94011d3 | 781 | * \internal |
sahilmgandhi | 18:6a4db94011d3 | 782 | * Callback for transfer finish. |
sahilmgandhi | 18:6a4db94011d3 | 783 | * |
sahilmgandhi | 18:6a4db94011d3 | 784 | * \param[in,out] module Pointer to SPI software instance struct |
sahilmgandhi | 18:6a4db94011d3 | 785 | */ |
sahilmgandhi | 18:6a4db94011d3 | 786 | void i2c_transfer_complete_callback(struct i2c_master_module *const module) |
sahilmgandhi | 18:6a4db94011d3 | 787 | { |
sahilmgandhi | 18:6a4db94011d3 | 788 | uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw); |
sahilmgandhi | 18:6a4db94011d3 | 789 | |
sahilmgandhi | 18:6a4db94011d3 | 790 | if (sercom_index >= SERCOM_INST_NUM) { |
sahilmgandhi | 18:6a4db94011d3 | 791 | /* TODO: Abort operation */ |
sahilmgandhi | 18:6a4db94011d3 | 792 | return; |
sahilmgandhi | 18:6a4db94011d3 | 793 | } |
sahilmgandhi | 18:6a4db94011d3 | 794 | |
sahilmgandhi | 18:6a4db94011d3 | 795 | i2c_t *obj = (i2c_t*)i2c_instances[sercom_index]; |
sahilmgandhi | 18:6a4db94011d3 | 796 | |
sahilmgandhi | 18:6a4db94011d3 | 797 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 798 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 799 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR); |
sahilmgandhi | 18:6a4db94011d3 | 800 | |
sahilmgandhi | 18:6a4db94011d3 | 801 | /* Call the handler function */ |
sahilmgandhi | 18:6a4db94011d3 | 802 | if (pI2C_S(obj)->handler) { |
sahilmgandhi | 18:6a4db94011d3 | 803 | ((I2CHandler)pI2C_S(obj)->handler)(); |
sahilmgandhi | 18:6a4db94011d3 | 804 | } |
sahilmgandhi | 18:6a4db94011d3 | 805 | } |
sahilmgandhi | 18:6a4db94011d3 | 806 | |
sahilmgandhi | 18:6a4db94011d3 | 807 | /** |
sahilmgandhi | 18:6a4db94011d3 | 808 | * \internal |
sahilmgandhi | 18:6a4db94011d3 | 809 | * Callback for write complete. Initiate read from here. |
sahilmgandhi | 18:6a4db94011d3 | 810 | * |
sahilmgandhi | 18:6a4db94011d3 | 811 | * \param[in,out] module Pointer to SPI software instance struct |
sahilmgandhi | 18:6a4db94011d3 | 812 | */ |
sahilmgandhi | 18:6a4db94011d3 | 813 | void i2c_write_complete_callback(struct i2c_master_module *const module) |
sahilmgandhi | 18:6a4db94011d3 | 814 | { |
sahilmgandhi | 18:6a4db94011d3 | 815 | uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw); |
sahilmgandhi | 18:6a4db94011d3 | 816 | |
sahilmgandhi | 18:6a4db94011d3 | 817 | if (sercom_index >= SERCOM_INST_NUM) { |
sahilmgandhi | 18:6a4db94011d3 | 818 | /* TODO: Abort operation */ |
sahilmgandhi | 18:6a4db94011d3 | 819 | return; |
sahilmgandhi | 18:6a4db94011d3 | 820 | } |
sahilmgandhi | 18:6a4db94011d3 | 821 | |
sahilmgandhi | 18:6a4db94011d3 | 822 | i2c_t *obj = (i2c_t*)i2c_instances[sercom_index]; |
sahilmgandhi | 18:6a4db94011d3 | 823 | |
sahilmgandhi | 18:6a4db94011d3 | 824 | if (!(pI2C_S(obj)->rd_packet.data) || (pI2C_S(obj)->rd_packet.data_length == 0)) { |
sahilmgandhi | 18:6a4db94011d3 | 825 | /* Call the handler function */ |
sahilmgandhi | 18:6a4db94011d3 | 826 | i2c_transfer_complete_callback(module); |
sahilmgandhi | 18:6a4db94011d3 | 827 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 828 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 829 | |
sahilmgandhi | 18:6a4db94011d3 | 830 | /* Register read complete callback */ |
sahilmgandhi | 18:6a4db94011d3 | 831 | i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 832 | i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 833 | |
sahilmgandhi | 18:6a4db94011d3 | 834 | /* Initiate read operation */ |
sahilmgandhi | 18:6a4db94011d3 | 835 | if (pI2C_S(obj)->master.send_stop) { |
sahilmgandhi | 18:6a4db94011d3 | 836 | i2c_master_read_packet_job(&pI2C_S(obj)->master,&pI2C_S(obj)->rd_packet); |
sahilmgandhi | 18:6a4db94011d3 | 837 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 838 | i2c_master_read_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->rd_packet); |
sahilmgandhi | 18:6a4db94011d3 | 839 | } |
sahilmgandhi | 18:6a4db94011d3 | 840 | } |
sahilmgandhi | 18:6a4db94011d3 | 841 | } |
sahilmgandhi | 18:6a4db94011d3 | 842 | |
sahilmgandhi | 18:6a4db94011d3 | 843 | /** Start i2c asynchronous transfer. |
sahilmgandhi | 18:6a4db94011d3 | 844 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 845 | * @param tx The buffer to send |
sahilmgandhi | 18:6a4db94011d3 | 846 | * @param tx_length The number of words to transmit |
sahilmgandhi | 18:6a4db94011d3 | 847 | * @param rx The buffer to receive |
sahilmgandhi | 18:6a4db94011d3 | 848 | * @param rx_length The number of words to receive |
sahilmgandhi | 18:6a4db94011d3 | 849 | * @param address The address to be set - 7bit or 9 bit |
sahilmgandhi | 18:6a4db94011d3 | 850 | * @param stop If true, stop will be generated after the transfer is done |
sahilmgandhi | 18:6a4db94011d3 | 851 | * @param handler The I2C IRQ handler to be set |
sahilmgandhi | 18:6a4db94011d3 | 852 | * @param hint DMA hint usage |
sahilmgandhi | 18:6a4db94011d3 | 853 | */ |
sahilmgandhi | 18:6a4db94011d3 | 854 | void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) |
sahilmgandhi | 18:6a4db94011d3 | 855 | { |
sahilmgandhi | 18:6a4db94011d3 | 856 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 857 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 858 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 859 | |
sahilmgandhi | 18:6a4db94011d3 | 860 | /* Return if in Slave mode */ |
sahilmgandhi | 18:6a4db94011d3 | 861 | if (pI2C_S(obj)->mode != I2C_MODE_MASTER) return; |
sahilmgandhi | 18:6a4db94011d3 | 862 | |
sahilmgandhi | 18:6a4db94011d3 | 863 | uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 864 | |
sahilmgandhi | 18:6a4db94011d3 | 865 | /* Init i2c packet. */ |
sahilmgandhi | 18:6a4db94011d3 | 866 | pI2C_S(obj)->wr_packet.address = address >> 1; |
sahilmgandhi | 18:6a4db94011d3 | 867 | pI2C_S(obj)->wr_packet.data_length = tx_length; |
sahilmgandhi | 18:6a4db94011d3 | 868 | pI2C_S(obj)->wr_packet.data = (uint8_t *)tx; |
sahilmgandhi | 18:6a4db94011d3 | 869 | |
sahilmgandhi | 18:6a4db94011d3 | 870 | pI2C_S(obj)->rd_packet.address = address >> 1; |
sahilmgandhi | 18:6a4db94011d3 | 871 | pI2C_S(obj)->rd_packet.data_length = rx_length; |
sahilmgandhi | 18:6a4db94011d3 | 872 | pI2C_S(obj)->rd_packet.data = rx; |
sahilmgandhi | 18:6a4db94011d3 | 873 | |
sahilmgandhi | 18:6a4db94011d3 | 874 | /* Save event mask and handler function pointer */ |
sahilmgandhi | 18:6a4db94011d3 | 875 | pI2C_S(obj)->events = event; |
sahilmgandhi | 18:6a4db94011d3 | 876 | pI2C_S(obj)->handler = handler; |
sahilmgandhi | 18:6a4db94011d3 | 877 | |
sahilmgandhi | 18:6a4db94011d3 | 878 | /* TODO: Current implementation is interrupt based only */ |
sahilmgandhi | 18:6a4db94011d3 | 879 | |
sahilmgandhi | 18:6a4db94011d3 | 880 | /* Set interrupt handler to default handler of ASF */ |
sahilmgandhi | 18:6a4db94011d3 | 881 | /* Enable interrupt */ |
sahilmgandhi | 18:6a4db94011d3 | 882 | NVIC_SetVector((IRQn_Type)((uint32_t)SERCOM0_IRQn + sercom_index), sercom_irq_handlers[sercom_index]); |
sahilmgandhi | 18:6a4db94011d3 | 883 | NVIC_EnableIRQ((IRQn_Type)((uint32_t)SERCOM0_IRQn + sercom_index)); |
sahilmgandhi | 18:6a4db94011d3 | 884 | |
sahilmgandhi | 18:6a4db94011d3 | 885 | /* Register callbacks */ |
sahilmgandhi | 18:6a4db94011d3 | 886 | i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_ERROR); |
sahilmgandhi | 18:6a4db94011d3 | 887 | i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR); |
sahilmgandhi | 18:6a4db94011d3 | 888 | if (tx && tx_length) { |
sahilmgandhi | 18:6a4db94011d3 | 889 | i2c_master_register_callback(&pI2C_S(obj)->master, i2c_write_complete_callback, I2C_MASTER_CALLBACK_WRITE_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 890 | i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 891 | |
sahilmgandhi | 18:6a4db94011d3 | 892 | /* Start I2C write */ |
sahilmgandhi | 18:6a4db94011d3 | 893 | if (stop) { |
sahilmgandhi | 18:6a4db94011d3 | 894 | i2c_master_write_packet_job(&pI2C_S(obj)->master, &pI2C_S(obj)->wr_packet); |
sahilmgandhi | 18:6a4db94011d3 | 895 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 896 | i2c_master_write_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->wr_packet); |
sahilmgandhi | 18:6a4db94011d3 | 897 | } |
sahilmgandhi | 18:6a4db94011d3 | 898 | } else if (rx && rx_length) { |
sahilmgandhi | 18:6a4db94011d3 | 899 | i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 900 | i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 901 | |
sahilmgandhi | 18:6a4db94011d3 | 902 | /* Start I2C read */ |
sahilmgandhi | 18:6a4db94011d3 | 903 | if (stop) { |
sahilmgandhi | 18:6a4db94011d3 | 904 | i2c_master_read_packet_job(&pI2C_S(obj)->master,&pI2C_S(obj)->rd_packet); |
sahilmgandhi | 18:6a4db94011d3 | 905 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 906 | i2c_master_read_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->rd_packet); |
sahilmgandhi | 18:6a4db94011d3 | 907 | } |
sahilmgandhi | 18:6a4db94011d3 | 908 | } else { |
sahilmgandhi | 18:6a4db94011d3 | 909 | /* Nothing to transfer, invoke callback */ |
sahilmgandhi | 18:6a4db94011d3 | 910 | i2c_transfer_complete_callback(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 911 | } |
sahilmgandhi | 18:6a4db94011d3 | 912 | } |
sahilmgandhi | 18:6a4db94011d3 | 913 | |
sahilmgandhi | 18:6a4db94011d3 | 914 | /** The asynchronous IRQ handler |
sahilmgandhi | 18:6a4db94011d3 | 915 | * @param obj The I2C object which holds the transfer information |
sahilmgandhi | 18:6a4db94011d3 | 916 | * @return event flags if a transfer termination condition was met or 0 otherwise. |
sahilmgandhi | 18:6a4db94011d3 | 917 | */ |
sahilmgandhi | 18:6a4db94011d3 | 918 | uint32_t i2c_irq_handler_asynch(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 919 | { |
sahilmgandhi | 18:6a4db94011d3 | 920 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 921 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 922 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 923 | |
sahilmgandhi | 18:6a4db94011d3 | 924 | uint32_t event_mask = pI2C_S(obj)->events; |
sahilmgandhi | 18:6a4db94011d3 | 925 | |
sahilmgandhi | 18:6a4db94011d3 | 926 | /* TODO: Current implementation is interrupt based only */ |
sahilmgandhi | 18:6a4db94011d3 | 927 | |
sahilmgandhi | 18:6a4db94011d3 | 928 | switch (pI2C_S(obj)->master.status) { |
sahilmgandhi | 18:6a4db94011d3 | 929 | case STATUS_OK: |
sahilmgandhi | 18:6a4db94011d3 | 930 | /* Transfer is complete */ |
sahilmgandhi | 18:6a4db94011d3 | 931 | return (I2C_EVENT_TRANSFER_COMPLETE & event_mask); |
sahilmgandhi | 18:6a4db94011d3 | 932 | |
sahilmgandhi | 18:6a4db94011d3 | 933 | case STATUS_ERR_BAD_ADDRESS: |
sahilmgandhi | 18:6a4db94011d3 | 934 | /* Received a NACK */ |
sahilmgandhi | 18:6a4db94011d3 | 935 | return (I2C_EVENT_ERROR_NO_SLAVE & event_mask); |
sahilmgandhi | 18:6a4db94011d3 | 936 | |
sahilmgandhi | 18:6a4db94011d3 | 937 | case STATUS_ERR_PACKET_COLLISION: |
sahilmgandhi | 18:6a4db94011d3 | 938 | /* An error occurred in between transfer */ |
sahilmgandhi | 18:6a4db94011d3 | 939 | return (I2C_EVENT_ERROR & event_mask); |
sahilmgandhi | 18:6a4db94011d3 | 940 | |
sahilmgandhi | 18:6a4db94011d3 | 941 | default: |
sahilmgandhi | 18:6a4db94011d3 | 942 | return 0; |
sahilmgandhi | 18:6a4db94011d3 | 943 | } |
sahilmgandhi | 18:6a4db94011d3 | 944 | |
sahilmgandhi | 18:6a4db94011d3 | 945 | //return 0; |
sahilmgandhi | 18:6a4db94011d3 | 946 | } |
sahilmgandhi | 18:6a4db94011d3 | 947 | |
sahilmgandhi | 18:6a4db94011d3 | 948 | /** Attempts to determine if I2C peripheral is already in use. |
sahilmgandhi | 18:6a4db94011d3 | 949 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 950 | * @return non-zero if the I2C module is active or zero if it is not |
sahilmgandhi | 18:6a4db94011d3 | 951 | */ |
sahilmgandhi | 18:6a4db94011d3 | 952 | uint8_t i2c_active(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 953 | { |
sahilmgandhi | 18:6a4db94011d3 | 954 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 955 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 956 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 957 | |
sahilmgandhi | 18:6a4db94011d3 | 958 | return (pI2C_S(obj)->master.status == STATUS_BUSY); |
sahilmgandhi | 18:6a4db94011d3 | 959 | } |
sahilmgandhi | 18:6a4db94011d3 | 960 | |
sahilmgandhi | 18:6a4db94011d3 | 961 | /** Abort ongoing asynchronous transaction. |
sahilmgandhi | 18:6a4db94011d3 | 962 | * @param obj The I2C object |
sahilmgandhi | 18:6a4db94011d3 | 963 | */ |
sahilmgandhi | 18:6a4db94011d3 | 964 | void i2c_abort_asynch(i2c_t *obj) |
sahilmgandhi | 18:6a4db94011d3 | 965 | { |
sahilmgandhi | 18:6a4db94011d3 | 966 | /* Sanity check arguments */ |
sahilmgandhi | 18:6a4db94011d3 | 967 | MBED_ASSERT(obj); |
sahilmgandhi | 18:6a4db94011d3 | 968 | MBED_ASSERT(pI2C_S(obj)->master.hw); |
sahilmgandhi | 18:6a4db94011d3 | 969 | |
sahilmgandhi | 18:6a4db94011d3 | 970 | /* Pointer to the hardware module instance */ |
sahilmgandhi | 18:6a4db94011d3 | 971 | SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM); |
sahilmgandhi | 18:6a4db94011d3 | 972 | |
sahilmgandhi | 18:6a4db94011d3 | 973 | /* Abort ongoing job */ |
sahilmgandhi | 18:6a4db94011d3 | 974 | |
sahilmgandhi | 18:6a4db94011d3 | 975 | /* Stop packet operation */ |
sahilmgandhi | 18:6a4db94011d3 | 976 | i2c_module->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB; |
sahilmgandhi | 18:6a4db94011d3 | 977 | |
sahilmgandhi | 18:6a4db94011d3 | 978 | pI2C_S(obj)->master.buffer_length = 0; |
sahilmgandhi | 18:6a4db94011d3 | 979 | pI2C_S(obj)->master.buffer_remaining = 0; |
sahilmgandhi | 18:6a4db94011d3 | 980 | |
sahilmgandhi | 18:6a4db94011d3 | 981 | /* Send nack and stop command unless arbitration is lost */ |
sahilmgandhi | 18:6a4db94011d3 | 982 | if ((pI2C_S(obj)->master.status != STATUS_ERR_PACKET_COLLISION) && pI2C_S(obj)->master.send_stop) { |
sahilmgandhi | 18:6a4db94011d3 | 983 | _i2c_master_wait_for_sync(&pI2C_S(obj)->master); |
sahilmgandhi | 18:6a4db94011d3 | 984 | i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT | SERCOM_I2CM_CTRLB_CMD(3); |
sahilmgandhi | 18:6a4db94011d3 | 985 | } |
sahilmgandhi | 18:6a4db94011d3 | 986 | |
sahilmgandhi | 18:6a4db94011d3 | 987 | /* Disable any registered callback */ |
sahilmgandhi | 18:6a4db94011d3 | 988 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 989 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE); |
sahilmgandhi | 18:6a4db94011d3 | 990 | i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR); |
sahilmgandhi | 18:6a4db94011d3 | 991 | |
sahilmgandhi | 18:6a4db94011d3 | 992 | pI2C_S(obj)->master.status = STATUS_ABORTED; |
sahilmgandhi | 18:6a4db94011d3 | 993 | } |
sahilmgandhi | 18:6a4db94011d3 | 994 | |
sahilmgandhi | 18:6a4db94011d3 | 995 | #endif |