REVONANO Milestones update
[librepilot.git] / flight / pios / stm32f4xx / pios_i2c.c
blob171669ac43749e45d69f5ede1f2a70e21092e560
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);
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,
393 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter)
395 #if defined(I2C_HALT_ON_ERRORS)
396 PIOS_DEBUG_Assert(0);
397 #endif
398 /* Note that this transfer has hit a bus error */
399 i2c_adapter->bus_error = true;
401 i2c_adapter_reset_bus(i2c_adapter);
404 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter)
406 /* Note that this transfer has hit a bus error */
407 i2c_adapter->bus_error = true;
409 i2c_adapter_reset_bus(i2c_adapter);
412 static void go_stopping(struct pios_i2c_adapter *i2c_adapter)
414 #ifdef USE_FREERTOS
415 signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
416 #endif
418 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
420 #ifdef USE_FREERTOS
421 if (xSemaphoreGiveFromISR(i2c_adapter->sem_ready, &pxHigherPriorityTaskWoken) != pdTRUE) {
422 #if defined(I2C_HALT_ON_ERRORS)
423 PIOS_DEBUG_Assert(0);
424 #endif
426 portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
427 #endif /* USE_FREERTOS */
429 if (i2c_adapter->callback) {
430 i2c_adapter_callback_handler(i2c_adapter);
434 static void go_stopped(struct pios_i2c_adapter *i2c_adapter)
436 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
437 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
440 static void go_starting(struct pios_i2c_adapter *i2c_adapter)
442 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
443 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
444 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
446 // check for an empty read/write
447 if (i2c_adapter->active_txn->buf != NULL && i2c_adapter->active_txn->len != 0) {
448 // Data available
449 i2c_adapter->active_byte = &(i2c_adapter->active_txn->buf[0]);
450 i2c_adapter->last_byte = &(i2c_adapter->active_txn->buf[i2c_adapter->active_txn->len - 1]);
451 } else {
452 // No Data available => Empty read/write
453 i2c_adapter->last_byte = NULL;
454 i2c_adapter->active_byte = i2c_adapter->last_byte + 1;
457 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
458 if (i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ) {
459 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
460 } else {
461 // For write operations, do not enable the IT_BUF events.
462 // The current driver does not act when the TX data register is not full, only when the complete byte is sent.
463 // With the IT_BUF enabled, we constantly get IRQs, See OP-326
464 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_ERR, ENABLE);
468 /* Common to 'more' and 'last' transaction */
469 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
471 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
472 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
473 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
475 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ);
477 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Receiver);
480 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
482 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
483 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
486 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
488 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
489 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
492 /* Common to 'more' and 'last' transaction */
493 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter)
495 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
498 /* Common to 'more' and 'last' transaction */
499 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter)
501 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
502 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
504 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
506 /* Move to the next byte */
507 i2c_adapter->active_byte++;
508 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
511 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
513 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
514 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
516 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
517 PIOS_IRQ_Disable();
518 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
519 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
520 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
521 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
522 PIOS_IRQ_Enable();
524 /* Move to the next byte */
525 i2c_adapter->active_byte++;
526 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
529 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
531 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
532 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
534 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
535 PIOS_IRQ_Disable();
536 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
537 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
538 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
539 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
540 PIOS_IRQ_Enable();
542 /* Move to the next byte */
543 i2c_adapter->active_byte++;
544 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
547 /* Common to 'more' and 'last' transaction */
548 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter)
550 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
551 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
552 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
553 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
554 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
556 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
558 /* Move to the next byte */
559 i2c_adapter->active_byte++;
561 /* Move to the next transaction */
562 i2c_adapter->active_txn++;
565 /* Common to 'more' and 'last' transaction */
566 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
568 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
569 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
570 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
572 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE);
574 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Transmitter);
577 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter)
579 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
580 PIOS_DEBUG_Assert(i2c_adapter->active_byte < i2c_adapter->last_byte);
581 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
582 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
583 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
585 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
587 /* Move to the next byte */
588 i2c_adapter->active_byte++;
589 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
592 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter)
594 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
595 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
596 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
597 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
598 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
600 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
602 /* Move to the next byte */
603 i2c_adapter->active_byte++;
605 /* Move to the next transaction */
606 i2c_adapter->active_txn++;
607 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
610 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter)
612 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
613 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
614 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
615 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
616 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
618 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
619 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
621 // SHOULD MOVE THIS INTO A STOPPING STATE AND SET IT ONLY AFTER THE BYTE WAS SENT
622 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
624 /* Move to the next byte */
625 i2c_adapter->active_byte++;
628 static void go_nack(struct pios_i2c_adapter *i2c_adapter)
630 i2c_adapter->nack = true;
631 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
632 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
633 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
636 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event)
638 PIOS_IRQ_Disable();
640 #if defined(PIOS_I2C_DIAGNOSTICS)
641 i2c_state_event_history[i2c_state_event_history_pointer] = event;
642 i2c_state_event_history_pointer = (i2c_state_event_history_pointer + 1) % I2C_LOG_DEPTH;
644 i2c_state_history[i2c_state_history_pointer] = i2c_adapter->curr_state;
645 i2c_state_history_pointer = (i2c_state_history_pointer + 1) % I2C_LOG_DEPTH;
647 if (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event] == I2C_STATE_FSM_FAULT) {
648 i2c_adapter_log_fault(PIOS_I2C_ERROR_FSM);
650 #endif
652 * Move to the next state
654 * This is done prior to calling the new state's entry function to
655 * guarantee that the entry function never depends on the previous
656 * state. This way, it cannot ever know what the previous state was.
658 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event];
660 /* Call the entry function (if any) for the next state. */
661 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
662 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
665 /* Process any AUTO transitions in the FSM */
666 i2c_adapter_process_auto(i2c_adapter);
668 PIOS_IRQ_Enable();
671 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter)
673 PIOS_IRQ_Disable();
675 while (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO]) {
676 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO];
678 /* Call the entry function (if any) for the next state. */
679 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
680 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
684 PIOS_IRQ_Enable();
687 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter)
689 i2c_adapter_reset_bus(i2c_adapter);
690 i2c_adapter->curr_state = I2C_STATE_STOPPED;
693 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter)
695 uint32_t guard;
698 * Wait for the bus to return to the stopped state.
699 * This was pulled out of the FSM due to occasional
700 * failures at this transition which previously resulted
701 * in spinning on this bit in the ISR forever.
703 for (guard = 1000000; /* FIXME: should use the configured bus timeout */
704 guard && (i2c_adapter->cfg->regs->CR1 & I2C_CR1_STOP); guard--) {
705 continue;
707 if (!guard) {
708 /* We timed out waiting for the stop condition */
709 return false;
712 return true;
715 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
717 /* Reset the I2C block */
718 I2C_DeInit(i2c_adapter->cfg->regs);
720 /* Make sure the bus is free by clocking it until any slaves release the bus. */
721 GPIO_InitTypeDef scl_gpio_init;
722 scl_gpio_init = i2c_adapter->cfg->scl.init;
723 scl_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
724 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
725 GPIO_Init(i2c_adapter->cfg->scl.gpio, &scl_gpio_init);
727 GPIO_InitTypeDef sda_gpio_init;
728 sda_gpio_init = i2c_adapter->cfg->sda.init;
729 sda_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
730 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
731 GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
733 /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
734 /* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
735 /* ESC */
736 // bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
737 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET) {
738 /* Set clock high and wait for any clock stretching to finish. */
739 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
740 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) {
743 PIOS_DELAY_WaituS(2);
745 /* Set clock low */
746 GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
747 PIOS_DELAY_WaituS(2);
749 /* Clock high again */
750 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
751 PIOS_DELAY_WaituS(2);
754 /* Generate a start then stop condition */
755 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
756 PIOS_DELAY_WaituS(2);
757 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
758 PIOS_DELAY_WaituS(2);
759 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
760 PIOS_DELAY_WaituS(2);
762 /* Set data and clock high and wait for any clock stretching to finish. */
763 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
764 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
765 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) {
768 /* Wait for data to be high */
769 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET) {
774 /* Bus signals are guaranteed to be high (ie. free) after this point */
775 /* Initialize the GPIO pins to the peripheral function */
776 if (i2c_adapter->cfg->remapSCL) {
777 GPIO_PinAFConfig(i2c_adapter->cfg->scl.gpio,
778 __builtin_ctz(i2c_adapter->cfg->scl.init.GPIO_Pin),
779 i2c_adapter->cfg->remapSCL);
781 if (i2c_adapter->cfg->remapSDA) {
782 GPIO_PinAFConfig(i2c_adapter->cfg->sda.gpio,
783 __builtin_ctz(i2c_adapter->cfg->sda.init.GPIO_Pin),
784 i2c_adapter->cfg->remapSDA);
786 GPIO_Init(i2c_adapter->cfg->scl.gpio, (GPIO_InitTypeDef *)&(i2c_adapter->cfg->scl.init)); // Struct is const, function signature not
787 GPIO_Init(i2c_adapter->cfg->sda.gpio, (GPIO_InitTypeDef *)&(i2c_adapter->cfg->sda.init));
789 /* Reset the I2C block */
790 I2C_DeInit(i2c_adapter->cfg->regs);
792 /* Initialize the I2C block */
793 I2C_Init(i2c_adapter->cfg->regs, (I2C_InitTypeDef *)&(i2c_adapter->cfg->init));
795 // for delays during transfer timeouts
796 // one tick correspond to transmission of 1 byte i.e. 9 clock ticks
797 i2c_adapter->transfer_delay_uS = 9000000 / (((I2C_InitTypeDef *)&(i2c_adapter->cfg->init))->I2C_ClockSpeed);
800 if (i2c_adapter->cfg->regs->SR2 & I2C_FLAG_BUSY) {
801 /* Reset the I2C block */
802 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, ENABLE);
803 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, DISABLE);
808 /* Return true if the FSM is in a terminal state */
809 static bool i2c_adapter_fsm_terminated(struct pios_i2c_adapter *i2c_adapter)
811 switch (i2c_adapter->curr_state) {
812 case I2C_STATE_STOPPING:
813 case I2C_STATE_STOPPED:
814 return true;
816 default:
817 return false;
821 uint32_t i2c_cb_count = 0;
822 static bool i2c_adapter_callback_handler(struct pios_i2c_adapter *i2c_adapter)
824 bool semaphore_success = true;
826 /* Wait for the transfer to complete */
827 #ifdef USE_FREERTOS
828 portTickType timeout;
829 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
830 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
831 xSemaphoreGive(i2c_adapter->sem_ready);
832 #endif /* USE_FREERTOS */
834 /* transfer_timeout_ticks is set by PIOS_I2C_Transfer_Callback */
835 /* Spin waiting for the transfer to finish */
836 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
837 // sleep 1 byte, as FSM can't be faster
838 // FIXME: clock stretching could make problems, but citing NPX: alsmost no slave device implements clock stretching
839 // three times the expected time should cover clock delay
840 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
842 i2c_adapter->transfer_timeout_ticks--;
843 if (i2c_adapter->transfer_timeout_ticks == 0) {
844 break;
848 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
849 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
850 } else {
851 i2c_adapter_fsm_init(i2c_adapter);
854 // Execute user supplied function
855 i2c_adapter->callback();
857 i2c_cb_count++;
859 #ifdef USE_FREERTOS
860 /* Unlock the bus */
861 xSemaphoreGive(i2c_adapter->sem_busy);
862 if (!semaphore_success) {
863 i2c_timeout_counter++;
865 #else
866 PIOS_IRQ_Disable();
867 i2c_adapter->busy = 0;
868 PIOS_IRQ_Enable();
869 #endif /* USE_FREERTOS */
872 return (!i2c_adapter->bus_error) && semaphore_success;
876 * Logs the last N state transitions and N IRQ events due to
877 * an error condition
878 * \param[in] i2c the adapter number to log an event for
880 void i2c_adapter_log_fault(enum pios_i2c_error_type type)
882 #if defined(PIOS_I2C_DIAGNOSTICS)
883 i2c_adapter_fault_history.type = type;
884 for (uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
885 i2c_adapter_fault_history.evirq[i] =
886 i2c_evirq_history[(I2C_LOG_DEPTH + i2c_evirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
887 i2c_adapter_fault_history.erirq[i] =
888 i2c_erirq_history[(I2C_LOG_DEPTH + i2c_erirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
889 i2c_adapter_fault_history.event[i] =
890 i2c_state_event_history[(I2C_LOG_DEPTH + i2c_state_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
891 i2c_adapter_fault_history.state[i] =
892 i2c_state_history[(I2C_LOG_DEPTH + i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
894 switch (type) {
895 case PIOS_I2C_ERROR_EVENT:
896 i2c_bad_event_counter++;
897 break;
898 case PIOS_I2C_ERROR_FSM:
899 i2c_fsm_fault_count++;
900 break;
901 case PIOS_I2C_ERROR_INTERRUPT:
902 i2c_error_interrupt_counter++;
903 break;
905 #endif /* if defined(PIOS_I2C_DIAGNOSTICS) */
910 * Logs the last N state transitions and N IRQ events due to
911 * an error condition
912 * \param[out] data address where to copy the pios_i2c_fault_history structure to
913 * \param[out] counts three uint16 that receive the bad event, fsm, and error irq
914 * counts
916 void PIOS_I2C_GetDiagnostics(struct pios_i2c_fault_history *data, uint8_t *counts)
918 #if defined(PIOS_I2C_DIAGNOSTICS)
919 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
920 counts[0] = i2c_bad_event_counter;
921 counts[1] = i2c_fsm_fault_count;
922 counts[2] = i2c_error_interrupt_counter;
923 counts[3] = i2c_nack_counter;
924 counts[4] = i2c_timeout_counter;
925 #else
926 struct pios_i2c_fault_history i2c_adapter_fault_history;
927 i2c_adapter_fault_history.type = PIOS_I2C_ERROR_EVENT;
929 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
930 counts[0] = counts[1] = counts[2] = 0;
931 #endif
934 static bool PIOS_I2C_validate(struct pios_i2c_adapter *i2c_adapter)
936 return i2c_adapter->magic == PIOS_I2C_DEV_MAGIC;
939 #if defined(PIOS_INCLUDE_FREERTOS) && 0
940 static struct pios_i2c_dev *PIOS_I2C_alloc(void)
942 struct pios_i2c_dev *i2c_adapter;
944 i2c_adapter = (struct pios_i2c_adapter *)pios_malloc(sizeof(*i2c_adapter));
945 if (!i2c_adapter) {
946 return NULL;
949 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
950 return i2c_adapter;
952 #else
953 static struct pios_i2c_adapter pios_i2c_adapters[PIOS_I2C_MAX_DEVS];
954 static uint8_t pios_i2c_num_adapters;
955 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
957 struct pios_i2c_adapter *i2c_adapter;
959 if (pios_i2c_num_adapters >= PIOS_I2C_MAX_DEVS) {
960 return NULL;
963 i2c_adapter = &pios_i2c_adapters[pios_i2c_num_adapters++];
964 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
966 return i2c_adapter;
968 #endif /* if defined(PIOS_INCLUDE_FREERTOS) && 0 */
972 * Initializes IIC driver
973 * \param[in] mode currently only mode 0 supported
974 * \return < 0 if initialisation failed
976 int32_t PIOS_I2C_Init(uint32_t *i2c_id, const struct pios_i2c_adapter_cfg *cfg)
978 PIOS_DEBUG_Assert(i2c_id);
979 PIOS_DEBUG_Assert(cfg);
981 struct pios_i2c_adapter *i2c_adapter;
983 i2c_adapter = (struct pios_i2c_adapter *)PIOS_I2C_alloc();
984 if (!i2c_adapter) {
985 goto out_fail;
988 /* Bind the configuration to the device instance */
989 i2c_adapter->cfg = cfg;
991 #ifdef USE_FREERTOS
993 * Must be done prior to calling i2c_adapter_fsm_init()
994 * since the sem_ready mutex is used in the initial state.
996 vSemaphoreCreateBinary(i2c_adapter->sem_ready);
997 i2c_adapter->sem_busy = xSemaphoreCreateMutex();
998 #else
999 i2c_adapter->busy = 0;
1000 #endif // USE_FREERTOS
1002 /* Initialize the state machine */
1003 i2c_adapter_fsm_init(i2c_adapter);
1005 *i2c_id = (uint32_t)i2c_adapter;
1007 /* Configure and enable I2C interrupts */
1008 NVIC_Init((NVIC_InitTypeDef *)&(i2c_adapter->cfg->event.init));
1009 NVIC_Init((NVIC_InitTypeDef *)&(i2c_adapter->cfg->error.init));
1012 /* No error */
1013 return 0;
1015 out_fail:
1016 return -1;
1019 int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
1021 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1023 if (!PIOS_I2C_validate(i2c_adapter)) {
1024 return -1;
1027 PIOS_DEBUG_Assert(txn_list);
1028 PIOS_DEBUG_Assert(num_txns);
1030 bool semaphore_success = true;
1032 #ifdef USE_FREERTOS
1033 /* Lock the bus */
1034 portTickType timeout;
1035 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
1036 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
1037 return -2;
1039 #else
1040 PIOS_IRQ_Disable();
1041 if (i2c_adapter->busy) {
1042 PIOS_IRQ_Enable();
1043 return -2;
1045 i2c_adapter->busy = 1;
1046 PIOS_IRQ_Enable();
1047 #endif /* USE_FREERTOS */
1049 PIOS_DEBUG_Assert(i2c_adapter->curr_state == I2C_STATE_STOPPED);
1051 i2c_adapter->first_txn = &txn_list[0];
1052 i2c_adapter->last_txn = &txn_list[num_txns - 1];
1053 i2c_adapter->active_txn = i2c_adapter->first_txn;
1055 #ifdef USE_FREERTOS
1056 /* Make sure the done/ready semaphore is consumed before we start */
1057 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1058 #endif
1060 // Estimate bytes of transmission. Per txns: 1 adress byte + length
1061 i2c_adapter->transfer_timeout_ticks = num_txns;
1062 for (uint32_t i = 0; i < num_txns; i++) {
1063 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
1065 // timeout if it takes eight times the expected time
1066 i2c_adapter->transfer_timeout_ticks <<= 3;
1068 i2c_adapter->callback = NULL;
1069 i2c_adapter->bus_error = false;
1070 i2c_adapter->nack = false;
1071 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
1073 /* Wait for the transfer to complete */
1074 #ifdef USE_FREERTOS
1075 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1076 xSemaphoreGive(i2c_adapter->sem_ready);
1077 #endif /* USE_FREERTOS */
1079 /* Spin waiting for the transfer to finish */
1080 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
1081 /* sleep 9 clock ticks (1 byte), because FSM can't be faster than one byte
1082 FIXME: clock stretching could make problems, but citing NPX: alsmost no slave device implements clock stretching
1083 three times the expected time should cover clock delay */
1084 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
1086 i2c_adapter->transfer_timeout_ticks--;
1087 if (i2c_adapter->transfer_timeout_ticks == 0) {
1088 break;
1092 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
1093 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
1094 } else {
1095 i2c_adapter_fsm_init(i2c_adapter);
1098 #ifdef USE_FREERTOS
1099 /* Unlock the bus */
1100 xSemaphoreGive(i2c_adapter->sem_busy);
1101 if (!semaphore_success) {
1102 i2c_timeout_counter++;
1104 #else
1105 PIOS_IRQ_Disable();
1106 i2c_adapter->busy = 0;
1107 PIOS_IRQ_Enable();
1108 #endif /* USE_FREERTOS */
1110 return !semaphore_success ? -2 :
1111 i2c_adapter->bus_error ? -1 :
1112 i2c_adapter->nack ? -3 :
1116 int32_t PIOS_I2C_Transfer_Callback(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns, void *callback)
1118 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1120 if (!PIOS_I2C_validate(i2c_adapter)) {
1121 return -1;
1124 PIOS_Assert(callback);
1126 PIOS_DEBUG_Assert(txn_list);
1127 PIOS_DEBUG_Assert(num_txns);
1129 bool semaphore_success = true;
1131 #ifdef USE_FREERTOS
1132 /* Lock the bus */
1133 portTickType timeout;
1134 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
1135 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
1136 return -2;
1138 #else
1139 if (i2c_adapter->busy) {
1140 PIOS_IRQ_Enable();
1141 return -2;
1143 #endif /* USE_FREERTOS */
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;
1151 #ifdef USE_FREERTOS
1152 /* Make sure the done/ready semaphore is consumed before we start */
1153 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
1154 #endif
1156 // used in the i2c_adapter_callback_handler function
1157 // Estimate bytes of transmission. Per txns: 1 adress byte + length
1158 i2c_adapter->transfer_timeout_ticks = num_txns;
1159 for (uint32_t i = 0; i < num_txns; i++) {
1160 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
1162 // timeout if it takes eight times the expected time
1163 i2c_adapter->transfer_timeout_ticks <<= 3;
1165 i2c_adapter->callback = callback;
1166 i2c_adapter->bus_error = false;
1167 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
1169 return !semaphore_success ? -2 : 0;
1172 void PIOS_I2C_EV_IRQ_Handler(uint32_t i2c_id)
1174 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1176 if (!PIOS_I2C_validate(i2c_adapter)) {
1177 return;
1180 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1182 #if defined(PIOS_I2C_DIAGNOSTICS)
1183 /* Store event for diagnostics */
1184 i2c_evirq_history[i2c_evirq_history_pointer] = event;
1185 i2c_evirq_history_pointer = (i2c_evirq_history_pointer + 1) % I2C_LOG_DEPTH;
1186 #endif
1188 #define EVENT_MASK 0x000700FF
1189 event &= EVENT_MASK;
1191 // This is very poor and inconsistent practice with the FSM since no other
1192 // throw event depends on the current state. However when accelerated (-Os)
1193 // we definitely catch this event twice and there is no clean way to do deal
1194 // with that in the FMS short of a special state for it
1195 if (i2c_adapter->curr_state == I2C_STATE_STARTING && event == 0x70084) {
1196 return;
1199 switch (event) { /* Mask out all the bits we don't care about */
1200 case (I2C_EVENT_MASTER_MODE_SELECT | 0x40):
1201 /* Unexplained event: EV5 + RxNE : Extraneous Rx. Probably a late NACK from previous read. */
1202 /* Clean up the extra Rx until the root cause is identified and just keep going */
1203 (void)I2C_ReceiveData(i2c_adapter->cfg->regs);
1204 /* Fall through */
1205 case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
1206 switch (i2c_adapter->active_txn->rw) {
1207 case PIOS_I2C_TXN_READ:
1208 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1209 /* Final transaction */
1210 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_READ);
1211 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1212 /* More transactions follow */
1213 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_READ);
1214 } else {
1215 PIOS_DEBUG_Assert(0);
1217 break;
1218 case PIOS_I2C_TXN_WRITE:
1219 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1220 /* Final transaction */
1221 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_WRITE);
1222 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1223 /* More transactions follow */
1224 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_WRITE);
1225 } else {
1226 PIOS_DEBUG_Assert(0);
1228 break;
1229 default:
1230 PIOS_DEBUG_Assert(0);
1231 break;
1233 break;
1234 case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
1235 case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
1236 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1237 case 0:
1238 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_0);
1239 break;
1240 case 1:
1241 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_1);
1242 break;
1243 case 2:
1244 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_2);
1245 break;
1246 default:
1247 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_GT_2);
1248 break;
1250 break;
1251 case 0x80: /* TxE only. TRA + MSL + BUSY have been cleared before we got here. */
1252 /* Ignore */
1254 static volatile bool halt = false;
1255 while (halt) {
1259 break;
1260 case 0: /* This triggers an FSM fault sometimes, but not having it stops things working */
1261 case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */
1262 case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */
1263 case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
1264 case (I2C_EVENT_MASTER_BYTE_RECEIVED | 0x4): /* EV7 + BTF */
1265 case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
1266 case 0x84: /* TxE + BTF. EV8_2 but TRA + MSL + BUSY have already been cleared by HW. */
1267 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1268 case 0:
1269 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0);
1270 break;
1271 case 1:
1272 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1);
1273 break;
1274 case 2:
1275 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2);
1276 break;
1277 default:
1278 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2);
1279 break;
1281 break;
1282 case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
1283 /* Ignore this event and wait for TRANSMITTED in case we can't keep up */
1284 goto skip_event;
1285 break;
1286 case 0x30084: /* BUSY + MSL + TXE + BFT Occurs between byte transmitted and master mode selected */
1287 case 0x30000: /* BUSY + MSL Need to throw away this spurious event */
1288 case 0x30403 & EVENT_MASK: /* BUSY + MSL + SB + ADDR Detected this after got a NACK, probably stop bit */
1289 goto skip_event;
1290 break;
1291 default:
1292 i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT);
1293 #if defined(I2C_HALT_ON_ERRORS)
1294 PIOS_DEBUG_Assert(0);
1295 #endif
1296 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1297 break;
1300 skip_event:
1305 void PIOS_I2C_ER_IRQ_Handler(uint32_t i2c_id)
1307 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1309 if (!PIOS_I2C_validate(i2c_adapter)) {
1310 return;
1313 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1315 #if defined(PIOS_I2C_DIAGNOSTICS)
1316 i2c_erirq_history[i2c_erirq_history_pointer] = event;
1317 i2c_erirq_history_pointer = (i2c_erirq_history_pointer + 1) % 5;
1318 #endif
1320 if (event & I2C_FLAG_AF) {
1321 i2c_nack_counter++;
1323 I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_AF);
1325 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
1326 } else { /* Mostly bus errors here */
1327 i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
1329 /* Fail hard on any errors for now */
1330 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1334 #endif /* PIOS_INCLUDE_I2C */
1337 * @}
1338 * @}