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 /* wake handler thread */
110
111 return true;
112}
113
114/*
115 * Transactions handler thread
116 */
117#pragma GCC diagnostic push
118#pragma GCC diagnostic ignored "-Wcast-qual"
119static void *i2c_thread(void *data)
120{
121 struct i2c_msg trx_msgs[2];
123 .msgs = trx_msgs,
124 .nmsgs = 2
125 };
126
128
129 struct i2c_periph *p = (struct i2c_periph *)data;
130 pthread_mutex_t *mutex = &(((struct i2c_thread_t *)(p->init_struct))->mutex);
131 pthread_cond_t *condition = &(((struct i2c_thread_t *)(p->init_struct))->condition);
132
133 while (1) {
134 /* wait for data to transfer */
136 if (p->trans_insert_idx == p->trans_extract_idx) {
138 }
139
140 int fd = (int)p->reg_addr;
141 struct i2c_transaction *t = p->trans[p->trans_extract_idx];
143
144 // Switch the different transaction types
145 switch (t->type) {
146 // Just transmitting
147 case I2CTransTx:
148 // Set the slave address, converted to 7 bit
149 ioctl(fd, I2C_SLAVE, t->slave_addr >> 1);
150 if (write(fd, (uint8_t *)t->buf, t->len_w) < 0) {
151 /* if write failed, increment error counter ack_fail_cnt */
153 p->errors->ack_fail_cnt++;
155 t->status = I2CTransFailed;
156 } else {
157 t->status = I2CTransSuccess;
158 }
159 break;
160 // Just reading
161 case I2CTransRx:
162 // Set the slave address, converted to 7 bit
163 ioctl(fd, I2C_SLAVE, t->slave_addr >> 1);
164 if (read(fd, (uint8_t *)t->buf, t->len_r) < 0) {
165 /* if read failed, increment error counter arb_lost_cnt */
167 p->errors->arb_lost_cnt++;
169 t->status = I2CTransFailed;
170 } else {
171 t->status = I2CTransSuccess;
172 }
173 break;
174 // First Transmit and then read with repeated start
175 case I2CTransTxRx:
176 trx_msgs[0].addr = t->slave_addr >> 1;
177 trx_msgs[0].flags = 0; /* tx */
178 trx_msgs[0].len = t->len_w;
179 trx_msgs[0].buf = (void *) t->buf;
180 trx_msgs[1].addr = t->slave_addr >> 1;
181 trx_msgs[1].flags = I2C_M_RD;
182 trx_msgs[1].len = t->len_r;
183 trx_msgs[1].buf = (void *) t->buf;
184 if (ioctl(fd, I2C_RDWR, &trx_data) < 0) {
185 /* if write/read failed, increment error counter miss_start_stop_cnt */
187 p->errors->miss_start_stop_cnt++;
189 t->status = I2CTransFailed;
190 } else {
191 t->status = I2CTransSuccess;
192 }
193 break;
194 default:
195 t->status = I2CTransFailed;
196 break;
197 }
198
200 p->trans_extract_idx = (p->trans_extract_idx + 1) % I2C_TRANSACTION_QUEUE_LEN;
202 }
203 return NULL;
204}
205#pragma GCC diagnostic pop
206
207#if USE_I2C0
210
211void i2c0_hw_init(void)
212{
213 i2c0.idle = i2c_linux_idle;
214 i2c0.submit = i2c_linux_submit;
215 i2c0.setbitrate = i2c_linux_setbitrate;
216
217 i2c0.reg_addr = (void *)open("/dev/i2c-0", O_RDWR);
218 i2c0.errors = &i2c0_errors;
219
220 /* zeros error counter */
222
225 i2c0.init_struct = (void *)(&i2c0_thread);
226
228}
229#endif
230
231#if USE_I2C1
234
235void i2c1_hw_init(void)
236{
237 i2c1.idle = i2c_linux_idle;
238 i2c1.submit = i2c_linux_submit;
239 i2c1.setbitrate = i2c_linux_setbitrate;
240
241 i2c1.reg_addr = (void *)open("/dev/i2c-1", O_RDWR);
242 i2c1.errors = &i2c1_errors;
243
244 /* zeros error counter */
246
249 i2c1.init_struct = (void *)(&i2c1_thread);
250
252}
253#endif
254
255#if USE_I2C2
258
259void i2c2_hw_init(void)
260{
261 i2c2.idle = i2c_linux_idle;
262 i2c2.submit = i2c_linux_submit;
263 i2c2.setbitrate = i2c_linux_setbitrate;
264
265 i2c2.reg_addr = (void *)open("/dev/i2c-2", O_RDWR);
266 i2c2.errors = &i2c2_errors;
267
268 /* zeros error counter */
270
273 i2c2.init_struct = (void *)(&i2c2_thread);
274
276}
277#endif
278
279#if USE_I2C3
282
283void i2c3_hw_init(void)
284{
285 i2c3.idle = i2c_linux_idle;
286 i2c3.submit = i2c_linux_submit;
287 i2c3.setbitrate = i2c_linux_setbitrate;
288
289 i2c3.reg_addr = (void *)open("/dev/i2c-3", O_RDWR);
290 i2c3.errors = &i2c3_errors;
291
292 /* zeros error counter */
294
297 i2c3.init_struct = (void *)(&i2c3_thread);
298
300}
301#endif
#define UNUSED(x)
static pthread_mutex_t mutex
void i2c_event(void)
i2c_event() function
Definition i2c_arch.c:393
#define ZEROS_ERR_COUNTER(_i2c_err)
Definition i2c.h:181
#define I2C_TRANSACTION_QUEUE_LEN
I2C transaction queue length.
Definition i2c.h:133
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:57
@ I2CTransFailed
transaction failed
Definition i2c.h:58
@ I2CTransPending
transaction is pending in queue
Definition i2c.h:55
@ I2CTransRx
receive only transaction
Definition i2c.h:48
@ I2CTransTx
transmit only transaction
Definition i2c.h:47
@ I2CTransTxRx
transmit and receive transaction
Definition i2c.h:49
I2C errors counter.
Definition i2c.h:165
I2C transaction structure.
Definition i2c.h:93
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:119
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.