Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
i2c_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 AggieAir, A Remote Sensing Unmanned Aerial System for Scientific Applications
3  * Utah State University, http://aggieair.usu.edu/
4  *
5  * Michal Podhradsky (michal.podhradsky@aggiemail.usu.edu)
6  * Calvin Coopmans (c.r.coopmans@ieee.org)
7  *
8  * Copyright (C) 2015 Gautier Hattenberger, Alexandre Bustico
9  *
10  * This file is part of paparazzi.
11  *
12  * paparazzi is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * paparazzi is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with paparazzi; see the file COPYING. If not, write to
24  * the Free Software Foundation, 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
34 #include "mcu_periph/i2c_arch.h"
35 #include "mcu_periph/i2c.h"
36 
37 #include BOARD_CONFIG
38 
39 #include <ch.h>
40 #include <hal.h>
41 
42 #if USE_I2C1 || USE_I2C2 || USE_I2C3
43 
44 // private I2C init structure
45 struct i2c_init {
46  semaphore_t *sem;
47  I2CConfig *cfg;
48 };
49 
50 
51 static void handle_i2c_thd(struct i2c_periph *p);
52 
53 // Timeout for I2C transaction
54 static const systime_t tmo = US2ST(1000000/PERIODIC_FREQUENCY);
55 
61 static void handle_i2c_thd(struct i2c_periph *p)
62 {
63  struct i2c_init *i = (struct i2c_init *) p->init_struct;
64 
65  // wait for a transaction to be pushed in the queue
66  chSemWait (i->sem);
67 
68  if (p->trans_insert_idx == p->trans_extract_idx) {
69  p->status = I2CIdle;
70  // no transaction pending
71  return;
72  }
73 
74  // Get next transation in queue
75  struct i2c_transaction *t = p->trans[p->trans_extract_idx];
76 
78  msg_t status;
79  // submit i2c transaction (R/W or R only depending of len_w)
80  if (t->len_w > 0) {
81  status = i2cMasterTransmitTimeout(
82  (I2CDriver*)p->reg_addr,
83  (i2caddr_t)((t->slave_addr)>>1),
84  (uint8_t*)t->buf, (size_t)(t->len_w),
85  (uint8_t*)t->buf, (size_t)(t->len_r),
86  tmo);
87  } else {
88  status = i2cMasterReceiveTimeout(
89  (I2CDriver*)p->reg_addr,
90  (i2caddr_t)((t->slave_addr)>>1),
91  (uint8_t*)t->buf, (size_t)(t->len_r),
92  tmo);
93  }
94 
95  chSysLock();
96  // end of transaction, handle fifo
97  p->trans_extract_idx++;
99  p->trans_extract_idx = 0;
100  }
101  p->status = I2CIdle;
102  chSysUnlock();
103 
104  // Set report status and errors
105  switch (status) {
106  case MSG_OK:
107  //if the function succeeded
108  t->status = I2CTransSuccess;
109  break;
110  case MSG_TIMEOUT:
111  //if a timeout occurred before operation end
112  // mark as failed and restart
113  t->status = I2CTransFailed;
114  i2cStart((I2CDriver*)p->reg_addr, i->cfg);
115  break;
116  case MSG_RESET:
117  //if one or more I2C errors occurred, the errors can
118  //be retrieved using @p i2cGetErrors().
119  t->status = I2CTransFailed;
120  i2cflags_t errors = i2cGetErrors((I2CDriver*)p->reg_addr);
121  if (errors & I2C_BUS_ERROR) {
123  }
124  if (errors & I2C_ARBITRATION_LOST) {
125  p->errors->arb_lost_cnt++;
126  }
127  if (errors & I2C_ACK_FAILURE) {
128  p->errors->ack_fail_cnt++;
129  }
130  if (errors & I2C_OVERRUN) {
131  p->errors->over_under_cnt++;
132  }
133  if (errors & I2C_PEC_ERROR) {
134  p->errors->pec_recep_cnt++;
135  }
136  if (errors & I2C_TIMEOUT) {
137  p->errors->timeout_tlow_cnt++;
138  }
139  if (errors & I2C_SMB_ALERT) {
140  p->errors->smbus_alert_cnt++;
141  }
142  break;
143  default:
144  break;
145  }
146 }
147 #endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 */
148 
149 #if USE_I2C1
150 // I2C1 config
151 PRINT_CONFIG_VAR(I2C1_CLOCK_SPEED)
152 static SEMAPHORE_DECL(i2c1_sem, 0);
153 static I2CConfig i2cfg1 = I2C1_CFG_DEF;
154 static struct i2c_init i2c1_init_s = {
155  .sem = &i2c1_sem,
156  .cfg = &i2cfg1
157 };
158 // Errors
159 struct i2c_errors i2c1_errors;
160 // Thread
161 static __attribute__((noreturn)) void thd_i2c1(void *arg);
162 static THD_WORKING_AREA(wa_thd_i2c1, 1024);
163 
164 /*
165  * I2C1 init
166  */
167 void i2c1_hw_init(void)
168 {
169  i2cStart(&I2CD1, &i2cfg1);
170  i2c1.reg_addr = &I2CD1;
171  i2c1.errors = &i2c1_errors;
172  i2c1.init_struct = &i2c1_init_s;
173  // Create thread
174  chThdCreateStatic(wa_thd_i2c1, sizeof(wa_thd_i2c1),
175  NORMALPRIO+1, thd_i2c1, NULL);
176 }
177 
178 /*
179  * I2C1 thread
180  *
181  */
182 static void thd_i2c1(void *arg)
183 {
184  (void) arg;
185  chRegSetThreadName("i2c1");
186 
187  while (TRUE) {
188  handle_i2c_thd(&i2c1);
189  }
190 }
191 #endif /* USE_I2C1 */
192 
193 #if USE_I2C2
194 // I2C2 config
195 PRINT_CONFIG_VAR(I2C2_CLOCK_SPEED)
196 static SEMAPHORE_DECL(i2c2_sem, 0);
197 static I2CConfig i2cfg2 = I2C2_CFG_DEF;
198 static struct i2c_init i2c2_init_s = {
199  .sem = &i2c2_sem,
200  .cfg = &i2cfg2
201 };
202 // Errors
203 struct i2c_errors i2c2_errors;
204 // Thread
205 static __attribute__((noreturn)) void thd_i2c2(void *arg);
206 static THD_WORKING_AREA(wa_thd_i2c2, 1024);
207 
208 /*
209  * I2C2 init
210  */
211 void i2c2_hw_init(void)
212 {
213  i2cStart(&I2CD2, &i2cfg2);
214  i2c2.reg_addr = &I2CD2;
215  i2c2.init_struct = NULL;
216  i2c2.errors = &i2c2_errors;
217  i2c2.init_struct = &i2c2_init_s;
218  // Create thread
219  chThdCreateStatic(wa_thd_i2c2, sizeof(wa_thd_i2c2),
220  NORMALPRIO+1, thd_i2c2, NULL);
221 }
222 
223 /*
224  * I2C2 thread
225  *
226  */
227 static void thd_i2c2(void *arg)
228 {
229  (void) arg;
230  chRegSetThreadName("i2c2");
231 
232  while (TRUE) {
233  handle_i2c_thd(&i2c2);
234  }
235 }
236 #endif /* USE_I2C2 */
237 
238 #if USE_I2C3
239 // I2C3 config
240 PRINT_CONFIG_VAR(I2C3_CLOCK_SPEED)
241 static SEMAPHORE_DECL(i2c3_sem, 0);
242 static I2CConfig i2cfg3 = I2C3_CFG_DEF;
243 static struct i2c_init i2c3_init_s = {
244  .sem = &i2c3_sem,
245  .cfg = &i2cfg3
246 };
247 // Errors
248 struct i2c_errors i2c3_errors;
249 // Thread
250 static __attribute__((noreturn)) void thd_i2c3(void *arg);
251 static THD_WORKING_AREA(wa_thd_i2c3, 1024);
252 
253 /*
254  * I2C3 init
255  */
256 void i2c3_hw_init(void)
257 {
258  i2cStart(&I2CD3, &i2cfg3);
259  i2c3.reg_addr = &I2CD3;
260  i2c3.init_struct = NULL;
261  i2c3.errors = &i2c3_errors;
262  i2c3.init_struct = &i2c3_init_s;
263  // Create thread
264  chThdCreateStatic(wa_thd_i2c3, sizeof(wa_thd_i2c3),
265  NORMALPRIO+1, thd_i2c3, NULL);
266 }
267 
268 /*
269  * I2C3 thread
270  *
271  */
272 static void thd_i2c3(void *arg)
273 {
274  (void) arg;
275  chRegSetThreadName("i2c3");
276 
277  while (TRUE) {
278  handle_i2c_thd(&i2c3);
279  }
280 }
281 #endif /* USE_I2C3 */
282 
283 
289 void i2c_event(void) {}
290 
297 void i2c_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) {}
298 
316 bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
317 {
318 #if USE_I2C1 || USE_I2C2 || USE_I2C3
319  // sys lock
320  chSysLock();
321  uint8_t temp;
322  temp = p->trans_insert_idx + 1;
323  if (temp >= I2C_TRANSACTION_QUEUE_LEN) { temp = 0; }
324  if (temp == p->trans_extract_idx) {
325  // queue full
326  p->errors->queue_full_cnt++;
327  t->status = I2CTransFailed;
328  chSysUnlock();
329  return FALSE;
330  }
331 
332  t->status = I2CTransPending;
333 
334  /* put transacation in queue */
335  p->trans[p->trans_insert_idx] = t;
336  p->trans_insert_idx = temp;
337 
338  chSysUnlock();
339  chSemSignal (((struct i2c_init *)p->init_struct)->sem);
340  // transaction submitted
341  return TRUE;
342 #else
343  // if no I2C peripheral is used fill in with dummy function
344  (void)p;
345  (void)t;
346  return FALSE;
347 #endif /* USE_I2C1 || USE_I2C2 || USE_I2C3 */
348 }
349 
355 bool i2c_idle(struct i2c_periph *p __attribute__((unused)))
356 {
357  return FALSE;
358 }
volatile uint16_t arb_lost_cnt
Definition: i2c.h:159
status
Definition: anemotaxis.c:10
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
Definition: i2c.h:133
I2C errors counter.
Definition: i2c.h:154
#define I2C_TIMEOUT
Definition: i2c_smbus.h:125
volatile uint16_t miss_start_stop_cnt
Definition: i2c.h:158
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
uint16_t len_r
Number of bytes to read/receive.
Definition: i2c.h:110
transaction successfully finished by I2C driver
Definition: i2c.h:57
#define I2C1_CFG_DEF
Definition: board.h:945
uint8_t trans_extract_idx
Definition: i2c.h:142
void i2c_init(struct i2c_periph *p)
Initialize I2C peripheral.
Definition: i2c.c:245
bool i2c_idle(struct i2c_periph *p)
i2c_idle() function
Definition: i2c_arch.c:355
Definition: i2c.h:66
volatile uint16_t queue_full_cnt
Definition: i2c.h:156
void i2c_setbitrate(struct i2c_periph *p, int bitrate)
i2c_setbitrate() function
Definition: i2c_arch.c:297
struct i2c_errors * errors
Definition: i2c.h:148
enum I2CStatus status
Definition: i2c.h:144
#define FALSE
Definition: std.h:5
static SEMAPHORE_DECL(spi1_sem, 0)
Configure SPI peripherals.
void * reg_addr
Definition: i2c.h:146
uint8_t len_w
Number of bytes to write/transmit.
Definition: i2c.h:116
#define TRUE
Definition: std.h:4
struct i2c_transaction * trans[I2C_TRANSACTION_QUEUE_LEN]
Definition: i2c.h:140
volatile uint16_t over_under_cnt
Definition: i2c.h:160
bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
i2c_submit() function
Definition: i2c_arch.c:316
transaction failed
Definition: i2c.h:58
I2C transaction structure.
Definition: i2c.h:93
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
void * init_struct
Definition: i2c.h:147
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
I2C peripheral structure.
Definition: i2c.h:138
#define I2C2_CFG_DEF
Definition: board.h:952
unsigned char uint8_t
Definition: types.h:14
static float p[2][2]
volatile uint16_t smbus_alert_cnt
Definition: i2c.h:163
void i2c_event(void)
i2c_event() function
Definition: i2c_arch.c:289
#define I2C1_CLOCK_SPEED
I2C defines.
Definition: board.h:944
uint8_t trans_insert_idx
Definition: i2c.h:141
volatile uint16_t pec_recep_cnt
Definition: i2c.h:161
#define I2C2_CLOCK_SPEED
Definition: board.h:951
transaction is pending in queue
Definition: i2c.h:55
static THD_WORKING_AREA(wa_thd_spi1, 1024)
volatile uint16_t ack_fail_cnt
Definition: i2c.h:157
volatile uint16_t timeout_tlow_cnt
Definition: i2c.h:162
Architecture independent I2C (Inter-Integrated Circuit Bus) API.