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