Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / flight / pios / stm32f10x / pios_i2c.c
blobc411d7eac5da4bfc18076afb29fc4af9fd13f967
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_I2C I2C Functions
6 * @brief STM32 Hardware dependent I2C functionality
7 * @{
9 * @file pios_i2c.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
11 * @brief I2C Enable/Disable routines
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "pios.h"
33 #ifdef PIOS_INCLUDE_I2C
35 #if defined(PIOS_INCLUDE_FREERTOS)
36 #define USE_FREERTOS
37 #endif
39 #include <pios_i2c_priv.h>
41 enum i2c_adapter_state {
42 I2C_STATE_FSM_FAULT = 0, /* Must be zero so undefined transitions land here */
44 I2C_STATE_BUS_ERROR,
46 I2C_STATE_STOPPED,
47 I2C_STATE_STOPPING,
48 I2C_STATE_STARTING,
50 I2C_STATE_R_MORE_TXN_ADDR,
51 I2C_STATE_R_MORE_TXN_PRE_ONE,
52 I2C_STATE_R_MORE_TXN_PRE_FIRST,
53 I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
54 I2C_STATE_R_MORE_TXN_PRE_LAST,
55 I2C_STATE_R_MORE_TXN_POST_LAST,
57 I2C_STATE_R_LAST_TXN_ADDR,
58 I2C_STATE_R_LAST_TXN_PRE_ONE,
59 I2C_STATE_R_LAST_TXN_PRE_FIRST,
60 I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
61 I2C_STATE_R_LAST_TXN_PRE_LAST,
62 I2C_STATE_R_LAST_TXN_POST_LAST,
64 I2C_STATE_W_MORE_TXN_ADDR,
65 I2C_STATE_W_MORE_TXN_MIDDLE,
66 I2C_STATE_W_MORE_TXN_LAST,
68 I2C_STATE_W_LAST_TXN_ADDR,
69 I2C_STATE_W_LAST_TXN_MIDDLE,
70 I2C_STATE_W_LAST_TXN_LAST,
72 I2C_STATE_NACK,
74 I2C_STATE_NUM_STATES /* Must be last */
77 // #define I2C_HALT_ON_ERRORS
79 enum i2c_adapter_event {
80 I2C_EVENT_BUS_ERROR,
81 I2C_EVENT_START,
82 I2C_EVENT_STARTED_MORE_TXN_READ,
83 I2C_EVENT_STARTED_MORE_TXN_WRITE,
84 I2C_EVENT_STARTED_LAST_TXN_READ,
85 I2C_EVENT_STARTED_LAST_TXN_WRITE,
86 I2C_EVENT_ADDR_SENT_LEN_EQ_0,
87 I2C_EVENT_ADDR_SENT_LEN_EQ_1,
88 I2C_EVENT_ADDR_SENT_LEN_EQ_2,
89 I2C_EVENT_ADDR_SENT_LEN_GT_2,
90 I2C_EVENT_TRANSFER_DONE_LEN_EQ_0,
91 I2C_EVENT_TRANSFER_DONE_LEN_EQ_1,
92 I2C_EVENT_TRANSFER_DONE_LEN_EQ_2,
93 I2C_EVENT_TRANSFER_DONE_LEN_GT_2,
94 I2C_EVENT_NACK,
95 I2C_EVENT_STOPPED,
96 I2C_EVENT_AUTO, /* FIXME: remove this */
98 I2C_EVENT_NUM_EVENTS /* Must be last */
101 #if defined(PIOS_I2C_DIAGNOSTICS)
102 static struct pios_i2c_fault_history i2c_adapter_fault_history;
104 volatile uint32_t i2c_evirq_history[I2C_LOG_DEPTH];
105 volatile uint8_t i2c_evirq_history_pointer = 0;
107 volatile uint32_t i2c_erirq_history[I2C_LOG_DEPTH];
108 volatile uint8_t i2c_erirq_history_pointer = 0;
110 volatile enum i2c_adapter_state i2c_state_history[I2C_LOG_DEPTH];
111 volatile uint8_t i2c_state_history_pointer = 0;
113 volatile enum i2c_adapter_event i2c_state_event_history[I2C_LOG_DEPTH];
114 volatile uint8_t i2c_state_event_history_pointer;
116 static uint8_t i2c_fsm_fault_count = 0;
117 static uint8_t i2c_bad_event_counter = 0;
118 static uint8_t i2c_error_interrupt_counter = 0;
119 static uint8_t i2c_nack_counter = 0;
120 static uint8_t i2c_timeout_counter = 0;
121 #endif
123 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter);
124 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter);
125 static void go_stopping(struct pios_i2c_adapter *i2c_adapter);
126 static void go_stopped(struct pios_i2c_adapter *i2c_adapter);
127 static void go_starting(struct pios_i2c_adapter *i2c_adapter);
128 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
129 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter);
130 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter);
131 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter);
132 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter);
133 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter);
135 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
136 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter);
137 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter);
138 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter);
139 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter);
140 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter);
142 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
143 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
144 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter);
146 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
147 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
148 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter);
150 static void go_nack(struct pios_i2c_adapter *i2c_adapter);
152 struct i2c_adapter_transition {
153 void (*entry_fn)(struct pios_i2c_adapter *i2c_adapter);
154 enum i2c_adapter_state next_state[I2C_EVENT_NUM_EVENTS];
157 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter);
158 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event);
159 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter);
160 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter);
161 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter);
163 static void i2c_adapter_log_fault(enum pios_i2c_error_type type);
165 static const struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
166 [I2C_STATE_FSM_FAULT] = {
167 .entry_fn = go_fsm_fault,
168 .next_state = {
169 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
172 [I2C_STATE_BUS_ERROR] = {
173 .entry_fn = go_bus_error,
174 .next_state = {
175 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
179 [I2C_STATE_STOPPED] = {
180 .entry_fn = go_stopped,
181 .next_state = {
182 [I2C_EVENT_START] = I2C_STATE_STARTING,
183 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
187 [I2C_STATE_STOPPING] = {
188 .entry_fn = go_stopping,
189 .next_state = {
190 [I2C_EVENT_STOPPED] = I2C_STATE_STOPPED,
191 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
195 [I2C_STATE_STARTING] = {
196 .entry_fn = go_starting,
197 .next_state = {
198 [I2C_EVENT_STARTED_MORE_TXN_READ] = I2C_STATE_R_MORE_TXN_ADDR,
199 [I2C_EVENT_STARTED_MORE_TXN_WRITE] = I2C_STATE_W_MORE_TXN_ADDR,
200 [I2C_EVENT_STARTED_LAST_TXN_READ] = I2C_STATE_R_LAST_TXN_ADDR,
201 [I2C_EVENT_STARTED_LAST_TXN_WRITE] = I2C_STATE_W_LAST_TXN_ADDR,
202 [I2C_EVENT_NACK] = I2C_STATE_NACK,
203 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
208 * Read with restart
211 [I2C_STATE_R_MORE_TXN_ADDR] = {
212 .entry_fn = go_r_any_txn_addr,
213 .next_state = {
214 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_PRE_ONE,
215 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
216 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
217 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
221 [I2C_STATE_R_MORE_TXN_PRE_ONE] = {
222 .entry_fn = go_r_more_txn_pre_one,
223 .next_state = {
224 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
225 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
229 [I2C_STATE_R_MORE_TXN_PRE_FIRST] = {
230 .entry_fn = go_r_any_txn_pre_first,
231 .next_state = {
232 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
233 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
234 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
238 [I2C_STATE_R_MORE_TXN_PRE_MIDDLE] = {
239 .entry_fn = go_r_any_txn_pre_middle,
240 .next_state = {
241 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
242 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
243 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
247 [I2C_STATE_R_MORE_TXN_PRE_LAST] = {
248 .entry_fn = go_r_more_txn_pre_last,
249 .next_state = {
250 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
251 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
255 [I2C_STATE_R_MORE_TXN_POST_LAST] = {
256 .entry_fn = go_r_any_txn_post_last,
257 .next_state = {
258 [I2C_EVENT_AUTO] = I2C_STATE_STARTING,
263 * Read
266 [I2C_STATE_R_LAST_TXN_ADDR] = {
267 .entry_fn = go_r_any_txn_addr,
268 .next_state = {
269 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_PRE_ONE,
270 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
271 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
272 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
276 [I2C_STATE_R_LAST_TXN_PRE_ONE] = {
277 .entry_fn = go_r_last_txn_pre_one,
278 .next_state = {
279 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
280 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
284 [I2C_STATE_R_LAST_TXN_PRE_FIRST] = {
285 .entry_fn = go_r_any_txn_pre_first,
286 .next_state = {
287 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
288 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
289 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
293 [I2C_STATE_R_LAST_TXN_PRE_MIDDLE] = {
294 .entry_fn = go_r_any_txn_pre_middle,
295 .next_state = {
296 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
297 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
298 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
302 [I2C_STATE_R_LAST_TXN_PRE_LAST] = {
303 .entry_fn = go_r_last_txn_pre_last,
304 .next_state = {
305 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
306 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
310 [I2C_STATE_R_LAST_TXN_POST_LAST] = {
311 .entry_fn = go_r_any_txn_post_last,
312 .next_state = {
313 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
318 * Write with restart
321 [I2C_STATE_W_MORE_TXN_ADDR] = {
322 .entry_fn = go_w_any_txn_addr,
323 .next_state = {
324 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
325 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
326 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
327 [I2C_EVENT_NACK] = I2C_STATE_NACK,
328 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
332 [I2C_STATE_W_MORE_TXN_MIDDLE] = {
333 .entry_fn = go_w_any_txn_middle,
334 .next_state = {
335 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
336 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
337 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
338 [I2C_EVENT_NACK] = I2C_STATE_NACK,
339 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
343 [I2C_STATE_W_MORE_TXN_LAST] = {
344 .entry_fn = go_w_more_txn_last,
345 .next_state = {
346 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STARTING,
347 [I2C_EVENT_NACK] = I2C_STATE_NACK,
348 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
353 * Write
356 [I2C_STATE_W_LAST_TXN_ADDR] = {
357 .entry_fn = go_w_any_txn_addr,
358 .next_state = {
359 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
360 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
361 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
362 [I2C_EVENT_NACK] = I2C_STATE_NACK,
363 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
367 [I2C_STATE_W_LAST_TXN_MIDDLE] = {
368 .entry_fn = go_w_any_txn_middle,
369 .next_state = {
370 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
371 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
372 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
373 [I2C_EVENT_NACK] = I2C_STATE_NACK,
374 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
378 [I2C_STATE_W_LAST_TXN_LAST] = {
379 .entry_fn = go_w_last_txn_last,
380 .next_state = {
381 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STOPPING,
382 [I2C_EVENT_NACK] = I2C_STATE_NACK,
383 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
386 [I2C_STATE_NACK] = {
387 .entry_fn = go_nack,
388 .next_state = {
389 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
394 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter)
396 #if defined(I2C_HALT_ON_ERRORS)
397 PIOS_DEBUG_Assert(0);
398 #endif
399 /* Note that this transfer has hit a bus error */
400 i2c_adapter->bus_error = true;
402 i2c_adapter_reset_bus(i2c_adapter);
405 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter)
407 /* Note that this transfer has hit a bus error */
408 i2c_adapter->bus_error = true;
410 i2c_adapter_reset_bus(i2c_adapter);
413 static void go_stopping(struct pios_i2c_adapter *i2c_adapter)
415 #ifdef USE_FREERTOS
416 signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
417 #endif
419 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
421 #ifdef USE_FREERTOS
422 if (xSemaphoreGiveFromISR(i2c_adapter->sem_ready, &pxHigherPriorityTaskWoken) != pdTRUE) {
423 #if defined(I2C_HALT_ON_ERRORS)
424 PIOS_DEBUG_Assert(0);
425 #endif
427 portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
428 #endif /* USE_FREERTOS */
431 static void go_stopped(struct pios_i2c_adapter *i2c_adapter)
433 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
434 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
437 static void go_starting(struct pios_i2c_adapter *i2c_adapter)
439 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
440 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
441 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
443 // check for an empty read/write
444 if (i2c_adapter->active_txn->buf != NULL && i2c_adapter->active_txn->len != 0) {
445 // Data available
446 i2c_adapter->active_byte = &(i2c_adapter->active_txn->buf[0]);
447 i2c_adapter->last_byte = &(i2c_adapter->active_txn->buf[i2c_adapter->active_txn->len - 1]);
448 } else {
449 // No Data available => Empty read/write
450 i2c_adapter->last_byte = NULL;
451 i2c_adapter->active_byte = i2c_adapter->last_byte + 1;
455 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
456 if (i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ) {
457 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
458 } else {
459 // For write operations, do not enable the IT_BUF events.
460 // The current driver does not act when the TX data register is not full, only when the complete byte is sent.
461 // With the IT_BUF enabled, we constantly get IRQs, See OP-326
462 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_ERR, ENABLE);
466 /* Common to 'more' and 'last' transaction */
467 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
469 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
470 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
471 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
473 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ);
475 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Receiver);
478 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
480 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
481 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
484 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
486 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
487 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
490 /* Common to 'more' and 'last' transaction */
491 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter)
493 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
496 /* Common to 'more' and 'last' transaction */
497 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter)
499 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
500 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
502 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
504 /* Move to the next byte */
505 i2c_adapter->active_byte++;
506 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
509 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
511 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
512 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
514 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
515 PIOS_IRQ_Disable();
516 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
517 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
518 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
519 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
520 PIOS_IRQ_Enable();
522 /* Move to the next byte */
523 i2c_adapter->active_byte++;
524 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
527 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
529 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
530 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
532 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
533 PIOS_IRQ_Disable();
534 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
535 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
536 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
537 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
538 PIOS_IRQ_Enable();
540 /* Move to the next byte */
541 i2c_adapter->active_byte++;
542 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
545 /* Common to 'more' and 'last' transaction */
546 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter)
548 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
549 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
550 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
551 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
552 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
554 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
556 /* Move to the next byte */
557 i2c_adapter->active_byte++;
559 /* Move to the next transaction */
560 i2c_adapter->active_txn++;
563 /* Common to 'more' and 'last' transaction */
564 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
566 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
567 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
568 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
570 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE);
572 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Transmitter);
575 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter)
577 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
578 PIOS_DEBUG_Assert(i2c_adapter->active_byte < i2c_adapter->last_byte);
579 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
580 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
581 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
583 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
585 /* Move to the next byte */
586 i2c_adapter->active_byte++;
587 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
590 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter)
592 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
593 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
594 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
595 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
596 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
598 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
600 /* Move to the next byte */
601 i2c_adapter->active_byte++;
603 /* Move to the next transaction */
604 i2c_adapter->active_txn++;
605 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
608 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter)
610 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
611 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
612 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
613 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
614 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
616 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
617 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
619 // SHOULD MOVE THIS INTO A STOPPING STATE AND SET IT ONLY AFTER THE BYTE WAS SENT
620 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
622 /* Move to the next byte */
623 i2c_adapter->active_byte++;
626 static void go_nack(struct pios_i2c_adapter *i2c_adapter)
628 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
629 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
630 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
633 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event)
635 PIOS_IRQ_Disable();
637 #if defined(PIOS_I2C_DIAGNOSTICS)
638 i2c_state_event_history[i2c_state_event_history_pointer] = event;
639 i2c_state_event_history_pointer = (i2c_state_event_history_pointer + 1) % I2C_LOG_DEPTH;
641 i2c_state_history[i2c_state_history_pointer] = i2c_adapter->curr_state;
642 i2c_state_history_pointer = (i2c_state_history_pointer + 1) % I2C_LOG_DEPTH;
644 if (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event] == I2C_STATE_FSM_FAULT) {
645 i2c_adapter_log_fault(PIOS_I2C_ERROR_FSM);
647 #endif
649 * Move to the next state
651 * This is done prior to calling the new state's entry function to
652 * guarantee that the entry function never depends on the previous
653 * state. This way, it cannot ever know what the previous state was.
655 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event];
657 /* Call the entry function (if any) for the next state. */
658 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
659 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
662 /* Process any AUTO transitions in the FSM */
663 i2c_adapter_process_auto(i2c_adapter);
665 PIOS_IRQ_Enable();
668 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter)
670 PIOS_IRQ_Disable();
671 while (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO]) {
672 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO];
674 /* Call the entry function (if any) for the next state. */
675 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
676 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
680 PIOS_IRQ_Enable();
683 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter)
685 i2c_adapter_reset_bus(i2c_adapter);
686 i2c_adapter->curr_state = I2C_STATE_STOPPED;
689 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter)
691 uint32_t guard;
694 * Wait for the bus to return to the stopped state.
695 * This was pulled out of the FSM due to occasional
696 * failures at this transition which previously resulted
697 * in spinning on this bit in the ISR forever.
699 #define I2C_CR1_STOP_REQUESTED 0x0200
700 for (guard = 1000000; /* FIXME: should use the configured bus timeout */
701 guard && (i2c_adapter->cfg->regs->CR1 & I2C_CR1_STOP_REQUESTED); guard--) {
702 continue;
704 if (!guard) {
705 /* We timed out waiting for the stop condition */
706 return false;
709 return true;
712 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
714 // retry with wait code from
715 // TauLabs 20150718 - Prevent F3 I2C Init Lockup #1728
716 uint8_t retry_count;
717 uint8_t retry_count_clk;
718 static const uint8_t MAX_I2C_RETRY_COUNT = 10;
720 /* Reset the I2C block */
721 I2C_DeInit(i2c_adapter->cfg->regs);
723 /* Make sure the bus is free by clocking it until any slaves release the bus. */
724 GPIO_InitTypeDef scl_gpio_init;
725 scl_gpio_init = i2c_adapter->cfg->scl.init;
726 scl_gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
727 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
728 GPIO_Init(i2c_adapter->cfg->scl.gpio, &scl_gpio_init);
730 GPIO_InitTypeDef sda_gpio_init;
731 sda_gpio_init = i2c_adapter->cfg->sda.init;
732 sda_gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
733 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
734 GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
736 /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
737 /* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
738 /* ESC */
739 // bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
740 retry_count_clk = 0;
741 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET && (retry_count_clk++ < MAX_I2C_RETRY_COUNT)) {
742 retry_count = 0;
743 /* Set clock high and wait for any clock stretching to finish. */
744 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
745 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
746 PIOS_DELAY_WaituS(1);
748 PIOS_DELAY_WaituS(2);
750 /* Set clock low */
751 GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
752 PIOS_DELAY_WaituS(2);
754 /* Clock high again */
755 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
756 PIOS_DELAY_WaituS(2);
759 /* Generate a start then stop condition */
760 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
761 PIOS_DELAY_WaituS(2);
762 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
763 PIOS_DELAY_WaituS(2);
764 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
765 PIOS_DELAY_WaituS(2);
767 /* Set data and clock high and wait for any clock stretching to finish. */
768 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
769 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
770 retry_count = 0;
771 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
772 PIOS_DELAY_WaituS(1);
774 /* Wait for data to be high */
775 retry_count = 0;
776 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
777 PIOS_DELAY_WaituS(1);
781 /* Bus signals are guaranteed to be high (ie. free) after this point */
782 /* Initialize the GPIO pins to the peripheral function */
783 GPIO_Init(i2c_adapter->cfg->scl.gpio, &(i2c_adapter->cfg->scl.init));
784 GPIO_Init(i2c_adapter->cfg->sda.gpio, &(i2c_adapter->cfg->sda.init));
786 /* Reset the I2C block */
787 I2C_DeInit(i2c_adapter->cfg->regs);
789 /* Initialize the I2C block */
790 I2C_Init(i2c_adapter->cfg->regs, &(i2c_adapter->cfg->init));
792 #define I2C_BUSY 0x20
793 if (i2c_adapter->cfg->regs->SR2 & I2C_BUSY) {
794 /* Reset the I2C block */
795 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, ENABLE);
796 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, DISABLE);
800 #include <pios_i2c_priv.h>
802 /* Return true if the FSM is in a terminal state */
803 static bool i2c_adapter_fsm_terminated(struct pios_i2c_adapter *i2c_adapter)
805 switch (i2c_adapter->curr_state) {
806 case I2C_STATE_STOPPING:
807 case I2C_STATE_STOPPED:
808 return true;
810 default:
811 return false;
816 * Logs the last N state transitions and N IRQ events due to
817 * an error condition
818 * \param[in] i2c the adapter number to log an event for
820 void i2c_adapter_log_fault(enum pios_i2c_error_type type)
822 #if defined(PIOS_I2C_DIAGNOSTICS)
823 i2c_adapter_fault_history.type = type;
824 for (uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
825 i2c_adapter_fault_history.evirq[i] =
826 i2c_evirq_history[(I2C_LOG_DEPTH + i2c_evirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
827 i2c_adapter_fault_history.erirq[i] =
828 i2c_erirq_history[(I2C_LOG_DEPTH + i2c_erirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
829 i2c_adapter_fault_history.event[i] =
830 i2c_state_event_history[(I2C_LOG_DEPTH + i2c_state_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
831 i2c_adapter_fault_history.state[i] =
832 i2c_state_history[(I2C_LOG_DEPTH + i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
834 switch (type) {
835 case PIOS_I2C_ERROR_EVENT:
836 i2c_bad_event_counter++;
837 break;
838 case PIOS_I2C_ERROR_FSM:
839 i2c_fsm_fault_count++;
840 break;
841 case PIOS_I2C_ERROR_INTERRUPT:
842 i2c_error_interrupt_counter++;
843 break;
845 #endif /* if defined(PIOS_I2C_DIAGNOSTICS) */
850 * Logs the last N state transitions and N IRQ events due to
851 * an error condition
852 * \param[out] data address where to copy the pios_i2c_fault_history structure to
853 * \param[out] counts three uint16 that receive the bad event, fsm, and error irq
854 * counts
856 void PIOS_I2C_GetDiagnostics(struct pios_i2c_fault_history *data, uint8_t *counts)
858 #if defined(PIOS_I2C_DIAGNOSTICS)
859 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
860 counts[PIOS_I2C_BAD_EVENT_COUNTER] = i2c_bad_event_counter;
861 counts[PIOS_I2C_FSM_FAULT_COUNT] = i2c_fsm_fault_count;
862 counts[PIOS_I2C_ERROR_INTERRUPT_COUNTER] = i2c_error_interrupt_counter;
863 counts[PIOS_I2C_NACK_COUNTER] = i2c_nack_counter;
864 counts[PIOS_I2C_TIMEOUT_COUNTER] = i2c_timeout_counter;
865 #else
866 struct pios_i2c_fault_history i2c_adapter_fault_history;
867 i2c_adapter_fault_history.type = PIOS_I2C_ERROR_EVENT;
869 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
870 memset(counts, 0, sizeof(*counts) * PIOS_I2C_ERROR_COUNT_NUMELEM);
871 #endif
874 static bool PIOS_I2C_validate(struct pios_i2c_adapter *i2c_adapter)
876 return i2c_adapter->magic == PIOS_I2C_DEV_MAGIC;
879 #if defined(PIOS_INCLUDE_FREERTOS)
880 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
882 struct pios_i2c_adapter *i2c_adapter;
884 i2c_adapter = (struct pios_i2c_adapter *)pios_malloc(sizeof(*i2c_adapter));
885 if (!i2c_adapter) {
886 return NULL;
889 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
890 return i2c_adapter;
892 #else
893 static struct pios_i2c_adapter pios_i2c_adapters[PIOS_I2C_MAX_DEVS];
894 static uint8_t pios_i2c_num_adapters;
895 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
897 struct pios_i2c_adapter *i2c_adapter;
899 if (pios_i2c_num_adapters >= PIOS_I2C_MAX_DEVS) {
900 return NULL;
903 i2c_adapter = &pios_i2c_adapters[pios_i2c_num_adapters++];
904 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
906 return i2c_adapter;
908 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
912 * Initializes IIC driver
913 * \param[in] mode currently only mode 0 supported
914 * \return < 0 if initialisation failed
916 int32_t PIOS_I2C_Init(uint32_t *i2c_id, const struct pios_i2c_adapter_cfg *cfg)
918 PIOS_DEBUG_Assert(i2c_id);
919 PIOS_DEBUG_Assert(cfg);
921 struct pios_i2c_adapter *i2c_adapter;
923 i2c_adapter = (struct pios_i2c_adapter *)PIOS_I2C_alloc();
924 if (!i2c_adapter) {
925 goto out_fail;
928 /* Bind the configuration to the device instance */
929 i2c_adapter->cfg = cfg;
931 #ifdef USE_FREERTOS
933 * Must be done prior to calling i2c_adapter_fsm_init()
934 * since the sem_ready mutex is used in the initial state.
936 vSemaphoreCreateBinary(i2c_adapter->sem_ready);
937 i2c_adapter->sem_busy = xSemaphoreCreateMutex();
938 #endif // USE_FREERTOS
940 /* Enable the associated peripheral clock */
941 switch ((uint32_t)i2c_adapter->cfg->regs) {
942 case (uint32_t)I2C1:
943 /* Enable I2C peripheral clock (APB1 == slow speed) */
944 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
945 break;
946 case (uint32_t)I2C2:
947 /* Enable I2C peripheral clock (APB1 == slow speed) */
948 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
949 break;
952 if (i2c_adapter->cfg->remap) {
953 GPIO_PinRemapConfig(i2c_adapter->cfg->remap, ENABLE);
956 /* Initialize the state machine */
957 i2c_adapter_fsm_init(i2c_adapter);
959 *i2c_id = (uint32_t)i2c_adapter;
961 /* Configure and enable I2C interrupts */
962 NVIC_Init(&(i2c_adapter->cfg->event.init));
963 NVIC_Init(&(i2c_adapter->cfg->error.init));
965 /* No error */
966 return 0;
968 out_fail:
969 return -1;
973 * @brief Perform a series of I2C transactions
974 * @returns 0 if success or error code
975 * @retval -1 for failed transaction
976 * @retval -2 for failure to get semaphore
978 int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
980 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
982 if (!PIOS_I2C_validate(i2c_adapter)) {
983 return PIOS_I2C_TRANSFER_DEVICE_ERROR;
986 PIOS_DEBUG_Assert(txn_list);
987 PIOS_DEBUG_Assert(num_txns);
989 bool semaphore_success = true;
991 #ifdef USE_FREERTOS
992 /* Lock the bus */
993 portTickType timeout;
994 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
995 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
996 return PIOS_I2C_TRANSFER_BUSY;
998 #else
999 #error PIOS_I2C_Transfer is broken for use without FreeRTOS
1000 uint32_t timeout = 0xfff;
1001 while (i2c_adapter->busy && --timeout) {
1004 if (timeout == 0) { // timed out
1005 return false;
1008 PIOS_IRQ_Disable();
1009 if (i2c_adapter->busy) {
1010 return false;
1012 i2c_adapter->busy = 1;
1013 PIOS_IRQ_Enable();
1014 #endif /* USE_FREERTOS */
1016 PIOS_DEBUG_Assert(i2c_adapter->curr_state == I2C_STATE_STOPPED);
1018 i2c_adapter->first_txn = &txn_list[0];
1019 i2c_adapter->last_txn = &txn_list[num_txns - 1];
1020 i2c_adapter->active_txn = i2c_adapter->first_txn;
1022 #ifdef USE_FREERTOS
1023 /* Make sure the done/ready semaphore is consumed before we start */
1024 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1025 #endif
1027 // Estimate bytes of transmission. Per txns: 1 adress byte + length
1028 i2c_adapter->transfer_timeout_ticks = num_txns;
1029 for (uint32_t i = 0; i < num_txns; i++) {
1030 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
1032 // timeout if it takes eight times the expected time
1033 i2c_adapter->transfer_timeout_ticks <<= 3;
1035 i2c_adapter->bus_error = false;
1036 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
1038 /* Wait for the transfer to complete */
1039 #ifdef USE_FREERTOS
1040 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1041 xSemaphoreGive(i2c_adapter->sem_ready);
1042 #else
1043 PIOS_IRQ_Disable();
1044 i2c_adapter->busy = 0;
1045 PIOS_IRQ_Enable();
1046 #endif /* USE_FREERTOS */
1048 /* Spin waiting for the transfer to finish */
1049 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
1050 /* sleep 9 clock ticks (1 byte), because FSM can't be faster than one byte
1051 FIXME: clock streching could make problems, but citing NPX: alsmost no slave device implements clock stretching
1052 three times the expected time should cover clock delay */
1053 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
1055 i2c_adapter->transfer_timeout_ticks--;
1056 if (i2c_adapter->transfer_timeout_ticks == 0) {
1057 break;
1061 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
1062 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
1063 } else {
1064 i2c_adapter_fsm_init(i2c_adapter);
1067 #ifdef USE_FREERTOS
1068 /* Unlock the bus */
1069 xSemaphoreGive(i2c_adapter->sem_busy);
1070 if (!semaphore_success) {
1071 i2c_timeout_counter++;
1073 #endif /* USE_FREERTOS */
1075 return !semaphore_success ? PIOS_I2C_TRANSFER_TIMEOUT :
1076 i2c_adapter->bus_error ? PIOS_I2C_TRANSFER_BUS_ERROR :
1077 PIOS_I2C_TRANSFER_OK;
1081 void PIOS_I2C_EV_IRQ_Handler(uint32_t i2c_id)
1083 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1085 if (!PIOS_I2C_validate(i2c_adapter)) {
1086 return;
1089 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1091 #if defined(PIOS_I2C_DIAGNOSTICS)
1092 /* Store event for diagnostics */
1093 i2c_evirq_history[i2c_evirq_history_pointer] = event;
1094 i2c_evirq_history_pointer = (i2c_evirq_history_pointer + 1) % I2C_LOG_DEPTH;
1095 #endif
1097 #define EVENT_MASK 0x000700FF
1098 event &= EVENT_MASK;
1101 switch (event) { /* Mask out all the bits we don't care about */
1102 case (I2C_EVENT_MASTER_MODE_SELECT | 0x40):
1103 /* Unexplained event: EV5 + RxNE : Extraneous Rx. Probably a late NACK from previous read. */
1104 /* Clean up the extra Rx until the root cause is identified and just keep going */
1105 (void)I2C_ReceiveData(i2c_adapter->cfg->regs);
1106 /* Fall through */
1107 case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
1108 switch (i2c_adapter->active_txn->rw) {
1109 case PIOS_I2C_TXN_READ:
1110 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1111 /* Final transaction */
1112 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_READ);
1113 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1114 /* More transactions follow */
1115 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_READ);
1116 } else {
1117 PIOS_DEBUG_Assert(0);
1119 break;
1120 case PIOS_I2C_TXN_WRITE:
1121 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1122 /* Final transaction */
1123 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_WRITE);
1124 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1125 /* More transactions follow */
1126 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_WRITE);
1127 } else {
1128 PIOS_DEBUG_Assert(0);
1130 break;
1131 default:
1132 PIOS_DEBUG_Assert(0);
1133 break;
1135 break;
1136 case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
1137 case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
1138 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1139 case 0:
1140 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_0);
1141 break;
1142 case 1:
1143 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_1);
1144 break;
1145 case 2:
1146 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_2);
1147 break;
1148 default:
1149 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_GT_2);
1150 break;
1152 break;
1153 case 0x80: /* TxE only. TRA + MSL + BUSY have been cleared before we got here. */
1154 /* Ignore */
1156 static volatile bool halt = FALSE;
1157 while (halt) {
1161 break;
1162 case 0: /* This triggers an FSM fault sometimes, but not having it stops things working */
1163 case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */
1164 case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */
1165 case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
1166 case (I2C_EVENT_MASTER_BYTE_RECEIVED | 0x4): /* EV7 + BTF */
1167 case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
1168 case 0x84: /* TxE + BTF. EV8_2 but TRA + MSL + BUSY have already been cleared by HW. */
1169 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1170 case 0:
1171 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0);
1172 break;
1173 case 1:
1174 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1);
1175 break;
1176 case 2:
1177 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2);
1178 break;
1179 default:
1180 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2);
1181 break;
1183 break;
1184 case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
1185 /* Ignore this event and wait for TRANSMITTED in case we can't keep up */
1186 goto skip_event;
1187 break;
1188 case 0x30084: /* Occurs between byte tranmistted and master mode selected */
1189 case 0x30000: /* Need to throw away this spurious event */
1190 case 0x30403 & EVENT_MASK: /* Detected this after got a NACK, probably stop bit */
1191 goto skip_event;
1192 break;
1193 default:
1194 i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT);
1195 #if defined(I2C_HALT_ON_ERRORS)
1196 PIOS_DEBUG_Assert(0);
1197 #endif
1198 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1199 break;
1202 skip_event:
1207 void PIOS_I2C_ER_IRQ_Handler(uint32_t i2c_id)
1209 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1211 if (!PIOS_I2C_validate(i2c_adapter)) {
1212 return;
1216 #if defined(PIOS_I2C_DIAGNOSTICS)
1217 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1219 i2c_erirq_history[i2c_erirq_history_pointer] = event;
1220 i2c_erirq_history_pointer = (i2c_erirq_history_pointer + 1) % 5;
1222 #endif
1224 if (event & I2C_FLAG_AF) {
1225 i2c_nack_counter++;
1227 I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_AF);
1229 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
1230 } else { /* Mostly bus errors here */
1231 i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
1233 /* Fail hard on any errors for now */
1234 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1238 #endif /* PIOS_INCLUDE_I2C */
1241 * @}
1242 * @}