fixed drive strength
Fork of mbed-dev by
targets/TARGET_Atmel/TARGET_SAM_CortexM0P/i2c_api.c@163:1d4c9d0af1e9, 2017-04-11 (annotated)
- Committer:
- cpadua
- Date:
- Tue Apr 11 20:39:24 2017 +0000
- Revision:
- 163:1d4c9d0af1e9
- Parent:
- 149:156823d33999
fixed i2c-api.c
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 |