PX4 Firmware
PX4 Autopilot Software http://px4.io
i2cdetect.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file i2cdetect.cpp
36  *
37  * Simple tool to scan an I2C bus.
38  *
39  */
40 
41 #include <px4_platform_common/px4_config.h>
42 #include <px4_platform_common/log.h>
43 #include <px4_platform_common/module.h>
44 #include <px4_platform_common/getopt.h>
45 #include <px4_platform_common/i2c.h>
46 
47 namespace i2cdetect
48 {
49 
50 int detect(int bus)
51 {
52  printf("Scanning I2C bus: %d\n", bus);
53 
54  int ret = PX4_ERROR;
55 
56  // attach to the i2c bus
57  struct i2c_master_s *i2c_dev = px4_i2cbus_initialize(bus);
58 
59  if (i2c_dev == nullptr) {
60  PX4_ERR("invalid bus %d", bus);
61  return PX4_ERROR;
62  }
63 
64  printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
65 
66  for (int i = 0; i < 128; i += 16) {
67  printf("%02x: ", i);
68 
69  for (int j = 0; j < 16; j++) {
70 
71  fflush(stdout);
72 
73  uint8_t addr = i + j;
74 
75  unsigned retry_count = 0;
76  const unsigned retries = 5;
77 
78  bool found = false;
79 
80  do {
81  uint8_t send_data = 0;
82  uint8_t recv_data = 0;
83  px4_i2c_msg_t msgv[2];
84 
85  // send
86  msgv[0].frequency = 100000;
87  msgv[0].addr = addr;
88  msgv[0].flags = 0;
89  msgv[0].buffer = &send_data;
90  msgv[0].length = sizeof(send_data);
91 
92  // recv
93  msgv[1].frequency = 100000;
94  msgv[1].addr = addr;
95  msgv[1].flags = I2C_M_READ;
96  msgv[1].buffer = &recv_data;;
97  msgv[1].length = sizeof(recv_data);
98 
99  ret = I2C_TRANSFER(i2c_dev, &msgv[0], 2);
100 
101  // success
102  if (ret == PX4_OK) {
103  found = true;
104  break;
105  }
106 
107  // if we have already retried once, or we are going to give up, then reset the bus
108  if ((retry_count >= 1) || (retry_count >= retries)) {
109  I2C_RESET(i2c_dev);
110  }
111 
112  } while (retry_count++ < retries);
113 
114  if (found) {
115  printf("%02x ", addr);
116 
117  } else {
118  printf("-- ");
119  }
120  }
121 
122  printf("\n");
123  }
124 
125  px4_i2cbus_uninitialize(i2c_dev);
126 
127  return ret;
128 }
129 
130 int usage(const char *reason = nullptr)
131 {
132  if (reason) {
133  PX4_ERR("%s", reason);
134  }
135 
136  PRINT_MODULE_DESCRIPTION("Utility to scan for I2C devices on a particular bus.");
137 
138  PRINT_MODULE_USAGE_NAME_SIMPLE("i2cdetect", "command");
139  PRINT_MODULE_USAGE_PARAM_INT('b', 1, 4, PX4_I2C_BUS_EXPANSION, "I2C bus", true);
140 
141  return PX4_OK;
142 }
143 
144 } // namespace i2cdetect
145 
146 extern "C" {
147  __EXPORT int i2cdetect_main(int argc, char *argv[]);
148 }
149 
150 int i2cdetect_main(int argc, char *argv[])
151 {
152  int i2c_bus = PX4_I2C_BUS_EXPANSION;
153 
154  int myoptind = 1;
155  int ch = 0;
156  const char *myoptarg = nullptr;
157 
158  while ((ch = px4_getopt(argc, argv, "b:", &myoptind, &myoptarg)) != EOF) {
159  switch (ch) {
160  case 'b':
161  // set i2c bus
162  i2c_bus = strtol(myoptarg, nullptr, 0);
163  break;
164 
165  default:
167  return -1;
168  break;
169  }
170  }
171 
172  return i2cdetect::detect(i2c_bus);
173 }
int detect(int bus)
Definition: i2cdetect.cpp:50
__EXPORT int i2cdetect_main(int argc, char *argv[])
Definition: i2cdetect.cpp:150
Definition: I2C.hpp:51
static int send_data(int uart, uint8_t *buffer, size_t size)
int usage(const char *reason=nullptr)
Print the correct usage.
Definition: i2cdetect.cpp:130
static int recv_data(int uart, uint8_t *buffer, size_t *size, uint8_t *id)