Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

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