2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
5 * @addtogroup PIOS_I2C I2C Functions
6 * @brief STM32 Hardware dependent I2C functionality
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
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
33 #ifdef PIOS_INCLUDE_I2C
35 #if defined(PIOS_INCLUDE_FREERTOS)
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 */
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
,
74 I2C_STATE_NUM_STATES
/* Must be last */
77 // #define I2C_HALT_ON_ERRORS
79 enum i2c_adapter_event
{
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
,
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;
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
,
169 [I2C_EVENT_AUTO
] = I2C_STATE_STOPPING
,
172 [I2C_STATE_BUS_ERROR
] = {
173 .entry_fn
= go_bus_error
,
175 [I2C_EVENT_AUTO
] = I2C_STATE_STOPPING
,
179 [I2C_STATE_STOPPED
] = {
180 .entry_fn
= go_stopped
,
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
,
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
,
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
,
211 [I2C_STATE_R_MORE_TXN_ADDR
] = {
212 .entry_fn
= go_r_any_txn_addr
,
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
,
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
,
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
,
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
,
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
,
258 [I2C_EVENT_AUTO
] = I2C_STATE_STARTING
,
266 [I2C_STATE_R_LAST_TXN_ADDR
] = {
267 .entry_fn
= go_r_any_txn_addr
,
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
,
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
,
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
,
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
,
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
,
313 [I2C_EVENT_AUTO
] = I2C_STATE_STOPPING
,
321 [I2C_STATE_W_MORE_TXN_ADDR
] = {
322 .entry_fn
= go_w_any_txn_addr
,
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
,
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
,
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
,
356 [I2C_STATE_W_LAST_TXN_ADDR
] = {
357 .entry_fn
= go_w_any_txn_addr
,
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
,
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
,
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
,
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);
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
)
416 signed portBASE_TYPE pxHigherPriorityTaskWoken
= pdFALSE
;
419 I2C_ITConfig(i2c_adapter
->cfg
->regs
, I2C_IT_EVT
| I2C_IT_BUF
| I2C_IT_ERR
, DISABLE
);
422 if (xSemaphoreGiveFromISR(i2c_adapter
->sem_ready
, &pxHigherPriorityTaskWoken
) != pdTRUE
) {
423 #if defined(I2C_HALT_ON_ERRORS)
424 PIOS_DEBUG_Assert(0);
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) {
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]);
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
);
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
);
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
);
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
);
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
);
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
)
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
);
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
);
668 static void i2c_adapter_process_auto(struct pios_i2c_adapter
*i2c_adapter
)
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
);
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
)
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
--) {
705 /* We timed out waiting for the stop condition */
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
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 */
739 // bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
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
)) {
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);
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
);
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 */
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
:
816 * Logs the last N state transitions and N IRQ events due to
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
];
835 case PIOS_I2C_ERROR_EVENT
:
836 i2c_bad_event_counter
++;
838 case PIOS_I2C_ERROR_FSM
:
839 i2c_fsm_fault_count
++;
841 case PIOS_I2C_ERROR_INTERRUPT
:
842 i2c_error_interrupt_counter
++;
845 #endif /* if defined(PIOS_I2C_DIAGNOSTICS) */
850 * Logs the last N state transitions and N IRQ events due to
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
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
;
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
);
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
));
889 i2c_adapter
->magic
= PIOS_I2C_DEV_MAGIC
;
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
) {
903 i2c_adapter
= &pios_i2c_adapters
[pios_i2c_num_adapters
++];
904 i2c_adapter
->magic
= PIOS_I2C_DEV_MAGIC
;
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();
928 /* Bind the configuration to the device instance */
929 i2c_adapter
->cfg
= cfg
;
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
) {
943 /* Enable I2C peripheral clock (APB1 == slow speed) */
944 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1
, ENABLE
);
947 /* Enable I2C peripheral clock (APB1 == slow speed) */
948 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2
, ENABLE
);
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
));
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;
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
;
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
1009 if (i2c_adapter
->busy
) {
1012 i2c_adapter
->busy
= 1;
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
;
1023 /* Make sure the done/ready semaphore is consumed before we start */
1024 semaphore_success
&= (xSemaphoreTake(i2c_adapter
->sem_ready
, timeout
) == pdTRUE
);
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 */
1040 semaphore_success
&= (xSemaphoreTake(i2c_adapter
->sem_ready
, timeout
) == pdTRUE
);
1041 xSemaphoreGive(i2c_adapter
->sem_ready
);
1044 i2c_adapter
->busy
= 0;
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) {
1061 if (i2c_adapter_wait_for_stopped(i2c_adapter
)) {
1062 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_STOPPED
);
1064 i2c_adapter_fsm_init(i2c_adapter
);
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
)) {
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
;
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
);
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
);
1117 PIOS_DEBUG_Assert(0);
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
);
1128 PIOS_DEBUG_Assert(0);
1132 PIOS_DEBUG_Assert(0);
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) {
1140 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_ADDR_SENT_LEN_EQ_0
);
1143 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_ADDR_SENT_LEN_EQ_1
);
1146 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_ADDR_SENT_LEN_EQ_2
);
1149 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_ADDR_SENT_LEN_GT_2
);
1153 case 0x80: /* TxE only. TRA + MSL + BUSY have been cleared before we got here. */
1156 static volatile bool halt
= FALSE
;
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) {
1171 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0
);
1174 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1
);
1177 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2
);
1180 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_TRANSFER_DONE_LEN_GT_2
);
1184 case I2C_EVENT_MASTER_BYTE_TRANSMITTING
: /* EV8 */
1185 /* Ignore this event and wait for TRANSMITTED in case we can't keep up */
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 */
1194 i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT
);
1195 #if defined(I2C_HALT_ON_ERRORS)
1196 PIOS_DEBUG_Assert(0);
1198 i2c_adapter_inject_event(i2c_adapter
, I2C_EVENT_BUS_ERROR
);
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
)) {
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;
1224 if (event
& I2C_FLAG_AF
) {
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 */