Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 *******************************************************************************
kadonotakashi 0:8fdf9a60065b 3 * Copyright (c) 2015, STMicroelectronics
kadonotakashi 0:8fdf9a60065b 4 * All rights reserved.
kadonotakashi 0:8fdf9a60065b 5 *
kadonotakashi 0:8fdf9a60065b 6 * Redistribution and use in source and binary forms, with or without
kadonotakashi 0:8fdf9a60065b 7 * modification, are permitted provided that the following conditions are met:
kadonotakashi 0:8fdf9a60065b 8 *
kadonotakashi 0:8fdf9a60065b 9 * 1. Redistributions of source code must retain the above copyright notice,
kadonotakashi 0:8fdf9a60065b 10 * this list of conditions and the following disclaimer.
kadonotakashi 0:8fdf9a60065b 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
kadonotakashi 0:8fdf9a60065b 12 * this list of conditions and the following disclaimer in the documentation
kadonotakashi 0:8fdf9a60065b 13 * and/or other materials provided with the distribution.
kadonotakashi 0:8fdf9a60065b 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
kadonotakashi 0:8fdf9a60065b 15 * may be used to endorse or promote products derived from this software
kadonotakashi 0:8fdf9a60065b 16 * without specific prior written permission.
kadonotakashi 0:8fdf9a60065b 17 *
kadonotakashi 0:8fdf9a60065b 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
kadonotakashi 0:8fdf9a60065b 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
kadonotakashi 0:8fdf9a60065b 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
kadonotakashi 0:8fdf9a60065b 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
kadonotakashi 0:8fdf9a60065b 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
kadonotakashi 0:8fdf9a60065b 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
kadonotakashi 0:8fdf9a60065b 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
kadonotakashi 0:8fdf9a60065b 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
kadonotakashi 0:8fdf9a60065b 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
kadonotakashi 0:8fdf9a60065b 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kadonotakashi 0:8fdf9a60065b 28 *******************************************************************************
kadonotakashi 0:8fdf9a60065b 29 */
kadonotakashi 0:8fdf9a60065b 30
kadonotakashi 0:8fdf9a60065b 31
kadonotakashi 0:8fdf9a60065b 32 #include "mbed_assert.h"
kadonotakashi 0:8fdf9a60065b 33 #include "i2c_api.h"
kadonotakashi 0:8fdf9a60065b 34 #include "platform/mbed_wait_api.h"
kadonotakashi 0:8fdf9a60065b 35
kadonotakashi 0:8fdf9a60065b 36 #if DEVICE_I2C
kadonotakashi 0:8fdf9a60065b 37
kadonotakashi 0:8fdf9a60065b 38 #include "cmsis.h"
kadonotakashi 0:8fdf9a60065b 39 #include "pinmap.h"
kadonotakashi 0:8fdf9a60065b 40 #include "PeripheralPins.h"
kadonotakashi 0:8fdf9a60065b 41 #include "i2c_device.h" // family specific defines
kadonotakashi 0:8fdf9a60065b 42
kadonotakashi 0:8fdf9a60065b 43 #ifndef DEBUG_STDIO
kadonotakashi 0:8fdf9a60065b 44 # define DEBUG_STDIO 0
kadonotakashi 0:8fdf9a60065b 45 #endif
kadonotakashi 0:8fdf9a60065b 46
kadonotakashi 0:8fdf9a60065b 47 #if DEBUG_STDIO
kadonotakashi 0:8fdf9a60065b 48 # include <stdio.h>
kadonotakashi 0:8fdf9a60065b 49 # define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
kadonotakashi 0:8fdf9a60065b 50 #else
kadonotakashi 0:8fdf9a60065b 51 # define DEBUG_PRINTF(...) {}
kadonotakashi 0:8fdf9a60065b 52 #endif
kadonotakashi 0:8fdf9a60065b 53
kadonotakashi 0:8fdf9a60065b 54 #if DEVICE_I2C_ASYNCH
kadonotakashi 0:8fdf9a60065b 55 #define I2C_S(obj) (struct i2c_s *) (&((obj)->i2c))
kadonotakashi 0:8fdf9a60065b 56 #else
kadonotakashi 0:8fdf9a60065b 57 #define I2C_S(obj) (struct i2c_s *) (obj)
kadonotakashi 0:8fdf9a60065b 58 #endif
kadonotakashi 0:8fdf9a60065b 59
kadonotakashi 0:8fdf9a60065b 60 /* Family specific description for I2C */
kadonotakashi 0:8fdf9a60065b 61 #define I2C_NUM (5)
kadonotakashi 0:8fdf9a60065b 62 static I2C_HandleTypeDef *i2c_handles[I2C_NUM];
kadonotakashi 0:8fdf9a60065b 63
kadonotakashi 0:8fdf9a60065b 64 /* Timeout values are based on core clock and I2C clock.
kadonotakashi 0:8fdf9a60065b 65 The BYTE_TIMEOUT is computed as twice the number of cycles it would
kadonotakashi 0:8fdf9a60065b 66 take to send 10 bits over I2C. Most Flags should take less than that.
kadonotakashi 0:8fdf9a60065b 67 This is for immediate FLAG or ACK check.
kadonotakashi 0:8fdf9a60065b 68 */
kadonotakashi 0:8fdf9a60065b 69 #define BYTE_TIMEOUT ((SystemCoreClock / obj_s->hz) * 2 * 10)
kadonotakashi 0:8fdf9a60065b 70 /* Timeout values based on I2C clock.
kadonotakashi 0:8fdf9a60065b 71 The BYTE_TIMEOUT_US is computed as 3x the time in us it would
kadonotakashi 0:8fdf9a60065b 72 take to send 10 bits over I2C. Most Flags should take less than that.
kadonotakashi 0:8fdf9a60065b 73 This is for complete transfers check.
kadonotakashi 0:8fdf9a60065b 74 */
kadonotakashi 0:8fdf9a60065b 75 #define BYTE_TIMEOUT_US ((SystemCoreClock / obj_s->hz) * 3 * 10)
kadonotakashi 0:8fdf9a60065b 76 /* Timeout values for flags and events waiting loops. These timeouts are
kadonotakashi 0:8fdf9a60065b 77 not based on accurate values, they just guarantee that the application will
kadonotakashi 0:8fdf9a60065b 78 not remain stuck if the I2C communication is corrupted.
kadonotakashi 0:8fdf9a60065b 79 */
kadonotakashi 0:8fdf9a60065b 80 #define FLAG_TIMEOUT ((int)0x1000)
kadonotakashi 0:8fdf9a60065b 81
kadonotakashi 0:8fdf9a60065b 82 /* GENERIC INIT and HELPERS FUNCTIONS */
kadonotakashi 0:8fdf9a60065b 83
kadonotakashi 0:8fdf9a60065b 84 #if defined(I2C1_BASE)
kadonotakashi 0:8fdf9a60065b 85 static void i2c1_irq(void)
kadonotakashi 0:8fdf9a60065b 86 {
kadonotakashi 0:8fdf9a60065b 87 I2C_HandleTypeDef *handle = i2c_handles[0];
kadonotakashi 0:8fdf9a60065b 88 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 89 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 90 }
kadonotakashi 0:8fdf9a60065b 91 #endif
kadonotakashi 0:8fdf9a60065b 92 #if defined(I2C2_BASE)
kadonotakashi 0:8fdf9a60065b 93 static void i2c2_irq(void)
kadonotakashi 0:8fdf9a60065b 94 {
kadonotakashi 0:8fdf9a60065b 95 I2C_HandleTypeDef *handle = i2c_handles[1];
kadonotakashi 0:8fdf9a60065b 96 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 97 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 98 }
kadonotakashi 0:8fdf9a60065b 99 #endif
kadonotakashi 0:8fdf9a60065b 100 #if defined(I2C3_BASE)
kadonotakashi 0:8fdf9a60065b 101 static void i2c3_irq(void)
kadonotakashi 0:8fdf9a60065b 102 {
kadonotakashi 0:8fdf9a60065b 103 I2C_HandleTypeDef *handle = i2c_handles[2];
kadonotakashi 0:8fdf9a60065b 104 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 105 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 106 }
kadonotakashi 0:8fdf9a60065b 107 #endif
kadonotakashi 0:8fdf9a60065b 108 #if defined(I2C4_BASE)
kadonotakashi 0:8fdf9a60065b 109 static void i2c4_irq(void)
kadonotakashi 0:8fdf9a60065b 110 {
kadonotakashi 0:8fdf9a60065b 111 I2C_HandleTypeDef *handle = i2c_handles[3];
kadonotakashi 0:8fdf9a60065b 112 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 113 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 114 }
kadonotakashi 0:8fdf9a60065b 115 #endif
kadonotakashi 0:8fdf9a60065b 116 #if defined(FMPI2C1_BASE)
kadonotakashi 0:8fdf9a60065b 117 static void i2c5_irq(void)
kadonotakashi 0:8fdf9a60065b 118 {
kadonotakashi 0:8fdf9a60065b 119 I2C_HandleTypeDef *handle = i2c_handles[4];
kadonotakashi 0:8fdf9a60065b 120 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 121 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 122 }
kadonotakashi 0:8fdf9a60065b 123 #endif
kadonotakashi 0:8fdf9a60065b 124
kadonotakashi 0:8fdf9a60065b 125 void i2c_ev_err_enable(i2c_t *obj, uint32_t handler)
kadonotakashi 0:8fdf9a60065b 126 {
kadonotakashi 0:8fdf9a60065b 127 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 128 IRQn_Type irq_event_n = obj_s->event_i2cIRQ;
kadonotakashi 0:8fdf9a60065b 129 IRQn_Type irq_error_n = obj_s->error_i2cIRQ;
kadonotakashi 0:8fdf9a60065b 130 /* default prio in master case is set to 2 */
kadonotakashi 0:8fdf9a60065b 131 uint32_t prio = 2;
kadonotakashi 0:8fdf9a60065b 132
kadonotakashi 0:8fdf9a60065b 133 /* Set up ITs using IRQ and handler tables */
kadonotakashi 0:8fdf9a60065b 134 NVIC_SetVector(irq_event_n, handler);
kadonotakashi 0:8fdf9a60065b 135 NVIC_SetVector(irq_error_n, handler);
kadonotakashi 0:8fdf9a60065b 136
kadonotakashi 0:8fdf9a60065b 137 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 138 /* Set higher priority to slave device than master.
kadonotakashi 0:8fdf9a60065b 139 * In case a device makes use of both master and slave, the
kadonotakashi 0:8fdf9a60065b 140 * slave needs higher responsiveness.
kadonotakashi 0:8fdf9a60065b 141 */
kadonotakashi 0:8fdf9a60065b 142 if (obj_s->slave) {
kadonotakashi 0:8fdf9a60065b 143 prio = 1;
kadonotakashi 0:8fdf9a60065b 144 }
kadonotakashi 0:8fdf9a60065b 145 #endif
kadonotakashi 0:8fdf9a60065b 146
kadonotakashi 0:8fdf9a60065b 147 NVIC_SetPriority(irq_event_n, prio);
kadonotakashi 0:8fdf9a60065b 148 NVIC_SetPriority(irq_error_n, prio);
kadonotakashi 0:8fdf9a60065b 149 NVIC_EnableIRQ(irq_event_n);
kadonotakashi 0:8fdf9a60065b 150 NVIC_EnableIRQ(irq_error_n);
kadonotakashi 0:8fdf9a60065b 151 }
kadonotakashi 0:8fdf9a60065b 152
kadonotakashi 0:8fdf9a60065b 153 void i2c_ev_err_disable(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 154 {
kadonotakashi 0:8fdf9a60065b 155 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 156 IRQn_Type irq_event_n = obj_s->event_i2cIRQ;
kadonotakashi 0:8fdf9a60065b 157 IRQn_Type irq_error_n = obj_s->error_i2cIRQ;
kadonotakashi 0:8fdf9a60065b 158
kadonotakashi 0:8fdf9a60065b 159 HAL_NVIC_DisableIRQ(irq_event_n);
kadonotakashi 0:8fdf9a60065b 160 HAL_NVIC_DisableIRQ(irq_error_n);
kadonotakashi 0:8fdf9a60065b 161 }
kadonotakashi 0:8fdf9a60065b 162
kadonotakashi 0:8fdf9a60065b 163 uint32_t i2c_get_irq_handler(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 164 {
kadonotakashi 0:8fdf9a60065b 165 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 166 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 167 uint32_t handler = 0;
kadonotakashi 0:8fdf9a60065b 168
kadonotakashi 0:8fdf9a60065b 169 switch (obj_s->index) {
kadonotakashi 0:8fdf9a60065b 170 #if defined(I2C1_BASE)
kadonotakashi 0:8fdf9a60065b 171 case 0:
kadonotakashi 0:8fdf9a60065b 172 handler = (uint32_t)&i2c1_irq;
kadonotakashi 0:8fdf9a60065b 173 break;
kadonotakashi 0:8fdf9a60065b 174 #endif
kadonotakashi 0:8fdf9a60065b 175 #if defined(I2C2_BASE)
kadonotakashi 0:8fdf9a60065b 176 case 1:
kadonotakashi 0:8fdf9a60065b 177 handler = (uint32_t)&i2c2_irq;
kadonotakashi 0:8fdf9a60065b 178 break;
kadonotakashi 0:8fdf9a60065b 179 #endif
kadonotakashi 0:8fdf9a60065b 180 #if defined(I2C3_BASE)
kadonotakashi 0:8fdf9a60065b 181 case 2:
kadonotakashi 0:8fdf9a60065b 182 handler = (uint32_t)&i2c3_irq;
kadonotakashi 0:8fdf9a60065b 183 break;
kadonotakashi 0:8fdf9a60065b 184 #endif
kadonotakashi 0:8fdf9a60065b 185 #if defined(I2C4_BASE)
kadonotakashi 0:8fdf9a60065b 186 case 3:
kadonotakashi 0:8fdf9a60065b 187 handler = (uint32_t)&i2c4_irq;
kadonotakashi 0:8fdf9a60065b 188 break;
kadonotakashi 0:8fdf9a60065b 189 #endif
kadonotakashi 0:8fdf9a60065b 190 #if defined(FMPI2C1_BASE)
kadonotakashi 0:8fdf9a60065b 191 case 4:
kadonotakashi 0:8fdf9a60065b 192 handler = (uint32_t)&i2c5_irq;
kadonotakashi 0:8fdf9a60065b 193 break;
kadonotakashi 0:8fdf9a60065b 194 #endif
kadonotakashi 0:8fdf9a60065b 195 }
kadonotakashi 0:8fdf9a60065b 196
kadonotakashi 0:8fdf9a60065b 197 i2c_handles[obj_s->index] = handle;
kadonotakashi 0:8fdf9a60065b 198 return handler;
kadonotakashi 0:8fdf9a60065b 199 }
kadonotakashi 0:8fdf9a60065b 200
kadonotakashi 0:8fdf9a60065b 201 void i2c_hw_reset(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 202 {
kadonotakashi 0:8fdf9a60065b 203 int timeout;
kadonotakashi 0:8fdf9a60065b 204 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 205 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 206
kadonotakashi 0:8fdf9a60065b 207 handle->Instance = (I2C_TypeDef *)(obj_s->i2c);
kadonotakashi 0:8fdf9a60065b 208
kadonotakashi 0:8fdf9a60065b 209 // wait before reset
kadonotakashi 0:8fdf9a60065b 210 timeout = BYTE_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 211 while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY)) && (--timeout != 0));
kadonotakashi 0:8fdf9a60065b 212 #if defined I2C1_BASE
kadonotakashi 0:8fdf9a60065b 213 if (obj_s->i2c == I2C_1) {
kadonotakashi 0:8fdf9a60065b 214 __HAL_RCC_I2C1_FORCE_RESET();
kadonotakashi 0:8fdf9a60065b 215 __HAL_RCC_I2C1_RELEASE_RESET();
kadonotakashi 0:8fdf9a60065b 216 }
kadonotakashi 0:8fdf9a60065b 217 #endif
kadonotakashi 0:8fdf9a60065b 218 #if defined I2C2_BASE
kadonotakashi 0:8fdf9a60065b 219 if (obj_s->i2c == I2C_2) {
kadonotakashi 0:8fdf9a60065b 220 __HAL_RCC_I2C2_FORCE_RESET();
kadonotakashi 0:8fdf9a60065b 221 __HAL_RCC_I2C2_RELEASE_RESET();
kadonotakashi 0:8fdf9a60065b 222 }
kadonotakashi 0:8fdf9a60065b 223 #endif
kadonotakashi 0:8fdf9a60065b 224 #if defined I2C3_BASE
kadonotakashi 0:8fdf9a60065b 225 if (obj_s->i2c == I2C_3) {
kadonotakashi 0:8fdf9a60065b 226 __HAL_RCC_I2C3_FORCE_RESET();
kadonotakashi 0:8fdf9a60065b 227 __HAL_RCC_I2C3_RELEASE_RESET();
kadonotakashi 0:8fdf9a60065b 228 }
kadonotakashi 0:8fdf9a60065b 229 #endif
kadonotakashi 0:8fdf9a60065b 230 #if defined I2C4_BASE
kadonotakashi 0:8fdf9a60065b 231 if (obj_s->i2c == I2C_4) {
kadonotakashi 0:8fdf9a60065b 232 __HAL_RCC_I2C4_FORCE_RESET();
kadonotakashi 0:8fdf9a60065b 233 __HAL_RCC_I2C4_RELEASE_RESET();
kadonotakashi 0:8fdf9a60065b 234 }
kadonotakashi 0:8fdf9a60065b 235 #endif
kadonotakashi 0:8fdf9a60065b 236 #if defined FMPI2C1_BASE
kadonotakashi 0:8fdf9a60065b 237 if (obj_s->i2c == FMPI2C_1) {
kadonotakashi 0:8fdf9a60065b 238 __HAL_RCC_FMPI2C1_FORCE_RESET();
kadonotakashi 0:8fdf9a60065b 239 __HAL_RCC_FMPI2C1_RELEASE_RESET();
kadonotakashi 0:8fdf9a60065b 240 }
kadonotakashi 0:8fdf9a60065b 241 #endif
kadonotakashi 0:8fdf9a60065b 242 }
kadonotakashi 0:8fdf9a60065b 243
kadonotakashi 0:8fdf9a60065b 244 void i2c_sw_reset(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 245 {
kadonotakashi 0:8fdf9a60065b 246 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 247 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 248 /* SW reset procedure:
kadonotakashi 0:8fdf9a60065b 249 * PE must be kept low during at least 3 APB clock cycles
kadonotakashi 0:8fdf9a60065b 250 * in order to perform the software reset.
kadonotakashi 0:8fdf9a60065b 251 * This is ensured by writing the following software sequence:
kadonotakashi 0:8fdf9a60065b 252 * - Write PE=0
kadonotakashi 0:8fdf9a60065b 253 * - Check PE=0
kadonotakashi 0:8fdf9a60065b 254 * - Write PE=1.
kadonotakashi 0:8fdf9a60065b 255 */
kadonotakashi 0:8fdf9a60065b 256 handle->Instance->CR1 &= ~I2C_CR1_PE;
kadonotakashi 0:8fdf9a60065b 257 while (handle->Instance->CR1 & I2C_CR1_PE);
kadonotakashi 0:8fdf9a60065b 258 handle->Instance->CR1 |= I2C_CR1_PE;
kadonotakashi 0:8fdf9a60065b 259 }
kadonotakashi 0:8fdf9a60065b 260
kadonotakashi 0:8fdf9a60065b 261 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
kadonotakashi 0:8fdf9a60065b 262 {
kadonotakashi 0:8fdf9a60065b 263
kadonotakashi 0:8fdf9a60065b 264 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 265
kadonotakashi 0:8fdf9a60065b 266 // Determine the I2C to use
kadonotakashi 0:8fdf9a60065b 267 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
kadonotakashi 0:8fdf9a60065b 268 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
kadonotakashi 0:8fdf9a60065b 269 obj_s->sda = sda;
kadonotakashi 0:8fdf9a60065b 270 obj_s->scl = scl;
kadonotakashi 0:8fdf9a60065b 271
kadonotakashi 0:8fdf9a60065b 272 obj_s->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
kadonotakashi 0:8fdf9a60065b 273 MBED_ASSERT(obj_s->i2c != (I2CName)NC);
kadonotakashi 0:8fdf9a60065b 274
kadonotakashi 0:8fdf9a60065b 275 #if defined I2C1_BASE
kadonotakashi 0:8fdf9a60065b 276 // Enable I2C1 clock and pinout if not done
kadonotakashi 0:8fdf9a60065b 277 if (obj_s->i2c == I2C_1) {
kadonotakashi 0:8fdf9a60065b 278 obj_s->index = 0;
kadonotakashi 0:8fdf9a60065b 279 __HAL_RCC_I2C1_CLK_ENABLE();
kadonotakashi 0:8fdf9a60065b 280 // Configure I2C pins
kadonotakashi 0:8fdf9a60065b 281 obj_s->event_i2cIRQ = I2C1_EV_IRQn;
kadonotakashi 0:8fdf9a60065b 282 obj_s->error_i2cIRQ = I2C1_ER_IRQn;
kadonotakashi 0:8fdf9a60065b 283 }
kadonotakashi 0:8fdf9a60065b 284 #endif
kadonotakashi 0:8fdf9a60065b 285 #if defined I2C2_BASE
kadonotakashi 0:8fdf9a60065b 286 // Enable I2C2 clock and pinout if not done
kadonotakashi 0:8fdf9a60065b 287 if (obj_s->i2c == I2C_2) {
kadonotakashi 0:8fdf9a60065b 288 obj_s->index = 1;
kadonotakashi 0:8fdf9a60065b 289 __HAL_RCC_I2C2_CLK_ENABLE();
kadonotakashi 0:8fdf9a60065b 290 obj_s->event_i2cIRQ = I2C2_EV_IRQn;
kadonotakashi 0:8fdf9a60065b 291 obj_s->error_i2cIRQ = I2C2_ER_IRQn;
kadonotakashi 0:8fdf9a60065b 292 }
kadonotakashi 0:8fdf9a60065b 293 #endif
kadonotakashi 0:8fdf9a60065b 294 #if defined I2C3_BASE
kadonotakashi 0:8fdf9a60065b 295 // Enable I2C3 clock and pinout if not done
kadonotakashi 0:8fdf9a60065b 296 if (obj_s->i2c == I2C_3) {
kadonotakashi 0:8fdf9a60065b 297 obj_s->index = 2;
kadonotakashi 0:8fdf9a60065b 298 __HAL_RCC_I2C3_CLK_ENABLE();
kadonotakashi 0:8fdf9a60065b 299 obj_s->event_i2cIRQ = I2C3_EV_IRQn;
kadonotakashi 0:8fdf9a60065b 300 obj_s->error_i2cIRQ = I2C3_ER_IRQn;
kadonotakashi 0:8fdf9a60065b 301 }
kadonotakashi 0:8fdf9a60065b 302 #endif
kadonotakashi 0:8fdf9a60065b 303 #if defined I2C4_BASE
kadonotakashi 0:8fdf9a60065b 304 // Enable I2C3 clock and pinout if not done
kadonotakashi 0:8fdf9a60065b 305 if (obj_s->i2c == I2C_4) {
kadonotakashi 0:8fdf9a60065b 306 obj_s->index = 3;
kadonotakashi 0:8fdf9a60065b 307 __HAL_RCC_I2C4_CLK_ENABLE();
kadonotakashi 0:8fdf9a60065b 308 obj_s->event_i2cIRQ = I2C4_EV_IRQn;
kadonotakashi 0:8fdf9a60065b 309 obj_s->error_i2cIRQ = I2C4_ER_IRQn;
kadonotakashi 0:8fdf9a60065b 310 }
kadonotakashi 0:8fdf9a60065b 311 #endif
kadonotakashi 0:8fdf9a60065b 312 #if defined FMPI2C1_BASE
kadonotakashi 0:8fdf9a60065b 313 // Enable I2C3 clock and pinout if not done
kadonotakashi 0:8fdf9a60065b 314 if (obj_s->i2c == FMPI2C_1) {
kadonotakashi 0:8fdf9a60065b 315 obj_s->index = 4;
kadonotakashi 0:8fdf9a60065b 316 __HAL_RCC_FMPI2C1_CLK_ENABLE();
kadonotakashi 0:8fdf9a60065b 317 obj_s->event_i2cIRQ = FMPI2C1_EV_IRQn;
kadonotakashi 0:8fdf9a60065b 318 obj_s->error_i2cIRQ = FMPI2C1_ER_IRQn;
kadonotakashi 0:8fdf9a60065b 319 }
kadonotakashi 0:8fdf9a60065b 320 #endif
kadonotakashi 0:8fdf9a60065b 321
kadonotakashi 0:8fdf9a60065b 322 // Configure I2C pins
kadonotakashi 0:8fdf9a60065b 323 pinmap_pinout(sda, PinMap_I2C_SDA);
kadonotakashi 0:8fdf9a60065b 324 pinmap_pinout(scl, PinMap_I2C_SCL);
kadonotakashi 0:8fdf9a60065b 325 pin_mode(sda, OpenDrainNoPull);
kadonotakashi 0:8fdf9a60065b 326 pin_mode(scl, OpenDrainNoPull);
kadonotakashi 0:8fdf9a60065b 327
kadonotakashi 0:8fdf9a60065b 328 // I2C configuration
kadonotakashi 0:8fdf9a60065b 329 // Default hz value used for timeout computation
kadonotakashi 0:8fdf9a60065b 330 if (!obj_s->hz) {
kadonotakashi 0:8fdf9a60065b 331 obj_s->hz = 100000; // 100 kHz per default
kadonotakashi 0:8fdf9a60065b 332 }
kadonotakashi 0:8fdf9a60065b 333
kadonotakashi 0:8fdf9a60065b 334 // Reset to clear pending flags if any
kadonotakashi 0:8fdf9a60065b 335 i2c_hw_reset(obj);
kadonotakashi 0:8fdf9a60065b 336 i2c_frequency(obj, obj_s->hz);
kadonotakashi 0:8fdf9a60065b 337
kadonotakashi 0:8fdf9a60065b 338 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 339 // I2C master by default
kadonotakashi 0:8fdf9a60065b 340 obj_s->slave = 0;
kadonotakashi 0:8fdf9a60065b 341 obj_s->pending_slave_tx_master_rx = 0;
kadonotakashi 0:8fdf9a60065b 342 obj_s->pending_slave_rx_maxter_tx = 0;
kadonotakashi 0:8fdf9a60065b 343 #endif
kadonotakashi 0:8fdf9a60065b 344
kadonotakashi 0:8fdf9a60065b 345 // I2C Xfer operation init
kadonotakashi 0:8fdf9a60065b 346 obj_s->event = 0;
kadonotakashi 0:8fdf9a60065b 347 obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 348 #ifdef I2C_IP_VERSION_V2
kadonotakashi 0:8fdf9a60065b 349 obj_s->pending_start = 0;
kadonotakashi 0:8fdf9a60065b 350 #endif
kadonotakashi 0:8fdf9a60065b 351 }
kadonotakashi 0:8fdf9a60065b 352
kadonotakashi 0:8fdf9a60065b 353 void i2c_frequency(i2c_t *obj, int hz)
kadonotakashi 0:8fdf9a60065b 354 {
kadonotakashi 0:8fdf9a60065b 355 int timeout;
kadonotakashi 0:8fdf9a60065b 356 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 357 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 358
kadonotakashi 0:8fdf9a60065b 359 // wait before init
kadonotakashi 0:8fdf9a60065b 360 timeout = BYTE_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 361 while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY)) && (--timeout != 0));
kadonotakashi 0:8fdf9a60065b 362
kadonotakashi 0:8fdf9a60065b 363 #ifdef I2C_IP_VERSION_V1
kadonotakashi 0:8fdf9a60065b 364 handle->Init.ClockSpeed = hz;
kadonotakashi 0:8fdf9a60065b 365 handle->Init.DutyCycle = I2C_DUTYCYCLE_2;
kadonotakashi 0:8fdf9a60065b 366 #endif
kadonotakashi 0:8fdf9a60065b 367 #ifdef I2C_IP_VERSION_V2
kadonotakashi 0:8fdf9a60065b 368 /* Only predefined timing for below frequencies are supported */
kadonotakashi 0:8fdf9a60065b 369 MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
kadonotakashi 0:8fdf9a60065b 370 handle->Init.Timing = get_i2c_timing(hz);
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 // Enable the Fast Mode Plus capability
kadonotakashi 0:8fdf9a60065b 373 if (hz == 1000000) {
kadonotakashi 0:8fdf9a60065b 374 #if defined(I2C1_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C1)
kadonotakashi 0:8fdf9a60065b 375 if (obj_s->i2c == I2C_1) {
kadonotakashi 0:8fdf9a60065b 376 HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C1);
kadonotakashi 0:8fdf9a60065b 377 }
kadonotakashi 0:8fdf9a60065b 378 #endif
kadonotakashi 0:8fdf9a60065b 379 #if defined(I2C2_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C2)
kadonotakashi 0:8fdf9a60065b 380 if (obj_s->i2c == I2C_2) {
kadonotakashi 0:8fdf9a60065b 381 HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C2);
kadonotakashi 0:8fdf9a60065b 382 }
kadonotakashi 0:8fdf9a60065b 383 #endif
kadonotakashi 0:8fdf9a60065b 384 #if defined(I2C3_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C3)
kadonotakashi 0:8fdf9a60065b 385 if (obj_s->i2c == I2C_3) {
kadonotakashi 0:8fdf9a60065b 386 HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C3);
kadonotakashi 0:8fdf9a60065b 387 }
kadonotakashi 0:8fdf9a60065b 388 #endif
kadonotakashi 0:8fdf9a60065b 389 #if defined(I2C4_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C4)
kadonotakashi 0:8fdf9a60065b 390 if (obj_s->i2c == I2C_4) {
kadonotakashi 0:8fdf9a60065b 391 HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C4);
kadonotakashi 0:8fdf9a60065b 392 }
kadonotakashi 0:8fdf9a60065b 393 #endif
kadonotakashi 0:8fdf9a60065b 394 }
kadonotakashi 0:8fdf9a60065b 395 #endif //I2C_IP_VERSION_V2
kadonotakashi 0:8fdf9a60065b 396
kadonotakashi 0:8fdf9a60065b 397 /*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
kadonotakashi 0:8fdf9a60065b 398 #if defined(I2C1_BASE) && defined (__HAL_RCC_I2C1_CONFIG)
kadonotakashi 0:8fdf9a60065b 399 if (obj_s->i2c == I2C_1) {
kadonotakashi 0:8fdf9a60065b 400 __HAL_RCC_I2C1_CONFIG(I2CAPI_I2C1_CLKSRC);
kadonotakashi 0:8fdf9a60065b 401 }
kadonotakashi 0:8fdf9a60065b 402 #endif
kadonotakashi 0:8fdf9a60065b 403 #if defined(I2C2_BASE) && defined(__HAL_RCC_I2C2_CONFIG)
kadonotakashi 0:8fdf9a60065b 404 if (obj_s->i2c == I2C_2) {
kadonotakashi 0:8fdf9a60065b 405 __HAL_RCC_I2C2_CONFIG(I2CAPI_I2C2_CLKSRC);
kadonotakashi 0:8fdf9a60065b 406 }
kadonotakashi 0:8fdf9a60065b 407 #endif
kadonotakashi 0:8fdf9a60065b 408 #if defined(I2C3_BASE) && defined(__HAL_RCC_I2C3_CONFIG)
kadonotakashi 0:8fdf9a60065b 409 if (obj_s->i2c == I2C_3) {
kadonotakashi 0:8fdf9a60065b 410 __HAL_RCC_I2C3_CONFIG(I2CAPI_I2C3_CLKSRC);
kadonotakashi 0:8fdf9a60065b 411 }
kadonotakashi 0:8fdf9a60065b 412 #endif
kadonotakashi 0:8fdf9a60065b 413 #if defined(I2C4_BASE) && defined(__HAL_RCC_I2C4_CONFIG)
kadonotakashi 0:8fdf9a60065b 414 if (obj_s->i2c == I2C_4) {
kadonotakashi 0:8fdf9a60065b 415 __HAL_RCC_I2C4_CONFIG(I2CAPI_I2C4_CLKSRC);
kadonotakashi 0:8fdf9a60065b 416 }
kadonotakashi 0:8fdf9a60065b 417 #endif
kadonotakashi 0:8fdf9a60065b 418
kadonotakashi 0:8fdf9a60065b 419 #ifdef I2C_ANALOGFILTER_ENABLE
kadonotakashi 0:8fdf9a60065b 420 /* Enable the Analog I2C Filter */
kadonotakashi 0:8fdf9a60065b 421 HAL_I2CEx_ConfigAnalogFilter(handle, I2C_ANALOGFILTER_ENABLE);
kadonotakashi 0:8fdf9a60065b 422 #endif
kadonotakashi 0:8fdf9a60065b 423
kadonotakashi 0:8fdf9a60065b 424 // I2C configuration
kadonotakashi 0:8fdf9a60065b 425 handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
kadonotakashi 0:8fdf9a60065b 426 handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
kadonotakashi 0:8fdf9a60065b 427 handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
kadonotakashi 0:8fdf9a60065b 428 handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
kadonotakashi 0:8fdf9a60065b 429 handle->Init.OwnAddress1 = 0;
kadonotakashi 0:8fdf9a60065b 430 handle->Init.OwnAddress2 = 0;
kadonotakashi 0:8fdf9a60065b 431 HAL_I2C_Init(handle);
kadonotakashi 0:8fdf9a60065b 432
kadonotakashi 0:8fdf9a60065b 433 /* store frequency for timeout computation */
kadonotakashi 0:8fdf9a60065b 434 obj_s->hz = hz;
kadonotakashi 0:8fdf9a60065b 435 }
kadonotakashi 0:8fdf9a60065b 436
kadonotakashi 0:8fdf9a60065b 437 i2c_t *get_i2c_obj(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 438 {
kadonotakashi 0:8fdf9a60065b 439 /* Aim of the function is to get i2c_s pointer using hi2c pointer */
kadonotakashi 0:8fdf9a60065b 440 /* Highly inspired from magical linux kernel's "container_of" */
kadonotakashi 0:8fdf9a60065b 441 /* (which was not directly used since not compatible with IAR toolchain) */
kadonotakashi 0:8fdf9a60065b 442 struct i2c_s *obj_s;
kadonotakashi 0:8fdf9a60065b 443 i2c_t *obj;
kadonotakashi 0:8fdf9a60065b 444
kadonotakashi 0:8fdf9a60065b 445 obj_s = (struct i2c_s *)((char *)hi2c - offsetof(struct i2c_s, handle));
kadonotakashi 0:8fdf9a60065b 446 obj = (i2c_t *)((char *)obj_s - offsetof(i2c_t, i2c));
kadonotakashi 0:8fdf9a60065b 447
kadonotakashi 0:8fdf9a60065b 448 return (obj);
kadonotakashi 0:8fdf9a60065b 449 }
kadonotakashi 0:8fdf9a60065b 450
kadonotakashi 0:8fdf9a60065b 451 void i2c_reset(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 452 {
kadonotakashi 0:8fdf9a60065b 453 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 454 /* As recommended in i2c_api.h, mainly send stop */
kadonotakashi 0:8fdf9a60065b 455 i2c_stop(obj);
kadonotakashi 0:8fdf9a60065b 456 /* then re-init */
kadonotakashi 0:8fdf9a60065b 457 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 458 }
kadonotakashi 0:8fdf9a60065b 459
kadonotakashi 0:8fdf9a60065b 460 /*
kadonotakashi 0:8fdf9a60065b 461 * UNITARY APIS.
kadonotakashi 0:8fdf9a60065b 462 * For very basic operations, direct registers access is needed
kadonotakashi 0:8fdf9a60065b 463 * There are 2 different IPs version that need to be supported
kadonotakashi 0:8fdf9a60065b 464 */
kadonotakashi 0:8fdf9a60065b 465 #ifdef I2C_IP_VERSION_V1
kadonotakashi 0:8fdf9a60065b 466 int i2c_start(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 467 {
kadonotakashi 0:8fdf9a60065b 468
kadonotakashi 0:8fdf9a60065b 469 int timeout;
kadonotakashi 0:8fdf9a60065b 470 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 471 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 472
kadonotakashi 0:8fdf9a60065b 473 // Clear Acknowledge failure flag
kadonotakashi 0:8fdf9a60065b 474 __HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
kadonotakashi 0:8fdf9a60065b 475
kadonotakashi 0:8fdf9a60065b 476 // Wait the STOP condition has been previously correctly sent
kadonotakashi 0:8fdf9a60065b 477 // This timeout can be avoid in some specific cases by simply clearing the STOP bit
kadonotakashi 0:8fdf9a60065b 478 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 479 while ((handle->Instance->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP) {
kadonotakashi 0:8fdf9a60065b 480 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 481 return 1;
kadonotakashi 0:8fdf9a60065b 482 }
kadonotakashi 0:8fdf9a60065b 483 }
kadonotakashi 0:8fdf9a60065b 484
kadonotakashi 0:8fdf9a60065b 485 // Generate the START condition
kadonotakashi 0:8fdf9a60065b 486 handle->Instance->CR1 |= I2C_CR1_START;
kadonotakashi 0:8fdf9a60065b 487
kadonotakashi 0:8fdf9a60065b 488 // Wait the START condition has been correctly sent
kadonotakashi 0:8fdf9a60065b 489 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 490 while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_SB) == RESET) {
kadonotakashi 0:8fdf9a60065b 491 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 492 return 1;
kadonotakashi 0:8fdf9a60065b 493 }
kadonotakashi 0:8fdf9a60065b 494 }
kadonotakashi 0:8fdf9a60065b 495
kadonotakashi 0:8fdf9a60065b 496 return 0;
kadonotakashi 0:8fdf9a60065b 497 }
kadonotakashi 0:8fdf9a60065b 498
kadonotakashi 0:8fdf9a60065b 499 int i2c_stop(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 500 {
kadonotakashi 0:8fdf9a60065b 501 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 502 I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
kadonotakashi 0:8fdf9a60065b 503
kadonotakashi 0:8fdf9a60065b 504 // Generate the STOP condition
kadonotakashi 0:8fdf9a60065b 505 i2c->CR1 |= I2C_CR1_STOP;
kadonotakashi 0:8fdf9a60065b 506
kadonotakashi 0:8fdf9a60065b 507 /* In case of mixed usage of the APIs (unitary + SYNC)
kadonotakashi 0:8fdf9a60065b 508 * re-init HAL state
kadonotakashi 0:8fdf9a60065b 509 */
kadonotakashi 0:8fdf9a60065b 510 if (obj_s->XferOperation != I2C_FIRST_AND_LAST_FRAME) {
kadonotakashi 0:8fdf9a60065b 511 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 512 }
kadonotakashi 0:8fdf9a60065b 513
kadonotakashi 0:8fdf9a60065b 514 return 0;
kadonotakashi 0:8fdf9a60065b 515 }
kadonotakashi 0:8fdf9a60065b 516
kadonotakashi 0:8fdf9a60065b 517 int i2c_byte_read(i2c_t *obj, int last)
kadonotakashi 0:8fdf9a60065b 518 {
kadonotakashi 0:8fdf9a60065b 519
kadonotakashi 0:8fdf9a60065b 520 int timeout;
kadonotakashi 0:8fdf9a60065b 521 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 522 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 523
kadonotakashi 0:8fdf9a60065b 524 if (last) {
kadonotakashi 0:8fdf9a60065b 525 // Don't acknowledge the last byte
kadonotakashi 0:8fdf9a60065b 526 handle->Instance->CR1 &= ~I2C_CR1_ACK;
kadonotakashi 0:8fdf9a60065b 527 } else {
kadonotakashi 0:8fdf9a60065b 528 // Acknowledge the byte
kadonotakashi 0:8fdf9a60065b 529 handle->Instance->CR1 |= I2C_CR1_ACK;
kadonotakashi 0:8fdf9a60065b 530 }
kadonotakashi 0:8fdf9a60065b 531
kadonotakashi 0:8fdf9a60065b 532 // Wait until the byte is received
kadonotakashi 0:8fdf9a60065b 533 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 534 while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE) == RESET) {
kadonotakashi 0:8fdf9a60065b 535 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 536 return -1;
kadonotakashi 0:8fdf9a60065b 537 }
kadonotakashi 0:8fdf9a60065b 538 }
kadonotakashi 0:8fdf9a60065b 539
kadonotakashi 0:8fdf9a60065b 540 return (int)handle->Instance->DR;
kadonotakashi 0:8fdf9a60065b 541 }
kadonotakashi 0:8fdf9a60065b 542
kadonotakashi 0:8fdf9a60065b 543 int i2c_byte_write(i2c_t *obj, int data)
kadonotakashi 0:8fdf9a60065b 544 {
kadonotakashi 0:8fdf9a60065b 545
kadonotakashi 0:8fdf9a60065b 546 int timeout;
kadonotakashi 0:8fdf9a60065b 547 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 548 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 549
kadonotakashi 0:8fdf9a60065b 550 handle->Instance->DR = (uint8_t)data;
kadonotakashi 0:8fdf9a60065b 551
kadonotakashi 0:8fdf9a60065b 552 // Wait until the byte (might be the address) is transmitted
kadonotakashi 0:8fdf9a60065b 553 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 554 while ((__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE) == RESET) &&
kadonotakashi 0:8fdf9a60065b 555 (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
kadonotakashi 0:8fdf9a60065b 556 (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET)) {
kadonotakashi 0:8fdf9a60065b 557 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 558 return 2;
kadonotakashi 0:8fdf9a60065b 559 }
kadonotakashi 0:8fdf9a60065b 560 }
kadonotakashi 0:8fdf9a60065b 561
kadonotakashi 0:8fdf9a60065b 562 if (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) != RESET) {
kadonotakashi 0:8fdf9a60065b 563 __HAL_I2C_CLEAR_ADDRFLAG(handle);
kadonotakashi 0:8fdf9a60065b 564 }
kadonotakashi 0:8fdf9a60065b 565
kadonotakashi 0:8fdf9a60065b 566 return 1;
kadonotakashi 0:8fdf9a60065b 567 }
kadonotakashi 0:8fdf9a60065b 568 #endif //I2C_IP_VERSION_V1
kadonotakashi 0:8fdf9a60065b 569 #ifdef I2C_IP_VERSION_V2
kadonotakashi 0:8fdf9a60065b 570
kadonotakashi 0:8fdf9a60065b 571 int i2c_start(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 572 {
kadonotakashi 0:8fdf9a60065b 573 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 574 /* This I2C IP doesn't */
kadonotakashi 0:8fdf9a60065b 575 obj_s->pending_start = 1;
kadonotakashi 0:8fdf9a60065b 576 return 0;
kadonotakashi 0:8fdf9a60065b 577 }
kadonotakashi 0:8fdf9a60065b 578
kadonotakashi 0:8fdf9a60065b 579 int i2c_stop(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 580 {
kadonotakashi 0:8fdf9a60065b 581 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 582 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 583 int timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 584 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 585 if (obj_s->slave) {
kadonotakashi 0:8fdf9a60065b 586 /* re-init slave when stop is requested */
kadonotakashi 0:8fdf9a60065b 587 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 588 return 0;
kadonotakashi 0:8fdf9a60065b 589 }
kadonotakashi 0:8fdf9a60065b 590 #endif
kadonotakashi 0:8fdf9a60065b 591 // Disable reload mode
kadonotakashi 0:8fdf9a60065b 592 handle->Instance->CR2 &= (uint32_t)~I2C_CR2_RELOAD;
kadonotakashi 0:8fdf9a60065b 593
kadonotakashi 0:8fdf9a60065b 594 // Ensure the transmission is started before sending a stop
kadonotakashi 0:8fdf9a60065b 595 if ((handle->Instance->CR2 & (uint32_t)I2C_CR2_RD_WRN) == 0) {
kadonotakashi 0:8fdf9a60065b 596 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 597 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXIS)) {
kadonotakashi 0:8fdf9a60065b 598 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 599 return I2C_ERROR_BUS_BUSY;
kadonotakashi 0:8fdf9a60065b 600 }
kadonotakashi 0:8fdf9a60065b 601 }
kadonotakashi 0:8fdf9a60065b 602 }
kadonotakashi 0:8fdf9a60065b 603
kadonotakashi 0:8fdf9a60065b 604 // Generate the STOP condition
kadonotakashi 0:8fdf9a60065b 605 handle->Instance->CR2 |= I2C_CR2_STOP;
kadonotakashi 0:8fdf9a60065b 606
kadonotakashi 0:8fdf9a60065b 607 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 608 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_STOPF)) {
kadonotakashi 0:8fdf9a60065b 609 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 610 return I2C_ERROR_BUS_BUSY;
kadonotakashi 0:8fdf9a60065b 611 }
kadonotakashi 0:8fdf9a60065b 612 }
kadonotakashi 0:8fdf9a60065b 613
kadonotakashi 0:8fdf9a60065b 614 /* Clear STOP Flag */
kadonotakashi 0:8fdf9a60065b 615 __HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_STOPF);
kadonotakashi 0:8fdf9a60065b 616
kadonotakashi 0:8fdf9a60065b 617 /* Erase slave address, this wiil be used as a marker
kadonotakashi 0:8fdf9a60065b 618 * to know when we need to prepare next start */
kadonotakashi 0:8fdf9a60065b 619 handle->Instance->CR2 &= ~I2C_CR2_SADD;
kadonotakashi 0:8fdf9a60065b 620
kadonotakashi 0:8fdf9a60065b 621 /*
kadonotakashi 0:8fdf9a60065b 622 * V2 IP is meant for automatic STOP, not user STOP
kadonotakashi 0:8fdf9a60065b 623 * SW reset the IP state machine before next transaction
kadonotakashi 0:8fdf9a60065b 624 */
kadonotakashi 0:8fdf9a60065b 625 i2c_sw_reset(obj);
kadonotakashi 0:8fdf9a60065b 626
kadonotakashi 0:8fdf9a60065b 627 /* In case of mixed usage of the APIs (unitary + SYNC)
kadonotakashi 0:8fdf9a60065b 628 * re-init HAL state */
kadonotakashi 0:8fdf9a60065b 629 if (obj_s->XferOperation != I2C_FIRST_AND_LAST_FRAME) {
kadonotakashi 0:8fdf9a60065b 630 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 631 }
kadonotakashi 0:8fdf9a60065b 632
kadonotakashi 0:8fdf9a60065b 633 return 0;
kadonotakashi 0:8fdf9a60065b 634 }
kadonotakashi 0:8fdf9a60065b 635
kadonotakashi 0:8fdf9a60065b 636 int i2c_byte_read(i2c_t *obj, int last)
kadonotakashi 0:8fdf9a60065b 637 {
kadonotakashi 0:8fdf9a60065b 638 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 639 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 640 int timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 641 uint32_t tmpreg = handle->Instance->CR2;
kadonotakashi 0:8fdf9a60065b 642 char data;
kadonotakashi 0:8fdf9a60065b 643 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 644 if (obj_s->slave) {
kadonotakashi 0:8fdf9a60065b 645 return i2c_slave_read(obj, &data, 1);
kadonotakashi 0:8fdf9a60065b 646 }
kadonotakashi 0:8fdf9a60065b 647 #endif
kadonotakashi 0:8fdf9a60065b 648 /* Then send data when there's room in the TX fifo */
kadonotakashi 0:8fdf9a60065b 649 if ((tmpreg & I2C_CR2_RELOAD) != 0) {
kadonotakashi 0:8fdf9a60065b 650 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
kadonotakashi 0:8fdf9a60065b 651 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 652 DEBUG_PRINTF("timeout in byte_read\r\n");
kadonotakashi 0:8fdf9a60065b 653 return -1;
kadonotakashi 0:8fdf9a60065b 654 }
kadonotakashi 0:8fdf9a60065b 655 }
kadonotakashi 0:8fdf9a60065b 656 }
kadonotakashi 0:8fdf9a60065b 657
kadonotakashi 0:8fdf9a60065b 658 /* Enable reload mode as we don't know how many bytes will be sent */
kadonotakashi 0:8fdf9a60065b 659 /* and set transfer size to 1 */
kadonotakashi 0:8fdf9a60065b 660 tmpreg |= I2C_CR2_RELOAD | (I2C_CR2_NBYTES & (1 << 16));
kadonotakashi 0:8fdf9a60065b 661 /* Set the prepared configuration */
kadonotakashi 0:8fdf9a60065b 662 handle->Instance->CR2 = tmpreg;
kadonotakashi 0:8fdf9a60065b 663
kadonotakashi 0:8fdf9a60065b 664 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 665 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE)) {
kadonotakashi 0:8fdf9a60065b 666 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 667 return -1;
kadonotakashi 0:8fdf9a60065b 668 }
kadonotakashi 0:8fdf9a60065b 669 }
kadonotakashi 0:8fdf9a60065b 670
kadonotakashi 0:8fdf9a60065b 671 /* Then Get Byte */
kadonotakashi 0:8fdf9a60065b 672 data = handle->Instance->RXDR;
kadonotakashi 0:8fdf9a60065b 673
kadonotakashi 0:8fdf9a60065b 674 if (last) {
kadonotakashi 0:8fdf9a60065b 675 /* Disable Address Acknowledge */
kadonotakashi 0:8fdf9a60065b 676 handle->Instance->CR2 |= I2C_CR2_NACK;
kadonotakashi 0:8fdf9a60065b 677 }
kadonotakashi 0:8fdf9a60065b 678
kadonotakashi 0:8fdf9a60065b 679 return data;
kadonotakashi 0:8fdf9a60065b 680 }
kadonotakashi 0:8fdf9a60065b 681
kadonotakashi 0:8fdf9a60065b 682 int i2c_byte_write(i2c_t *obj, int data)
kadonotakashi 0:8fdf9a60065b 683 {
kadonotakashi 0:8fdf9a60065b 684 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 685 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 686 int timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 687 uint32_t tmpreg = handle->Instance->CR2;
kadonotakashi 0:8fdf9a60065b 688 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 689 if (obj_s->slave) {
kadonotakashi 0:8fdf9a60065b 690 return i2c_slave_write(obj, (char *) &data, 1);
kadonotakashi 0:8fdf9a60065b 691 }
kadonotakashi 0:8fdf9a60065b 692 #endif
kadonotakashi 0:8fdf9a60065b 693 if (obj_s->pending_start) {
kadonotakashi 0:8fdf9a60065b 694 obj_s->pending_start = 0;
kadonotakashi 0:8fdf9a60065b 695 //* First byte after the start is the address */
kadonotakashi 0:8fdf9a60065b 696 tmpreg |= (uint32_t)((uint32_t)data & I2C_CR2_SADD);
kadonotakashi 0:8fdf9a60065b 697 if (data & 0x01) {
kadonotakashi 0:8fdf9a60065b 698 tmpreg |= I2C_CR2_START | I2C_CR2_RD_WRN;
kadonotakashi 0:8fdf9a60065b 699 } else {
kadonotakashi 0:8fdf9a60065b 700 tmpreg |= I2C_CR2_START;
kadonotakashi 0:8fdf9a60065b 701 tmpreg &= ~I2C_CR2_RD_WRN;
kadonotakashi 0:8fdf9a60065b 702 }
kadonotakashi 0:8fdf9a60065b 703 /* Disable reload first to use it later */
kadonotakashi 0:8fdf9a60065b 704 tmpreg &= ~I2C_CR2_RELOAD;
kadonotakashi 0:8fdf9a60065b 705 /* Disable Autoend */
kadonotakashi 0:8fdf9a60065b 706 tmpreg &= ~I2C_CR2_AUTOEND;
kadonotakashi 0:8fdf9a60065b 707 /* Do not set any transfer size for now */
kadonotakashi 0:8fdf9a60065b 708 tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
kadonotakashi 0:8fdf9a60065b 709 /* Set the prepared configuration */
kadonotakashi 0:8fdf9a60065b 710 handle->Instance->CR2 = tmpreg;
kadonotakashi 0:8fdf9a60065b 711 } else {
kadonotakashi 0:8fdf9a60065b 712 /* Set the prepared configuration */
kadonotakashi 0:8fdf9a60065b 713 tmpreg = handle->Instance->CR2;
kadonotakashi 0:8fdf9a60065b 714
kadonotakashi 0:8fdf9a60065b 715 /* Then send data when there's room in the TX fifo */
kadonotakashi 0:8fdf9a60065b 716 if ((tmpreg & I2C_CR2_RELOAD) != 0) {
kadonotakashi 0:8fdf9a60065b 717 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
kadonotakashi 0:8fdf9a60065b 718 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 719 DEBUG_PRINTF("timeout in byte_write\r\n");
kadonotakashi 0:8fdf9a60065b 720 return 2;
kadonotakashi 0:8fdf9a60065b 721 }
kadonotakashi 0:8fdf9a60065b 722 }
kadonotakashi 0:8fdf9a60065b 723 }
kadonotakashi 0:8fdf9a60065b 724 /* Enable reload mode as we don't know how many bytes will eb sent */
kadonotakashi 0:8fdf9a60065b 725 tmpreg |= I2C_CR2_RELOAD;
kadonotakashi 0:8fdf9a60065b 726 /* Set transfer size to 1 */
kadonotakashi 0:8fdf9a60065b 727 tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
kadonotakashi 0:8fdf9a60065b 728 /* Set the prepared configuration */
kadonotakashi 0:8fdf9a60065b 729 handle->Instance->CR2 = tmpreg;
kadonotakashi 0:8fdf9a60065b 730 /* Prepare next write */
kadonotakashi 0:8fdf9a60065b 731 timeout = FLAG_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 732 while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE)) {
kadonotakashi 0:8fdf9a60065b 733 if ((timeout--) == 0) {
kadonotakashi 0:8fdf9a60065b 734 return 2;
kadonotakashi 0:8fdf9a60065b 735 }
kadonotakashi 0:8fdf9a60065b 736 }
kadonotakashi 0:8fdf9a60065b 737 /* Write byte */
kadonotakashi 0:8fdf9a60065b 738 handle->Instance->TXDR = data;
kadonotakashi 0:8fdf9a60065b 739 }
kadonotakashi 0:8fdf9a60065b 740
kadonotakashi 0:8fdf9a60065b 741 return 1;
kadonotakashi 0:8fdf9a60065b 742 }
kadonotakashi 0:8fdf9a60065b 743 #endif //I2C_IP_VERSION_V2
kadonotakashi 0:8fdf9a60065b 744
kadonotakashi 0:8fdf9a60065b 745 /*
kadonotakashi 0:8fdf9a60065b 746 * SYNC APIS
kadonotakashi 0:8fdf9a60065b 747 */
kadonotakashi 0:8fdf9a60065b 748 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
kadonotakashi 0:8fdf9a60065b 749 {
kadonotakashi 0:8fdf9a60065b 750 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 751 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 752 int count = I2C_ERROR_BUS_BUSY, ret = 0;
kadonotakashi 0:8fdf9a60065b 753 uint32_t timeout = 0;
kadonotakashi 0:8fdf9a60065b 754
kadonotakashi 0:8fdf9a60065b 755 // Trick to remove compiler warning "left and right operands are identical" in some cases
kadonotakashi 0:8fdf9a60065b 756 uint32_t op1 = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 757 uint32_t op2 = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 758 if ((obj_s->XferOperation == op1) || (obj_s->XferOperation == op2)) {
kadonotakashi 0:8fdf9a60065b 759 if (stop) {
kadonotakashi 0:8fdf9a60065b 760 obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 761 } else {
kadonotakashi 0:8fdf9a60065b 762 obj_s->XferOperation = I2C_FIRST_FRAME;
kadonotakashi 0:8fdf9a60065b 763 }
kadonotakashi 0:8fdf9a60065b 764 } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) ||
kadonotakashi 0:8fdf9a60065b 765 (obj_s->XferOperation == I2C_NEXT_FRAME)) {
kadonotakashi 0:8fdf9a60065b 766 if (stop) {
kadonotakashi 0:8fdf9a60065b 767 obj_s->XferOperation = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 768 } else {
kadonotakashi 0:8fdf9a60065b 769 obj_s->XferOperation = I2C_NEXT_FRAME;
kadonotakashi 0:8fdf9a60065b 770 }
kadonotakashi 0:8fdf9a60065b 771 }
kadonotakashi 0:8fdf9a60065b 772
kadonotakashi 0:8fdf9a60065b 773 obj_s->event = 0;
kadonotakashi 0:8fdf9a60065b 774
kadonotakashi 0:8fdf9a60065b 775 /* Activate default IRQ handlers for sync mode
kadonotakashi 0:8fdf9a60065b 776 * which would be overwritten in async mode
kadonotakashi 0:8fdf9a60065b 777 */
kadonotakashi 0:8fdf9a60065b 778 i2c_ev_err_enable(obj, i2c_get_irq_handler(obj));
kadonotakashi 0:8fdf9a60065b 779
kadonotakashi 0:8fdf9a60065b 780 ret = HAL_I2C_Master_Sequential_Receive_IT(handle, address, (uint8_t *) data, length, obj_s->XferOperation);
kadonotakashi 0:8fdf9a60065b 781
kadonotakashi 0:8fdf9a60065b 782 if (ret == HAL_OK) {
kadonotakashi 0:8fdf9a60065b 783 timeout = BYTE_TIMEOUT_US * (length + 1);
kadonotakashi 0:8fdf9a60065b 784 /* transfer started : wait completion or timeout */
kadonotakashi 0:8fdf9a60065b 785 while (!(obj_s->event & I2C_EVENT_ALL) && (--timeout != 0)) {
kadonotakashi 0:8fdf9a60065b 786 wait_us(1);
kadonotakashi 0:8fdf9a60065b 787 }
kadonotakashi 0:8fdf9a60065b 788
kadonotakashi 0:8fdf9a60065b 789 i2c_ev_err_disable(obj);
kadonotakashi 0:8fdf9a60065b 790
kadonotakashi 0:8fdf9a60065b 791 if ((timeout == 0) || (obj_s->event != I2C_EVENT_TRANSFER_COMPLETE)) {
kadonotakashi 0:8fdf9a60065b 792 DEBUG_PRINTF(" TIMEOUT or error in i2c_read\r\n");
kadonotakashi 0:8fdf9a60065b 793 /* re-init IP to try and get back in a working state */
kadonotakashi 0:8fdf9a60065b 794 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 795 } else {
kadonotakashi 0:8fdf9a60065b 796 count = length;
kadonotakashi 0:8fdf9a60065b 797 }
kadonotakashi 0:8fdf9a60065b 798 } else {
kadonotakashi 0:8fdf9a60065b 799 DEBUG_PRINTF("ERROR in i2c_read:%d\r\n", ret);
kadonotakashi 0:8fdf9a60065b 800 }
kadonotakashi 0:8fdf9a60065b 801
kadonotakashi 0:8fdf9a60065b 802 return count;
kadonotakashi 0:8fdf9a60065b 803 }
kadonotakashi 0:8fdf9a60065b 804
kadonotakashi 0:8fdf9a60065b 805 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
kadonotakashi 0:8fdf9a60065b 806 {
kadonotakashi 0:8fdf9a60065b 807 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 808 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 809 int count = I2C_ERROR_BUS_BUSY, ret = 0;
kadonotakashi 0:8fdf9a60065b 810 uint32_t timeout = 0;
kadonotakashi 0:8fdf9a60065b 811
kadonotakashi 0:8fdf9a60065b 812 // Trick to remove compiler warning "left and right operands are identical" in some cases
kadonotakashi 0:8fdf9a60065b 813 uint32_t op1 = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 814 uint32_t op2 = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 815 if ((obj_s->XferOperation == op1) || (obj_s->XferOperation == op2)) {
kadonotakashi 0:8fdf9a60065b 816 if (stop) {
kadonotakashi 0:8fdf9a60065b 817 obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 818 } else {
kadonotakashi 0:8fdf9a60065b 819 obj_s->XferOperation = I2C_FIRST_FRAME;
kadonotakashi 0:8fdf9a60065b 820 }
kadonotakashi 0:8fdf9a60065b 821 } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) ||
kadonotakashi 0:8fdf9a60065b 822 (obj_s->XferOperation == I2C_NEXT_FRAME)) {
kadonotakashi 0:8fdf9a60065b 823 if (stop) {
kadonotakashi 0:8fdf9a60065b 824 obj_s->XferOperation = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 825 } else {
kadonotakashi 0:8fdf9a60065b 826 obj_s->XferOperation = I2C_NEXT_FRAME;
kadonotakashi 0:8fdf9a60065b 827 }
kadonotakashi 0:8fdf9a60065b 828 }
kadonotakashi 0:8fdf9a60065b 829
kadonotakashi 0:8fdf9a60065b 830 obj_s->event = 0;
kadonotakashi 0:8fdf9a60065b 831
kadonotakashi 0:8fdf9a60065b 832 i2c_ev_err_enable(obj, i2c_get_irq_handler(obj));
kadonotakashi 0:8fdf9a60065b 833
kadonotakashi 0:8fdf9a60065b 834 ret = HAL_I2C_Master_Sequential_Transmit_IT(handle, address, (uint8_t *) data, length, obj_s->XferOperation);
kadonotakashi 0:8fdf9a60065b 835
kadonotakashi 0:8fdf9a60065b 836 if (ret == HAL_OK) {
kadonotakashi 0:8fdf9a60065b 837 timeout = BYTE_TIMEOUT_US * (length + 1);
kadonotakashi 0:8fdf9a60065b 838 /* transfer started : wait completion or timeout */
kadonotakashi 0:8fdf9a60065b 839 while (!(obj_s->event & I2C_EVENT_ALL) && (--timeout != 0)) {
kadonotakashi 0:8fdf9a60065b 840 wait_us(1);
kadonotakashi 0:8fdf9a60065b 841 }
kadonotakashi 0:8fdf9a60065b 842
kadonotakashi 0:8fdf9a60065b 843 i2c_ev_err_disable(obj);
kadonotakashi 0:8fdf9a60065b 844
kadonotakashi 0:8fdf9a60065b 845 if ((timeout == 0) || (obj_s->event != I2C_EVENT_TRANSFER_COMPLETE)) {
kadonotakashi 0:8fdf9a60065b 846 DEBUG_PRINTF(" TIMEOUT or error in i2c_write\r\n");
kadonotakashi 0:8fdf9a60065b 847 /* re-init IP to try and get back in a working state */
kadonotakashi 0:8fdf9a60065b 848 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 849 } else {
kadonotakashi 0:8fdf9a60065b 850 count = length;
kadonotakashi 0:8fdf9a60065b 851 }
kadonotakashi 0:8fdf9a60065b 852 } else {
kadonotakashi 0:8fdf9a60065b 853 DEBUG_PRINTF("ERROR in i2c_read\r\n");
kadonotakashi 0:8fdf9a60065b 854 }
kadonotakashi 0:8fdf9a60065b 855
kadonotakashi 0:8fdf9a60065b 856 return count;
kadonotakashi 0:8fdf9a60065b 857 }
kadonotakashi 0:8fdf9a60065b 858
kadonotakashi 0:8fdf9a60065b 859 void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 860 {
kadonotakashi 0:8fdf9a60065b 861 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 862 i2c_t *obj = get_i2c_obj(hi2c);
kadonotakashi 0:8fdf9a60065b 863 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 864
kadonotakashi 0:8fdf9a60065b 865 #if DEVICE_I2C_ASYNCH
kadonotakashi 0:8fdf9a60065b 866 /* Handle potential Tx/Rx use case */
kadonotakashi 0:8fdf9a60065b 867 if ((obj->tx_buff.length) && (obj->rx_buff.length)) {
kadonotakashi 0:8fdf9a60065b 868 if (obj_s->stop) {
kadonotakashi 0:8fdf9a60065b 869 obj_s->XferOperation = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 870 } else {
kadonotakashi 0:8fdf9a60065b 871 obj_s->XferOperation = I2C_NEXT_FRAME;
kadonotakashi 0:8fdf9a60065b 872 }
kadonotakashi 0:8fdf9a60065b 873
kadonotakashi 0:8fdf9a60065b 874 HAL_I2C_Master_Sequential_Receive_IT(hi2c, obj_s->address, (uint8_t *)obj->rx_buff.buffer, obj->rx_buff.length, obj_s->XferOperation);
kadonotakashi 0:8fdf9a60065b 875 } else
kadonotakashi 0:8fdf9a60065b 876 #endif
kadonotakashi 0:8fdf9a60065b 877 {
kadonotakashi 0:8fdf9a60065b 878 /* Set event flag */
kadonotakashi 0:8fdf9a60065b 879 obj_s->event = I2C_EVENT_TRANSFER_COMPLETE;
kadonotakashi 0:8fdf9a60065b 880 }
kadonotakashi 0:8fdf9a60065b 881 }
kadonotakashi 0:8fdf9a60065b 882
kadonotakashi 0:8fdf9a60065b 883 void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 884 {
kadonotakashi 0:8fdf9a60065b 885 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 886 i2c_t *obj = get_i2c_obj(hi2c);
kadonotakashi 0:8fdf9a60065b 887 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 888
kadonotakashi 0:8fdf9a60065b 889 /* Set event flag */
kadonotakashi 0:8fdf9a60065b 890 obj_s->event = I2C_EVENT_TRANSFER_COMPLETE;
kadonotakashi 0:8fdf9a60065b 891 }
kadonotakashi 0:8fdf9a60065b 892
kadonotakashi 0:8fdf9a60065b 893 void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 894 {
kadonotakashi 0:8fdf9a60065b 895 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 896 i2c_t *obj = get_i2c_obj(hi2c);
kadonotakashi 0:8fdf9a60065b 897 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 898 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 899 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 900 uint32_t address = 0;
kadonotakashi 0:8fdf9a60065b 901 /* Store address to handle it after reset */
kadonotakashi 0:8fdf9a60065b 902 if (obj_s->slave) {
kadonotakashi 0:8fdf9a60065b 903 address = handle->Init.OwnAddress1;
kadonotakashi 0:8fdf9a60065b 904 }
kadonotakashi 0:8fdf9a60065b 905 #endif
kadonotakashi 0:8fdf9a60065b 906
kadonotakashi 0:8fdf9a60065b 907 DEBUG_PRINTF("HAL_I2C_ErrorCallback:%d, index=%d\r\n", (int) hi2c->ErrorCode, obj_s->index);
kadonotakashi 0:8fdf9a60065b 908
kadonotakashi 0:8fdf9a60065b 909 /* re-init IP to try and get back in a working state */
kadonotakashi 0:8fdf9a60065b 910 i2c_init(obj, obj_s->sda, obj_s->scl);
kadonotakashi 0:8fdf9a60065b 911
kadonotakashi 0:8fdf9a60065b 912 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 913 /* restore slave address */
kadonotakashi 0:8fdf9a60065b 914 if (address != 0) {
kadonotakashi 0:8fdf9a60065b 915 obj_s->slave = 1;
kadonotakashi 0:8fdf9a60065b 916 i2c_slave_address(obj, 0, address, 0);
kadonotakashi 0:8fdf9a60065b 917 }
kadonotakashi 0:8fdf9a60065b 918 #endif
kadonotakashi 0:8fdf9a60065b 919
kadonotakashi 0:8fdf9a60065b 920 /* Keep Set event flag */
kadonotakashi 0:8fdf9a60065b 921 obj_s->event = I2C_EVENT_ERROR;
kadonotakashi 0:8fdf9a60065b 922 }
kadonotakashi 0:8fdf9a60065b 923
kadonotakashi 0:8fdf9a60065b 924 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 925 /* SLAVE API FUNCTIONS */
kadonotakashi 0:8fdf9a60065b 926 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
kadonotakashi 0:8fdf9a60065b 927 {
kadonotakashi 0:8fdf9a60065b 928 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 929 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 930
kadonotakashi 0:8fdf9a60065b 931 // I2C configuration
kadonotakashi 0:8fdf9a60065b 932 handle->Init.OwnAddress1 = address;
kadonotakashi 0:8fdf9a60065b 933 HAL_I2C_Init(handle);
kadonotakashi 0:8fdf9a60065b 934
kadonotakashi 0:8fdf9a60065b 935 i2c_ev_err_enable(obj, i2c_get_irq_handler(obj));
kadonotakashi 0:8fdf9a60065b 936
kadonotakashi 0:8fdf9a60065b 937 HAL_I2C_EnableListen_IT(handle);
kadonotakashi 0:8fdf9a60065b 938 }
kadonotakashi 0:8fdf9a60065b 939
kadonotakashi 0:8fdf9a60065b 940 void i2c_slave_mode(i2c_t *obj, int enable_slave)
kadonotakashi 0:8fdf9a60065b 941 {
kadonotakashi 0:8fdf9a60065b 942
kadonotakashi 0:8fdf9a60065b 943 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 944 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 945
kadonotakashi 0:8fdf9a60065b 946 if (enable_slave) {
kadonotakashi 0:8fdf9a60065b 947 obj_s->slave = 1;
kadonotakashi 0:8fdf9a60065b 948 HAL_I2C_EnableListen_IT(handle);
kadonotakashi 0:8fdf9a60065b 949 } else {
kadonotakashi 0:8fdf9a60065b 950 obj_s->slave = 0;
kadonotakashi 0:8fdf9a60065b 951 HAL_I2C_DisableListen_IT(handle);
kadonotakashi 0:8fdf9a60065b 952 }
kadonotakashi 0:8fdf9a60065b 953 }
kadonotakashi 0:8fdf9a60065b 954
kadonotakashi 0:8fdf9a60065b 955 // See I2CSlave.h
kadonotakashi 0:8fdf9a60065b 956 #define NoData 0 // the slave has not been addressed
kadonotakashi 0:8fdf9a60065b 957 #define ReadAddressed 1 // the master has requested a read from this slave (slave = transmitter)
kadonotakashi 0:8fdf9a60065b 958 #define WriteGeneral 2 // the master is writing to all slave
kadonotakashi 0:8fdf9a60065b 959 #define WriteAddressed 3 // the master is writing to this slave (slave = receiver)
kadonotakashi 0:8fdf9a60065b 960
kadonotakashi 0:8fdf9a60065b 961
kadonotakashi 0:8fdf9a60065b 962 void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
kadonotakashi 0:8fdf9a60065b 963 {
kadonotakashi 0:8fdf9a60065b 964 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 965 i2c_t *obj = get_i2c_obj(hi2c);
kadonotakashi 0:8fdf9a60065b 966 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 967
kadonotakashi 0:8fdf9a60065b 968 /* Transfer direction in HAL is from Master point of view */
kadonotakashi 0:8fdf9a60065b 969 if (TransferDirection == I2C_DIRECTION_RECEIVE) {
kadonotakashi 0:8fdf9a60065b 970 obj_s->pending_slave_tx_master_rx = 1;
kadonotakashi 0:8fdf9a60065b 971 }
kadonotakashi 0:8fdf9a60065b 972
kadonotakashi 0:8fdf9a60065b 973 if (TransferDirection == I2C_DIRECTION_TRANSMIT) {
kadonotakashi 0:8fdf9a60065b 974 obj_s->pending_slave_rx_maxter_tx = 1;
kadonotakashi 0:8fdf9a60065b 975 }
kadonotakashi 0:8fdf9a60065b 976 }
kadonotakashi 0:8fdf9a60065b 977
kadonotakashi 0:8fdf9a60065b 978 void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
kadonotakashi 0:8fdf9a60065b 979 {
kadonotakashi 0:8fdf9a60065b 980 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 981 i2c_t *obj = get_i2c_obj(I2cHandle);
kadonotakashi 0:8fdf9a60065b 982 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 983 obj_s->pending_slave_tx_master_rx = 0;
kadonotakashi 0:8fdf9a60065b 984 }
kadonotakashi 0:8fdf9a60065b 985
kadonotakashi 0:8fdf9a60065b 986 void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
kadonotakashi 0:8fdf9a60065b 987 {
kadonotakashi 0:8fdf9a60065b 988 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 989 i2c_t *obj = get_i2c_obj(I2cHandle);
kadonotakashi 0:8fdf9a60065b 990 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 991 obj_s->pending_slave_rx_maxter_tx = 0;
kadonotakashi 0:8fdf9a60065b 992 }
kadonotakashi 0:8fdf9a60065b 993
kadonotakashi 0:8fdf9a60065b 994 void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 995 {
kadonotakashi 0:8fdf9a60065b 996 /* restart listening for master requests */
kadonotakashi 0:8fdf9a60065b 997 HAL_I2C_EnableListen_IT(hi2c);
kadonotakashi 0:8fdf9a60065b 998 }
kadonotakashi 0:8fdf9a60065b 999
kadonotakashi 0:8fdf9a60065b 1000 int i2c_slave_receive(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 1001 {
kadonotakashi 0:8fdf9a60065b 1002
kadonotakashi 0:8fdf9a60065b 1003 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1004 int retValue = NoData;
kadonotakashi 0:8fdf9a60065b 1005
kadonotakashi 0:8fdf9a60065b 1006 if (obj_s->pending_slave_rx_maxter_tx) {
kadonotakashi 0:8fdf9a60065b 1007 retValue = WriteAddressed;
kadonotakashi 0:8fdf9a60065b 1008 }
kadonotakashi 0:8fdf9a60065b 1009
kadonotakashi 0:8fdf9a60065b 1010 if (obj_s->pending_slave_tx_master_rx) {
kadonotakashi 0:8fdf9a60065b 1011 retValue = ReadAddressed;
kadonotakashi 0:8fdf9a60065b 1012 }
kadonotakashi 0:8fdf9a60065b 1013
kadonotakashi 0:8fdf9a60065b 1014 return (retValue);
kadonotakashi 0:8fdf9a60065b 1015 }
kadonotakashi 0:8fdf9a60065b 1016
kadonotakashi 0:8fdf9a60065b 1017 int i2c_slave_read(i2c_t *obj, char *data, int length)
kadonotakashi 0:8fdf9a60065b 1018 {
kadonotakashi 0:8fdf9a60065b 1019 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1020 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1021 int count = 0;
kadonotakashi 0:8fdf9a60065b 1022 int ret = 0;
kadonotakashi 0:8fdf9a60065b 1023 uint32_t timeout = 0;
kadonotakashi 0:8fdf9a60065b 1024
kadonotakashi 0:8fdf9a60065b 1025 /* Always use I2C_NEXT_FRAME as slave will just adapt to master requests */
kadonotakashi 0:8fdf9a60065b 1026 ret = HAL_I2C_Slave_Sequential_Receive_IT(handle, (uint8_t *) data, length, I2C_NEXT_FRAME);
kadonotakashi 0:8fdf9a60065b 1027
kadonotakashi 0:8fdf9a60065b 1028 if (ret == HAL_OK) {
kadonotakashi 0:8fdf9a60065b 1029 timeout = BYTE_TIMEOUT_US * (length + 1);
kadonotakashi 0:8fdf9a60065b 1030 while (obj_s->pending_slave_rx_maxter_tx && (--timeout != 0)) {
kadonotakashi 0:8fdf9a60065b 1031 wait_us(1);
kadonotakashi 0:8fdf9a60065b 1032 }
kadonotakashi 0:8fdf9a60065b 1033
kadonotakashi 0:8fdf9a60065b 1034 if (timeout != 0) {
kadonotakashi 0:8fdf9a60065b 1035 count = length;
kadonotakashi 0:8fdf9a60065b 1036 } else {
kadonotakashi 0:8fdf9a60065b 1037 DEBUG_PRINTF("TIMEOUT or error in i2c_slave_read\r\n");
kadonotakashi 0:8fdf9a60065b 1038 }
kadonotakashi 0:8fdf9a60065b 1039 }
kadonotakashi 0:8fdf9a60065b 1040 return count;
kadonotakashi 0:8fdf9a60065b 1041 }
kadonotakashi 0:8fdf9a60065b 1042
kadonotakashi 0:8fdf9a60065b 1043 int i2c_slave_write(i2c_t *obj, const char *data, int length)
kadonotakashi 0:8fdf9a60065b 1044 {
kadonotakashi 0:8fdf9a60065b 1045 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1046 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1047 int count = 0;
kadonotakashi 0:8fdf9a60065b 1048 int ret = 0;
kadonotakashi 0:8fdf9a60065b 1049 uint32_t timeout = 0;
kadonotakashi 0:8fdf9a60065b 1050
kadonotakashi 0:8fdf9a60065b 1051 /* Always use I2C_NEXT_FRAME as slave will just adapt to master requests */
kadonotakashi 0:8fdf9a60065b 1052 ret = HAL_I2C_Slave_Sequential_Transmit_IT(handle, (uint8_t *) data, length, I2C_NEXT_FRAME);
kadonotakashi 0:8fdf9a60065b 1053
kadonotakashi 0:8fdf9a60065b 1054 if (ret == HAL_OK) {
kadonotakashi 0:8fdf9a60065b 1055 timeout = BYTE_TIMEOUT_US * (length + 1);
kadonotakashi 0:8fdf9a60065b 1056 while (obj_s->pending_slave_tx_master_rx && (--timeout != 0)) {
kadonotakashi 0:8fdf9a60065b 1057 wait_us(1);
kadonotakashi 0:8fdf9a60065b 1058 }
kadonotakashi 0:8fdf9a60065b 1059
kadonotakashi 0:8fdf9a60065b 1060 if (timeout != 0) {
kadonotakashi 0:8fdf9a60065b 1061 count = length;
kadonotakashi 0:8fdf9a60065b 1062 } else {
kadonotakashi 0:8fdf9a60065b 1063 DEBUG_PRINTF("TIMEOUT or error in i2c_slave_write\r\n");
kadonotakashi 0:8fdf9a60065b 1064 }
kadonotakashi 0:8fdf9a60065b 1065 }
kadonotakashi 0:8fdf9a60065b 1066
kadonotakashi 0:8fdf9a60065b 1067 return count;
kadonotakashi 0:8fdf9a60065b 1068 }
kadonotakashi 0:8fdf9a60065b 1069 #endif // DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 1070
kadonotakashi 0:8fdf9a60065b 1071 #if DEVICE_I2C_ASYNCH
kadonotakashi 0:8fdf9a60065b 1072 /* ASYNCH MASTER API FUNCTIONS */
kadonotakashi 0:8fdf9a60065b 1073 void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c)
kadonotakashi 0:8fdf9a60065b 1074 {
kadonotakashi 0:8fdf9a60065b 1075 /* Get object ptr based on handler ptr */
kadonotakashi 0:8fdf9a60065b 1076 i2c_t *obj = get_i2c_obj(hi2c);
kadonotakashi 0:8fdf9a60065b 1077 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1078 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1079
kadonotakashi 0:8fdf9a60065b 1080 /* Disable IT. Not always done before calling macro */
kadonotakashi 0:8fdf9a60065b 1081 __HAL_I2C_DISABLE_IT(handle, I2C_IT_ALL);
kadonotakashi 0:8fdf9a60065b 1082 i2c_ev_err_disable(obj);
kadonotakashi 0:8fdf9a60065b 1083
kadonotakashi 0:8fdf9a60065b 1084 /* Set event flag */
kadonotakashi 0:8fdf9a60065b 1085 obj_s->event = I2C_EVENT_ERROR;
kadonotakashi 0:8fdf9a60065b 1086 }
kadonotakashi 0:8fdf9a60065b 1087
kadonotakashi 0:8fdf9a60065b 1088 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 1089 {
kadonotakashi 0:8fdf9a60065b 1090
kadonotakashi 0:8fdf9a60065b 1091 // TODO: DMA usage is currently ignored by this way
kadonotakashi 0:8fdf9a60065b 1092 (void) hint;
kadonotakashi 0:8fdf9a60065b 1093
kadonotakashi 0:8fdf9a60065b 1094 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1095 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1096
kadonotakashi 0:8fdf9a60065b 1097 /* Update object */
kadonotakashi 0:8fdf9a60065b 1098 obj->tx_buff.buffer = (void *)tx;
kadonotakashi 0:8fdf9a60065b 1099 obj->tx_buff.length = tx_length;
kadonotakashi 0:8fdf9a60065b 1100 obj->tx_buff.pos = 0;
kadonotakashi 0:8fdf9a60065b 1101 obj->tx_buff.width = 8;
kadonotakashi 0:8fdf9a60065b 1102
kadonotakashi 0:8fdf9a60065b 1103 obj->rx_buff.buffer = (void *)rx;
kadonotakashi 0:8fdf9a60065b 1104 obj->rx_buff.length = rx_length;
kadonotakashi 0:8fdf9a60065b 1105 obj->rx_buff.pos = SIZE_MAX;
kadonotakashi 0:8fdf9a60065b 1106 obj->rx_buff.width = 8;
kadonotakashi 0:8fdf9a60065b 1107
kadonotakashi 0:8fdf9a60065b 1108 obj_s->available_events = event;
kadonotakashi 0:8fdf9a60065b 1109 obj_s->event = 0;
kadonotakashi 0:8fdf9a60065b 1110 obj_s->address = address;
kadonotakashi 0:8fdf9a60065b 1111 obj_s->stop = stop;
kadonotakashi 0:8fdf9a60065b 1112
kadonotakashi 0:8fdf9a60065b 1113 i2c_ev_err_enable(obj, handler);
kadonotakashi 0:8fdf9a60065b 1114
kadonotakashi 0:8fdf9a60065b 1115 /* Set operation step depending if stop sending required or not */
kadonotakashi 0:8fdf9a60065b 1116 if ((tx_length && !rx_length) || (!tx_length && rx_length)) {
kadonotakashi 0:8fdf9a60065b 1117 // Trick to remove compiler warning "left and right operands are identical" in some cases
kadonotakashi 0:8fdf9a60065b 1118 uint32_t op1 = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1119 uint32_t op2 = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1120 if ((obj_s->XferOperation == op1) || (obj_s->XferOperation == op2)) {
kadonotakashi 0:8fdf9a60065b 1121 if (stop) {
kadonotakashi 0:8fdf9a60065b 1122 obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1123 } else {
kadonotakashi 0:8fdf9a60065b 1124 obj_s->XferOperation = I2C_FIRST_FRAME;
kadonotakashi 0:8fdf9a60065b 1125 }
kadonotakashi 0:8fdf9a60065b 1126 } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) ||
kadonotakashi 0:8fdf9a60065b 1127 (obj_s->XferOperation == I2C_NEXT_FRAME)) {
kadonotakashi 0:8fdf9a60065b 1128 if (stop) {
kadonotakashi 0:8fdf9a60065b 1129 obj_s->XferOperation = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1130 } else {
kadonotakashi 0:8fdf9a60065b 1131 obj_s->XferOperation = I2C_NEXT_FRAME;
kadonotakashi 0:8fdf9a60065b 1132 }
kadonotakashi 0:8fdf9a60065b 1133 }
kadonotakashi 0:8fdf9a60065b 1134
kadonotakashi 0:8fdf9a60065b 1135 if (tx_length > 0) {
kadonotakashi 0:8fdf9a60065b 1136 HAL_I2C_Master_Sequential_Transmit_IT(handle, address, (uint8_t *)tx, tx_length, obj_s->XferOperation);
kadonotakashi 0:8fdf9a60065b 1137 }
kadonotakashi 0:8fdf9a60065b 1138 if (rx_length > 0) {
kadonotakashi 0:8fdf9a60065b 1139 HAL_I2C_Master_Sequential_Receive_IT(handle, address, (uint8_t *)rx, rx_length, obj_s->XferOperation);
kadonotakashi 0:8fdf9a60065b 1140 }
kadonotakashi 0:8fdf9a60065b 1141 } else if (tx_length && rx_length) {
kadonotakashi 0:8fdf9a60065b 1142 /* Two steps operation, don't modify XferOperation, keep it for next step */
kadonotakashi 0:8fdf9a60065b 1143 // Trick to remove compiler warning "left and right operands are identical" in some cases
kadonotakashi 0:8fdf9a60065b 1144 uint32_t op1 = I2C_FIRST_AND_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1145 uint32_t op2 = I2C_LAST_FRAME;
kadonotakashi 0:8fdf9a60065b 1146 if ((obj_s->XferOperation == op1) || (obj_s->XferOperation == op2)) {
kadonotakashi 0:8fdf9a60065b 1147 HAL_I2C_Master_Sequential_Transmit_IT(handle, address, (uint8_t *)tx, tx_length, I2C_FIRST_FRAME);
kadonotakashi 0:8fdf9a60065b 1148 } else if ((obj_s->XferOperation == I2C_FIRST_FRAME) ||
kadonotakashi 0:8fdf9a60065b 1149 (obj_s->XferOperation == I2C_NEXT_FRAME)) {
kadonotakashi 0:8fdf9a60065b 1150 HAL_I2C_Master_Sequential_Transmit_IT(handle, address, (uint8_t *)tx, tx_length, I2C_NEXT_FRAME);
kadonotakashi 0:8fdf9a60065b 1151 }
kadonotakashi 0:8fdf9a60065b 1152 }
kadonotakashi 0:8fdf9a60065b 1153 }
kadonotakashi 0:8fdf9a60065b 1154
kadonotakashi 0:8fdf9a60065b 1155
kadonotakashi 0:8fdf9a60065b 1156 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 1157 {
kadonotakashi 0:8fdf9a60065b 1158
kadonotakashi 0:8fdf9a60065b 1159 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1160 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1161
kadonotakashi 0:8fdf9a60065b 1162 HAL_I2C_EV_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 1163 HAL_I2C_ER_IRQHandler(handle);
kadonotakashi 0:8fdf9a60065b 1164
kadonotakashi 0:8fdf9a60065b 1165 /* Return I2C event status */
kadonotakashi 0:8fdf9a60065b 1166 return (obj_s->event & obj_s->available_events);
kadonotakashi 0:8fdf9a60065b 1167 }
kadonotakashi 0:8fdf9a60065b 1168
kadonotakashi 0:8fdf9a60065b 1169 uint8_t i2c_active(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 1170 {
kadonotakashi 0:8fdf9a60065b 1171
kadonotakashi 0:8fdf9a60065b 1172 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1173 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1174
kadonotakashi 0:8fdf9a60065b 1175 if (handle->State == HAL_I2C_STATE_READY) {
kadonotakashi 0:8fdf9a60065b 1176 return 0;
kadonotakashi 0:8fdf9a60065b 1177 } else {
kadonotakashi 0:8fdf9a60065b 1178 return 1;
kadonotakashi 0:8fdf9a60065b 1179 }
kadonotakashi 0:8fdf9a60065b 1180 }
kadonotakashi 0:8fdf9a60065b 1181
kadonotakashi 0:8fdf9a60065b 1182 void i2c_abort_asynch(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 1183 {
kadonotakashi 0:8fdf9a60065b 1184
kadonotakashi 0:8fdf9a60065b 1185 struct i2c_s *obj_s = I2C_S(obj);
kadonotakashi 0:8fdf9a60065b 1186 I2C_HandleTypeDef *handle = &(obj_s->handle);
kadonotakashi 0:8fdf9a60065b 1187
kadonotakashi 0:8fdf9a60065b 1188 /* Abort HAL requires DevAddress, but is not used. Use Dummy */
kadonotakashi 0:8fdf9a60065b 1189 uint16_t Dummy_DevAddress = 0x00;
kadonotakashi 0:8fdf9a60065b 1190
kadonotakashi 0:8fdf9a60065b 1191 HAL_I2C_Master_Abort_IT(handle, Dummy_DevAddress);
kadonotakashi 0:8fdf9a60065b 1192 }
kadonotakashi 0:8fdf9a60065b 1193
kadonotakashi 0:8fdf9a60065b 1194 #endif // DEVICE_I2C_ASYNCH
kadonotakashi 0:8fdf9a60065b 1195
kadonotakashi 0:8fdf9a60065b 1196 #endif // DEVICE_I2C