Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2012 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
28 #include "mcu_periph/i2c.h"
29 #include "mcu_periph/sys_time.h"
30 
31 #if PERIODIC_TELEMETRY
33 #endif
34 
35 #if USE_I2C0
36 
37 struct i2c_periph i2c0;
38 
39 #if PERIODIC_TELEMETRY
40 static void send_i2c0_err(struct transport_tx *trans, struct link_device *dev)
41 {
42  uint16_t i2c0_wd_reset_cnt = i2c0.errors->wd_reset_cnt;
43  uint16_t i2c0_queue_full_cnt = i2c0.errors->queue_full_cnt;
44  uint16_t i2c0_ack_fail_cnt = i2c0.errors->ack_fail_cnt;
45  uint16_t i2c0_miss_start_stop_cnt = i2c0.errors->miss_start_stop_cnt;
46  uint16_t i2c0_arb_lost_cnt = i2c0.errors->arb_lost_cnt;
47  uint16_t i2c0_over_under_cnt = i2c0.errors->over_under_cnt;
48  uint16_t i2c0_pec_recep_cnt = i2c0.errors->pec_recep_cnt;
49  uint16_t i2c0_timeout_tlow_cnt = i2c0.errors->timeout_tlow_cnt;
50  uint16_t i2c0_smbus_alert_cnt = i2c0.errors->smbus_alert_cnt;
51  uint16_t i2c0_unexpected_event_cnt = i2c0.errors->unexpected_event_cnt;
52  uint32_t i2c0_last_unexpected_event = i2c0.errors->last_unexpected_event;
53  uint8_t _bus0 = 0;
54  pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
55  &i2c0_wd_reset_cnt,
56  &i2c0_queue_full_cnt,
57  &i2c0_ack_fail_cnt,
58  &i2c0_miss_start_stop_cnt,
59  &i2c0_arb_lost_cnt,
60  &i2c0_over_under_cnt,
61  &i2c0_pec_recep_cnt,
62  &i2c0_timeout_tlow_cnt,
63  &i2c0_smbus_alert_cnt,
64  &i2c0_unexpected_event_cnt,
65  &i2c0_last_unexpected_event,
66  &_bus0);
67 }
68 #endif
69 
70 void i2c0_init(void)
71 {
72  i2c_init(&i2c0);
73  i2c0_hw_init();
74 }
75 
76 #endif /* USE_I2C0 */
77 
78 
79 #if USE_I2C1
80 
81 struct i2c_periph i2c1;
82 
83 #if PERIODIC_TELEMETRY
84 static void send_i2c1_err(struct transport_tx *trans, struct link_device *dev)
85 {
86  uint16_t i2c1_wd_reset_cnt = i2c1.errors->wd_reset_cnt;
87  uint16_t i2c1_queue_full_cnt = i2c1.errors->queue_full_cnt;
88  uint16_t i2c1_ack_fail_cnt = i2c1.errors->ack_fail_cnt;
89  uint16_t i2c1_miss_start_stop_cnt = i2c1.errors->miss_start_stop_cnt;
90  uint16_t i2c1_arb_lost_cnt = i2c1.errors->arb_lost_cnt;
91  uint16_t i2c1_over_under_cnt = i2c1.errors->over_under_cnt;
92  uint16_t i2c1_pec_recep_cnt = i2c1.errors->pec_recep_cnt;
93  uint16_t i2c1_timeout_tlow_cnt = i2c1.errors->timeout_tlow_cnt;
94  uint16_t i2c1_smbus_alert_cnt = i2c1.errors->smbus_alert_cnt;
95  uint16_t i2c1_unexpected_event_cnt = i2c1.errors->unexpected_event_cnt;
96  uint32_t i2c1_last_unexpected_event = i2c1.errors->last_unexpected_event;
97  uint8_t _bus1 = 1;
98  pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
99  &i2c1_wd_reset_cnt,
100  &i2c1_queue_full_cnt,
101  &i2c1_ack_fail_cnt,
102  &i2c1_miss_start_stop_cnt,
103  &i2c1_arb_lost_cnt,
104  &i2c1_over_under_cnt,
105  &i2c1_pec_recep_cnt,
106  &i2c1_timeout_tlow_cnt,
107  &i2c1_smbus_alert_cnt,
108  &i2c1_unexpected_event_cnt,
109  &i2c1_last_unexpected_event,
110  &_bus1);
111 }
112 #endif
113 
114 void i2c1_init(void)
115 {
116  i2c_init(&i2c1);
117  i2c1_hw_init();
118 }
119 
120 #endif /* USE_I2C1 */
121 
122 
123 #if USE_I2C2
124 
125 struct i2c_periph i2c2;
126 
127 #if PERIODIC_TELEMETRY
128 static void send_i2c2_err(struct transport_tx *trans, struct link_device *dev)
129 {
130  uint16_t i2c2_wd_reset_cnt = i2c2.errors->wd_reset_cnt;
131  uint16_t i2c2_queue_full_cnt = i2c2.errors->queue_full_cnt;
132  uint16_t i2c2_ack_fail_cnt = i2c2.errors->ack_fail_cnt;
133  uint16_t i2c2_miss_start_stop_cnt = i2c2.errors->miss_start_stop_cnt;
134  uint16_t i2c2_arb_lost_cnt = i2c2.errors->arb_lost_cnt;
135  uint16_t i2c2_over_under_cnt = i2c2.errors->over_under_cnt;
136  uint16_t i2c2_pec_recep_cnt = i2c2.errors->pec_recep_cnt;
137  uint16_t i2c2_timeout_tlow_cnt = i2c2.errors->timeout_tlow_cnt;
138  uint16_t i2c2_smbus_alert_cnt = i2c2.errors->smbus_alert_cnt;
139  uint16_t i2c2_unexpected_event_cnt = i2c2.errors->unexpected_event_cnt;
140  uint32_t i2c2_last_unexpected_event = i2c2.errors->last_unexpected_event;
141  uint8_t _bus2 = 2;
142  pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
143  &i2c2_wd_reset_cnt,
144  &i2c2_queue_full_cnt,
145  &i2c2_ack_fail_cnt,
146  &i2c2_miss_start_stop_cnt,
147  &i2c2_arb_lost_cnt,
148  &i2c2_over_under_cnt,
149  &i2c2_pec_recep_cnt,
150  &i2c2_timeout_tlow_cnt,
151  &i2c2_smbus_alert_cnt,
152  &i2c2_unexpected_event_cnt,
153  &i2c2_last_unexpected_event,
154  &_bus2);
155 }
156 #endif
157 
158 void i2c2_init(void)
159 {
160  i2c_init(&i2c2);
161  i2c2_hw_init();
162 }
163 
164 #endif /* USE_I2C2 */
165 
166 #if USE_I2C3
167 
168 struct i2c_periph i2c3;
169 
170 void i2c3_init(void)
171 {
172  i2c_init(&i2c3);
173  i2c3_hw_init();
174 }
175 
176 #if PERIODIC_TELEMETRY
177 static void send_i2c3_err(struct transport_tx *trans, struct link_device *dev)
178 {
179  uint16_t i2c3_wd_reset_cnt = i2c3.errors->wd_reset_cnt;
180  uint16_t i2c3_queue_full_cnt = i2c3.errors->queue_full_cnt;
181  uint16_t i2c3_ack_fail_cnt = i2c3.errors->ack_fail_cnt;
182  uint16_t i2c3_miss_start_stop_cnt = i2c3.errors->miss_start_stop_cnt;
183  uint16_t i2c3_arb_lost_cnt = i2c3.errors->arb_lost_cnt;
184  uint16_t i2c3_over_under_cnt = i2c3.errors->over_under_cnt;
185  uint16_t i2c3_pec_recep_cnt = i2c3.errors->pec_recep_cnt;
186  uint16_t i2c3_timeout_tlow_cnt = i2c3.errors->timeout_tlow_cnt;
187  uint16_t i2c3_smbus_alert_cnt = i2c3.errors->smbus_alert_cnt;
188  uint16_t i2c3_unexpected_event_cnt = i2c3.errors->unexpected_event_cnt;
189  uint32_t i2c3_last_unexpected_event = i2c3.errors->last_unexpected_event;
190  uint8_t _bus3 = 3;
191  pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
192  &i2c3_wd_reset_cnt,
193  &i2c3_queue_full_cnt,
194  &i2c3_ack_fail_cnt,
195  &i2c3_miss_start_stop_cnt,
196  &i2c3_arb_lost_cnt,
197  &i2c3_over_under_cnt,
198  &i2c3_pec_recep_cnt,
199  &i2c3_timeout_tlow_cnt,
200  &i2c3_smbus_alert_cnt,
201  &i2c3_unexpected_event_cnt,
202  &i2c3_last_unexpected_event,
203  &_bus3);
204 }
205 #endif
206 
207 #endif /* USE_I2C3 */
208 
209 #if USE_I2C4
210 
211 struct i2c_periph i2c4;
212 
213 void i2c4_init(void)
214 {
215  i2c_init(&i2c4);
216  i2c4_hw_init();
217 }
218 
219 #if PERIODIC_TELEMETRY
220 static void send_i2c4_err(struct transport_tx *trans, struct link_device *dev)
221 {
222  uint16_t i2c4_wd_reset_cnt = i2c4.errors->wd_reset_cnt;
223  uint16_t i2c4_queue_full_cnt = i2c4.errors->queue_full_cnt;
224  uint16_t i2c4_ack_fail_cnt = i2c4.errors->ack_fail_cnt;
225  uint16_t i2c4_miss_start_stop_cnt = i2c4.errors->miss_start_stop_cnt;
226  uint16_t i2c4_arb_lost_cnt = i2c4.errors->arb_lost_cnt;
227  uint16_t i2c4_over_under_cnt = i2c4.errors->over_under_cnt;
228  uint16_t i2c4_pec_recep_cnt = i2c4.errors->pec_recep_cnt;
229  uint16_t i2c4_timeout_tlow_cnt = i2c4.errors->timeout_tlow_cnt;
230  uint16_t i2c4_smbus_alert_cnt = i2c4.errors->smbus_alert_cnt;
231  uint16_t i2c4_unexpected_event_cnt = i2c4.errors->unexpected_event_cnt;
232  uint32_t i2c4_last_unexpected_event = i2c4.errors->last_unexpected_event;
233  uint8_t _bus4 = 4;
234  pprz_msg_send_I2C_ERRORS(trans, dev, AC_ID,
235  &i2c4_wd_reset_cnt,
236  &i2c4_queue_full_cnt,
237  &i2c4_ack_fail_cnt,
238  &i2c4_miss_start_stop_cnt,
239  &i2c4_arb_lost_cnt,
240  &i2c4_over_under_cnt,
241  &i2c4_pec_recep_cnt,
242  &i2c4_timeout_tlow_cnt,
243  &i2c4_smbus_alert_cnt,
244  &i2c4_unexpected_event_cnt,
245  &i2c4_last_unexpected_event,
246  &_bus4);
247 }
248 #endif
249 
250 #endif /* USE_I2C4 */
251 
252 #if USE_SOFTI2C0
253 extern void send_softi2c0_err(struct transport_tx *trans, struct link_device *dev);
254 #endif /* USE_SOFTI2C0 */
255 
256 #if USE_SOFTI2C1
257 extern void send_softi2c1_err(struct transport_tx *trans, struct link_device *dev);
258 #endif /* USE_SOFTI2C1 */
259 
260 #if PERIODIC_TELEMETRY
261 static void send_i2c_err(struct transport_tx *trans __attribute__((unused)),
262  struct link_device *dev __attribute__((unused)))
263 {
264  static uint8_t _i2c_nb_cnt = 0;
265  switch (_i2c_nb_cnt) {
266  case 0:
267 #if USE_I2C0
268  send_i2c0_err(trans, dev);
269 #endif
270  break;
271  case 1:
272 #if USE_I2C1
273  send_i2c1_err(trans, dev);
274 #endif
275  break;
276  case 2:
277 #if USE_I2C2
278  send_i2c2_err(trans, dev);
279 #endif
280  break;
281  case 3:
282 #if USE_I2C3
283  send_i2c3_err(trans, dev);
284 #endif
285  break;
286  case 4:
287 #if USE_I2C4
288  send_i2c4_err(trans, dev);
289 #endif
290  case 5:
291 #if USE_SOFTI2C0
292  send_softi2c0_err(trans, dev);
293 #endif
294  case 6:
295 #if USE_SOFTI2C1
296  send_softi2c1_err(trans, dev);
297 #endif
298  break;
299  default:
300  break;
301  }
302  _i2c_nb_cnt++;
303  if (_i2c_nb_cnt == 7) {
304  _i2c_nb_cnt = 0;
305  }
306 }
307 #endif
308 
309 
310 void i2c_init(struct i2c_periph *p)
311 {
312  p->trans_insert_idx = 0;
313  p->trans_extract_idx = 0;
314  p->status = I2CIdle;
315  p->reg_addr = NULL;
316 
317 #if PERIODIC_TELEMETRY
318  // the first to register do it for the others
319  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_I2C_ERRORS, send_i2c_err);
320 #endif
321 }
322 
323 
324 bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t,
325  uint8_t s_addr, uint8_t len)
326 {
327  t->type = I2CTransTx;
328  t->slave_addr = s_addr;
329  t->len_w = len;
330  t->len_r = 0;
331  return i2c_submit(p, t);
332 }
333 
334 bool i2c_receive(struct i2c_periph *p, struct i2c_transaction *t,
335  uint8_t s_addr, uint16_t len)
336 {
337  t->type = I2CTransRx;
338  t->slave_addr = s_addr;
339  t->len_w = 0;
340  t->len_r = len;
341  return i2c_submit(p, t);
342 }
343 
344 bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t,
345  uint8_t s_addr, uint8_t len_w, uint16_t len_r)
346 {
347  t->type = I2CTransTxRx;
348  t->slave_addr = s_addr;
349  t->len_w = len_w;
350  t->len_r = len_r;
351  return i2c_submit(p, t);
352 }
353 
355 #ifndef I2C_BLOCKING_TIMEOUT
356 #define I2C_BLOCKING_TIMEOUT 1.f
357 #endif
358 
360  uint8_t s_addr, uint8_t len)
361 {
362  t->type = I2CTransTx;
363  t->slave_addr = s_addr;
364  t->len_w = len;
365  t->len_r = 0;
366  if (!i2c_submit(p, t)) {
367  return false;
368  }
369 
370  // Wait for transaction to complete
371  float start_t = get_sys_time_float();
372  while (t->status == I2CTransPending || t->status == I2CTransRunning) {
373  if (p->spin) p->spin(p);
374  if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
375  break; // timeout after 1 second
376  }
377  }
378  return true;
379 }
380 
382  uint8_t s_addr, uint16_t len)
383 {
384  t->type = I2CTransRx;
385  t->slave_addr = s_addr;
386  t->len_w = 0;
387  t->len_r = len;
388  if (!i2c_submit(p, t)) {
389  return false;
390  }
391 
392  // Wait for transaction to complete
393  float start_t = get_sys_time_float();
394  while (t->status == I2CTransPending || t->status == I2CTransRunning) {
395  if (p->spin) p->spin(p);
396  if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
397  break; // timeout after 1 second
398  }
399  }
400  return true;
401 }
402 
404  uint8_t s_addr, uint8_t len_w, uint16_t len_r)
405 {
406  t->type = I2CTransTxRx;
407  t->slave_addr = s_addr;
408  t->len_w = len_w;
409  t->len_r = len_r;
410  if (!i2c_submit(p, t)) {
411  return false;
412  }
413 
414  // Wait for transaction to complete
415  float start_t = get_sys_time_float();
416  while (t->status == I2CTransPending || t->status == I2CTransRunning) {
417  if (p->spin) p->spin(p);
418  if (get_sys_time_float() - start_t > I2C_BLOCKING_TIMEOUT) {
419  break; // timeout after 1 second
420  }
421  }
422  return true;
423 }
uint16_t
unsigned short uint16_t
Definition: types.h:16
i2c_transaction::len_r
uint16_t len_r
Number of bytes to read/receive.
Definition: i2c.h:110
send_i2c_err
static void send_i2c_err(struct transport_tx *trans, struct link_device *dev)
Definition: i2c.c:261
I2C_BLOCKING_TIMEOUT
#define I2C_BLOCKING_TIMEOUT
Default timeout for blocking I2C transactions.
Definition: i2c.c:356
I2CTransTx
@ I2CTransTx
transmit only transaction
Definition: i2c.h:47
get_sys_time_float
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:129
i2c_init
void i2c_init(struct i2c_periph *p)
Initialize I2C peripheral.
Definition: i2c.c:310
i2c_periph::errors
struct i2c_errors * errors
Definition: i2c.h:159
uint32_t
unsigned long uint32_t
Definition: types.h:18
i2c_blocking_transceive
bool i2c_blocking_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction and wait for it to complete.
Definition: i2c.c:403
i2c_transaction::len_w
uint8_t len_w
Number of bytes to write/transmit.
Definition: i2c.h:116
telemetry.h
i2c_transmit
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition: i2c.c:324
I2CTransRx
@ I2CTransRx
receive only transaction
Definition: i2c.h:48
dev
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
i2c_periph::trans
struct i2c_transaction * trans[I2C_TRANSACTION_QUEUE_LEN]
Definition: i2c.h:151
i2c_transceive
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition: i2c.c:344
I2CTransRunning
@ I2CTransRunning
transaction is currently ongoing
Definition: i2c.h:56
sys_time.h
Architecture independent timing functions.
uint8_t
unsigned char uint8_t
Definition: types.h:14
register_periodic_telemetry
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
i2c_transaction::status
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
I2CIdle
@ I2CIdle
Definition: i2c.h:66
i2c_blocking_receive
bool i2c_blocking_receive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint16_t len)
Submit a read only transaction and wait for it to complete.
Definition: i2c.c:381
I2CTransTxRx
@ I2CTransTxRx
transmit and receive transaction
Definition: i2c.h:49
i2c_transaction
I2C transaction structure.
Definition: i2c.h:93
i2c_transaction::slave_addr
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
I2CTransPending
@ I2CTransPending
transaction is pending in queue
Definition: i2c.h:55
i2c_submit
static bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
Submit a I2C transaction.
Definition: i2c.h:266
i2c_errors::wd_reset_cnt
volatile uint16_t wd_reset_cnt
Definition: i2c.h:166
i2c_periph
Definition: i2c.h:144
i2c_transaction::type
enum I2CTransactionType type
Transaction type.
Definition: i2c.h:98
i2c.h
i2c_blocking_transmit
bool i2c_blocking_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction and wait for it to complete.
Definition: i2c.c:359
DefaultPeriodic
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
p
static float p[2][2]
Definition: ins_alt_float.c:268
i2c_receive
bool i2c_receive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint16_t len)
Submit a read only transaction.
Definition: i2c.c:334