Paparazzi UAS v7.0_unstable
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 *
3 * Copyright (C) 2014 Freek van Tienen <freek.v.tienen@gmail.com>
4 * 2018 Kirk Scheper <kirkscheper@gmail.com>
5 *
6 * This file is part of paparazzi.
7 *
8 * paparazzi is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * paparazzi is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with paparazzi; see the file COPYING. If not, write to
20 * the Free Software Foundation, 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 *
23 */
24
29#include "mcu_periph/i2c.h"
30#include <stdio.h>
31#include <fcntl.h>
32#include <unistd.h>
33#include <sys/ioctl.h>
34#include <linux/i2c.h>
35#include <linux/i2c-dev.h>
36#include <errno.h>
37
38#include <pthread.h>
39#include "rt_priority.h"
40
41#ifndef I2C_THREAD_PRIO
42#define I2C_THREAD_PRIO 10
43#endif
44
45
46static bool i2c_linux_idle(struct i2c_periph *p __attribute__((unused))) __attribute__((unused));
47static bool i2c_linux_submit(struct i2c_periph *p, struct i2c_transaction *t) __attribute__((unused));
48static void i2c_linux_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused))) __attribute__((unused));
49
50
51static void *i2c_thread(void *thread_data);
52
53// private I2C init structure
58
59static void UNUSED i2c_arch_init(struct i2c_periph *p)
60{
62 if (pthread_create(&tid, NULL, i2c_thread, (void *)p) != 0) {
63 fprintf(stderr, "i2c_arch_init: Could not create I2C thread.\n");
64 return;
65 }
66#ifndef __APPLE__
67 pthread_setname_np(tid, "i2c");
68#endif
69}
70
71void i2c_event(void)
72{
73}
74
75static void i2c_linux_setbitrate(struct i2c_periph *p __attribute__((unused)), int bitrate __attribute__((unused)))
76{
77}
78
79static bool i2c_linux_idle(struct i2c_periph *p __attribute__((unused)))
80{
81 return true;
82}
83
84static bool i2c_linux_submit(struct i2c_periph *p, struct i2c_transaction *t)
85{
86 // get mutex lock and condition
87 pthread_mutex_t *mutex = &(((struct i2c_thread_t *)(p->init_struct))->mutex);
88 pthread_cond_t *condition = &(((struct i2c_thread_t *)(p->init_struct))->condition);
89
92 next_idx = (p->trans_insert_idx + 1) % I2C_TRANSACTION_QUEUE_LEN;
93 if (next_idx == p->trans_extract_idx) {
94 // queue full
95 p->errors->queue_full_cnt++;
96 t->status = I2CTransFailed;
98 return false;
99 }
100
101 t->status = I2CTransPending;
102
103 /* put transaction in queue */
104 p->trans[p->trans_insert_idx] = t;
105 p->trans_insert_idx = next_idx;
106
107 pprz_bsem_init(&t->bsem, true);
108 /* wake handler thread */
111
112 return true;
113}
114
115/*
116 * Transactions handler thread
117 */
118#pragma GCC diagnostic push
119#pragma GCC diagnostic ignored "-Wcast-qual"
120static void *i2c_thread(void *data)
121{
122 struct i2c_msg trx_msgs[2];
124 .msgs = trx_msgs,
125 .nmsgs = 2
126 };
127
129
130 struct i2c_periph *p = (struct i2c_periph *)data;
131 pthread_mutex_t *mutex = &(((struct i2c_thread_t *)(p->init_struct))->mutex);
132 pthread_cond_t *condition = &(((struct i2c_thread_t *)(p->init_struct))->condition);
133
134 while (1) {
135 /* wait for data to transfer */
137 if (p->trans_insert_idx == p->trans_extract_idx) {
139 }
140
141 int fd = (int)p->reg_addr;
142 struct i2c_transaction *t = p->trans[p->trans_extract_idx];
144
145 // Switch the different transaction types
146 switch (t->type) {
147 // Just transmitting
148 case I2CTransTx:
149 // Set the slave address, converted to 7 bit
150 ioctl(fd, I2C_SLAVE, t->slave_addr >> 1);
151 if (write(fd, (uint8_t *)t->buf, t->len_w) < 0) {
152 /* if write failed, increment error counter ack_fail_cnt */
154 p->errors->ack_fail_cnt++;
156 t->status = I2CTransFailed;
157 } else {
158 t->status = I2CTransSuccess;
159 }
160 break;
161 // Just reading
162 case I2CTransRx:
163 // Set the slave address, converted to 7 bit
164 ioctl(fd, I2C_SLAVE, t->slave_addr >> 1);
165 if (read(fd, (uint8_t *)t->buf, t->len_r) < 0) {
166 /* if read failed, increment error counter arb_lost_cnt */
168 p->errors->arb_lost_cnt++;
170 t->status = I2CTransFailed;
171 } else {
172 t->status = I2CTransSuccess;
173 }
174 break;
175 // First Transmit and then read with repeated start
176 case I2CTransTxRx:
177 trx_msgs[0].addr = t->slave_addr >> 1;
178 trx_msgs[0].flags = 0; /* tx */
179 trx_msgs[0].len = t->len_w;
180 trx_msgs[0].buf = (void *) t->buf;
181 trx_msgs[1].addr = t->slave_addr >> 1;
182 trx_msgs[1].flags = I2C_M_RD;
183 trx_msgs[1].len = t->len_r;
184 trx_msgs[1].buf = (void *) t->buf;
185 if (ioctl(fd, I2C_RDWR, &trx_data) < 0) {
186 /* if write/read failed, increment error counter miss_start_stop_cnt */
188 p->errors->miss_start_stop_cnt++;
190 t->status = I2CTransFailed;
191 } else {
192 t->status = I2CTransSuccess;
193 }
194 break;
195 default:
196 t->status = I2CTransFailed;
197 break;
198 }
199
201 p->trans_extract_idx = (p->trans_extract_idx + 1) % I2C_TRANSACTION_QUEUE_LEN;
203 pprz_bsem_signal(&t->bsem);
204 }
205 return NULL;
206}
207#pragma GCC diagnostic pop
208
209#if USE_I2C0
212
213void i2c0_hw_init(void)
214{
215 i2c0.idle = i2c_linux_idle;
216 i2c0.submit = i2c_linux_submit;
217 i2c0.setbitrate = i2c_linux_setbitrate;
218
219 i2c0.reg_addr = (void *)open("/dev/i2c-0", O_RDWR);
220 i2c0.errors = &i2c0_errors;
221
222 /* zeros error counter */
224
227 i2c0.init_struct = (void *)(&i2c0_thread);
228
230}
231#endif
232
233#if USE_I2C1
236
237void i2c1_hw_init(void)
238{
239 i2c1.idle = i2c_linux_idle;
240 i2c1.submit = i2c_linux_submit;
241 i2c1.setbitrate = i2c_linux_setbitrate;
242
243 i2c1.reg_addr = (void *)open("/dev/i2c-1", O_RDWR);
244 i2c1.errors = &i2c1_errors;
245
246 /* zeros error counter */
248
251 i2c1.init_struct = (void *)(&i2c1_thread);
252
254}
255#endif
256
257#if USE_I2C2
260
261void i2c2_hw_init(void)
262{
263 i2c2.idle = i2c_linux_idle;
264 i2c2.submit = i2c_linux_submit;
265 i2c2.setbitrate = i2c_linux_setbitrate;
266
267 i2c2.reg_addr = (void *)open("/dev/i2c-2", O_RDWR);
268 i2c2.errors = &i2c2_errors;
269
270 /* zeros error counter */
272
275 i2c2.init_struct = (void *)(&i2c2_thread);
276
278}
279#endif
280
281#if USE_I2C3
284
285void i2c3_hw_init(void)
286{
287 i2c3.idle = i2c_linux_idle;
288 i2c3.submit = i2c_linux_submit;
289 i2c3.setbitrate = i2c_linux_setbitrate;
290
291 i2c3.reg_addr = (void *)open("/dev/i2c-3", O_RDWR);
292 i2c3.errors = &i2c3_errors;
293
294 /* zeros error counter */
296
299 i2c3.init_struct = (void *)(&i2c3_thread);
300
302}
303#endif
#define UNUSED(x)
void pprz_bsem_init(pprz_bsem_t *bsem, bool taken)
void pprz_bsem_signal(pprz_bsem_t *bsem)
static pthread_mutex_t mutex
void i2c_event(void)
i2c_event() function
Definition i2c_arch.c:394
#define ZEROS_ERR_COUNTER(_i2c_err)
Definition i2c.h:186
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
Definition i2c.h:138
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:58
@ I2CTransFailed
transaction failed
Definition i2c.h:59
@ I2CTransPending
transaction is pending in queue
Definition i2c.h:56
@ I2CTransRx
receive only transaction
Definition i2c.h:49
@ I2CTransTx
transmit only transaction
Definition i2c.h:48
@ I2CTransTxRx
transmit and receive transaction
Definition i2c.h:50
I2C errors counter.
Definition i2c.h:170
I2C transaction structure.
Definition i2c.h:94
Architecture independent I2C (Inter-Integrated Circuit Bus) API.
#define I2C_RDWR
Definition i2c_smbus.h:138
#define I2C_SLAVE
Definition i2c_smbus.h:129
#define I2C_M_RD
Definition i2c_smbus.h:44
static float p[2][2]
static void UNUSED i2c_arch_init(struct i2c_periph *p)
Definition i2c_arch.c:59
static bool i2c_linux_submit(struct i2c_periph *p, struct i2c_transaction *t)
Definition i2c_arch.c:84
static void * i2c_thread(void *thread_data)
Definition i2c_arch.c:120
static bool i2c_linux_idle(struct i2c_periph *p)
Definition i2c_arch.c:79
pthread_cond_t condition
Definition i2c_arch.c:56
static void i2c_linux_setbitrate(struct i2c_periph *p, int bitrate)
Definition i2c_arch.c:75
pthread_mutex_t mutex
Definition i2c_arch.c:55
#define I2C_THREAD_PRIO
Definition i2c_arch.c:42
uint16_t foo
Definition main_demo5.c:58
Functions to obtain rt priority or set the nice level.
static int get_rt_prio(int prio)
Definition rt_priority.h:32
int fd
Definition serial.c:26
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.