dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_i2c.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  */
31 
32 /* Project Includes */
33 #include "pios.h"
34 
35 #if defined(PIOS_INCLUDE_I2C)
36 
37 #include <pios_i2c_priv.h>
38 
39 struct pios_i2c_adapter {
41  const struct pios_i2c_adapter_cfg * cfg;
42 
43  struct pios_mutex *lock;
44  struct pios_semaphore *sem_ready;
45 
46  bool bus_error;
47  bool nack;
48 
49  volatile enum i2c_adapter_state state;
50  const struct pios_i2c_txn *active_txn;
51  const struct pios_i2c_txn *last_txn;
52 
53  uint8_t *active_byte;
54  uint8_t *last_byte;
55 
56 #if defined(PIOS_I2C_DIAGNOSTICS)
57  volatile struct pios_i2c_fault_history i2c_adapter_fault_history;
58 
59  volatile uint32_t i2c_evirq_history[I2C_LOG_DEPTH];
60  volatile uint8_t i2c_evirq_history_pointer;
61 
62  volatile uint32_t i2c_erirq_history[I2C_LOG_DEPTH];
63  volatile uint8_t i2c_erirq_history_pointer;
64 
65  volatile enum i2c_adapter_state i2c_state_history[I2C_LOG_DEPTH];
66  volatile uint8_t i2c_state_history_pointer;
67 
68  volatile enum i2c_adapter_event i2c_state_event_history[I2C_LOG_DEPTH];
69  volatile uint8_t i2c_state_event_history_pointer;
70 
71  volatile uint32_t i2c_fsm_fault_count;
72  volatile uint32_t i2c_bad_event_counter;
73  volatile uint32_t i2c_error_interrupt_counter;
74  volatile uint32_t i2c_nack_counter;
75  volatile uint32_t i2c_timeout_counter;
76 #endif
77 };
78 
79 #if defined(PIOS_I2C_DIAGNOSTICS)
80 
81 #define I2C_DIAG(adapter, field, val) \
82  do { \
83  (adapter)->i2c_##field##_history[(adapter)->i2c_##field##_history_pointer] = val; \
84  (adapter)->i2c_##field##_history_pointer = ((adapter)->i2c_##field##_history_pointer + 1) % I2C_LOG_DEPTH; \
85  } while (0)
86 
87 #define I2C_DIAG_INCR(adapter, field) do { (adapter)->field++; } while (0)
88 #else
89 
90 #define I2C_DIAG(adapter, field, val) do { (void) (adapter); (void) (val); } while (0)
91 
92 #define I2C_DIAG_INCR(adapter, field) do { (void) (adapter); } while (0)
93 
94 #define i2c_adapter_log_fault(adapter, val) do { (void) (adapter); (void) (val); } while (0)
95 #endif
96 
97 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event, bool *woken);
98 
99 static bool PIOS_I2C_validate(struct pios_i2c_adapter *i2c_adapter)
100 {
101  return i2c_adapter->magic == PIOS_I2C_DEV_MAGIC;
102 }
103 
104 static struct pios_i2c_adapter *PIOS_I2C_alloc(void)
105 {
106  struct pios_i2c_adapter *i2c_adapter;
107 
108  i2c_adapter = PIOS_malloc(sizeof(struct pios_i2c_adapter));
109 
110  if (i2c_adapter == NULL)
111  return NULL;
112 
113  // init all to zero
114  memset(i2c_adapter, 0, sizeof(*i2c_adapter));
115 
116  // set magic
117  i2c_adapter->magic = PIOS_I2C_DEV_MAGIC;
118 
119  return i2c_adapter;
120 }
121 
122 static void i2c_adapter_reset_bus(struct pios_i2c_adapter *i2c_adapter)
123 {
124  uint8_t retry_count = 0;
125  uint8_t retry_count_clk = 0;
126  static const uint8_t MAX_I2C_RETRY_COUNT = 10;
127 
128  /* Reset the I2C block */
129  I2C_DeInit(i2c_adapter->cfg->regs);
130 
131  /* Make sure the bus is free by clocking it until any slaves release the bus. */
132  GPIO_InitTypeDef scl_gpio_init;
133  scl_gpio_init = i2c_adapter->cfg->scl.init;
134  scl_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
135  GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
136  GPIO_Init(i2c_adapter->cfg->scl.gpio, &scl_gpio_init);
137 
138  GPIO_InitTypeDef sda_gpio_init;
139  sda_gpio_init = i2c_adapter->cfg->sda.init;
140  sda_gpio_init.GPIO_Mode = GPIO_Mode_OUT;
141  GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
142  GPIO_Init(i2c_adapter->cfg->sda.gpio, &sda_gpio_init);
143 
144  /* Check SDA line to determine if slave is asserting bus and clock out if so, this may */
145  /* have to be repeated (due to further bus errors) but better than clocking 0xFF into an */
146  /* ESC */
147 
148  retry_count_clk = 0;
149  while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET && (retry_count_clk++ < MAX_I2C_RETRY_COUNT)) {
150  retry_count = 0;
151  /* Set clock high and wait for any clock stretching to finish. */
152  GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
153  while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT))
155 
157 
158  /* Set clock low */
159  GPIO_ResetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
161 
162  /* Clock high again */
163  GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
165  }
166 
167  /* Generate a start then stop condition */
168  GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
170  GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
172  GPIO_ResetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
174 
175  /* Set data and clock high and wait for any clock stretching to finish. */
176  GPIO_SetBits(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin);
177  GPIO_SetBits(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin);
178 
179  retry_count = 0;
180  while (GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET && (retry_count++ < MAX_I2C_RETRY_COUNT))
182 
183  /* Wait for data to be high */
184  retry_count = 0;
185  while (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) != Bit_SET && (retry_count++ < MAX_I2C_RETRY_COUNT))
187 
188  /* Bus signals are guaranteed to be high (ie. free) after this point */
189  /* Initialize the GPIO pins to the peripheral function */
190  if (i2c_adapter->cfg->remap) {
191  GPIO_PinAFConfig(i2c_adapter->cfg->scl.gpio,
192  __builtin_ctz(i2c_adapter->cfg->scl.init.GPIO_Pin),
193  i2c_adapter->cfg->remap);
194  GPIO_PinAFConfig(i2c_adapter->cfg->sda.gpio,
195  __builtin_ctz(i2c_adapter->cfg->sda.init.GPIO_Pin),
196  i2c_adapter->cfg->remap);
197  }
198  GPIO_Init(i2c_adapter->cfg->scl.gpio, (GPIO_InitTypeDef *) & (i2c_adapter->cfg->scl.init)); // Struct is const, function signature not
199  GPIO_Init(i2c_adapter->cfg->sda.gpio, (GPIO_InitTypeDef *) & (i2c_adapter->cfg->sda.init));
200 
201  /* Reset the I2C block */
202  I2C_DeInit(i2c_adapter->cfg->regs);
203 
204  /* Initialize the I2C block */
205  I2C_Init(i2c_adapter->cfg->regs, (I2C_InitTypeDef *) & (i2c_adapter->cfg->init));
206 
207  /* Enable the I2C block */
208  I2C_Cmd(i2c_adapter->cfg->regs, ENABLE);
209 
210 #if defined(STM32F30X)
211  if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_BUSY))
212  I2C_SoftwareResetCmd(i2c_adapter->cfg->regs);
213 #elif defined(STM32F4XX)
214  if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_BUSY))
215  I2C_SoftwareResetCmd(i2c_adapter->cfg->regs, ENABLE);
216 #endif
217 }
218 
225 int32_t PIOS_I2C_CheckClear(pios_i2c_t i2c_adapter)
226 {
227  bool valid = PIOS_I2C_validate(i2c_adapter);
228  PIOS_Assert(valid);
229 
230  if (PIOS_Mutex_Lock(i2c_adapter->lock, 0) == false)
231  return -1;
232 
233  if (i2c_adapter->state != I2C_STATE_STOPPED) {
234  PIOS_Mutex_Unlock(i2c_adapter->lock);
235  return -2;
236  }
237 
238  if (GPIO_ReadInputDataBit(i2c_adapter->cfg->sda.gpio, i2c_adapter->cfg->sda.init.GPIO_Pin) == Bit_RESET ||
239  GPIO_ReadInputDataBit(i2c_adapter->cfg->scl.gpio, i2c_adapter->cfg->scl.init.GPIO_Pin) == Bit_RESET) {
240  PIOS_Mutex_Unlock(i2c_adapter->lock);
241  return -3;
242  }
243 
244  PIOS_Mutex_Unlock(i2c_adapter->lock);
245 
246  return 0;
247 }
248 
249 static void i2c_adapter_fsm_init(struct pios_i2c_adapter *i2c_adapter)
250 {
251  i2c_adapter_reset_bus(i2c_adapter);
252  i2c_adapter->state = I2C_STATE_STOPPED;
253 }
254 
260 int32_t PIOS_I2C_Init(pios_i2c_t *i2c_id, const struct pios_i2c_adapter_cfg *cfg)
261 {
262  PIOS_DEBUG_Assert(i2c_id);
263  PIOS_DEBUG_Assert(cfg);
264 
265  struct pios_i2c_adapter *i2c_adapter;
266 
267  i2c_adapter = (struct pios_i2c_adapter *) PIOS_I2C_alloc();
268  if (!i2c_adapter)
269  goto out_fail;
270 
271  /* Bind the configuration to the device instance */
272  i2c_adapter->cfg = cfg;
273 
274  i2c_adapter->sem_ready = PIOS_Semaphore_Create();
275  i2c_adapter->lock = PIOS_Mutex_Create();
276 
277  /* Initialize the state machine */
278  i2c_adapter_fsm_init(i2c_adapter);
279 
280  if (PIOS_I2C_CheckClear(i2c_adapter)) {
281  /* Check for sanity before returning adapter and
282  * initing interrupts
283  */
284  goto out_fail;
285  }
286 
287  *i2c_id = i2c_adapter;
288 
289  /* Configure and enable I2C interrupts */
290  NVIC_Init((NVIC_InitTypeDef *) & (i2c_adapter->cfg->event.init));
291  NVIC_Init((NVIC_InitTypeDef *) & (i2c_adapter->cfg->error.init));
292 
293  /* No error */
294  return 0;
295 
296 out_fail:
297  return -1;
298 }
299 
300 int32_t PIOS_I2C_Transfer(pios_i2c_t i2c_adapter, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
301 {
302  bool valid = PIOS_I2C_validate(i2c_adapter);
303  PIOS_Assert(valid);
304 
305  PIOS_DEBUG_Assert(txn_list);
306  PIOS_DEBUG_Assert(num_txns);
307 
308  if (PIOS_Mutex_Lock(i2c_adapter->lock, i2c_adapter->cfg->transfer_timeout_ms) == false)
309  return -2;
310 
311  PIOS_DEBUG_Assert(i2c_adapter->state == I2C_STATE_STOPPED);
312 
313  i2c_adapter->last_txn = &txn_list[num_txns - 1];
314  i2c_adapter->active_txn = &txn_list[0];
315  i2c_adapter->bus_error = false;
316  i2c_adapter->nack = false;
317 
318  /* Make sure the done/ready semaphore is consumed before we start */
319  PIOS_Semaphore_Take(i2c_adapter->sem_ready, 0);
320 
321  bool dummy = false;
322  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_START, &dummy);
323 
324  /* Wait for the transfer to complete */
325  bool semaphore_success = (PIOS_Semaphore_Take(i2c_adapter->sem_ready, i2c_adapter->cfg->transfer_timeout_ms) == true);
326 
327  if (!semaphore_success)
328  I2C_DIAG_INCR(i2c_adapter, i2c_timeout_counter);
329 
330  int32_t result = !semaphore_success ? -2 :
331  i2c_adapter->bus_error ? -1 :
332  i2c_adapter->nack ? -3 :
333  0;
334 
335  PIOS_Mutex_Unlock(i2c_adapter->lock);
336 
337  return result;
338 }
339 
340 #if defined(PIOS_I2C_DIAGNOSTICS)
341 
346 static void i2c_adapter_log_fault(struct pios_i2c_adapter *i2c_adapter, enum pios_i2c_error_type type)
347 {
348  i2c_adapter->i2c_adapter_fault_history.type = type;
349  for (uint8_t i = 0; i < I2C_LOG_DEPTH; i++) {
350  i2c_adapter->i2c_adapter_fault_history.evirq[i] =
351  i2c_adapter->i2c_evirq_history[(I2C_LOG_DEPTH + i2c_adapter->i2c_evirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
352  i2c_adapter->i2c_adapter_fault_history.erirq[i] =
353  i2c_adapter->i2c_erirq_history[(I2C_LOG_DEPTH + i2c_adapter->i2c_erirq_history_pointer - 1 - i) % I2C_LOG_DEPTH];
354  i2c_adapter->i2c_adapter_fault_history.event[i] =
355  i2c_adapter->i2c_state_event_history[(I2C_LOG_DEPTH + i2c_adapter->i2c_state_event_history_pointer - 1 - i) % I2C_LOG_DEPTH];
356  i2c_adapter->i2c_adapter_fault_history.state[i] =
357  i2c_adapter->i2c_state_history[(I2C_LOG_DEPTH + i2c_adapter->i2c_state_history_pointer - 1 - i) % I2C_LOG_DEPTH];
358  }
359  switch (type) {
361  i2c_adapter->i2c_bad_event_counter++;
362  break;
363  case PIOS_I2C_ERROR_FSM:
364  i2c_adapter->i2c_fsm_fault_count++;
365  break;
367  i2c_adapter->i2c_error_interrupt_counter++;
368  break;
369  }
370 }
371 #endif
372 
373 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter, bool *woken);
374 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter, bool *woken);
375 static void go_stopped(struct pios_i2c_adapter *i2c_adapter, bool *woken);
376 static void go_starting(struct pios_i2c_adapter *i2c_adapter, bool *woken);
377 static void go_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken);
378 
379 //#define I2C_HALT_ON_ERRORS
380 
381 static void receive_byte(struct pios_i2c_adapter *i2c_adapter, bool *woken)
382 {
383  // read received byte from buffer
384  *i2c_adapter->active_byte = I2C_ReceiveData(i2c_adapter->cfg->regs);
385 
386  /* Move to the next byte */
387  i2c_adapter->active_byte++;
388 }
389 
390 static void send_byte(struct pios_i2c_adapter *i2c_adapter, bool *woken)
391 {
392  // write byte to buffer
393  I2C_SendData(i2c_adapter->cfg->regs, *i2c_adapter->active_byte);
394 
395  /* Move to the next byte */
396  i2c_adapter->active_byte++;
397 }
398 
399 
400 struct i2c_adapter_transition {
401  void (*entry_fn)(struct pios_i2c_adapter *i2c_adapter, bool *woken);
402  enum i2c_adapter_state next_state[I2C_EVENT_NUM_EVENTS];
403 };
404 
405 #if defined(STM32F30X)
406 static void go_transfer_complete(struct pios_i2c_adapter *i2c_adapter, bool *woken);
407 
408 const static struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
409  [I2C_STATE_FSM_FAULT] = {
410  .entry_fn = go_fsm_fault,
411  .next_state = {
413  },
414  },
415  [I2C_STATE_BUS_ERROR] = {
416  .entry_fn = go_bus_error,
417  .next_state = {
419  },
420  },
421 
422  [I2C_STATE_STOPPED] = {
423  .entry_fn = go_stopped,
424  .next_state = {
427  },
428  },
429 
430  [I2C_STATE_STARTING] = {
431  .entry_fn = go_starting,
432  .next_state = {
433  [I2C_EVENT_TRANSMIT_BUFFER_EMPTY] = I2C_STATE_WRITE_BYTE,
434  [I2C_EVENT_RECEIVER_BUFFER_NOT_EMPTY] = I2C_STATE_READ_BYTE,
437  },
438  },
439 
440  [I2C_STATE_WRITE_BYTE] = {
441  .entry_fn = send_byte,
442  .next_state = {
443  [I2C_EVENT_TRANSMIT_BUFFER_EMPTY] = I2C_STATE_WRITE_BYTE,
444  [I2C_EVENT_RECEIVER_BUFFER_NOT_EMPTY] = I2C_STATE_READ_BYTE,
445  [I2C_EVENT_TRANSFER_COMPLETE] = I2C_STATE_TRANSFER_COMPLETE,
448  },
449  },
450 
451  [I2C_STATE_READ_BYTE] = {
452  .entry_fn = receive_byte,
453  .next_state = {
454  [I2C_EVENT_TRANSMIT_BUFFER_EMPTY] = I2C_STATE_WRITE_BYTE,
455  [I2C_EVENT_RECEIVER_BUFFER_NOT_EMPTY] = I2C_STATE_READ_BYTE,
456  [I2C_EVENT_TRANSFER_COMPLETE] = I2C_STATE_TRANSFER_COMPLETE,
459  },
460  },
461 
463  .entry_fn = go_transfer_complete,
464  .next_state = {
467  },
468  },
469 
470  [I2C_STATE_NACK] = {
471  .entry_fn = go_nack,
472  .next_state = {
474  },
475  },
476 };
477 #elif defined(STM32F4XX)
478 
479 static void prepare_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken);
480 static void prepare_ack(struct pios_i2c_adapter *i2c_adapter, bool *woken);
481 static void receive_byte(struct pios_i2c_adapter *i2c_adapter, bool *woken);
482 static void send_byte(struct pios_i2c_adapter *i2c_adapter, bool *woken);
483 static void send_address_and_enable_BUF_intr(struct pios_i2c_adapter *i2c_adapter,
484  bool *woken);
485 static void send_w_address(struct pios_i2c_adapter *i2c_adapter, bool *woken);
486 static void receive_and_setup_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken);
487 static void advance_txn_and_start(struct pios_i2c_adapter *i2c_adapter, bool *woken);
488 
489 static void go_r_last_txn_post_last(struct pios_i2c_adapter *i2c_adapter, bool *woken);
490 
491 static void go_w_last_txn_post_last(struct pios_i2c_adapter *i2c_adapter, bool *woken);
492 
493 static const struct i2c_adapter_transition i2c_adapter_transitions[I2C_STATE_NUM_STATES] = {
494  [I2C_STATE_FSM_FAULT] = {
495  .entry_fn = go_fsm_fault,
496  .next_state = {
498  },
499  },
500  [I2C_STATE_BUS_ERROR] = {
501  .entry_fn = go_bus_error,
502  .next_state = {
504  },
505  },
506  [I2C_STATE_NACK] = {
507  .entry_fn = go_nack,
508  .next_state = {
510  },
511  },
512  [I2C_STATE_STOPPED] = {
513  .entry_fn = go_stopped,
514  .next_state = {
517  },
518  },
519  [I2C_STATE_STARTING] = {
520  .entry_fn = go_starting,
521  .next_state = {
522  [I2C_EVENT_R_MORE_TXN_STARTED] = I2C_STATE_R_MORE_TXN_ADDR,
523  [I2C_EVENT_W_MORE_TXN_STARTED] = I2C_STATE_W_MORE_TXN_ADDR,
524  [I2C_EVENT_R_LAST_TXN_STARTED] = I2C_STATE_R_LAST_TXN_ADDR,
525  [I2C_EVENT_W_LAST_TXN_STARTED] = I2C_STATE_W_LAST_TXN_ADDR,
528  },
529  },
530 
531  /*
532  * Read with restart
533  */
534  [I2C_STATE_R_MORE_TXN_ADDR] = {
535  .entry_fn = send_address_and_enable_BUF_intr,
536  .next_state = {
537  [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_MORE_TXN_PRE_ONE,
538  [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
539  [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_FIRST,
541  },
542  },
543  [I2C_STATE_R_MORE_TXN_PRE_ONE] = {
544  .entry_fn = prepare_nack,
545  .next_state = {
546  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_MORE_TXN_POST_LAST,
548  },
549  },
550  [I2C_STATE_R_MORE_TXN_PRE_FIRST] = {
551  .entry_fn = prepare_ack,
552  .next_state = {
553  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
554  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
556  },
557  },
558  [I2C_STATE_R_MORE_TXN_PRE_MIDDLE] = {
559  .entry_fn = receive_byte,
560  .next_state = {
561  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_MORE_TXN_PRE_LAST,
562  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_MORE_TXN_PRE_MIDDLE,
564  },
565  },
566  [I2C_STATE_R_MORE_TXN_PRE_LAST] = {
567  .entry_fn = receive_and_setup_nack,
568  .next_state = {
569  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_MORE_TXN_POST_LAST,
571  },
572  },
573 
574  /*
575  * Read with stop
576  */
577  [I2C_STATE_R_LAST_TXN_ADDR] = {
578  .entry_fn = send_address_and_enable_BUF_intr,
579  .next_state = {
580  [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_PRE_ONE,
581  [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
582  [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_FIRST,
584  },
585  },
586  [I2C_STATE_R_LAST_TXN_PRE_ONE] = {
587  .entry_fn = prepare_nack,
588  .next_state = {
589  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
591  },
592  },
593  [I2C_STATE_R_LAST_TXN_PRE_FIRST] = {
594  .entry_fn = prepare_ack,
595  .next_state = {
596  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
597  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
599  },
600  },
601  [I2C_STATE_R_LAST_TXN_PRE_MIDDLE] = {
602  .entry_fn = receive_byte,
603  .next_state = {
604  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_R_LAST_TXN_PRE_LAST,
605  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_R_LAST_TXN_PRE_MIDDLE,
607  },
608  },
609  [I2C_STATE_R_LAST_TXN_PRE_LAST] = {
610  .entry_fn = receive_and_setup_nack,
611  .next_state = {
612  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_R_LAST_TXN_POST_LAST,
614  },
615  },
616  [I2C_STATE_R_LAST_TXN_POST_LAST] = {
617  .entry_fn = go_r_last_txn_post_last,
618  .next_state = {
620  },
621  },
622 
623  /*
624  * Write with restart
625  */
626  [I2C_STATE_W_MORE_TXN_ADDR] = {
627  .entry_fn = send_w_address,
628  .next_state = {
629  [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_PRE,
630  [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_PRE,
631  [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_MORE_TXN_PRE,
633  },
634  },
635  [I2C_STATE_W_MORE_TXN_PRE] = {
636  .entry_fn = send_byte,
637  .next_state = {
638  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_MORE_TXN_POST_LAST,
639  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_MORE_TXN_PRE,
640  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_MORE_TXN_PRE,
641  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_MORE_TXN_PRE,
643  },
644  },
645 
646  /* Translation finishup before end of sequence */
647  [I2C_STATE_MORE_TXN_POST_LAST] = {
648  .entry_fn = advance_txn_and_start,
649  .next_state = {
650  [I2C_EVENT_R_MORE_TXN_STARTED] = I2C_STATE_R_MORE_TXN_ADDR,
651  [I2C_EVENT_W_MORE_TXN_STARTED] = I2C_STATE_W_MORE_TXN_ADDR,
652  [I2C_EVENT_R_LAST_TXN_STARTED] = I2C_STATE_R_LAST_TXN_ADDR,
653  [I2C_EVENT_W_LAST_TXN_STARTED] = I2C_STATE_W_LAST_TXN_ADDR,
656  },
657  },
658 
659  /*
660  * Write with stop
661  */
662  [I2C_STATE_W_LAST_TXN_ADDR] = {
663  .entry_fn = send_w_address,
664  .next_state = {
665  [I2C_EVENT_ADDR_SENT_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_PRE,
666  [I2C_EVENT_ADDR_SENT_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_PRE,
667  [I2C_EVENT_ADDR_SENT_LEN_GT_2] = I2C_STATE_W_LAST_TXN_PRE,
669  },
670  },
671  [I2C_STATE_W_LAST_TXN_PRE] = {
672  .entry_fn = send_byte,
673  .next_state = {
674  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_0] = I2C_STATE_W_LAST_TXN_POST_LAST,
675  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_1] = I2C_STATE_W_LAST_TXN_PRE,
676  [I2C_EVENT_TRANSFER_DONE_LEN_EQ_2] = I2C_STATE_W_LAST_TXN_PRE,
677  [I2C_EVENT_TRANSFER_DONE_LEN_GT_2] = I2C_STATE_W_LAST_TXN_PRE,
679  },
680  },
681  [I2C_STATE_W_LAST_TXN_POST_LAST] = {
682  .entry_fn = go_w_last_txn_post_last,
683  .next_state = {
685  },
686  },
687 };
688 
689 #endif /* STM32F4XX */
690 
691 static void i2c_adapter_process_auto(struct pios_i2c_adapter *i2c_adapter, bool *woken)
692 {
693  enum i2c_adapter_state prev_state = i2c_adapter->state;
694  if (prev_state);
695 
696  while (i2c_adapter_transitions[i2c_adapter->state].next_state[I2C_EVENT_AUTO]) {
697  i2c_adapter->state = i2c_adapter_transitions[i2c_adapter->state].next_state[I2C_EVENT_AUTO];
698 
699  /* Call the entry function (if any) for the next state. */
700  if (i2c_adapter_transitions[i2c_adapter->state].entry_fn) {
701  i2c_adapter_transitions[i2c_adapter->state].entry_fn(i2c_adapter, woken);
702  }
703  }
704 }
705 
706 static void i2c_adapter_inject_event(struct pios_i2c_adapter *i2c_adapter, enum i2c_adapter_event event, bool *woken)
707 {
708  I2C_DIAG(i2c_adapter, state_event, event);
709  I2C_DIAG(i2c_adapter, state, i2c_adapter->state);
710 
711  if (i2c_adapter_transitions[i2c_adapter->state].next_state[event] == I2C_STATE_FSM_FAULT)
712  i2c_adapter_log_fault(i2c_adapter, PIOS_I2C_ERROR_FSM);
713 
714  /*
715  * Move to the next state
716  *
717  * This is done prior to calling the new state's entry function to
718  * guarantee that the entry function never depends on the previous
719  * state. This way, it cannot ever know what the previous state was.
720  */
721  enum i2c_adapter_state prev_state = i2c_adapter->state;
722  if (prev_state);
723 
724  i2c_adapter->state = i2c_adapter_transitions[i2c_adapter->state].next_state[event];
725 
726  /* Call the entry function (if any) for the next state. */
727  if (i2c_adapter_transitions[i2c_adapter->state].entry_fn) {
728  i2c_adapter_transitions[i2c_adapter->state].entry_fn(i2c_adapter, woken);
729  }
730 
731  /* Process any AUTO transitions in the FSM */
732  i2c_adapter_process_auto(i2c_adapter, woken);
733 }
734 
735 static void go_fsm_fault(struct pios_i2c_adapter *i2c_adapter, bool *woken)
736 {
737 #if defined(I2C_HALT_ON_ERRORS)
739 #endif
740  /* Note that this transfer has hit a bus error */
741  i2c_adapter->bus_error = true;
742 
743  i2c_adapter_reset_bus(i2c_adapter);
744 }
745 
746 static void go_bus_error(struct pios_i2c_adapter *i2c_adapter, bool *woken)
747 {
748  /* Note that this transfer has hit a bus error */
749  i2c_adapter->bus_error = true;
750 
751  i2c_adapter_reset_bus(i2c_adapter);
752 }
753 
754 static void set_i2c_irqs(struct pios_i2c_adapter *i2c_adapter, FunctionalState new_state)
755 {
756 #if defined(STM32F30X)
757  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_NACKI | I2C_IT_RXI | I2C_IT_STOPI | I2C_IT_TXI, new_state);
758 #elif defined(STM32F4XX)
759  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, new_state);
760 #endif
761 }
762 
763 static void go_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken)
764 {
765  i2c_adapter->nack = true;
766  set_i2c_irqs(i2c_adapter, DISABLE); // XXX this one used to only happen on F3
767 
768  I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
769  I2C_GenerateSTART(i2c_adapter->cfg->regs, DISABLE);
770  I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
771 }
772 
773 static void go_stopped(struct pios_i2c_adapter *i2c_adapter, bool *woken)
774 {
775  set_i2c_irqs(i2c_adapter, DISABLE);
776 
777  /* wake up blocked PIOS_I2C_Transfer() */
778  if (PIOS_Semaphore_Give_FromISR(i2c_adapter->sem_ready, woken) == false) {
779 #if defined(I2C_HALT_ON_ERRORS)
781 #endif
782  }
783 }
784 
785 static void setup_txn_ptrs(struct pios_i2c_adapter *i2c_adapter)
786 {
787  // set up current txn byte pointers
788  i2c_adapter->active_byte = &(i2c_adapter->active_txn->buf[0]);
789  i2c_adapter->last_byte = &(i2c_adapter->active_txn->buf[i2c_adapter->active_txn->len - 1]);
790 }
791 
792 #if defined(STM32F30X)
793 static void go_starting(struct pios_i2c_adapter *i2c_adapter, bool *woken)
794 {
795  PIOS_DEBUG_Assert(i2c_adapter->active_txn);
796  PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
797  PIOS_DEBUG_Assert(i2c_adapter->active_txn->len <= 255); //FIXME: implement this using TCR
798 
799  setup_txn_ptrs(i2c_adapter);
800 
801  set_i2c_irqs(i2c_adapter, ENABLE);
802 
803  I2C_TransferHandling(
804  i2c_adapter->cfg->regs,
805  (i2c_adapter->active_txn->addr << 1),
806  i2c_adapter->active_txn->len,
807  i2c_adapter->active_txn == i2c_adapter->last_txn ? I2C_AutoEnd_Mode : I2C_SoftEnd_Mode,
808  i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE ? I2C_Generate_Start_Write : I2C_Generate_Start_Read);
809 }
810 
811 static void go_transfer_complete(struct pios_i2c_adapter *i2c_adapter, bool *woken)
812 {
813  /* Move to the next transaction */
814  i2c_adapter->active_txn++;
815  PIOS_DEBUG_Assert(i2c_adapter->active_txn <= i2c_adapter->last_txn);
816 }
817 
818 void PIOS_I2C_EV_IRQ_Handler(pios_i2c_t i2c_adapter)
819 {
821 
822  bool valid = PIOS_I2C_validate(i2c_adapter);
823  PIOS_Assert(valid);
824 
825  bool woken = false;
826 
827  if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_RXNE)) {
828  //flag will be cleared by event
829  I2C_DIAG(i2c_adapter, evirq, I2C_FLAG_RXNE);
830  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_RECEIVER_BUFFER_NOT_EMPTY, &woken);
831  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_TXIS)) {
832  //flag will be cleared by event
833  I2C_DIAG(i2c_adapter, evirq, I2C_FLAG_TXIS);
834  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSMIT_BUFFER_EMPTY, &woken);
835  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_NACKF)) {
836  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_NACKF);
837  I2C_DIAG(i2c_adapter, evirq, I2C_FLAG_NACKF);
838  I2C_DIAG_INCR(i2c_adapter, i2c_nack_counter);
839  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK, &woken);
840  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_TC)) {
841  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_TC);
842  I2C_DIAG(i2c_adapter, evirq, I2C_FLAG_TC);
843  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_COMPLETE, &woken);
844  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_STOPF)) {
845  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_STOPF);
846  I2C_DIAG(i2c_adapter, evirq, I2C_FLAG_STOPF);
847  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_STOP, &woken);
848  }
849 
851 }
852 
853 
854 void PIOS_I2C_ER_IRQ_Handler(pios_i2c_t i2c_adapter)
855 {
857 
858  bool valid = PIOS_I2C_validate(i2c_adapter);
859  PIOS_Assert(valid);
860 
861  if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_BERR)) {
862  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_BERR);
863  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_BERR);
864  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_ARLO)) {
865  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_ARLO);
866  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_ARLO);
867  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_OVR)) {
868  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_OVR);
869  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_OVR);
870  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_PECERR)) {
871  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_PECERR);
872  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_PECERR);
873  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_TIMEOUT)) {
874  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_TIMEOUT);
875  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_TIMEOUT);
876  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_ALERT)) {
877  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_ALERT);
878  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_ALERT);
879  } else if (I2C_GetFlagStatus(i2c_adapter->cfg->regs, I2C_FLAG_BUSY)) {
880  I2C_ClearFlag(i2c_adapter->cfg->regs, I2C_FLAG_BUSY);
881  I2C_DIAG(i2c_adapter, erirq, I2C_FLAG_BUSY);
882  }
883 
884  i2c_adapter_log_fault(i2c_adapter, PIOS_I2C_ERROR_INTERRUPT);
885 
886  /* Fail hard on any errors for now */
887  bool woken = false;
888  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR, &woken);
889 
891 }
892 
893 #elif defined(STM32F4XX)
894 
895 static void go_starting(struct pios_i2c_adapter *i2c_adapter, bool *woken)
896 {
897  setup_txn_ptrs(i2c_adapter);
898 
899  // enable interrupts
900  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_EVT | I2C_IT_ERR, ENABLE);
901 
902  // generate a start condition
903  I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
904 }
905 
906 static void send_address_and_enable_BUF_intr(struct pios_i2c_adapter *i2c_adapter,
907  bool *woken)
908 {
909  // enable buffer RxNE
910  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, ENABLE);
911 
912  I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Receiver);
913 }
914 
915 static void prepare_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken)
916 {
917  I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
918 }
919 
920 static void prepare_ack(struct pios_i2c_adapter *i2c_adapter, bool *woken)
921 {
922  I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, ENABLE);
923 }
924 
925 static void advance_txn_and_start(struct pios_i2c_adapter *i2c_adapter, bool *woken)
926 {
927  // the last byte of this txn has been transmitted, so disable the buffer TxE
928  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
929 
930  if (i2c_adapter->active_txn->rw == PIOS_I2C_TXN_WRITE) {
931  // do a dummy read to clear buf
932  (void)I2C_ReceiveData(i2c_adapter->cfg->regs);
933  } else {
934  receive_byte(i2c_adapter, woken);
935  }
936 
937  /* Move to the next transaction */
938  i2c_adapter->active_txn++;
939 
940  setup_txn_ptrs(i2c_adapter);
941 
942  // generate restart
943  I2C_GenerateSTART(i2c_adapter->cfg->regs, ENABLE);
944 }
945 
946 static void send_w_address(struct pios_i2c_adapter *i2c_adapter, bool *woken)
947 {
948  I2C_Send7bitAddress(i2c_adapter->cfg->regs, (i2c_adapter->active_txn->addr) << 1, I2C_Direction_Transmitter);
949 }
950 
951 static void receive_and_setup_nack(struct pios_i2c_adapter *i2c_adapter, bool *woken)
952 {
953  receive_byte(i2c_adapter, woken);
954 
955  // send a nack on the last byte
956  I2C_AcknowledgeConfig(i2c_adapter->cfg->regs, DISABLE);
957 }
958 
959 /*
960  * Read with stop
961  */
962 static void go_r_last_txn_post_last(struct pios_i2c_adapter *i2c_adapter, bool *woken)
963 {
964  // the last byte of this txn has been received, so disable the buffer RxNE
965  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
966 
967  receive_byte(i2c_adapter, woken);
968 
969  // generate a stop condition
970  I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
971 
972  /* Move to the next transaction */
973  i2c_adapter->active_txn++;
974 }
975 
976 
977 /*
978  * Write with stop
979  */
980 static void go_w_last_txn_post_last(struct pios_i2c_adapter *i2c_adapter, bool *woken)
981 {
982  // the last byte of this txn has been transmitted, so disable the buffer TxE
983  I2C_ITConfig(i2c_adapter->cfg->regs, I2C_IT_BUF, DISABLE);
984 
985  // setup handling of this byte
986  I2C_GenerateSTOP(i2c_adapter->cfg->regs, ENABLE);
987 
988  /* Move to the next transaction */
989  i2c_adapter->active_txn++;
990 }
991 
992 void PIOS_I2C_EV_IRQ_Handler(pios_i2c_t i2c_adapter)
993 {
995 
996  PIOS_Assert(PIOS_I2C_validate(i2c_adapter) == true);
997 
998  bool woken = false;
999 
1000  // reading the event clears the interrupt flags
1001  uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1002 
1003  I2C_DIAG(i2c_adapter, evirq, event);
1004 
1005  switch (event) {
1006  case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
1007  switch (i2c_adapter->active_txn->rw) {
1008  case PIOS_I2C_TXN_READ:
1009  if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1010  /* Final transaction */
1011  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_R_LAST_TXN_STARTED, &woken);
1012  } else {
1013  /* More transactions follow */
1014  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_R_MORE_TXN_STARTED, &woken);
1015  }
1016  break;
1017  case PIOS_I2C_TXN_WRITE:
1018  if (i2c_adapter->active_txn == i2c_adapter->last_txn) {
1019  /* Final transaction */
1020  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_W_LAST_TXN_STARTED, &woken);
1021  } else {
1022  /* More transactions follow */
1023  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_W_MORE_TXN_STARTED, &woken);
1024  }
1025  break;
1026  }
1027  break;
1028  case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
1029  case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
1030  switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1031  case 0:
1032  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_0, &woken);
1033  break;
1034  case 1:
1035  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_1, &woken);
1036  break;
1037  case 2:
1038  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_EQ_2, &woken);
1039  break;
1040  default:
1041  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_ADDR_SENT_LEN_GT_2, &woken);
1042  break;
1043  }
1044  break;
1045  case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
1046  case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
1047  switch (i2c_adapter->last_byte - i2c_adapter->active_byte + 1) {
1048  case 0:
1049  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_0, &woken);
1050  break;
1051  case 1:
1052  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_1, &woken);
1053  break;
1054  case 2:
1055  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_EQ_2, &woken);
1056  break;
1057  default:
1058  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_TRANSFER_DONE_LEN_GT_2, &woken);
1059  break;
1060  }
1061  break;
1062  case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
1063  // This event is being ignored. It may be used to speed up transfer by reloading data buffer earlier.
1064  break;
1065  default:
1066  i2c_adapter_log_fault(i2c_adapter, PIOS_I2C_ERROR_EVENT);
1067 
1068  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR, &woken);
1069  break;
1070  }
1071 
1073 }
1074 
1075 void PIOS_I2C_ER_IRQ_Handler(pios_i2c_t i2c_adapter)
1076 {
1078 
1079  bool valid = PIOS_I2C_validate(i2c_adapter);
1080  PIOS_Assert(valid);
1081 
1082  bool woken = false;
1083 
1084  uint32_t event = I2C_GetLastEvent(i2c_adapter->cfg->regs);
1085 
1086  // clear all flags
1087  I2C_ClearFlag(i2c_adapter->cfg->regs,
1088  I2C_FLAG_SMBALERT |
1089  I2C_FLAG_TIMEOUT |
1090  I2C_FLAG_PECERR |
1091  I2C_FLAG_OVR |
1092  I2C_FLAG_AF |
1093  I2C_FLAG_ARLO |
1094  I2C_FLAG_BERR);
1095 
1096  I2C_DIAG(i2c_adapter, erirq, event);
1097 
1098  // explicitly handle NACK
1099  if (event & I2C_FLAG_AF) {
1100  I2C_DIAG_INCR(i2c_adapter, i2c_nack_counter);
1101  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_NACK, &woken);
1102  } else { /* Mostly bus errors here */
1103  i2c_adapter_log_fault(i2c_adapter, PIOS_I2C_ERROR_INTERRUPT);
1104 
1105  /* Fail hard on any errors for now */
1106  i2c_adapter_inject_event(i2c_adapter, I2C_EVENT_BUS_ERROR, &woken);
1107  }
1108 
1110 }
1111 
1112 #else /* STM32F4xx */
1113 #error NoImplForArch
1114 #endif
1115 
1116 #endif
1117 
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_I2C_CheckClear(pios_i2c_t i2c_id)
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
i2c_adapter_state
Definition: pios_i2c_priv.h:48
#define PIOS_IRQ_Epilogue()
Definition: pios_irq.h:46
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
static void go_fsm_fault(struct bl_fsm_context *context)
Definition: main.c:292
bool PIOS_Mutex_Unlock(struct pios_mutex *mtx)
Definition: pios_mutex.c:104
struct pios_mutex * PIOS_Mutex_Create(void)
Definition: pios_mutex.c:43
int32_t PIOS_I2C_Init(pios_i2c_t *i2c_id, const char *path)
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
pios_i2c_adapter_magic
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
struct pios_i2c_adapter * pios_i2c_t
Definition: pios_i2c.h:48
void PIOS_I2C_EV_IRQ_Handler(pios_i2c_t i2c_id)
uint8_t i
Definition: msp_messages.h:97
int32_t PIOS_I2C_Transfer(pios_i2c_t i2c_id, const struct pios_i2c_txn txn_list[], uint32_t num_txns)
uint32_t magic
void PIOS_I2C_ER_IRQ_Handler(pios_i2c_t i2c_id)
pios_i2c_error_type
static struct pios_mutex * lock
Definition: alarms.c:43
uint8_t type
i2c_adapter_event
Definition: pios_i2c_priv.h:97
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
#define PIOS_IRQ_Prologue()
Definition: pios_irq.h:45
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_DELAY_WaituS(uint32_t uS)
Definition: pios_delay.c:116
bool PIOS_Mutex_Lock(struct pios_mutex *mtx, uint32_t timeout_ms)
Definition: pios_mutex.c:66
enum arena_state state