OP-1483 Added velocity filter to correct EKF's velocity estimate for static velocity...
[librepilot.git] / flight / pios / stm32f10x / pios_i2c.c
blob1f4348b93986481100f534b3e6f4fee14f57c7a5
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_I2C I2C Functions
6 * @brief STM32 Hardware dependent I2C functionality
7 * @{
9 * @file pios_i2c.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
11 * @brief I2C Enable/Disable routines
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "pios.h"
33 #ifdef PIOS_INCLUDE_I2C
35 #if defined(PIOS_INCLUDE_FREERTOS)
36 #define USE_FREERTOS
37 #endif
39 #include <pios_i2c_priv.h>
41 // #define I2C_HALT_ON_ERRORS
43 enum i2c_adapter_event {
44 I2C_EVENT_BUS_ERROR,
45 I2C_EVENT_START,
46 I2C_EVENT_STARTED_MORE_TXN_READ,
47 I2C_EVENT_STARTED_MORE_TXN_WRITE,
48 I2C_EVENT_STARTED_LAST_TXN_READ,
49 I2C_EVENT_STARTED_LAST_TXN_WRITE,
50 I2C_EVENT_ADDR_SENT_LEN_EQ_0,
51 I2C_EVENT_ADDR_SENT_LEN_EQ_1,
52 I2C_EVENT_ADDR_SENT_LEN_EQ_2,
53 I2C_EVENT_ADDR_SENT_LEN_GT_2,
54 I2C_EVENT_TRANSFER_DONE_LEN_EQ_0,
55 I2C_EVENT_TRANSFER_DONE_LEN_EQ_1,
56 I2C_EVENT_TRANSFER_DONE_LEN_EQ_2,
57 I2C_EVENT_TRANSFER_DONE_LEN_GT_2,
58 I2C_EVENT_NACK,
59 I2C_EVENT_STOPPED,
60 I2C_EVENT_AUTO, /* FIXME: remove this */
62 I2C_EVENT_NUM_EVENTS /* Must be last */
65 #if defined(PIOS_I2C_DIAGNOSTICS)
66 static struct pios_i2c_fault_history i2c_adapter_fault_history;
68 volatile uint32_t i2c_evirq_history[I2C_LOG_DEPTH];
69 volatile uint8_t i2c_evirq_history_pointer = 0;
71 volatile uint32_t i2c_erirq_history[I2C_LOG_DEPTH];
72 volatile uint8_t i2c_erirq_history_pointer = 0;
74 volatile enum i2c_adapter_state i2c_state_history[I2C_LOG_DEPTH];
75 volatile uint8_t i2c_state_history_pointer = 0;
77 volatile enum i2c_adapter_event i2c_state_event_history[I2C_LOG_DEPTH];
78 volatile uint8_t i2c_state_event_history_pointer;
80 static uint8_t i2c_fsm_fault_count = 0;
81 static uint8_t i2c_bad_event_counter = 0;
82 static uint8_t i2c_error_interrupt_counter = 0;
83 static uint8_t i2c_nack_counter = 0;
84 static uint8_t i2c_timeout_counter = 0;
85 #endif
87 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter);
88 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter);
89 static void go_stopping(struct pios_i2c_adapter *i2c_adapter);
90 static void go_stopped(struct pios_i2c_adapter *i2c_adapter);
91 static void go_starting(struct pios_i2c_adapter *i2c_adapter);
92 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
93 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter);
94 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter);
95 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter);
96 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter);
97 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter);
99 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
100 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter);
101 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter);
102 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter);
103 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter);
104 static void go_r_any_txn_post_last(struct pios_i2c_adapter *i2c_adapter);
106 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
107 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
108 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter);
110 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter);
111 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter);
112 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter);
114 static void go_nack(struct pios_i2c_adapter *i2c_adapter);
116 struct i2c_adapter_transition {
117 void (*entry_fn)(struct pios_i2c_adapter *i2c_adapter);
118 enum i2c_adapter_state next_state[I2C_EVENT_NUM_EVENTS];
121 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter);
122 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event);
123 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter);
124 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter);
125 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter);
127 static void i2c_adapter_log_fault(enum pios_i2c_error_type type);
129 static const struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
130 [I2C_STATE_FSM_FAULT] = {
131 .entry_fn = go_fsm_fault,
132 .next_state = {
133 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
136 [I2C_STATE_BUS_ERROR] = {
137 .entry_fn = go_bus_error,
138 .next_state = {
139 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
143 [I2C_STATE_STOPPED] = {
144 .entry_fn = go_stopped,
145 .next_state = {
146 [I2C_EVENT_START] = I2C_STATE_STARTING,
147 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
151 [I2C_STATE_STOPPING] = {
152 .entry_fn = go_stopping,
153 .next_state = {
154 [I2C_EVENT_STOPPED] = I2C_STATE_STOPPED,
155 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
159 [I2C_STATE_STARTING] = {
160 .entry_fn = go_starting,
161 .next_state = {
162 [I2C_EVENT_STARTED_MORE_TXN_READ] = I2C_STATE_R_MORE_TXN_ADDR,
163 [I2C_EVENT_STARTED_MORE_TXN_WRITE] = I2C_STATE_W_MORE_TXN_ADDR,
164 [I2C_EVENT_STARTED_LAST_TXN_READ] = I2C_STATE_R_LAST_TXN_ADDR,
165 [I2C_EVENT_STARTED_LAST_TXN_WRITE] = I2C_STATE_W_LAST_TXN_ADDR,
166 [I2C_EVENT_NACK] = I2C_STATE_NACK,
167 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
172 * Read with restart
175 [I2C_STATE_R_MORE_TXN_ADDR] = {
176 .entry_fn = go_r_any_txn_addr,
177 .next_state = {
178 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_PRE_ONE,
179 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
180 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
181 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
185 [I2C_STATE_R_MORE_TXN_PRE_ONE] = {
186 .entry_fn = go_r_more_txn_pre_one,
187 .next_state = {
188 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
189 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
193 [I2C_STATE_R_MORE_TXN_PRE_FIRST] = {
194 .entry_fn = go_r_any_txn_pre_first,
195 .next_state = {
196 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
197 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
198 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
202 [I2C_STATE_R_MORE_TXN_PRE_MIDDLE] = {
203 .entry_fn = go_r_any_txn_pre_middle,
204 .next_state = {
205 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
206 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
207 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
211 [I2C_STATE_R_MORE_TXN_PRE_LAST] = {
212 .entry_fn = go_r_more_txn_pre_last,
213 .next_state = {
214 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_POST_LAST,
215 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
219 [I2C_STATE_R_MORE_TXN_POST_LAST] = {
220 .entry_fn = go_r_any_txn_post_last,
221 .next_state = {
222 [I2C_EVENT_AUTO] = I2C_STATE_STARTING,
227 * Read
230 [I2C_STATE_R_LAST_TXN_ADDR] = {
231 .entry_fn = go_r_any_txn_addr,
232 .next_state = {
233 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_PRE_ONE,
234 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
235 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
236 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
240 [I2C_STATE_R_LAST_TXN_PRE_ONE] = {
241 .entry_fn = go_r_last_txn_pre_one,
242 .next_state = {
243 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
244 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
248 [I2C_STATE_R_LAST_TXN_PRE_FIRST] = {
249 .entry_fn = go_r_any_txn_pre_first,
250 .next_state = {
251 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
252 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
253 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
257 [I2C_STATE_R_LAST_TXN_PRE_MIDDLE] = {
258 .entry_fn = go_r_any_txn_pre_middle,
259 .next_state = {
260 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
261 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
262 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
266 [I2C_STATE_R_LAST_TXN_PRE_LAST] = {
267 .entry_fn = go_r_last_txn_pre_last,
268 .next_state = {
269 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
270 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
274 [I2C_STATE_R_LAST_TXN_POST_LAST] = {
275 .entry_fn = go_r_any_txn_post_last,
276 .next_state = {
277 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
282 * Write with restart
285 [I2C_STATE_W_MORE_TXN_ADDR] = {
286 .entry_fn = go_w_any_txn_addr,
287 .next_state = {
288 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
289 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
290 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
291 [I2C_EVENT_NACK] = I2C_STATE_NACK,
292 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
296 [I2C_STATE_W_MORE_TXN_MIDDLE] = {
297 .entry_fn = go_w_any_txn_middle,
298 .next_state = {
299 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_LAST,
300 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
301 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_MORE_TXN_MIDDLE,
302 [I2C_EVENT_NACK] = I2C_STATE_NACK,
303 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
307 [I2C_STATE_W_MORE_TXN_LAST] = {
308 .entry_fn = go_w_more_txn_last,
309 .next_state = {
310 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STARTING,
311 [I2C_EVENT_NACK] = I2C_STATE_NACK,
312 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
317 * Write
320 [I2C_STATE_W_LAST_TXN_ADDR] = {
321 .entry_fn = go_w_any_txn_addr,
322 .next_state = {
323 [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
324 [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
325 [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
326 [I2C_EVENT_NACK] = I2C_STATE_NACK,
327 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
331 [I2C_STATE_W_LAST_TXN_MIDDLE] = {
332 .entry_fn = go_w_any_txn_middle,
333 .next_state = {
334 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_LAST,
335 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
336 [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_LAST_TXN_MIDDLE,
337 [I2C_EVENT_NACK] = I2C_STATE_NACK,
338 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
342 [I2C_STATE_W_LAST_TXN_LAST] = {
343 .entry_fn = go_w_last_txn_last,
344 .next_state = {
345 [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_STOPPING,
346 [I2C_EVENT_NACK] = I2C_STATE_NACK,
347 [I2C_EVENT_BUS_ERROR] = I2C_STATE_BUS_ERROR,
350 [I2C_STATE_NACK] = {
351 .entry_fn = go_nack,
352 .next_state = {
353 [I2C_EVENT_AUTO] = I2C_STATE_STOPPING,
358 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter)
360 #if defined(I2C_HALT_ON_ERRORS)
361 PIOS_DEBUG_Assert(0);
362 #endif
363 /* Note that this transfer has hit a bus error */
364 i2c_adapter->bus_error = true;
366 i2c_adapter_reset_bus(i2c_adapter);
369 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter)
371 /* Note that this transfer has hit a bus error */
372 i2c_adapter->bus_error = true;
374 i2c_adapter_reset_bus(i2c_adapter);
377 static void go_stopping(struct pios_i2c_adapter *i2c_adapter)
379 #ifdef USE_FREERTOS
380 signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
381 #endif
383 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
385 #ifdef USE_FREERTOS
386 if (xSemaphoreGiveFromISR(i2c_adapter->sem_ready, &pxHigherPriorityTaskWoken) != pdTRUE) {
387 #if defined(I2C_HALT_ON_ERRORS)
388 PIOS_DEBUG_Assert(0);
389 #endif
391 portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
392 #endif /* USE_FREERTOS */
395 static void go_stopped(struct pios_i2c_adapter *i2c_adapter)
397 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
398 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
401 static void go_starting(struct pios_i2c_adapter *i2c_adapter)
403 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
404 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
405 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
407 // check for an empty read/write
408 if (i2c_adapter->active_txn->buf != NULL && i2c_adapter->active_txn->len != 0) {
409 // Data available
410 i2c_adapter->active_byte = &(i2c_adapter->active_txn->buf[0]);
411 i2c_adapter->last_byte = &(i2c_adapter->active_txn->buf[i2c_adapter->active_txn->len - 1]);
412 } else {
413 // No Data available => Empty read/write
414 i2c_adapter->last_byte = NULL;
415 i2c_adapter->active_byte = i2c_adapter->last_byte + 1;
419 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
420 if (i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ) {
421 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
422 } else {
423 // For write operations, do not enable the IT_BUF events.
424 // The current driver does not act when the TX data register is not full, only when the complete byte is sent.
425 // With the IT_BUF enabled, we constantly get IRQs, See OP-326
426 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_ERR, ENABLE);
430 /* Common to 'more' and 'last' transaction */
431 static void go_r_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
433 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
434 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
435 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
437 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_READ);
439 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Receiver);
442 static void go_r_more_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
444 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
445 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
448 static void go_r_last_txn_pre_one(struct pios_i2c_adapter *i2c_adapter)
450 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
451 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
454 /* Common to 'more' and 'last' transaction */
455 static void go_r_any_txn_pre_first(struct pios_i2c_adapter *i2c_adapter)
457 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
460 /* Common to 'more' and 'last' transaction */
461 static void go_r_any_txn_pre_middle(struct pios_i2c_adapter *i2c_adapter)
463 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
464 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
466 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
468 /* Move to the next byte */
469 i2c_adapter->active_byte++;
470 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
473 static void go_r_more_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
475 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
476 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
478 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
479 PIOS_IRQ_Disable();
480 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
481 I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
482 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
483 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
484 PIOS_IRQ_Enable();
486 /* Move to the next byte */
487 i2c_adapter->active_byte++;
488 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
491 static void go_r_last_txn_pre_last(struct pios_i2c_adapter *i2c_adapter)
493 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
494 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
496 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
497 PIOS_IRQ_Disable();
498 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
499 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
500 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
501 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
502 PIOS_IRQ_Enable();
504 /* Move to the next byte */
505 i2c_adapter->active_byte++;
506 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
509 /* Common to 'more' and 'last' transaction */
510 static void go_r_any_txn_post_last(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);
514 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
515 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
516 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
518 *(i2c_adapter->active_byte) = I2C_ReceiveData(i2c_adapter->cfg->regs);
520 /* Move to the next byte */
521 i2c_adapter->active_byte++;
523 /* Move to the next transaction */
524 i2c_adapter->active_txn++;
527 /* Common to 'more' and 'last' transaction */
528 static void go_w_any_txn_addr(struct pios_i2c_adapter *i2c_adapter)
530 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
531 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
532 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
534 PIOS_DEBUG_Assert(i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE);
536 I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Transmitter);
539 static void go_w_any_txn_middle(struct pios_i2c_adapter *i2c_adapter)
541 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
542 PIOS_DEBUG_Assert(i2c_adapter->active_byte < i2c_adapter->last_byte);
543 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
544 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
545 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
547 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
549 /* Move to the next byte */
550 i2c_adapter->active_byte++;
551 PIOS_DEBUG_Assert(i2c_adapter->active_byte <= i2c_adapter->last_byte);
554 static void go_w_more_txn_last(struct pios_i2c_adapter *i2c_adapter)
556 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
557 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
558 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
559 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
560 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
562 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
564 /* Move to the next byte */
565 i2c_adapter->active_byte++;
567 /* Move to the next transaction */
568 i2c_adapter->active_txn++;
569 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
572 static void go_w_last_txn_last(struct pios_i2c_adapter *i2c_adapter)
574 PIOS_DEBUG_Assert(i2c_adapter->active_byte);
575 PIOS_DEBUG_Assert(i2c_adapter->active_byte == i2c_adapter->last_byte);
576 PIOS_DEBUG_Assert(i2c_adapter->active_txn);
577 PIOS_DEBUG_Assert(i2c_adapter->active_txn >= i2c_adapter->first_txn);
578 PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
580 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
581 I2C_SendData(i2c_adapter->cfg->regs, *(i2c_adapter->active_byte));
583 // SHOULD MOVE THIS INTO A STOPPING STATE AND SET IT ONLY AFTER THE BYTE WAS SENT
584 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
586 /* Move to the next byte */
587 i2c_adapter->active_byte++;
590 static void go_nack(struct pios_i2c_adapter *i2c_adapter)
592 I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
593 I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
594 I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
597 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event)
599 PIOS_IRQ_Disable();
601 #if defined(PIOS_I2C_DIAGNOSTICS)
602 i2c_state_event_history[i2c_state_event_history_pointer] = event;
603 i2c_state_event_history_pointer = (i2c_state_event_history_pointer + 1) % I2C_LOG_DEPTH;
605 i2c_state_history[i2c_state_history_pointer] = i2c_adapter->curr_state;
606 i2c_state_history_pointer = (i2c_state_history_pointer + 1) % I2C_LOG_DEPTH;
608 if (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event] == I2C_STATE_FSM_FAULT) {
609 i2c_adapter_log_fault(PIOS_I2C_ERROR_FSM);
611 #endif
613 * Move to the next state
615 * This is done prior to calling the new state's entry function to
616 * guarantee that the entry function never depends on the previous
617 * state. This way, it cannot ever know what the previous state was.
619 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[event];
621 /* Call the entry function (if any) for the next state. */
622 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
623 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
626 /* Process any AUTO transitions in the FSM */
627 i2c_adapter_process_auto(i2c_adapter);
629 PIOS_IRQ_Enable();
632 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter)
634 PIOS_IRQ_Disable();
635 while (i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO]) {
636 i2c_adapter->curr_state = i2c_adapter_transitions[i2c_adapter->curr_state].next_state[I2C_EVENT_AUTO];
638 /* Call the entry function (if any) for the next state. */
639 if (i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn) {
640 i2c_adapter_transitions[i2c_adapter->curr_state].entry_fn(i2c_adapter);
644 PIOS_IRQ_Enable();
647 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter)
649 i2c_adapter_reset_bus(i2c_adapter);
650 i2c_adapter->curr_state = I2C_STATE_STOPPED;
653 static bool i2c_adapter_wait_for_stopped(struct pios_i2c_adapter *i2c_adapter)
655 uint32_t guard;
658 * Wait for the bus to return to the stopped state.
659 * This was pulled out of the FSM due to occasional
660 * failures at this transition which previously resulted
661 * in spinning on this bit in the ISR forever.
663 #define I2C_CR1_STOP_REQUESTED 0x0200
664 for (guard = 1000000; /* FIXME: should use the configured bus timeout */
665 guard && (i2c_adapter->cfg->regs->CR1 & I2C_CR1_STOP_REQUESTED); guard--) {
666 continue;
668 if (!guard) {
669 /* We timed out waiting for the stop condition */
670 return false;
673 return true;
676 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
678 /* Reset the I2C block */
679 I2C_DeInit(i2c_adapter->cfg->regs);
681 /* Make sure the bus is free by clocking it until any slaves release the bus. */
682 GPIO_InitTypeDef scl_gpio_init;
683 scl_gpio_init = i2c_adapter->cfg->scl.init;
684 scl_gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
685 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
686 GPIO_Init(i2c_adapter->cfg->scl.gpio, &scl_gpio_init);
688 GPIO_InitTypeDef sda_gpio_init;
689 sda_gpio_init = i2c_adapter->cfg->sda.init;
690 sda_gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
691 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
692 GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
694 /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
695 /* have to be repeated (due to futher bus errors) but better than clocking 0xFF into an */
696 /* ESC */
697 // bool sda_hung = GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET;
698 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET) {
699 /* Set clock high and wait for any clock stretching to finish. */
700 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
701 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) {
704 PIOS_DELAY_WaituS(2);
706 /* Set clock low */
707 GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
708 PIOS_DELAY_WaituS(2);
710 /* Clock high again */
711 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
712 PIOS_DELAY_WaituS(2);
715 /* Generate a start then stop condition */
716 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
717 PIOS_DELAY_WaituS(2);
718 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
719 PIOS_DELAY_WaituS(2);
720 GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
721 PIOS_DELAY_WaituS(2);
723 /* Set data and clock high and wait for any clock stretching to finish. */
724 GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
725 GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
726 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) {
729 /* Wait for data to be high */
730 while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET) {
735 /* Bus signals are guaranteed to be high (ie. free) after this point */
736 /* Initialize the GPIO pins to the peripheral function */
737 GPIO_Init(i2c_adapter->cfg->scl.gpio, &(i2c_adapter->cfg->scl.init));
738 GPIO_Init(i2c_adapter->cfg->sda.gpio, &(i2c_adapter->cfg->sda.init));
740 /* Reset the I2C block */
741 I2C_DeInit(i2c_adapter->cfg->regs);
743 /* Initialize the I2C block */
744 I2C_Init(i2c_adapter->cfg->regs, &(i2c_adapter->cfg->init));
746 #define I2C_BUSY 0x20
747 if (i2c_adapter->cfg->regs->SR2 & I2C_BUSY) {
748 /* Reset the I2C block */
749 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, ENABLE);
750 I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, DISABLE);
754 #include <pios_i2c_priv.h>
756 /* Return true if the FSM is in a terminal state */
757 static bool i2c_adapter_fsm_terminated(struct pios_i2c_adapter *i2c_adapter)
759 switch (i2c_adapter->curr_state) {
760 case I2C_STATE_STOPPING:
761 case I2C_STATE_STOPPED:
762 return true;
764 default:
765 return false;
770 * Logs the last N state transitions and N IRQ events due to
771 * an error condition
772 * \param[in] i2c the adapter number to log an event for
774 void i2c_adapter_log_fault(enum pios_i2c_error_type type)
776 #if defined(PIOS_I2C_DIAGNOSTICS)
777 i2c_adapter_fault_history.type = type;
778 for (uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
779 i2c_adapter_fault_history.evirq[i] =
780 i2c_evirq_history[(I2C_LOG_DEPTH + i2c_evirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
781 i2c_adapter_fault_history.erirq[i] =
782 i2c_erirq_history[(I2C_LOG_DEPTH + i2c_erirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
783 i2c_adapter_fault_history.event[i] =
784 i2c_state_event_history[(I2C_LOG_DEPTH + i2c_state_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
785 i2c_adapter_fault_history.state[i] =
786 i2c_state_history[(I2C_LOG_DEPTH + i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
788 switch (type) {
789 case PIOS_I2C_ERROR_EVENT:
790 i2c_bad_event_counter++;
791 break;
792 case PIOS_I2C_ERROR_FSM:
793 i2c_fsm_fault_count++;
794 break;
795 case PIOS_I2C_ERROR_INTERRUPT:
796 i2c_error_interrupt_counter++;
797 break;
799 #endif /* if defined(PIOS_I2C_DIAGNOSTICS) */
804 * Logs the last N state transitions and N IRQ events due to
805 * an error condition
806 * \param[out] data address where to copy the pios_i2c_fault_history structure to
807 * \param[out] counts three uint16 that receive the bad event, fsm, and error irq
808 * counts
810 void PIOS_I2C_GetDiagnostics(struct pios_i2c_fault_history *data, uint8_t *counts)
812 #if defined(PIOS_I2C_DIAGNOSTICS)
813 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
814 counts[0] = i2c_bad_event_counter;
815 counts[1] = i2c_fsm_fault_count;
816 counts[2] = i2c_error_interrupt_counter;
817 counts[3] = i2c_nack_counter;
818 counts[4] = i2c_timeout_counter;
819 #else
820 struct pios_i2c_fault_history i2c_adapter_fault_history;
821 i2c_adapter_fault_history.type = PIOS_I2C_ERROR_EVENT;
823 memcpy(data, &i2c_adapter_fault_history, sizeof(i2c_adapter_fault_history));
824 counts[0] = counts[1] = counts[2] = 0;
825 #endif
828 static bool PIOS_I2C_validate(struct pios_i2c_adapter *i2c_adapter)
830 return i2c_adapter->magic == PIOS_I2C_DEV_MAGIC;
833 #if defined(PIOS_INCLUDE_FREERTOS)
834 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
836 struct pios_i2c_adapter *i2c_adapter;
838 i2c_adapter = (struct pios_i2c_adapter *)pios_malloc(sizeof(*i2c_adapter));
839 if (!i2c_adapter) {
840 return NULL;
843 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
844 return i2c_adapter;
846 #else
847 static struct pios_i2c_adapter pios_i2c_adapters[PIOS_I2C_MAX_DEVS];
848 static uint8_t pios_i2c_num_adapters;
849 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
851 struct pios_i2c_adapter *i2c_adapter;
853 if (pios_i2c_num_adapters >= PIOS_I2C_MAX_DEVS) {
854 return NULL;
857 i2c_adapter = &pios_i2c_adapters[pios_i2c_num_adapters++];
858 i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
860 return i2c_adapter;
862 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
866 * Initializes IIC driver
867 * \param[in] mode currently only mode 0 supported
868 * \return < 0 if initialisation failed
870 int32_t PIOS_I2C_Init(uint32_t *i2c_id, const struct pios_i2c_adapter_cfg *cfg)
872 PIOS_DEBUG_Assert(i2c_id);
873 PIOS_DEBUG_Assert(cfg);
875 struct pios_i2c_adapter *i2c_adapter;
877 i2c_adapter = (struct pios_i2c_adapter *)PIOS_I2C_alloc();
878 if (!i2c_adapter) {
879 goto out_fail;
882 /* Bind the configuration to the device instance */
883 i2c_adapter->cfg = cfg;
885 #ifdef USE_FREERTOS
887 * Must be done prior to calling i2c_adapter_fsm_init()
888 * since the sem_ready mutex is used in the initial state.
890 vSemaphoreCreateBinary(i2c_adapter->sem_ready);
891 i2c_adapter->sem_busy = xSemaphoreCreateMutex();
892 #endif // USE_FREERTOS
894 /* Enable the associated peripheral clock */
895 switch ((uint32_t)i2c_adapter->cfg->regs) {
896 case (uint32_t)I2C1:
897 /* Enable I2C peripheral clock (APB1 == slow speed) */
898 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
899 break;
900 case (uint32_t)I2C2:
901 /* Enable I2C peripheral clock (APB1 == slow speed) */
902 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
903 break;
906 if (i2c_adapter->cfg->remap) {
907 GPIO_PinRemapConfig(i2c_adapter->cfg->remap, ENABLE);
910 /* Initialize the state machine */
911 i2c_adapter_fsm_init(i2c_adapter);
913 *i2c_id = (uint32_t)i2c_adapter;
915 /* Configure and enable I2C interrupts */
916 NVIC_Init(&(i2c_adapter->cfg->event.init));
917 NVIC_Init(&(i2c_adapter->cfg->error.init));
919 /* No error */
920 return 0;
922 out_fail:
923 return -1;
927 * @brief Perform a series of I2C transactions
928 * @returns 0 if success or error code
929 * @retval -1 for failed transaction
930 * @retval -2 for failure to get semaphore
932 int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
934 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
936 if (!PIOS_I2C_validate(i2c_adapter)) {
937 return -1;
940 PIOS_DEBUG_Assert(txn_list);
941 PIOS_DEBUG_Assert(num_txns);
943 bool semaphore_success = true;
945 #ifdef USE_FREERTOS
946 /* Lock the bus */
947 portTickType timeout;
948 timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS;
949 if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) {
950 return -2;
952 #else
953 uint32_t timeout = 0xfff;
954 while (i2c_adapter->busy && --timeout) {
957 if (timeout == 0) { // timed out
958 return false;
961 PIOS_IRQ_Disable();
962 if (i2c_adapter->busy) {
963 return false;
965 i2c_adapter->busy = 1;
966 PIOS_IRQ_Enable();
967 #endif /* USE_FREERTOS */
969 PIOS_DEBUG_Assert(i2c_adapter->curr_state == I2C_STATE_STOPPED);
971 i2c_adapter->first_txn = &txn_list[0];
972 i2c_adapter->last_txn = &txn_list[num_txns - 1];
973 i2c_adapter->active_txn = i2c_adapter->first_txn;
975 #ifdef USE_FREERTOS
976 /* Make sure the done/ready semaphore is consumed before we start */
977 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
978 #endif
980 // Estimate bytes of transmission. Per txns: 1 adress byte + length
981 i2c_adapter->transfer_timeout_ticks = num_txns;
982 for (uint32_t i = 0; i < num_txns; i++) {
983 i2c_adapter->transfer_timeout_ticks += txn_list[i].len;
985 // timeout if it takes eight times the expected time
986 i2c_adapter->transfer_timeout_ticks <<= 3;
988 i2c_adapter->bus_error = false;
989 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START);
991 /* Wait for the transfer to complete */
992 #ifdef USE_FREERTOS
993 semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_ready, timeout) == pdTRUE);
994 xSemaphoreGive(i2c_adapter->sem_ready);
995 #else
996 PIOS_IRQ_Disable();
997 i2c_adapter->busy = 0;
998 PIOS_IRQ_Enable();
999 #endif /* USE_FREERTOS */
1001 /* Spin waiting for the transfer to finish */
1002 while (!i2c_adapter_fsm_terminated(i2c_adapter)) {
1003 /* sleep 9 clock ticks (1 byte), because FSM can't be faster than one byte
1004 FIXME: clock streching could make problems, but citing NPX: alsmost no slave device implements clock stretching
1005 three times the expected time should cover clock delay */
1006 PIOS_DELAY_WaituS(i2c_adapter->transfer_delay_uS);
1008 i2c_adapter->transfer_timeout_ticks--;
1009 if (i2c_adapter->transfer_timeout_ticks == 0) {
1010 break;
1014 if (i2c_adapter_wait_for_stopped(i2c_adapter)) {
1015 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOPPED);
1016 } else {
1017 i2c_adapter_fsm_init(i2c_adapter);
1020 #ifdef USE_FREERTOS
1021 /* Unlock the bus */
1022 xSemaphoreGive(i2c_adapter->sem_busy);
1023 if (!semaphore_success) {
1024 i2c_timeout_counter++;
1026 #endif /* USE_FREERTOS */
1028 return !semaphore_success ? -2 :
1029 i2c_adapter->bus_error ? -1 :
1034 void PIOS_I2C_EV_IRQ_Handler(uint32_t i2c_id)
1036 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1038 if (!PIOS_I2C_validate(i2c_adapter)) {
1039 return;
1042 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1044 #if defined(PIOS_I2C_DIAGNOSTICS)
1045 /* Store event for diagnostics */
1046 i2c_evirq_history[i2c_evirq_history_pointer] = event;
1047 i2c_evirq_history_pointer = (i2c_evirq_history_pointer + 1) % I2C_LOG_DEPTH;
1048 #endif
1050 #define EVENT_MASK 0x000700FF
1051 event &= EVENT_MASK;
1054 switch (event) { /* Mask out all the bits we don't care about */
1055 case (I2C_EVENT_MASTER_MODE_SELECT | 0x40):
1056 /* Unexplained event: EV5 + RxNE : Extraneous Rx. Probably a late NACK from previous read. */
1057 /* Clean up the extra Rx until the root cause is identified and just keep going */
1058 (void)I2C_ReceiveData(i2c_adapter->cfg->regs);
1059 /* Fall through */
1060 case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
1061 switch (i2c_adapter->active_txn->rw) {
1062 case PIOS_I2C_TXN_READ:
1063 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1064 /* Final transaction */
1065 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_READ);
1066 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1067 /* More transactions follow */
1068 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_READ);
1069 } else {
1070 PIOS_DEBUG_Assert(0);
1072 break;
1073 case PIOS_I2C_TXN_WRITE:
1074 if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1075 /* Final transaction */
1076 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_LAST_TXN_WRITE);
1077 } else if (i2c_adapter->active_txn < i2c_adapter->last_txn) {
1078 /* More transactions follow */
1079 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STARTED_MORE_TXN_WRITE);
1080 } else {
1081 PIOS_DEBUG_Assert(0);
1083 break;
1084 default:
1085 PIOS_DEBUG_Assert(0);
1086 break;
1088 break;
1089 case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
1090 case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
1091 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1092 case 0:
1093 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_0);
1094 break;
1095 case 1:
1096 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_1);
1097 break;
1098 case 2:
1099 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_2);
1100 break;
1101 default:
1102 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_GT_2);
1103 break;
1105 break;
1106 case 0x80: /* TxE only. TRA + MSL + BUSY have been cleared before we got here. */
1107 /* Ignore */
1109 static volatile bool halt = FALSE;
1110 while (halt) {
1114 break;
1115 case 0: /* This triggers an FSM fault sometimes, but not having it stops things working */
1116 case 0x40: /* RxNE only. MSL + BUSY have already been cleared by HW. */
1117 case 0x44: /* RxNE + BTF. MSL + BUSY have already been cleared by HW. */
1118 case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
1119 case (I2C_EVENT_MASTER_BYTE_RECEIVED | 0x4): /* EV7 + BTF */
1120 case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
1121 case 0x84: /* TxE + BTF. EV8_2 but TRA + MSL + BUSY have already been cleared by HW. */
1122 switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1123 case 0:
1124 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0);
1125 break;
1126 case 1:
1127 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1);
1128 break;
1129 case 2:
1130 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2);
1131 break;
1132 default:
1133 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2);
1134 break;
1136 break;
1137 case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
1138 /* Ignore this event and wait for TRANSMITTED in case we can't keep up */
1139 goto skip_event;
1140 break;
1141 case 0x30084: /* Occurs between byte tranmistted and master mode selected */
1142 case 0x30000: /* Need to throw away this spurious event */
1143 case 0x30403 & EVENT_MASK: /* Detected this after got a NACK, probably stop bit */
1144 goto skip_event;
1145 break;
1146 default:
1147 i2c_adapter_log_fault(PIOS_I2C_ERROR_EVENT);
1148 #if defined(I2C_HALT_ON_ERRORS)
1149 PIOS_DEBUG_Assert(0);
1150 #endif
1151 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1152 break;
1155 skip_event:
1160 void PIOS_I2C_ER_IRQ_Handler(uint32_t i2c_id)
1162 struct pios_i2c_adapter *i2c_adapter = (struct pios_i2c_adapter *)i2c_id;
1164 if (!PIOS_I2C_validate(i2c_adapter)) {
1165 return;
1169 #if defined(PIOS_I2C_DIAGNOSTICS)
1170 uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1172 i2c_erirq_history[i2c_erirq_history_pointer] = event;
1173 i2c_erirq_history_pointer = (i2c_erirq_history_pointer + 1) % 5;
1175 #endif
1177 if (event & I2C_FLAG_AF) {
1178 i2c_nack_counter++;
1180 I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_AF);
1182 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK);
1183 } else { /* Mostly bus errors here */
1184 i2c_adapter_log_fault(PIOS_I2C_ERROR_INTERRUPT);
1186 /* Fail hard on any errors for now */
1187 i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR);
1191 #endif /* PIOS_INCLUDE_I2C */
1194 * @}
1195 * @}