LP-602 significant change to USB layer. force complete USB stack reset on replug...
[librepilot.git] / flight / pios / stm32f4xx / pios_i2c.c
blob92bb65bc59cc3612e9ea7e215e8c1486aad61222
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_I2C I2C Functions
6 * @brief STM32F4xx Hardware dependent I2C functionality
7 * @{
9 * @file pios_i2c.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
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
32 * @note This is very closely related to the F1xx code and should really
33 * be merged.
36 #include "pios.h"
38 #ifdef PIOS_INCLUDE_I2C
40 #ifdef PIOS_INCLUDE_FREERTOS
41 #define USE_FREERTOS
42 #endif
44 #include <pios_i2c_priv.h>
46 enum i2c_adapter_state {
47 I2C_STATE_FSM_FAULT = 0, /* Must be zero so undefined transitions land here */
49 I2C_STATE_BUS_ERROR,
51 I2C_STATE_STOPPED,
52 I2C_STATE_STOPPING,
53 I2C_STATE_STARTING,
55 I2C_STATE_R_MORE_TXN_ADDR,
56 I2C_STATE_R_MORE_TXN_PRE_ONE,
57 I2C_STATE_R_MORE_TXN_PRE_FIRST,
58 I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
59 I2C_STATE_R_MORE_TXN_PRE_LAST,
60 I2C_STATE_R_MORE_TXN_POST_LAST,
62 I2C_STATE_R_LAST_TXN_ADDR,
63 I2C_STATE_R_LAST_TXN_PRE_ONE,
64 I2C_STATE_R_LAST_TXN_PRE_FIRST,
65 I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
66 I2C_STATE_R_LAST_TXN_PRE_LAST,
67 I2C_STATE_R_LAST_TXN_POST_LAST,
69 I2C_STATE_W_MORE_TXN_ADDR,
70 I2C_STATE_W_MORE_TXN_MIDDLE,
71 I2C_STATE_W_MORE_TXN_LAST,
73 I2C_STATE_W_LAST_TXN_ADDR,
74 I2C_STATE_W_LAST_TXN_MIDDLE,
75 I2C_STATE_W_LAST_TXN_LAST,
77 I2C_STATE_NACK,
79 I2C_STATE_NUM_STATES /* Must be last */
82 // #define I2C_HALT_ON_ERRORS
84 enum i2c_adapter_event {
85 I2C_EVENT_BUS_ERROR,
86 I2C_EVENT_START,
87 I2C_EVENT_STARTED_MORE_TXN_READ,
88 I2C_EVENT_STARTED_MORE_TXN_WRITE,
89 I2C_EVENT_STARTED_LAST_TXN_READ,
90 I2C_EVENT_STARTED_LAST_TXN_WRITE,
91 I2C_EVENT_ADDR_SENT_LEN_EQ_0,
92 I2C_EVENT_ADDR_SENT_LEN_EQ_1,
93 I2C_EVENT_ADDR_SENT_LEN_EQ_2,
94 I2C_EVENT_ADDR_SENT_LEN_GT_2,
95 I2C_EVENT_TRANSFER_DONE_LEN_EQ_0,
96 I2C_EVENT_TRANSFER_DONE_LEN_EQ_1,
97 I2C_EVENT_TRANSFER_DONE_LEN_EQ_2,
98 I2C_EVENT_TRANSFER_DONE_LEN_GT_2,
99 I2C_EVENT_NACK,
100 I2C_EVENT_STOPPED,
101 I2C_EVENT_AUTO, /* FIXME: remove this */
103 I2C_EVENT_NUM_EVENTS /* Must be last */
106 #if defined(PIOS_I2C_DIAGNOSTICS)
107 static struct pios_i2c_fault_history i2c_adapter_fault_history;
109 volatile uint32_t i2c_evirq_history[I2C_LOG_DEPTH];
110 volatile uint8_t i2c_evirq_history_pointer = 0;
112 volatile uint32_t i2c_erirq_history[I2C_LOG_DEPTH];
113 volatile uint8_t i2c_erirq_history_pointer = 0;
115 volatile enum i2c_adapter_state i2c_state_history[I2C_LOG_DEPTH];
116 volatile uint8_t i2c_state_history_pointer = 0;
118 volatile enum i2c_adapter_event i2c_state_event_history[I2C_LOG_DEPTH];
119 volatile uint8_t i2c_state_event_history_pointer;
121 static uint8_t i2c_fsm_fault_count = 0;
122 static uint8_t i2c_bad_event_counter = 0;
123 static uint8_t i2c_error_interrupt_counter = 0;
124 static uint8_t i2c_nack_counter = 0;
125 static uint8_t i2c_timeout_counter = 0;
126 #endif
128 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter);
129 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter);
130 static void go_stopping(struct pios_i2c_adapter *i2c_adapter);
131 static void go_stopped(struct pios_i2c_adapter *i2c_adapter);
132 static void go_starting(struct pios_i2c_adapter *i2c_adapter);
134 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
135 static void go_r_more_txn_pre_one(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_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter);
141 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter);
143 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
144 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
145 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter);
146 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter);
148 static void go_nack(struct pios_i2c_adapter *i2c_adapter);
150 struct i2c_adapter_transition {
151 void (*entry_fn)(struct pios_i2c_adapter *i2c_adapter);
152 enum i2c_adapter_state next_state[I2C_EVENT_NUM_EVENTS];
155 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter);
156 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event);
157 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter);
158 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter);
159 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter);
161 static void i2c_adapter_log_fault(enum pios_i2c_error_type type);
162 static bool i2c_adapter_callback_handler(struct pios_i2c_adapter *i2c_adapter, signed portBASE_TYPE *pxHigherPriorityTaskWoken);
164 static const struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
165 [I2C_STATE_FSM_FAULT] = {
166 .entry_fn = go_fsm_fault,
167 .next_state = {
168 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
171 [I2C_STATE_BUS_ERROR] = {
172 .entry_fn = go_bus_error,
173 .next_state = {
174 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
178 [I2C_STATE_STOPPED] = {
179 .entry_fn = go_stopped,
180 .next_state = {
181 [I2C_EVENT_START] = I2C_STATE_STARTING,
182 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
186 [I2C_STATE_STOPPING] = {
187 .entry_fn = go_stopping,
188 .next_state = {
189 [I2C_EVENT_STOPPED] = I2C_STATE_STOPPED,
190 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
194 [I2C_STATE_STARTING] = {
195 .entry_fn = go_starting,
196 .next_state = {
197 [I2C_EVENT_STARTED_MORE_TXN_READ] = I2C_STATE_R_MORE_TXN_ADDR,
198 [I2C_EVENT_STARTED_MORE_TXN_WRITE] = I2C_STATE_W_MORE_TXN_ADDR,
199 [I2C_EVENT_STARTED_LAST_TXN_READ] = I2C_STATE_R_LAST_TXN_ADDR,
200 [I2C_EVENT_STARTED_LAST_TXN_WRITE] = I2C_STATE_W_LAST_TXN_ADDR,
201 [I2C_EVENT_NACK] = I2C_STATE_NACK,
202 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
207 * Read with restart
210 [I2C_STATE_R_MORE_TXN_ADDR] = {
211 .entry_fn = go_r_any_txn_addr,
212 .next_state = {
213 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_PRE_ONE,
214 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
215 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
216 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
220 [I2C_STATE_R_MORE_TXN_PRE_ONE] = {
221 .entry_fn = go_r_more_txn_pre_one,
222 .next_state = {
223 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
224 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
228 [I2C_STATE_R_MORE_TXN_PRE_FIRST] = {
229 .entry_fn = go_r_any_txn_pre_first,
230 .next_state = {
231 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
232 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
233 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
237 [I2C_STATE_R_MORE_TXN_PRE_MIDDLE] = {
238 .entry_fn = go_r_any_txn_pre_middle,
239 .next_state = {
240 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
241 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
242 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
246 [I2C_STATE_R_MORE_TXN_PRE_LAST] = {
247 .entry_fn = go_r_more_txn_pre_last,
248 .next_state = {
249 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
250 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
254 [I2C_STATE_R_MORE_TXN_POST_LAST] = {
255 .entry_fn = go_r_any_txn_post_last,
256 .next_state = {
257 [I2C_EVENT_AUTO] = I2C_STATE_STARTING,
262 * Read
265 [I2C_STATE_R_LAST_TXN_ADDR] = {
266 .entry_fn = go_r_any_txn_addr,
267 .next_state = {
268 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_PRE_ONE,
269 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
270 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
271 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
275 [I2C_STATE_R_LAST_TXN_PRE_ONE] = {
276 .entry_fn = go_r_last_txn_pre_one,
277 .next_state = {
278 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
279 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
283 [I2C_STATE_R_LAST_TXN_PRE_FIRST] = {
284 .entry_fn = go_r_any_txn_pre_first,
285 .next_state = {
286 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
287 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
288 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
292 [I2C_STATE_R_LAST_TXN_PRE_MIDDLE] = {
293 .entry_fn = go_r_any_txn_pre_middle,
294 .next_state = {
295 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
296 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
297 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
301 [I2C_STATE_R_LAST_TXN_PRE_LAST] = {
302 .entry_fn = go_r_last_txn_pre_last,
303 .next_state = {
304 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
305 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
309 [I2C_STATE_R_LAST_TXN_POST_LAST] = {
310 .entry_fn = go_r_any_txn_post_last,
311 .next_state = {
312 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
317 * Write with restart
320 [I2C_STATE_W_MORE_TXN_ADDR] = {
321 .entry_fn = go_w_any_txn_addr,
322 .next_state = {
323 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
324 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
325 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
326 [I2C_EVENT_NACK] = I2C_STATE_NACK,
327 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
331 [I2C_STATE_W_MORE_TXN_MIDDLE] = {
332 .entry_fn = go_w_any_txn_middle,
333 .next_state = {
334 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
335 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
336 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
337 [I2C_EVENT_NACK] = I2C_STATE_NACK,
338 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
342 [I2C_STATE_W_MORE_TXN_LAST] = {
343 .entry_fn = go_w_more_txn_last,
344 .next_state = {
345 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STARTING,
346 [I2C_EVENT_NACK] = I2C_STATE_NACK,
347 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
352 * Write
355 [I2C_STATE_W_LAST_TXN_ADDR] = {
356 .entry_fn = go_w_any_txn_addr,
357 .next_state = {
358 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
359 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
360 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
361 [I2C_EVENT_NACK] = I2C_STATE_NACK,
362 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
366 [I2C_STATE_W_LAST_TXN_MIDDLE] = {
367 .entry_fn = go_w_any_txn_middle,
368 .next_state = {
369 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
370 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
371 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
372 [I2C_EVENT_NACK] = I2C_STATE_NACK,
373 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
377 [I2C_STATE_W_LAST_TXN_LAST] = {
378 .entry_fn = go_w_last_txn_last,
379 .next_state = {
380 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STOPPING,
381 [I2C_EVENT_NACK] = I2C_STATE_NACK,
382 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
385 [I2C_STATE_NACK] = {
386 .entry_fn = go_nack,
387 .next_state = {
388 [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);
406 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter)
408 /* Note that this transfer has hit a bus error */
409 i2c_adapter->bus_error = true;
411 i2c_adapter_reset_bus(i2c_adapter);
415 static void go_stopping(struct pios_i2c_adapter *i2c_adapter)
417 #ifdef USE_FREERTOS
418 signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
419 #endif
421 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
423 if (i2c_adapter->callback) {
424 i2c_adapter_callback_handler(i2c_adapter, &pxHigherPriorityTaskWoken);
425 } else {
426 #ifdef USE_FREERTOS
427 if (xSemaphoreGiveFromISR(i2c_adapter->sem_ready, &pxHigherPriorityTaskWoken) != pdTRUE) {
428 #if defined(I2C_HALT_ON_ERRORS)
429 PIOS_DEBUG_Assert(0);
430 #endif
432 #endif /* USE_FREERTOS */
435 portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
439 static void go_stopped(struct pios_i2c_adapter *i2c_adapter)
441 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
442 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
446 static void go_starting(struct pios_i2c_adapter *i2c_adapter)
448 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
449 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
450 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
452 // check for an empty read/write
453 if (i2c_adapter->active_txn->buf != NULL && i2c_adapter->active_txn->len != 0) {
454 // Data available
455 i2c_adapter->active_byte = &(i2c_adapter->active_txn->buf[0]);
456 i2c_adapter->last_byte = &(i2c_adapter->active_txn->buf[i2c_adapter->active_txn->len - 1]);
457 } else {
458 // No Data available => Empty read/write
459 i2c_adapter->last_byte = NULL;
460 i2c_adapter->active_byte = i2c_adapter->last_byte + 1;
463 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
464 if (i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ) {
465 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
466 } else {
467 // For write operations, do not enable the IT_BUF events.
468 // The current driver does not act when the TX data register is not full, only when the complete byte is sent.
469 // With the IT_BUF enabled, we constantly get IRQs, See OP-326
470 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_ERR, ENABLE);
475 /* Common to 'more' and 'last' transaction */
476 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
478 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
479 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
480 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
482 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ);
484 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Receiver);
488 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
490 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
491 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
495 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
497 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
498 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
502 /* Common to 'more' and 'last' transaction */
503 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter)
505 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
509 /* Common to 'more' and 'last' transaction */
510 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter)
512 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
513 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
515 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
517 /* Move to the next byte */
518 i2c_adapter->active_byte++;
519 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
523 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
525 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
526 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
528 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
529 PIOS_IRQ_Disable();
530 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
531 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
532 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
533 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
534 PIOS_IRQ_Enable();
536 /* Move to the next byte */
537 i2c_adapter->active_byte++;
538 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
542 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
544 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
545 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
547 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
548 PIOS_IRQ_Disable();
549 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
550 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
551 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
552 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
553 PIOS_IRQ_Enable();
555 /* Move to the next byte */
556 i2c_adapter->active_byte++;
557 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
561 /* Common to 'more' and 'last' transaction */
562 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter)
564 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
565 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
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 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
572 /* Move to the next byte */
573 i2c_adapter->active_byte++;
575 /* Move to the next transaction */
576 i2c_adapter->active_txn++;
580 /* Common to 'more' and 'last' transaction */
581 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
583 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
584 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
585 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
587 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE);
589 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Transmitter);
593 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter)
595 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
596 PIOS_DEBUG_Assert(i2c_adapter->active_byte < i2c_adapter->last_byte);
597 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
598 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
599 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
601 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
603 /* Move to the next byte */
604 i2c_adapter->active_byte++;
605 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
609 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter)
611 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
612 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
613 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
614 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
615 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
617 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
619 /* Move to the next byte */
620 i2c_adapter->active_byte++;
622 /* Move to the next transaction */
623 i2c_adapter->active_txn++;
624 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
628 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter)
630 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
631 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
632 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
633 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
634 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
636 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
637 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
639 // SHOULD MOVE THIS INTO A STOPPING STATE AND SET IT ONLY AFTER THE BYTE WAS SENT
640 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
642 /* Move to the next byte */
643 i2c_adapter->active_byte++;
647 static void go_nack(struct pios_i2c_adapter *i2c_adapter)
649 i2c_adapter->nack = true;
650 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
651 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
652 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
656 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event)
658 PIOS_IRQ_Disable();
660 #if defined(PIOS_I2C_DIAGNOSTICS)
661 i2c_state_event_history[i2c_state_event_history_pointer] = event;
662 i2c_state_event_history_pointer = (i2c_state_event_history_pointer + 1) % I2C_LOG_DEPTH;
664 i2c_state_history[i2c_state_history_pointer] = i2c_adapter->curr_state;
665 i2c_state_history_pointer = (i2c_state_history_pointer + 1) % I2C_LOG_DEPTH;
667 if (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event] == I2C_STATE_FSM_FAULT) {
668 i2c_adapter_log_fault(PIOS_I2C_ERROR_FSM);
670 #endif
672 * Move to the next state
674 * This is done prior to calling the new state's entry function to
675 * guarantee that the entry function never depends on the previous
676 * state. This way, it cannot ever know what the previous state was.
678 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event];
680 /* Call the entry function (if any) for the next state. */
681 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
682 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
685 /* Process any AUTO transitions in the FSM */
686 i2c_adapter_process_auto(i2c_adapter);
688 PIOS_IRQ_Enable();
692 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter)
694 PIOS_IRQ_Disable();
696 while (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO]) {
697 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO];
699 /* Call the entry function (if any) for the next state. */
700 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
701 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
705 PIOS_IRQ_Enable();
709 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter)
711 i2c_adapter_reset_bus(i2c_adapter);
712 i2c_adapter->curr_state = I2C_STATE_STOPPED;
716 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter)
718 uint32_t guard;
721 * Wait for the bus to return to the stopped state.
722 * This was pulled out of the FSM due to occasional
723 * failures at this transition which previously resulted
724 * in spinning on this bit in the ISR forever.
726 for (guard = 1000000; /* FIXME: should use the configured bus timeout */
727 guard && (i2c_adapter->cfg->regs->CR1 & I2C_CR1_STOP); guard--) {
728 continue;
730 if (!guard) {
731 /* We timed out waiting for the stop condition */
732 return false;
735 return true;
739 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
741 // retry with wait code from
742 // TauLabs 20150718 - Prevent F3 I2C Init Lockup #1728
743 uint8_t retry_count;
744 uint8_t retry_count_clk;
745 static const uint8_t MAX_I2C_RETRY_COUNT = 10;
747 /* Reset the I2C block */
748 I2C_DeInit(i2c_adapter->cfg->regs);
750 /* Make sure the bus is free by clocking it until any slaves release the bus. */
751 GPIO_InitTypeDef scl_gpio_init;
752 scl_gpio_init = i2c_adapter->cfg->scl.init;
753 scl_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
754 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
755 GPIO_Init(i2c_adapter->cfg->scl.gpio, &scl_gpio_init);
757 GPIO_InitTypeDef sda_gpio_init;
758 sda_gpio_init = i2c_adapter->cfg->sda.init;
759 sda_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
760 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
761 GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
763 /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
764 /* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
765 /* ESC */
766 // bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
767 retry_count_clk = 0;
768 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET && (retry_count_clk++ < MAX_I2C_RETRY_COUNT)) {
769 retry_count = 0;
770 /* Set clock high and wait for any clock stretching to finish. */
771 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
772 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
773 PIOS_DELAY_WaituS(1);
775 PIOS_DELAY_WaituS(2);
777 /* Set clock low */
778 GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
779 PIOS_DELAY_WaituS(2);
781 /* Clock high again */
782 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
783 PIOS_DELAY_WaituS(2);
786 /* Generate a start then stop condition */
787 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
788 PIOS_DELAY_WaituS(2);
789 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
790 PIOS_DELAY_WaituS(2);
791 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
792 PIOS_DELAY_WaituS(2);
794 /* Set data and clock high and wait for any clock stretching to finish. */
795 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
796 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
797 retry_count = 0;
798 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
799 PIOS_DELAY_WaituS(1);
801 /* Wait for data to be high */
802 retry_count = 0;
803 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET && (retry_count++ < MAX_I2C_RETRY_COUNT)) {
804 PIOS_DELAY_WaituS(1);
808 /* Bus signals are guaranteed to be high (ie. free) after this point */
809 /* Initialize the GPIO pins to the peripheral function */
810 if (i2c_adapter->cfg->remapSCL) {
811 GPIO_PinAFConfig(i2c_adapter->cfg->scl.gpio,
812 __builtin_ctz(i2c_adapter->cfg->scl.init.GPIO_Pin),
813 i2c_adapter->cfg->remapSCL);
815 if (i2c_adapter->cfg->remapSDA) {
816 GPIO_PinAFConfig(i2c_adapter->cfg->sda.gpio,
817 __builtin_ctz(i2c_adapter->cfg->sda.init.GPIO_Pin),
818 i2c_adapter->cfg->remapSDA);
820 GPIO_Init(i2c_adapter->cfg->scl.gpio, (GPIO_InitTypeDef *)&(i2c_adapter->cfg->scl.init)); // Struct is const, function signature not
821 GPIO_Init(i2c_adapter->cfg->sda.gpio, (GPIO_InitTypeDef *)&(i2c_adapter->cfg->sda.init));
823 /* Reset the I2C block */
824 I2C_DeInit(i2c_adapter->cfg->regs);
826 /* Initialize the I2C block */
827 I2C_Init(i2c_adapter->cfg->regs, (I2C_InitTypeDef *)&(i2c_adapter->cfg->init));
829 // for delays during transfer timeouts
830 // one tick correspond to transmission of 1 byte i.e. 9 clock ticks
831 i2c_adapter->transfer_delay_uS = 9000000 / (((I2C_InitTypeDef *)&(i2c_adapter->cfg->init))->I2C_ClockSpeed);
834 if (i2c_adapter->cfg->regs->SR2 & I2C_FLAG_BUSY) {
835 /* Reset the I2C block */
836 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, ENABLE);
837 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, DISABLE);
842 /* Return true if the FSM is in a terminal state */
843 static bool i2c_adapter_fsm_terminated(struct pios_i2c_adapter *i2c_adapter)
845 switch (i2c_adapter->curr_state) {
846 case I2C_STATE_STOPPING:
847 case I2C_STATE_STOPPED:
848 return true;
850 default:
851 return false;
856 uint32_t i2c_cb_count = 0;
857 static bool i2c_adapter_callback_handler(struct pios_i2c_adapter *i2c_adapter, signed portBASE_TYPE *pxHigherPriorityTaskWoken)
859 /* transfer_timeout_ticks is set by PIOS_I2C_Transfer_Callback */
860 /* Spin waiting for the transfer to finish */
861 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
862 // sleep 1 byte, as FSM can't be faster
863 // FIXME: clock stretching could make problems, but citing NPX: alsmost no slave device implements clock stretching
864 // three times the expected time should cover clock delay
865 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
867 i2c_adapter->transfer_timeout_ticks--;
868 if (i2c_adapter->transfer_timeout_ticks == 0) {
869 break;
873 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
874 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
875 } else {
876 i2c_adapter_fsm_init(i2c_adapter);
879 #ifdef USE_FREERTOS
880 /* Unlock the bus */
881 xSemaphoreGiveFromISR(i2c_adapter->sem_busy, pxHigherPriorityTaskWoken);
883 #else
884 PIOS_IRQ_Disable();
885 i2c_adapter->busy = 0;
886 PIOS_IRQ_Enable();
887 #endif /* USE_FREERTOS */
890 // Execute user supplied function
891 if (i2c_adapter->callback(PIOS_I2C_TRANSFER_OK)) {
892 *pxHigherPriorityTaskWoken = pdTRUE;
895 i2c_cb_count++;
897 return !i2c_adapter->bus_error;
902 * Logs the last N state transitions and N IRQ events due to
903 * an error condition
904 * \param[in] i2c the adapter number to log an event for
906 void i2c_adapter_log_fault(enum pios_i2c_error_type type)
908 #if defined(PIOS_I2C_DIAGNOSTICS)
909 i2c_adapter_fault_history.type = type;
910 for (uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
911 i2c_adapter_fault_history.evirq[i] =
912 i2c_evirq_history[(I2C_LOG_DEPTH + i2c_evirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
913 i2c_adapter_fault_history.erirq[i] =
914 i2c_erirq_history[(I2C_LOG_DEPTH + i2c_erirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
915 i2c_adapter_fault_history.event[i] =
916 i2c_state_event_history[(I2C_LOG_DEPTH + i2c_state_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
917 i2c_adapter_fault_history.state[i] =
918 i2c_state_history[(I2C_LOG_DEPTH + i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
920 switch (type) {
921 case PIOS_I2C_ERROR_EVENT:
922 i2c_bad_event_counter++;
923 break;
924 case PIOS_I2C_ERROR_FSM:
925 i2c_fsm_fault_count++;
926 break;
927 case PIOS_I2C_ERROR_INTERRUPT:
928 i2c_error_interrupt_counter++;
929 break;
931 #endif /* if defined(PIOS_I2C_DIAGNOSTICS) */
936 * Logs the last N state transitions and N IRQ events due to
937 * an error condition
938 * \param[out] data address where to copy the pios_i2c_fault_history structure to
939 * \param[out] counts three uint16 that receive the bad event, fsm, and error irq
940 * counts
942 void PIOS_I2C_GetDiagnostics(struct pios_i2c_fault_history *data, uint8_t *counts)
944 #if defined(PIOS_I2C_DIAGNOSTICS)
945 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
946 counts[PIOS_I2C_BAD_EVENT_COUNTER] = i2c_bad_event_counter;
947 counts[PIOS_I2C_FSM_FAULT_COUNT] = i2c_fsm_fault_count;
948 counts[PIOS_I2C_ERROR_INTERRUPT_COUNTER] = i2c_error_interrupt_counter;
949 counts[PIOS_I2C_NACK_COUNTER] = i2c_nack_counter;
950 counts[PIOS_I2C_TIMEOUT_COUNTER] = i2c_timeout_counter;
951 #else
952 struct pios_i2c_fault_history i2c_adapter_fault_history;
953 i2c_adapter_fault_history.type = PIOS_I2C_ERROR_EVENT;
955 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
956 memset(counts, 0, sizeof(*counts) * PIOS_I2C_ERROR_COUNT_NUMELEM);
957 #endif
960 static bool PIOS_I2C_validate(struct pios_i2c_adapter *i2c_adapter)
962 return i2c_adapter->magic == PIOS_I2C_DEV_MAGIC;
966 #if defined(PIOS_INCLUDE_FREERTOS) && 0
967 static struct pios_i2c_dev *PIOS_I2C_alloc(void)
969 struct pios_i2c_dev *i2c_adapter;
971 i2c_adapter = (struct pios_i2c_adapter *)pios_malloc(sizeof(*i2c_adapter));
972 if (!i2c_adapter) {
973 return NULL;
976 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
977 return i2c_adapter;
979 #else
980 static struct pios_i2c_adapter pios_i2c_adapters[PIOS_I2C_MAX_DEVS];
981 static uint8_t pios_i2c_num_adapters;
982 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
984 struct pios_i2c_adapter *i2c_adapter;
986 if (pios_i2c_num_adapters >= PIOS_I2C_MAX_DEVS) {
987 return NULL;
990 i2c_adapter = &pios_i2c_adapters[pios_i2c_num_adapters++];
991 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
993 return i2c_adapter;
995 #endif /* if defined(PIOS_INCLUDE_FREERTOS) && 0 */
999 * Initializes IIC driver
1000 * \param[in] mode currently only mode 0 supported
1001 * \return < 0 if initialisation failed
1003 int32_t PIOS_I2C_Init(uint32_t *i2c_id, const struct pios_i2c_adapter_cfg *cfg)
1005 PIOS_DEBUG_Assert(i2c_id);
1006 PIOS_DEBUG_Assert(cfg);
1008 struct pios_i2c_adapter *i2c_adapter;
1010 i2c_adapter = (struct pios_i2c_adapter *)PIOS_I2C_alloc();
1011 if (!i2c_adapter) {
1012 goto out_fail;
1015 /* Bind the configuration to the device instance */
1016 i2c_adapter->cfg = cfg;
1018 #ifdef USE_FREERTOS
1020 * Must be done prior to calling i2c_adapter_fsm_init()
1021 * since the sem_ready mutex is used in the initial state.
1023 vSemaphoreCreateBinary(i2c_adapter->sem_ready);
1024 i2c_adapter->sem_busy = xSemaphoreCreateMutex();
1025 #else
1026 i2c_adapter->busy = 0;
1027 #endif // USE_FREERTOS
1029 /* Initialize the state machine */
1030 i2c_adapter_fsm_init(i2c_adapter);
1032 *i2c_id = (uint32_t)i2c_adapter;
1034 /* Configure and enable I2C interrupts */
1035 NVIC_Init((NVIC_InitTypeDef *)&(i2c_adapter->cfg->event.init));
1036 NVIC_Init((NVIC_InitTypeDef *)&(i2c_adapter->cfg->error.init));
1039 /* No error */
1040 return 0;
1042 out_fail:
1043 return -1;
1046 int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
1048 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1050 if (!PIOS_I2C_validate(i2c_adapter)) {
1051 return PIOS_I2C_TRANSFER_DEVICE_ERROR;
1054 PIOS_DEBUG_Assert(txn_list);
1055 PIOS_DEBUG_Assert(num_txns);
1057 bool semaphore_success = true;
1059 #ifdef USE_FREERTOS
1060 /* Lock the bus */
1061 portTickType timeout;
1062 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
1063 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
1064 return PIOS_I2C_TRANSFER_BUSY;
1066 #else
1067 PIOS_IRQ_Disable();
1068 if (i2c_adapter->busy) {
1069 PIOS_IRQ_Enable();
1070 return PIOS_I2C_TRANSFER_BUSY;
1072 i2c_adapter->busy = 1;
1073 PIOS_IRQ_Enable();
1074 #endif /* USE_FREERTOS */
1076 PIOS_DEBUG_Assert(i2c_adapter->curr_state == I2C_STATE_STOPPED);
1078 i2c_adapter->first_txn = &txn_list[0];
1079 i2c_adapter->last_txn = &txn_list[num_txns - 1];
1080 i2c_adapter->active_txn = i2c_adapter->first_txn;
1082 #ifdef USE_FREERTOS
1083 /* Make sure the done/ready semaphore is consumed before we start */
1084 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1085 #endif
1087 // Estimate bytes of transmission. Per txns: 1 adress byte + length
1088 i2c_adapter->transfer_timeout_ticks = num_txns;
1089 for (uint32_t i = 0; i < num_txns; i++) {
1090 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
1092 // timeout if it takes eight times the expected time
1093 i2c_adapter->transfer_timeout_ticks <<= 3;
1095 i2c_adapter->callback = NULL;
1096 i2c_adapter->bus_error = false;
1097 i2c_adapter->nack = false;
1098 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
1100 /* Wait for the transfer to complete */
1101 #ifdef USE_FREERTOS
1102 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1103 xSemaphoreGive(i2c_adapter->sem_ready);
1104 #endif /* USE_FREERTOS */
1106 /* Spin waiting for the transfer to finish */
1107 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
1108 /* sleep 9 clock ticks (1 byte), because FSM can't be faster than one byte
1109 FIXME: clock stretching could make problems, but citing NPX: alsmost no slave device implements clock stretching
1110 three times the expected time should cover clock delay */
1111 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
1113 i2c_adapter->transfer_timeout_ticks--;
1114 if (i2c_adapter->transfer_timeout_ticks == 0) {
1115 break;
1119 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
1120 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
1121 } else {
1122 i2c_adapter_fsm_init(i2c_adapter);
1125 #ifdef USE_FREERTOS
1126 /* Unlock the bus */
1127 xSemaphoreGive(i2c_adapter->sem_busy);
1128 if (!semaphore_success) {
1129 i2c_timeout_counter++;
1131 #else
1132 PIOS_IRQ_Disable();
1133 i2c_adapter->busy = 0;
1134 PIOS_IRQ_Enable();
1135 #endif /* USE_FREERTOS */
1137 return !semaphore_success ? PIOS_I2C_TRANSFER_TIMEOUT :
1138 i2c_adapter->bus_error ? PIOS_I2C_TRANSFER_BUS_ERROR :
1139 i2c_adapter->nack ? PIOS_I2C_TRANSFER_NACK :
1140 PIOS_I2C_TRANSFER_OK;
1143 static int32_t PIOS_I2C_Transfer_Callback_Internal(struct pios_i2c_adapter *i2c_adapter, const struct pios_i2c_txn txn_list[], uint32_t num_txns, pios_i2c_callback callback)
1145 PIOS_DEBUG_Assert(i2c_adapter->curr_state == I2C_STATE_STOPPED);
1147 i2c_adapter->first_txn = &txn_list[0];
1148 i2c_adapter->last_txn = &txn_list[num_txns - 1];
1149 i2c_adapter->active_txn = i2c_adapter->first_txn;
1150 i2c_adapter->bus_error = false;
1151 i2c_adapter->nack = false;
1152 i2c_adapter->callback = callback;
1154 // Estimate bytes of transmission. Per txns: 1 adress byte + length
1155 i2c_adapter->transfer_timeout_ticks = num_txns;
1156 for (uint32_t i = 0; i < num_txns; i++) {
1157 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
1159 // timeout if it takes eight times the expected time
1160 i2c_adapter->transfer_timeout_ticks <<= 3;
1162 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
1164 return 0;
1167 int32_t PIOS_I2C_Transfer_Callback(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns, pios_i2c_callback callback)
1169 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1171 if (!PIOS_I2C_validate(i2c_adapter)) {
1172 return -1;
1175 PIOS_Assert(callback);
1177 PIOS_DEBUG_Assert(txn_list);
1178 PIOS_DEBUG_Assert(num_txns);
1180 #ifdef USE_FREERTOS
1181 /* Lock the bus */
1182 portTickType timeout;
1183 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
1184 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
1185 return PIOS_I2C_TRANSFER_BUSY;
1187 #else
1188 PIOS_IRQ_Disable();
1189 if (i2c_adapter->busy) {
1190 PIOS_IRQ_Enable();
1191 return PIOS_I2C_TRANSFER_BUSY;
1193 i2c_adapter->busy = 1;
1194 PIOS_IRQ_Enable();
1195 #endif /* USE_FREERTOS */
1197 return PIOS_I2C_Transfer_Callback_Internal(i2c_adapter, txn_list, num_txns, callback);
1200 int32_t PIOS_I2C_Transfer_CallbackFromISR(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns, pios_i2c_callback callback, bool *woken)
1202 // FIXME: only supports transfer sizes up to 255 bytes
1203 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1205 bool valid = PIOS_I2C_validate(i2c_adapter);
1207 PIOS_Assert(valid)
1209 PIOS_DEBUG_Assert(txn_list);
1210 PIOS_DEBUG_Assert(num_txns);
1212 #ifdef USE_FREERTOS
1213 signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
1215 /* Lock the bus */
1216 bool locked = xSemaphoreTakeFromISR(i2c_adapter->sem_busy, &xHigherPriorityTaskWoken) == pdTRUE;
1218 if (xHigherPriorityTaskWoken == pdTRUE) {
1219 *woken = true;
1222 if (!locked) {
1223 return PIOS_I2C_TRANSFER_BUSY;
1225 #else
1226 PIOS_IRQ_Disable();
1227 if (i2c_adapter->busy) {
1228 PIOS_IRQ_Enable();
1229 return PIOS_I2C_TRANSFER_BUSY;
1231 i2c_adapter->busy = 1;
1232 PIOS_IRQ_Enable();
1233 #endif /* USE_FREERTOS */
1235 return PIOS_I2C_Transfer_Callback_Internal(i2c_adapter, txn_list, num_txns, callback);
1238 void PIOS_I2C_EV_IRQ_Handler(uint32_t i2c_id)
1240 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1242 if (!PIOS_I2C_validate(i2c_adapter)) {
1243 return;
1246 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1248 #if defined(PIOS_I2C_DIAGNOSTICS)
1249 /* Store event for diagnostics */
1250 i2c_evirq_history[i2c_evirq_history_pointer] = event;
1251 i2c_evirq_history_pointer = (i2c_evirq_history_pointer + 1) % I2C_LOG_DEPTH;
1252 #endif
1254 #define EVENT_MASK 0x000700FF
1255 event &= EVENT_MASK;
1257 // This is very poor and inconsistent practice with the FSM since no other
1258 // throw event depends on the current state. However when accelerated (-Os)
1259 // we definitely catch this event twice and there is no clean way to do deal
1260 // with that in the FMS short of a special state for it
1261 if (i2c_adapter->curr_state == I2C_STATE_STARTING && event == 0x70084) {
1262 return;
1265 switch (event) { /* Mask out all the bits we don't care about */
1266 case (I2C_EVENT_MASTER_MODE_SELECT | 0x40):
1267 /* Unexplained event: EV5 + RxNE : Extraneous Rx. Probably a late NACK from previous read. */
1268 /* Clean up the extra Rx until the root cause is identified and just keep going */
1269 (void)I2C_ReceiveData(i2c_adapter->cfg->regs);
1270 /* Fall through */
1271 case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
1272 switch (i2c_adapter->active_txn->rw) {
1273 case PIOS_I2C_TXN_READ:
1274 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1275 /* Final transaction */
1276 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_READ);
1277 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1278 /* More transactions follow */
1279 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_READ);
1280 } else {
1281 PIOS_DEBUG_Assert(0);
1283 break;
1284 case PIOS_I2C_TXN_WRITE:
1285 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1286 /* Final transaction */
1287 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_WRITE);
1288 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1289 /* More transactions follow */
1290 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_WRITE);
1291 } else {
1292 PIOS_DEBUG_Assert(0);
1294 break;
1295 default:
1296 PIOS_DEBUG_Assert(0);
1297 break;
1299 break;
1300 case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
1301 case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
1302 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1303 case 0:
1304 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_0);
1305 break;
1306 case 1:
1307 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_1);
1308 break;
1309 case 2:
1310 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_2);
1311 break;
1312 default:
1313 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_GT_2);
1314 break;
1316 break;
1317 case 0x80: /* TxE only. TRA + MSL + BUSY have been cleared before we got here. */
1318 /* Ignore */
1320 static volatile bool halt = false;
1321 while (halt) {
1325 break;
1326 case 0: /* This triggers an FSM fault sometimes, but not having it stops things working */
1327 case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */
1328 case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */
1329 case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
1330 case (I2C_EVENT_MASTER_BYTE_RECEIVED | 0x4): /* EV7 + BTF */
1331 case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
1332 case 0x84: /* TxE + BTF. EV8_2 but TRA + MSL + BUSY have already been cleared by HW. */
1333 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1334 case 0:
1335 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0);
1336 break;
1337 case 1:
1338 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1);
1339 break;
1340 case 2:
1341 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2);
1342 break;
1343 default:
1344 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2);
1345 break;
1347 break;
1348 case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
1349 /* Ignore this event and wait for TRANSMITTED in case we can't keep up */
1350 goto skip_event;
1351 break;
1352 case 0x30084: /* BUSY + MSL + TXE + BFT Occurs between byte transmitted and master mode selected */
1353 case 0x30000: /* BUSY + MSL Need to throw away this spurious event */
1354 case 0x30403 & EVENT_MASK: /* BUSY + MSL + SB + ADDR Detected this after got a NACK, probably stop bit */
1355 goto skip_event;
1356 break;
1357 default:
1358 i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT);
1359 #if defined(I2C_HALT_ON_ERRORS)
1360 PIOS_DEBUG_Assert(0);
1361 #endif
1362 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1363 break;
1366 skip_event:
1371 void PIOS_I2C_ER_IRQ_Handler(uint32_t i2c_id)
1373 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1375 if (!PIOS_I2C_validate(i2c_adapter)) {
1376 return;
1379 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1381 #if defined(PIOS_I2C_DIAGNOSTICS)
1382 i2c_erirq_history[i2c_erirq_history_pointer] = event;
1383 i2c_erirq_history_pointer = (i2c_erirq_history_pointer + 1) % 5;
1384 #endif
1386 if (event & I2C_FLAG_AF) {
1387 i2c_nack_counter++;
1389 I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_AF);
1391 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
1392 } else { /* Mostly bus errors here */
1393 i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
1395 /* Fail hard on any errors for now */
1396 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1400 #endif /* PIOS_INCLUDE_I2C */
1403 * @}
1404 * @}